2、ROS通信基础回顾:ROS节点与Master(或ROS2 Discovery)、Topic通信机制(Publisher/Subscriber)、Service通信机制(Server/Client)、Action通信机制(Goal/Feedback/Result)
好,咱们正式开始聊MoveIt之前,我得先带你回顾一下ROS的通信基础。你别嫌我啰嗦,这玩意儿是后面所有复杂机制的基石。我见过太多人,一上来就啃MoveIt源码,结果被里面的通信绕得晕头转向。
说白了,ROS就是一个“软件总线”。各个模块(节点)之间怎么说话?就是靠下面这三种方式。咱们一个一个捋清楚。
2.1 节点与Master(ROS1) / Discovery(ROS2)
先说说节点。节点就是可执行程序的最小单位。一个机器人系统可能有几十个节点:控制电机的、处理激光雷达的、做路径规划的……它们之间需要互相知道对方的存在。
在ROS1里,这个“介绍人”叫Master。 每个节点启动时,都会去Master那里注册:我叫啥、我能发布什么话题、我能订阅什么话题。Master就像一个电话总机,它不负责传数据,只负责“牵线搭桥”。
到了ROS2,这个机制变了。 去中心化了,没有Master了。节点之间通过DDS(数据分发服务)的Discovery机制自动发现对方。我个人觉得ROS2这种方式更健壮,Master挂了整个系统就瘫了,这在ROS1里是真实发生过的事故。
核心区别一句话: ROS1是“中央集权”,ROS2是“分布式自治”。
嗯,这里要注意:虽然ROS2没有Master了,但通信模型(Topic、Service、Action)的抽象概念是高度一致的。所以咱们后面讲概念时,还是以ROS1的术语为主,但我会指出ROS2的对应变化。
2.2 Topic通信机制(Publisher/Subscriber)
Topic是ROS里最常用的通信方式。它是一种异步、多对多的模型。
- Publisher(发布者):只管往某个话题里扔数据,它不关心谁在收。
- Subscriber(订阅者):只管从某个话题里收数据,它不关心是谁发的。
我在项目中遇到过一个问题:激光雷达的数据频率是10Hz,但我的路径规划算法跑一次要200ms。如果直接用Topic,规划器收到的数据永远是“过时”的。后来我加了时间戳校验,才解决了这个问题。
Topic适合什么场景?连续的数据流。比如:
- 传感器数据(激光雷达点云、摄像头图像)
- 机器人状态(关节位置、速度)
- 里程计信息
Topic的缺点也很明显:没有反馈。你发了一个指令,它到底执行了没有?执行结果怎么样?Topic不关心这个。这就引出了下一种通信方式。
2.3 Service通信机制(Server/Client)
Service是同步、一对一的通信模型。它像是一个RPC(远程过程调用)。
- Server(服务端):提供某种功能,等待被调用。
- Client(客户端):发起请求,然后阻塞等待响应。
你想想看,什么时候需要Service?当你需要“问一个问题,然后得到一个确定答案”的时候。比如:
- “帮我计算一下这两个坐标之间的逆运动学解。”
- “当前机械臂的末端执行器位姿是多少?”
- “重置一下仿真环境。”
我的建议: 别用Service做高频调用。因为它是同步阻塞的,如果Server处理慢了,整个Client线程就卡死了。我曾经在一个项目里用Service做视觉伺服,结果每帧图像都要等200ms的响应,帧率直接掉到5fps,惨不忍睹。
Service的局限性在于:它只能处理“请求-响应”这种一次性的交互。如果任务需要很长时间(比如让机械臂走一段轨迹),Service就不合适了。因为Client会一直阻塞,直到任务完成。这时候,Action就登场了。
2.4 Action通信机制(Goal/Feedback/Result)
Action是ROS里最强大的通信机制,专门为长时间、可中断、有反馈的任务设计的。
它本质上是一个“增强版的Service”。它包含三个核心部分:
| 组件 | 作用 | 类比 |
|---|---|---|
| Goal | 客户端发送的目标 | “把机械臂移动到位置A” |
| Feedback | 服务端在执行过程中持续反馈的状态 | “当前进度50%,还剩10秒” |
| Result | 任务最终的结果 | “已到达位置A,最终误差0.01mm” |
Action还支持取消和抢占。比如你正在让机械臂去抓A点,突然发现B点更紧急,你可以直接发送一个新的Goal,旧的Goal会被自动取消。这在MoveIt里是家常便饭。
注意: 在ROS2里,Action的底层实现变了,但接口概念完全一致。如果你从ROS1迁移到ROS2,Action的代码改动是最小的。
为了让你更直观地理解这三种通信方式的关系,我画了一张图:
这张图把三种通信方式放在一起对比,你应该能看出它们的区别了。Topic是“广播”,Service是“打电话”,Action是“发快递(带物流跟踪)”。
在MoveIt里,这三种方式都会用到。比如:
- Topic:发布机器人当前关节状态(/joint_states),订阅规划好的轨迹(/move_group/display_planned_path)
- Service:查询逆运动学解(/compute_ik),获取规划场景信息(/get_planning_scene)
- Action:执行运动规划(/move_action),执行抓取任务(/pick_action)
我个人觉得,理解Action是理解MoveIt内部机制的关键。因为MoveIt的核心——运动规划与执行,本质上就是一个长时间、可中断、需要反馈的Action任务。后面的章节,我们会深入MoveIt的Action Server内部,看看它到底是怎么工作的。