ROS2 核心概念:节点、话题、服务、动作、参数与图

ROS2 的软件架构建立在一组清晰的核心抽象之上。如果把机器人系统比作一个团队,节点就是每个成员,话题是公开的白板,服务是点对点的问答,动作是长期任务的下达与反馈,参数则是成员的可调配置。理解这些概念之间的区别与协作方式,是掌握 ROS2 开发的第一步。

核心原理:六类基本概念

概念 通信模式 关键特征 典型用途
节点 (Node) — 可执行的最小单元,拥有唯一名称 封装传感器驱动、算法、控制逻辑
话题 (Topic) 发布/订阅 (异步) 一对多、多对多,数据流持续单向 图像流、激光扫描、里程计、状态发布
服务 (Service) 请求/响应 (同步) 一次性调用,有超时机制 开关灯、获取地图、设置参数快照
动作 (Action) 目标/反馈/结果 (长时) 可取消、可反馈进度、可预empt 导航到目标点、机械臂抓取、路径跟踪
参数 (Parameter) 键值存储 运行时动态读写,可持久化 PID 系数、最大速度、传感器频率
图 (Graph) 全局拓扑 描述所有节点与通信关系的网络 系统监控、调试、运行时发现

核心要点:话题是“持续广播”,服务是“一问一答”,动作是“带反馈的长任务”。节点通过图(Graph)机制自动发现彼此,无需手动配置 IP 地址。

ROS2 图(Graph)— 节点自动发现与通信拓扑 DDS 中间件负责节点发现、连接建立与消息传输 传感器节点 /camera_driver 导航节点 /nav2_controller 底盘驱动节点 /motor_controller 话题:/image_raw sensor_msgs/Image (持续发布) 话题:/cmd_vel geometry_msgs/Twist (持续订阅) 服务:/set_led_state (同步请求/响应) 调用方发送请求 → 服务端处理 → 返回响应 std_srvs/srv/SetBool 动作:/navigate_to_pose (长时任务) 发送目标 → 持续反馈进度 → 返回最终结果 nav2_msgs/action/NavigateToPose 参数服务器(每个节点私有参数空间) /motor_controller/max_speed = 1.2 m/s | /camera_driver/exposure = 200 | /nav2_controller/pid_kp = 0.8

方法流程:节点间通信的三种模式

在 ROS2 中,节点之间的交互方式决定了系统的实时性、可靠性和复杂度。选择正确的通信模式是架构设计的关键。

  1. 话题通信(异步、持续):发布者将消息放入 DDS 中间件,订阅者异步接收。适用于高频数据流,如激光雷达扫描、摄像头图像、IMU 数据。多个订阅者可以同时接收同一话题,实现一对多解耦。
  2. 服务通信(同步、一次性):客户端发送请求后阻塞等待服务端响应。适用于低频、需要确认结果的交互,如“打开机械臂夹爪”“查询当前地图”。服务不适合高频调用,因为同步等待会阻塞调用方。
  3. 动作通信(长时、可反馈):动作客户端发送目标,服务端返回“已接收”后开始执行,期间持续发送反馈(如进度百分比),最终返回结果。动作支持取消和抢占(新目标替换旧目标),适合导航、机械臂规划等耗时操作。

选择建议:如果数据是“持续产生且不需要回复”,用话题;如果“需要立即得到结果且频率低”,用服务;如果“任务耗时数秒以上且需要进度反馈”,用动作。

案例场景:机器人导航中的概念协作

以移动机器人执行“从 A 点导航到 B 点”为例,观察各概念如何协同工作:

  • 传感器节点(/lidar_driver)通过话题 /scan 持续发布激光数据。
  • 定位节点(/amcl)订阅 /scan 和 /odom,通过话题 /amcl_pose 发布机器人当前位姿。
  • 导航节点(/nav2_controller)订阅 /amcl_pose 和 /map,计算路径后通过话题 /cmd_vel 发布速度指令。
  • 底盘驱动节点(/motor_controller)订阅 /cmd_vel,将速度指令转换为电机 PWM 信号。
  • 用户通过动作客户端向导航节点发送 /navigate_to_pose 目标,导航节点反馈“已到达 50%”等进度。
  • 若需要临时打开机器人上的指示灯,用户调用服务 /set_led_state,同步等待“成功/失败”响应。
  • 所有节点的 PID 参数、最大速度等通过参数动态调整,无需重新编译。
# 查看当前图结构
ros2 node list
ros2 topic list
ros2 service list
ros2 action list

# 查看话题数据流
ros2 topic echo /scan --once

# 调用服务
ros2 service call /set_led_state std_srvs/srv/SetBool "{data: true}"

# 发送动作目标
ros2 action send_goal /navigate_to_pose nav2_msgs/action/NavigateToPose "{pose: {pose: {position: {x: 2.0, y: 1.0}}}}"

误区与复盘:常见理解偏差

误区一:把服务当话题用。 有开发者试图用服务高频传输传感器数据,导致调用方阻塞、系统卡顿。正确做法:高频数据一律走话题,服务只用于低频控制指令。

误区二:忽略动作的反馈机制。 动作的反馈通道是设计亮点,但很多初学者只关心最终结果,不处理 feedback,导致无法监控任务进度。应始终订阅反馈以更新状态显示或做异常判断。

误区三:混淆参数与话题。 参数适合低频配置(如 PID 系数),不适合传输高频状态(如当前速度)。参数变化不会产生消息流,需要主动读取或监听参数事件。

复盘要点:ROS2 的图(Graph)机制让所有节点在运行时动态发现彼此,无需静态配置。使用 rqt_graph 可以可视化当前通信拓扑,是排查“节点间为何没有数据”的首选工具。若话题没有数据,先检查发布者是否在运行、话题名称是否拼写一致、消息类型是否匹配。