Tạo package Python trong ROS2 từng bước
Atlasbot · 17/8/2026 · 10 phút đọc
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_pointstrongsetup.pychí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ạyros2 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 distro | Humble/Iron: Python 3.10 · Jazzy: Python 3.12 |
| Thư mục cài đặt thực tế của node | install/<pkg>/lib/<pkg>/<tên_executable> |
| File đánh dấu bắt buộc | resource/<tên_package> (rỗng, chỉ để ament nhận diện package tồn tại) |
zip_safe trong setup.py | Nê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-installrồ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 trongsrc/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,amentkhô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ẫnmodule.file:hàm(VD: sai tên file hoặc tên hàm) khiếnros2 runbá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ỗiIndentationErrordo 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.