Action trong ROS2 là gì?
Atlasbot · 16/8/2026 · 10 phút đọc
Lệnh "di chuyển robot tới toạ độ (5, 3)" không giống việc "cộng hai số" — nó có thể mất hàng chục giây, người dùng muốn biết robot đang tiến tới đâu (tiến độ), và có thể cần huỷ giữa chừng nếu đổi ý. Đây là bài toán mà cả Topic (không có khái niệm "hoàn thành") lẫn Service (chỉ trả về một kết quả duy nhất, không báo tiến độ, và block trong lúc chờ) đều xử lý không gọn — Action sinh ra để giải quyết đúng vấn đề này.
Khái niệm chính
Action kết hợp cả ba khái niệm đã học trước đó thành một cơ chế thống nhất:
- Goal — mục tiêu gửi đi lúc bắt đầu (giống gửi request của Service), ví dụ "di chuyển tới toạ độ (5, 3)"
- Feedback — dữ liệu tiến độ được gửi liên tục trong lúc tác vụ đang chạy (giống một Topic), ví dụ "đã đi được 40%, còn cách đích 3m"
- Result — kết quả cuối cùng khi tác vụ hoàn tất, thất bại, hoặc bị huỷ (giống response của Service)
Khác với Service (client bị block chờ tới khi có response), client của Action gửi goal xong không bị chặn — nó tiếp tục nhận feedback dồn dập trong lúc goal đang thực thi, và có quyền huỷ (cancel) goal đang chạy bất cứ lúc nào nếu cần.
Tóm lại: Dùng Topic cho dữ liệu chảy liên tục · Service cho một hành động ngắn có kết quả tức thì · Action cho tác vụ dài, cần theo dõi tiến độ và có khả năng huỷ giữa chừng — đây chính xác là cơ chế Nav2 dùng để nhận lệnh "di chuyển tới một điểm" từ RViz hoặc code.
Nguyên lý hoạt động
Action Client Action Server
│ gửi Goal ("đi tới (5,3)") │
├──────────────────────────────────────►│ bắt đầu thực thi
│ │
│◄──────────── Feedback (20%) ───────────┤
│◄──────────── Feedback (55%) ───────────┤
│◄──────────── Feedback (90%) ───────────┤
│ │
│◄──────────── Result (thành công) ──────┤
Gọi thử một action có sẵn từ dòng lệnh, quan sát feedback trực tiếp trên terminal:
ros2 action list # liệt kê action đang hoạt động
ros2 action send_goal /navigate_to_pose nav2_msgs/action/NavigateToPose \
"{pose: {pose: {position: {x: 5.0, y: 3.0}}}}" --feedback
Cờ --feedback khiến terminal in liên tục mọi bản tin tiến độ nhận được cho tới khi action hoàn tất — đúng luồng goal → feedback → result vừa mô tả ở trên.
Kiến thức kỹ thuật
Thông số
Một goal action luôn ở đúng 1 trong các trạng thái sau tại một thời điểm — kiểm tra đúng trạng thái cuối cùng là bắt buộc trước khi coi tác vụ là "thành công":
| Trạng thái | Ý nghĩa |
|---|---|
PENDING | Goal đã gửi, chưa được server chấp nhận |
ACTIVE | Server đang thực thi goal |
CANCELING | Client đã yêu cầu huỷ, server đang dừng lại |
SUCCEEDED | Hoàn thành thành công |
ABORTED | Server tự huỷ do gặp lỗi trong lúc thực thi |
CANCELED | Đã huỷ thành công theo yêu cầu client |
Protocol
Ở tầng dưới, Action thực chất được ghép từ những khối đã học: 2 Service (1 để gửi goal + xác nhận chấp nhận, 1 để gửi yêu cầu huỷ) và 2 Topic (1 để server phát feedback liên tục, 1 để phát trạng thái/kết quả cuối) — không phải một cơ chế hoàn toàn mới ở tầng DDS, mà là một lớp API tiện lợi đóng gói lại Service + Topic theo đúng quy ước goal-feedback-result. Chi tiết đầy đủ về cách quản lý trạng thái nội bộ này có ở bài Action trong mục ROS2 Communication.
Ứng dụng thực tế
Ngoài NavigateToPose của Nav2 đã nhắc ở trên, action rất phù hợp cho tác vụ tự động về trạm sạc (auto-docking) của AMR — client gửi goal "về sạc", server liên tục báo feedback khoảng cách còn lại tới trạm sạc, và quan trọng là có thể huỷ giữa chừng nếu hệ thống phát hiện có người/vật cản bất ngờ xuất hiện trên đường về sạc — khả năng huỷ an toàn giữa chừng chính là lý do action phù hợp hơn hẳn service cho các tác vụ vận động vật lý có thể cần dừng khẩn cấp bất cứ lúc nào.
Ví dụ thực tế
$ ros2 action send_goal /navigate_to_pose nav2_msgs/action/NavigateToPose \
"{pose: {pose: {position: {x: 2.0, y: 1.0}}}}" --feedback
Output:
Waiting for an action server to become available...
Sending goal:
pose: ...
Goal accepted with ID: 8f3a2b1c...
Feedback:
distance_remaining: 4.85
Feedback:
distance_remaining: 2.10
Feedback:
distance_remaining: 0.32
Result:
error_code: 0
Goal finished with status: SUCCEEDED
distance_remaining giảm dần qua từng feedback cho thấy robot đang thực sự tiến gần đích — status: SUCCEEDED ở cuối là điều bắt buộc phải kiểm tra trong code (không chỉ giả định "gửi goal xong là robot đã tới nơi"), vì goal hoàn toàn có thể kết thúc với ABORTED nếu robot gặp vật cản không thể vượt qua.
Lỗi thường gặp
- Không kiểm tra trạng thái result cuối cùng, giả định luôn thành công — code chỉ gửi goal rồi coi như xong, không kiểm tra
statustrả về làSUCCEEDEDhayABORTED/CANCELED— dẫn tới logic phía sau chạy tiếp dù tác vụ thực tế đã thất bại. - Server không xử lý đúng yêu cầu huỷ (cancel) — nếu code phía server không kiểm tra cờ huỷ định kỳ trong vòng lặp thực thi goal, goal vẫn tiếp tục chạy dù client đã gửi yêu cầu cancel — với tác vụ vận động vật lý, đây có thể là vấn đề an toàn nghiêm trọng.
- Sai tên hoặc kiểu action giữa client và server — giống lỗi ở Topic/Service, không có thông báo lỗi rõ ràng, chỉ đơn giản client không bao giờ tìm thấy server tương ứng.
- Gửi nhiều goal liên tiếp mà không huỷ goal cũ — một số action server chỉ xử lý 1 goal tại một thời điểm; gửi goal mới trong khi goal cũ chưa hoàn tất có thể bị từ chối hoặc gây hành vi không mong muốn tuỳ cách server được lập trình xử lý goal chồng chéo.
Kết luận
Action là cơ chế đầy đủ nhất trong bộ ba Topic/Service/Action — kết hợp gửi mục tiêu, theo dõi tiến độ liên tục, và khả năng huỷ an toàn giữa chừng, phù hợp cho mọi tác vụ vận động vật lý chạy lâu của robot. Đây cũng là bài cuối cùng của chuyên mục ROS2 cơ bản — đủ nền tảng khái niệm để đi sâu vào chi tiết kỹ thuật của từng cơ chế giao tiếp ở chuyên mục ROS2 Communication tiếp theo.