Atlas Robotics
ROS2 PackageTrung bình

Tạo package Python trong ROS2 từng bước

Atlasbot · 17/8/2026 · 10 phút đọc

Tạo package Python trong ROS2 từng bước
Quy trình tạo và build một package Python trong ROS2

Song song với bài Tạo package C++, đây là quy trình tương đương cho ament_python — kiểu package phổ biến cho các node xử lý logic cấp cao (state machine, gọi API, xử lý ảnh bằng OpenCV) nơi tốc độ phát triển quan trọng hơn hiệu năng thuần.

Khái niệm chính

cd ~/ros2_ws/src
ros2 pkg create --build-type ament_python my_py_pkg \
  --dependencies rclpy std_msgs

Cấu trúc sinh ra khác C++ ở chỗ có setup.py/setup.cfg thay cho CMakeLists.txt, và thư mục code trùng tên package thay vì src/:

my_py_pkg/
├── package.xml
├── setup.py             ← khai cách cài đặt + executable
├── setup.cfg
├── resource/my_py_pkg   ← file đánh dấu package (ament index)
└── my_py_pkg/
    └── __init__.py

Nguyên lý hoạt động

Tạo my_py_pkg/hello_node.py:

import rclpy
from rclpy.node import Node

def main(args=None):
    rclpy.init(args=args)
    node = Node("hello_node")
    node.get_logger().info("hello_node đã khởi động")
    rclpy.spin(node)
    rclpy.shutdown()

if __name__ == "__main__":
    main()

Khác với C++ (khai executable trong CMakeLists.txt), Python khai trong setup.py, mục entry_points:

entry_points={
    "console_scripts": [
        "hello_node = my_py_pkg.hello_node:main",
    ],
},

Cú pháp "tên_lệnh = module.file:hàm" — vế trái là tên bạn gõ sau ros2 run my_py_pkg, vế phải là đường dẫn Python thực tới hàm main() cần gọi.

Tóm lại: entry_points trong setup.py chính là "CMakeLists.txt của thế giới Python" — cả hai đều trả lời cùng một câu hỏi: chạy ros2 run <package> <tên> thì thực thi file/hàm nào.

Build và chạy — mẹo symlink-install:

cd ~/ros2_ws
colcon build --packages-select my_py_pkg --symlink-install
source install/setup.bash
ros2 run my_py_pkg hello_node

Cờ --symlink-install chỉ có ý nghĩa với package Python: thay vì copy file .py vào install/, colcon tạo symlink trỏ ngược về src/. Kết quả là sửa code Python xong chạy lại được ngay, không cần colcon build lại.

Kiến thức kỹ thuật

Thông số

Một số thông số/quy ước cần biết khi làm việc với package Python trong ROS2:

Thông sốGiá trị
Phiên bản Python theo distroHumble/Iron: Python 3.10 · Jazzy: Python 3.12
Thư mục cài đặt thực tế của nodeinstall/<pkg>/lib/<pkg>/<tên_executable>
File đánh dấu bắt buộcresource/<tên_package> (rỗng, chỉ để ament nhận diện package tồn tại)
zip_safe trong setup.pyNên đặt False — tránh setuptools nén package thành file .egg, gây lỗi khi ROS2 cần đọc trực tiếp file trong thư mục cài đặt

Một package Python cũng có thể khai nhiều executable cùng lúc trong entry_points, mỗi dòng là 1 chương trình độc lập chạy được bằng ros2 run:

entry_points={
    "console_scripts": [
        "hello_node = my_py_pkg.hello_node:main",
        "diagnostic_tool = my_py_pkg.diagnostic_tool:main",
    ],
},

Ứng dụng thực tế

Quy trình phát triển thực tế phổ biến là prototype bằng Python trước, port sang C++ sau nếu cần: viết thử logic thuật toán (VD: một chiến lược tránh vật cản mới) bằng Python nhờ tốc độ lặp nhanh (sửa code, chạy lại ngay nhờ --symlink-install, không cần chờ biên dịch), sau khi xác nhận logic đúng và cần tối ưu hiệu năng (chạy tần suất cao, độ trễ thấp), mới viết lại phần "đường nóng" (hot path) đó bằng C++. Cách tiếp cận này tận dụng đúng thế mạnh của mỗi ngôn ngữ ở đúng giai đoạn phát triển — nhiều package robot thực tế cũng viết node cấu hình/giao diện bằng Python (VD: đọc file YAML phức tạp, gọi API bên ngoài) song song với node xử lý dữ liệu tần suất cao bằng C++ trong cùng workspace, không nhất thiết phải chọn 1 ngôn ngữ duy nhất cho toàn bộ dự án.

Ví dụ thực tế

$ ros2 run my_py_pkg hello_node
Output:
[INFO] [1723000000.111] [hello_node]: hello_node đã khởi động
# Sửa dòng log trong hello_node.py, LƯU FILE, không build lại
$ ros2 run my_py_pkg hello_node
Output (thay đổi có hiệu lực ngay, không cần colcon build):
[INFO] [1723000005.222] [hello_node]: hello_node đã khởi động (bản mới)

Đây chính là lợi ích thực tế của --symlink-install — vòng lặp sửa-chạy-thử rút ngắn đáng kể so với việc phải build lại (dù nhanh) mỗi lần chỉ đổi 1 dòng code Python.

Lỗi thường gặp

  • Quên --symlink-install rồi thắc mắc vì sao sửa code không có tác dụng — nếu build không dùng cờ này, install/ chứa bản copy tĩnh của code lúc build — sửa file nguồn trong src/ sau đó không tự động cập nhật, phải build lại mỗi lần.
  • Thiếu file đánh dấu resource/<tên_package> — nếu file này bị xoá nhầm hoặc tên không khớp chính xác tên package, ament không nhận diện được package tồn tại dù mọi file khác đều đúng.
  • Sai cú pháp entry_points — lỗi chính tả trong đường dẫn module.file:hàm (VD: sai tên file hoặc tên hàm) khiến ros2 run báo "no executable found" dù package build thành công.
  • Trộn lẫn tab và space trong setup.py — Python nhạy cảm với thụt lề, lỗi IndentationError do trộn tab/space là lỗi cú pháp phổ biến khi copy code từ nhiều nguồn khác nhau vào cùng 1 file.

Kết luận

Package Python đơn giản hơn C++ ở chỗ không cần biên dịch, nhưng vẫn cần qua colcon build để cài đặt đúng vị trí — entry_points trong setup.py đóng vai trò tương đương CMakeLists.txt. Dùng --symlink-install để có vòng lặp phát triển nhanh nhất. Bài tiếp theo trong chuyên mục đi sâu vào CMakeLists.txt — file cấu hình build quan trọng nhất của package C++ vừa học.

Tạo package Python trong ROS2 từng bước — Atlasbot