核心概念:节点、话题、服务、动作、参数的定义与作用

在深入 ROS2 的代码实现之前,必须先建立一套清晰的心智模型。ROS2 的通信机制并非单一协议,而是由五种核心概念共同构成的协作体系:节点是执行单元,话题与服务是同步/异步的两种数据通路,动作是面向长时任务的“服务升级版”,参数则是运行时的配置接口。理解它们各自的定位与边界,是后续编写可靠机器人程序的前提。

3.1 节点:功能的最小执行单元

节点(Node)是 ROS2 中一个可执行文件内实现特定功能的进程模块。一个机器人系统通常由多个节点组成,例如:/camera_node 负责采集图像,/lidar_node 处理激光扫描,/nav_node 负责路径规划。每个节点在计算图中拥有唯一的名称,并通过 DDS(数据分发服务)与外界通信。

节点的核心价值在于故障隔离与复用性。如果导航节点崩溃,摄像头节点不会受影响,系统仍可降级运行。在代码层面,节点通过 rclcpp::Node 类创建,其构造函数中可声明话题发布者、订阅者、服务端等通信对象。

// 创建节点的典型 C++ 代码结构
#include "rclcpp/rclcpp.hpp"

class MyNode : public rclcpp::Node {
public:
  MyNode() : Node("my_node_name") {
    // 在此处创建发布者、订阅者、服务等
  }
};

int main(int argc, char** argv) {
  rclcpp::init(argc, argv);
  rclcpp::spin(std::make_shared<MyNode>());
  rclcpp::shutdown();
  return 0;
}
关键认知:节点是“计算”的载体,而不是“数据”的载体。数据通过话题、服务等通道流动,节点本身只负责处理与决策。一个进程可以包含多个节点(通过 component 机制),但通常建议一个节点对应一个独立功能模块,便于调试与资源管理。
ROS2 五大核心概念协作关系图 /camera_node 发布图像话题 /lidar_node 发布点云话题 /nav_node 订阅话题 + 调用服务 执行动作客户端 /motor_node 订阅速度指令 /image_raw /scan /cmd_vel /plan_path (服务) /navigate_to_pose (动作) 参数服务器 /nav_node/max_speed 读取/设置 图例: 话题(异步流) 服务(同步请求) 动作(长时任务) 参数(配置)

3.2 话题:持续单向的数据流

话题(Topic)是 ROS2 中最常用的通信方式,采用发布/订阅模式。发布者(Publisher)将消息广播到指定名称的话题上,订阅者(Subscriber)接收该话题的所有消息。话题通信是异步、单向、多对多的:一个话题可有多个发布者和多个订阅者,双方无需等待对方响应。

话题适用于高频、周期性、持续更新的数据,如传感器数据、状态估计、控制指令。其底层基于 DDS 的 QoS(服务质量)策略,可控制消息的可靠性、历史深度和时效性。例如,激光雷达点云适合 RELIABLE 传输,而 IMU 姿态数据可用 BEST_EFFORT 降低延迟。

实践建议:话题消息类型需在 .msg 文件中定义,编译后生成对应语言的类。查看当前所有话题可用命令:ros2 topic list,查看话题实时数据流:ros2 topic echo /topic_name。

3.3 服务:同步的请求-应答

服务(Service)用于一次性、短时、需要立即返回结果的交互。客户端(Client)发送请求,服务端(Server)处理并返回响应,整个过程是同步阻塞的。服务由 .srv 文件定义,包含请求(Request)和响应(Response)两部分。

典型场景包括:查询机器人状态(如“当前电量是多少?”)、触发一次性动作(如“开启机械臂夹爪”)、设置参数(如“切换到自主导航模式”)。服务不适合传输大规模连续数据,因为每次调用都有网络往返开销。

# 服务接口定义示例:SetLED.srv
# 请求部分
bool enable        # 是否点亮
int32 brightness   # 亮度值 0-255

# 响应部分
bool success       # 是否成功
string message     # 结果描述

3.4 动作:长时任务的“服务+反馈”

动作(Action)是 ROS2 为长时间执行、需要中途反馈、可被取消的任务设计的通信机制。它由三部分组成:目标(Goal)、反馈(Feedback)和结果(Result)。动作客户端发送目标后,服务端持续执行,并周期性发送反馈;任务完成后返回最终结果。

动作的典型应用是导航到目标点、机械臂抓取、自主充电等。与普通服务相比,动作支持任务执行过程中的实时监控与取消操作。动作接口由 .action 文件定义,内部自动生成三个话题:/goal、/feedback、/result,以及一个取消服务。

通信方式 方向 同步性 适用场景 典型示例
话题 单向流 异步 高频持续数据 /camera/image_raw
服务 请求-应答 同步 短时查询/触发 /set_led
动作 目标-反馈-结果 异步+反馈 长时可取消任务 /navigate_to_pose
参数 节点配置 同步 运行时参数调整 /nav_node/max_speed

3.5 参数:节点的运行时配置

参数(Parameter)是附着在节点上的键值对,用于配置节点行为而不需要重新编译代码。每个节点维护自己的参数列表,可通过命令行、代码或 YAML 文件动态设置。参数类型支持整数、浮点、布尔、字符串、数组等。

参数与话题/服务的本质区别在于:参数不属于通信通道,而是节点内部的配置状态。但 ROS2 提供了参数服务(/parameter_events),允许其他节点远程读取或修改某节点的参数,这本质上是一种特殊服务调用。

常见误区:初学者容易混淆“话题”与“参数”。例如,想动态调整机器人的最大速度,正确做法是设置参数 /nav_node/max_speed,而不是创建一个名为 /max_speed 的话题。话题用于传输状态数据,参数用于配置项。若某个值需要被多个节点共享且频繁变化,才考虑用话题。

3.6 综合案例:导航任务中的概念协作

假设机器人需要从当前位置导航到坐标 (5.0, 3.0),完整流程展示了各概念的配合:

  1. 参数读取:导航节点启动时从参数服务器读取 max_speed、goal_tolerance 等配置。
  2. 话题订阅:持续接收 /scan(激光雷达)和 /odom(里程计)话题数据,构建环境地图并定位。
  3. 服务调用:调用 /map_server 的 /load_map 服务加载静态地图。
  4. 动作发送:向 /navigate_to_pose 动作服务器发送目标坐标,开始导航。
  5. 反馈循环:动作服务器在导航过程中通过反馈通道发送当前进度(如“剩余距离 2.3m”),导航节点可据此更新状态显示。
  6. 话题发布:导航节点将计算出的速度指令发布到 /cmd_vel 话题,底盘驱动节点订阅后执行。

这个案例清晰展示了:话题负责“感知-决策-执行”的持续数据流,服务处理离散的查询/配置请求,动作管理需要监控的长时任务,参数提供灵活的运行时配置。理解这五种概念的分工,是设计复杂机器人软件架构的基础。

复盘要点:选择通信方式时,先问三个问题——①数据是持续流还是单次请求?②是否需要中途反馈或取消?③是节点间通信还是节点自身配置?持续流→话题;单次请求→服务;长时任务→动作;自身配置→参数。切勿将高频传感器数据放入服务,也不要用话题实现需要应答的指令。