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

ROS2 的本质是一个分布式通信中间件,它并不直接传输机器人的传感器数据或电机指令,而是提供一套标准化的“语言”和“交通规则”,让不同功能模块能够协同工作。理解 ROS2 的第一步,就是掌握它的六大核心概念:节点(Node)、话题(Topic)、服务(Service)、动作(Action)、参数(Parameter)以及描述它们关系的图(Graph)。这六个概念构成了 ROS2 应用的基本骨架,也是后续所有开发工作的基础。

1. 节点(Node):功能的最小执行单元

节点是 ROS2 中可执行文件运行时的实例。一个机器人系统通常由多个节点组成,每个节点负责一项专门的任务。例如,一个激光雷达驱动节点负责读取扫描数据,一个里程计节点负责计算位置,一个导航节点负责规划路径。节点之间相互独立、互不依赖,这种设计带来了两个关键优势:故障隔离(单个节点崩溃不会拖垮整个系统)和代码复用(同一节点可被不同机器人项目直接使用)。

在代码层面,创建一个节点只需继承 rclpy 或 rclcpp 中的 Node 类,并为其指定一个唯一名称。节点名称是图(Graph)中的唯一标识,不能与同一台机器上运行的其他节点重名。

# Python 示例:创建并运行一个最小节点
import rclpy
from rclpy.node import Node

class MinimalNode(Node):
    def __init__(self):
        super().__init__('minimal_node')  # 节点名称
        self.get_logger().info('节点已启动')

def main(args=None):
    rclpy.init(args=args)
    node = MinimalNode()
    rclpy.spin(node)  # 保持节点运行,等待回调
    node.destroy_node()
    rclpy.shutdown()

2. 话题(Topic):异步的“发布-订阅”通信

话题是 ROS2 中最常用的通信方式,适用于持续、单向、高频的数据流,例如传感器数据、状态信息等。其核心模型是发布者(Publisher)与订阅者(Subscriber):发布者将数据“广播”到某个话题上,任何对该话题感兴趣的订阅者都能收到数据副本。这种模式是异步的——发布者不关心谁在接收,订阅者也不等待数据到达,两者在时间上完全解耦。

话题通信的关键在于消息类型(Message Type)。发布者和订阅者必须使用相同的消息类型才能正确解析数据。例如,激光雷达数据通常使用 sensor_msgs/msg/LaserScan,而图像数据使用 sensor_msgs/msg/Image。ROS2 内置了大量标准消息类型,也支持用户自定义。

适用场景判断:如果数据是“持续产生、需要被多个模块同时使用”,例如摄像头图像、IMU 数据、机器人速度指令,优先选择话题通信。

3. 服务(Service):同步的“请求-响应”通信

与话题的“广播”模式不同,服务采用客户端-服务器(Client-Server)模式,适用于一次性、需要立即返回结果的任务。例如,请求机器人拍照、查询当前电量、执行一次路径规划。客户端发送请求后,会阻塞等待服务器处理完毕并返回响应。这种通信是同步的,具有明确的因果逻辑。

服务由一对消息类型定义:请求(Request)和响应(Response)。例如,一个“设置目标点”的服务,请求包含目标坐标,响应包含是否成功及执行时间。

# 服务接口定义示例(.srv 文件)
# SetTarget.srv
---
# 请求部分
float32 x
float32 y
float32 theta
---
# 响应部分
bool success
string message

4. 动作(Action):带反馈的长时间任务

动作是 ROS2 中专门为长时间、可取消、需要进度反馈的任务设计的通信机制。它结合了话题和服务的优点:客户端发送一个目标(Goal),服务器执行任务并通过反馈(Feedback)话题持续上报进度,任务完成后发送结果(Result)。整个过程可以被客户端随时取消。

动作的典型应用是机器人导航:发送“移动到 A 点”的目标后,导航节点会持续反馈“当前走到 30%”、“前方有障碍物绕行中”,最终返回“已到达”或“失败”。动作在底层由三个话题和一个服务组成,但对开发者封装了复杂细节。

5. 参数(Parameter):节点的可配置变量

参数是节点的静态配置项,用于在运行时调整节点行为而无需修改代码。例如,激光雷达的扫描频率、PID 控制器的增益系数、摄像头的曝光时间。参数具有名称、类型和值,可以在节点启动时通过命令行或 YAML 文件加载,也可以在运行时动态修改。

ROS2 的参数系统支持基础类型(整型、浮点、字符串、布尔)以及数组和字节流。参数通常用于低频配置,不适合传输高频动态数据。

6. 图(Graph):全局拓扑的实时视图

所有运行中的节点、话题、服务、动作和参数共同构成了一个计算图(Compute Graph)。这个图不是静态的——节点可以随时加入或退出,话题可以动态建立连接。ROS2 提供了一套图查询机制,允许开发者实时发现当前系统中存在哪些节点、它们发布了哪些话题、谁在订阅谁。

下图展示了 ROS2 中一个典型机器人系统的图结构,清晰呈现了节点间通过不同通信机制建立的连接关系:

图例: 话题发布 话题订阅 服务请求 动作目标 参数 激光雷达驱动 /lidar_driver 轮式里程计 /wheel_odom 导航节点 /nav2_controller (含参数: max_speed) 底盘控制器 /base_controller RViz 可视化 /rviz /scan /odom /cmd_vel /save_map /navigate max_speed=1.5 持续广播 实时接收 请求速度设置 发送目标点 请求保存地图

上图展示了一个典型的 ROS2 导航系统图结构。可以看到,激光雷达驱动节点将 /scan 数据发布到话题,导航节点订阅该话题;轮式里程计发布 /odom,导航节点同样订阅。导航节点计算后,将速度指令发布到 /cmd_vel,底盘控制器订阅并执行。RViz 通过动作接口向导航节点发送目标点,而“保存地图”则通过服务实现。所有节点都可以通过参数服务器读取配置。

7. 通信机制对比与选择

通信方式 方向 同步性 典型场景 是否可取消
话题 单向广播 异步 传感器数据、状态发布 否
服务 请求-响应 同步 查询、开关、一次性计算 否
动作 目标-反馈-结果 异步+反馈 导航、机械臂运动 是
参数 节点配置 同步 运行参数调整 —

8. 常见误区与复盘

误区一:所有通信都用话题。话题适合高频单向数据,但如果需要“请求-应答”逻辑(例如查询地图),使用话题会非常别扭——你需要手动管理请求 ID、超时和匹配,而服务天然支持这种模式。
误区二:动作就是“带反馈的服务”。动作的取消机制和反馈流是服务无法直接提供的。如果任务可能执行数秒以上,且用户可能中途取消,必须使用动作。强行用服务实现长任务会导致客户端阻塞,且无法中断。
复盘建议:在设计通信架构时,先问三个问题:①数据是持续产生还是偶发请求?②是否需要立即返回结果?③任务是否可能被取消?根据答案选择话题、服务或动作。参数只用于配置,不要试图用参数传输实时数据。