03 · Action 长任务(带进度)
目标
写并跑通一对 Action:客户端发 order,服务端边算斐波那契边发 feedback,最后返回完整 result。理解 Action 与 Topic / Service 的差别。
概念
client --goal(order)--> Action /fibonacci
<---feedback--- server 逐步计算
<---result------ 全部完成(或取消)| Topic | Service | Action | |
|---|---|---|---|
| 模式 | 持续广播 | 一问一答 | 目标 + 进度 + 结果 |
| 像什么 | 电台 | 函数调用 | 可取消的长任务 |
| 本课 | chatter | add_two_ints | fibonacci |
| 适合 | 传感器流 | 短查询/短命令 | 导航、抓取、长时间运算 |
Action 接口三部分(--- 分隔):
# Goal(目标)
int32 order
---
# Result(最终结果)
int32[] sequence
---
# Feedback(过程进度)
int32[] sequence类型名:example_interfaces/action/Fibonacci。
生命周期(入门版):
- 客户端发 goal
- 服务端 accept / reject
- 执行中反复发 feedback
- 结束时给 result(成功 / 取消 / 中止)
逐步说明:Action 比「长 Service」多了什么(点击展开)
把导航做成一个阻塞 Service:客户端几分钟收不到返回,也无法看走了多远,取消只能杀进程。Action 把一次任务拆成 goal(去哪)、feedback(现在在哪)、result(到了或失败),并且 goal 可抢占/取消。底层仍用若干话题,但 API 保证这套生命周期。斐波那契例子是教学骨架;真机上是 NavigateToPose 一类。
通俗理解
Action 像外卖订单:
- 你下单(goal):要算长度为 8 的斐波那契。
- 商家接单或拒单(accept/reject)。
- 配送中不断推送进度(feedback)。
- 送到后给你最终结果(result);中途也可以取消。
Service 像“问一句立刻答完”;Action 适合较久、要进度、可能取消的事:导航到点、机械臂运动、长时间计算。
常见疑问
Q:为什么不直接用 Service 做长任务?
Service 期间你很难优雅地拿中间进度,取消也不如 Action 标准。长任务用 Action 是社区习惯。
Q:feedback 和 result 有什么区别?
feedback = 过程快照(可以很多条);result = 最终答卷(通常一次)。
Q:本课一定要会多线程 executor 吗?
入门先记住:Action 执行可能较久,服务端要用能同时处理取消/反馈的 executor。细节以后再挖。
Q:和 Topic 怎么分工?
Topic 持续播报状态;Action 是“请完成这个目标”。导航里两者常一起出现。
动手
cd $ROS_WS
source /opt/ros/humble/setup.bash
source install/setup.bash终端 A:
ros2 run py_pubsub fibonacci_action_server终端 B:
ros2 run py_pubsub fibonacci_action_client 8应看到多行 进度 feedback: [...],最后:
最终结果: [0, 1, 1, 2, 3, 5, 8, 13]也可用命令行发 goal(服务端需已启动):
ros2 action send_goal /fibonacci example_interfaces/action/Fibonacci "{order: 6}" --feedback关键命令
ros2 action list
ros2 action info /fibonacci
ros2 interface show example_interfaces/action/Fibonacci
ros2 action send_goal /fibonacci example_interfaces/action/Fibonacci "{order: 5}" --feedback对照代码
| 文件 | 作用 |
|---|---|
fibonacci_action_server.py | 接受 goal、发 feedback、返回 result |
fibonacci_action_client.py | 发 goal、收 feedback、打印 result |
setup.py | 注册两个可执行入口 |
服务端关键几行:
ActionServer(self, Fibonacci, 'fibonacci', execute_callback=...)
goal_handle.publish_feedback(feedback_msg)
goal_handle.succeed()客户端关键几行:
ActionClient(self, Fibonacci, 'fibonacci')
send_goal_async(goal_msg, feedback_callback=...)
goal_handle.get_result_async()说明:服务端用了 MultiThreadedExecutor,以便执行长任务时仍能处理取消等回调;入门先记住「Action 执行可能较久,executor 要能并发」即可。
小练习(可选)
- 把
order改成10,观察 feedback 变长。 - 用
ros2 action send_goal ... --feedback代替自己的客户端。 - 对比 Service:
add_two_ints没有中间进度;Action 有。
验证标准(给学员与 AI)
- [ ]
fibonacci_action_server显示 Action 就绪 - [ ]
fibonacci_action_client 8出现多条 feedback,最终结果含13 - [ ] 或
ros2 action send_goal /fibonacci ... --feedback能看到进度
失败时:确认已 source 工作区;server 需保持运行。
小结
- Action = Goal + Feedback + Result,适合长任务。
- 三种通信学完:Topic 流数据、Service 短请求、Action 长任务。
- 上一课:02 · Service · 下一课:04 · Parameter · 目录:README