前言

在学习 ROS 2 时,我们最先接触的通信方式通常是 Topic。

传感器通过 Topic 发布数据,控制节点订阅 Topic 获取指令,Publisher 和 Subscriber 也因此成为许多初学者最熟悉的 ROS 2 概念。

但在一个完整的机器人系统中,并不是所有任务都适合使用 Topic。

例如:

  • 激光雷达需要持续发送扫描数据;
  • 用户需要查询机器人当前状态;
  • 导航任务需要持续汇报进度,并允许中途取消;
  • 控制器需要根据不同场景调整最大速度。

这四类需求的性质完全不同。如果全部使用 Topic 实现,系统中就需要额外设计请求标识、响应匹配、任务状态、取消机制以及配置管理,最终会让节点之间的关系变得复杂。

因此,ROS 2 提供了几种不同的交互机制:

  • Topic:用于连续的数据流;
  • Service:用于快速的请求与响应;
  • Action:用于耗时较长、需要反馈和取消的任务;
  • Parameter:用于配置节点的运行行为。

一、先理解 ROS 2 Graph

ROS 2 通常会将一个复杂的机器人系统拆分成多个功能相对独立的 Node。

例如,一个移动机器人中可能存在以下节点:

  • 激光雷达驱动节点;
  • 里程计节点;
  • 地图服务器节点;
  • 定位节点;
  • 路径规划节点;
  • 运动控制节点;
  • 用户界面节点。

这些节点可能位于同一个进程中,也可能运行在不同进程、不同容器,甚至不同计算机上。

节点及其通信关系共同构成了 ROS 2 Graph

激光雷达节点 ──▶ 定位节点 ──▶ 规划节点 ──▶ 控制节点
      │              │             │
      └── 扫描数据    └── 机器人位姿 └── 速度指令

一个节点通常不会只使用一种通信机制。它可以同时拥有:

  • Publisher 和 Subscriber;
  • Service Server 和 Service Client;
  • Action Server 和 Action Client;
  • 一组用于配置自身行为的 Parameter。

因此,Topic、Service、Action 和 Parameter 并不是互相替代的关系,而是解决不同问题的工具。


二、Topic:持续流动的数据

2.1 Topic 的核心思想

Topic 使用的是发布—订阅模型,即 Publish–Subscribe。

Publisher 将消息发布到某个 Topic,Subscriber 订阅这个 Topic,并在消息到达时进行处理。

Publisher ──▶ Topic ──▶ Subscriber A
                    ├──▶ Subscriber B
                    └──▶ Subscriber C

Publisher 通常不需要知道有哪些 Subscriber,也不需要等待 Subscriber 返回处理结果。

同一个 Topic 可以存在多个 Publisher,也可以存在多个 Subscriber。这种机制降低了节点之间的直接依赖,使系统更容易扩展。

2.2 Topic 适合什么任务?

Topic 最适合以下类型的数据:

  • 持续产生的数据;
  • 周期性更新的状态;
  • 事件通知;
  • 不要求立即返回处理结果的信息。

常见示例包括:

Topic用途
/scan激光雷达扫描数据
/camera/image_raw相机图像
/odom机器人里程计
/cmd_vel机器人速度指令
/tf坐标变换
/battery_state电池状态

这些数据都有一个共同特点:它们会持续产生,接收方只需要处理当前到达的数据,而不需要对每条消息返回一个明确结果。

2.3 Topic 的优势

Topic 的主要优势包括:

  1. 节点之间耦合度低

    Publisher 不需要知道 Subscriber 的具体身份。

  2. 支持一对多和多对多通信

    同一份传感器数据可以同时提供给定位、避障、可视化和数据记录节点。

  3. 适合高频数据

    激光雷达、相机、IMU 和里程计等数据通常需要以较高频率传输。

  4. 可以通过 QoS 调整通信行为

    系统可以根据网络环境和数据性质设置可靠性、历史深度、持久性等策略。

2.4 Topic 不适合什么任务?

Topic 本身不提供标准的请求—响应关系。

如果一个节点发布了请求消息,它通常无法直接知道:

  • 哪个节点处理了请求;
  • 请求是否处理成功;
  • 返回结果属于哪个请求;
  • 任务是否仍在执行;
  • 如何取消正在执行的任务。

当然,我们可以创建一个请求 Topic 和一个响应 Topic,但还需要自行维护请求 ID、超时和状态。这通常意味着应该考虑 Service 或 Action。

2.5 一句话理解 Topic

Topic 关注的是“数据正在流动”,而不是“某个请求是否完成”。


三、Service:一次请求,一次响应

3.1 Service 的核心思想

Service 使用的是请求—响应模型,即 Request–Response。

Client 向 Service Server 发送一个请求,Server 处理后返回响应。

Service Client ──Request──▶ Service Server
Service Client ◀─Response── Service Server

与 Topic 不同,Service Client 会关心请求的处理结果。

例如,用户询问机器人:“当前是否已经完成定位?”

服务器可以返回:

localized: true
message: "Localization is ready."

这里存在明确的问题和明确的答案,因此使用 Service 比 Topic 更自然。

3.2 Service 适合什么任务?

Service 适合以下类型的操作:

  • 执行时间较短;
  • 有明确的请求和响应;
  • 调用频率不高;
  • 不需要持续反馈;
  • 通常不需要在执行过程中取消。

典型场景包括:

  • 查询节点当前状态;
  • 清除局部代价地图;
  • 重置某个模块;
  • 启用或关闭某项功能;
  • 请求一次简单计算;
  • 查询机器人当前模式。

3.3 Service 为什么不适合连续数据?

假设我们使用 Service 获取激光雷达数据,那么客户端就必须不断发送请求:

请求一帧数据 → 返回一帧数据
请求一帧数据 → 返回一帧数据
请求一帧数据 → 返回一帧数据

这种设计不仅繁琐,也违背了传感器数据持续产生的特点。

对于连续更新的数据,Publisher 主动发布、Subscriber 按需订阅更加合理。因此,激光雷达、相机、IMU 和里程计通常使用 Topic,而不是 Service。

3.4 Service 为什么不适合长时间任务?

假设我们使用 Service 命令机器人导航到某个位置。

导航可能持续几十秒,甚至几分钟。在此期间,用户通常希望知道:

  • 目标是否已被接受;
  • 机器人距离目标还有多远;
  • 当前任务处于什么状态;
  • 是否遇到了障碍物;
  • 能否取消当前导航;
  • 任务最终成功还是失败。

普通 Service 只描述请求和响应,不具备标准化的持续反馈与取消机制。因此,长时间任务更适合使用 Action。

3.5 一句话理解 Service

Service 关注的是“请帮我快速完成一件事,然后告诉我结果”。


四、Action:可以反馈和取消的长时间任务

4.1 Action 的核心思想

Action 面向的是执行时间较长的任务。

一个完整的 Action 通常包含以下几个部分:

  1. Goal:客户端发送任务目标;
  2. Feedback:服务器在执行过程中持续返回反馈;
  3. Result:任务结束后返回最终结果;
  4. Cancel:客户端可以请求取消任务。
Action Client ──Goal──────▶ Action Server
Action Client ◀─Feedback── Action Server
Action Client ◀─Feedback── Action Server
Action Client ──Cancel────▶ Action Server
Action Client ◀─Result──── Action Server

Action Server 接收到目标后,可以接受或拒绝该目标。接受目标后,它会在任务执行期间持续反馈进度,并在任务结束时返回结果。

4.2 Action 适合什么任务?

Action 适合以下类型的任务:

  • 执行时间较长;
  • 需要持续反馈;
  • 需要返回最终结果;
  • 可能需要中途取消;
  • 任务本身具有明显的开始、执行和结束过程。

典型示例包括:

  • 导航到指定位置;
  • 控制机械臂完成抓取;
  • 执行一段轨迹;
  • 自动停靠和充电;
  • 执行耗时较长的感知任务;
  • 完成一组连续动作。

4.3 为什么导航使用 Action?

以 Nav2 的 NavigateToPose 为例,用户发送的不是一条普通数据,而是一个明确的任务目标:

请让机器人移动到地图中的指定位置。

导航服务器接收目标后,需要进行路径规划、局部避障、速度控制和恢复处理。

在执行过程中,客户端可能需要获得:

  • 当前导航时间;
  • 剩余距离;
  • 恢复行为次数;
  • 当前任务状态。

如果现场突然出现危险,用户还需要取消导航。

因此,导航天然符合 Action 的设计语义:

Goal:移动到目标位置
Feedback:剩余距离、导航时间等
Result:成功、失败或被取消
Cancel:停止当前导航

4.4 Action 是“更高级的 Service”吗?

不能简单地这样理解。

Service 和 Action 面向的是两种不同的任务语义:

  • Service 表示一次短暂的请求与响应;
  • Action 表示一个具有生命周期的任务。

如果一个操作能够快速完成,并且不需要反馈和取消,使用 Service 更简单。

如果任务需要数秒甚至更长时间,并且用户需要查看进度或中途停止,那么应该使用 Action。

4.5 一句话理解 Action

Action 关注的是“开始执行一个任务,并在执行过程中告诉我进度,同时允许我取消它”。


五、Parameter:节点运行行为的配置

5.1 Parameter 与前三者并不完全相同

严格来说,Topic、Service 和 Action 是节点之间的通信接口,而 Parameter 更接近节点自身的配置机制。

在 ROS 2 中,Parameter 通常与具体节点关联,用于改变节点的运行行为。

例如,一个控制器节点可能包含以下参数:

max_linear_velocity
max_angular_velocity
goal_tolerance
control_frequency

这些值不是连续传输的数据,也不是一个需要执行的任务,而是节点工作时使用的配置。

5.2 Parameter 适合保存什么?

Parameter 适合保存以下内容:

  • 最大线速度;
  • 最大角速度;
  • 控制频率;
  • 地图或坐标系名称;
  • 机器人半径;
  • 膨胀半径;
  • 目标容差;
  • 传感器阈值;
  • 插件名称;
  • 功能开关。

Parameter 可以在节点启动时通过命令行、Launch 文件或 YAML 文件加载。节点也可以根据自身设计,允许部分参数在运行时被修改。

5.3 Parameter 不应该承担什么职责?

Parameter 不适合:

  • 传输激光雷达或图像等连续数据;
  • 发送高频控制指令;
  • 表示需要返回结果的一次性请求;
  • 启动一个具有进度和取消需求的长时间任务。

例如,“最大速度设置为 0.5 m/s”属于节点配置,可以使用 Parameter。

但是,“立即向前移动 0.5 米”是一个动作指令,不应该通过修改 Parameter 表达。

5.4 ROS 2 Parameter 的作用域

ROS 2 中的 Parameter 通常属于具体节点,而不是存放在一个全局参数服务器中。

例如,两个节点可以分别拥有同名参数:

/controller_server.max_vel_x
/safety_controller.max_vel_x

虽然参数名称相同,但它们属于不同节点,含义和取值也可以不同。

参数的生命周期通常与节点绑定。节点重启后,如果希望恢复原来的配置,通常需要通过 YAML 文件、Launch 文件或其他持久化方式重新加载。

5.5 一句话理解 Parameter

Parameter 关注的是“这个节点应该以什么方式运行”。


六、四种机制的核心区别

对比维度TopicServiceActionParameter
核心目的传输数据请求一个快速操作执行长时间任务配置节点行为
交互模式发布—订阅请求—响应目标—反馈—结果读取或修改配置
是否持续传输可以通常不持续执行期间可以反馈通常不持续
是否返回结果不直接返回返回一次响应返回最终结果返回设置或查询结果
是否支持执行反馈不负责不支持持续反馈支持不适用
是否支持取消不支持任务取消不提供标准取消机制支持不适用
典型持续时间持续存在短时间数秒到数分钟与节点运行周期相关
典型用途传感器、状态、控制流查询、重置、快速操作导航、轨迹、抓取速度、频率、阈值
Nav2 示例/scan/odom/tf清除代价地图NavigateToPose控制器和代价地图参数

七、用一个移动机器人理解四种机制

假设我们正在设计一台室内移动机器人。

7.1 激光雷达不断产生扫描数据

激光雷达每秒可能产生多帧扫描数据,定位和避障节点需要持续接收。

选择:

Topic

原因:

  • 数据持续产生;
  • 可能有多个订阅者;
  • 不需要每帧返回处理结果。
LiDAR Driver ──/scan──▶ Localization
                    ├──▶ Costmap
                    └──▶ RViz

7.2 用户要求立即清除局部代价地图

这是一个明确、短暂的操作。用户只需要知道清除是否成功。

选择:

Service

原因:

  • 有明确请求;
  • 可以快速完成;
  • 需要返回成功或失败;
  • 不需要持续反馈。

7.3 用户要求机器人导航到会议室

导航需要较长时间。用户希望查看剩余距离,并可能中途取消任务。

选择:

Action

原因:

  • 任务具有明确目标;
  • 执行时间较长;
  • 需要反馈;
  • 需要最终结果;
  • 需要取消能力。

7.4 用户将最大速度从 0.5 m/s 调整为 0.3 m/s

这是对控制器运行行为的调整,而不是机器人需要执行的一次任务。

选择:

Parameter

原因:

  • 修改的是节点配置;
  • 参数属于具体节点;
  • 不需要建立持续的数据流;
  • 不需要任务反馈和取消机制。

八、实际项目中如何选择?

面对一个新的功能需求时,可以依次提出以下问题。

问题一:它描述的是节点配置吗?

如果这个值决定节点“如何运行”,优先考虑 Parameter。

例如:

  • 最大速度;
  • 控制频率;
  • 机器人半径;
  • 目标容差;
  • 是否启用某个功能。

问题二:它是持续产生的数据吗?

如果数据会不断产生,或者多个节点都可能需要接收,优先考虑 Topic。

例如:

  • 激光雷达数据;
  • 图像;
  • 里程计;
  • 电池状态;
  • 速度指令。

问题三:它能否快速完成并立即返回?

如果操作具有明确的请求和响应,并且通常能够快速完成,优先考虑 Service。

例如:

  • 查询状态;
  • 清除缓存;
  • 重置模块;
  • 启用或关闭功能。

问题四:它是否需要较长时间执行?

如果任务需要持续执行,并且需要反馈、结果或取消能力,优先考虑 Action。

例如:

  • 导航;
  • 轨迹执行;
  • 机械臂抓取;
  • 自动停靠;
  • 长时间感知任务。

可以将这个判断过程简化为:

这是节点配置吗?
├── 是:Parameter
└── 否
    ├── 数据是否持续产生?
    │   └── 是:Topic
    └── 否
        ├── 能否快速完成并返回?
        │   └── 是:Service
        └── 是否需要反馈或取消?
            └── 是:Action

九、常见设计误区

9.1 所有通信都使用 Topic

Topic 使用简单,而且非常灵活,因此初学者容易用两个 Topic 模拟请求和响应。

这种方式并非绝对不可行,但通常需要自行解决:

  • 请求和响应的匹配;
  • 请求超时;
  • 重复请求;
  • 并发请求;
  • 任务状态;
  • 错误处理。

如果需求本身就是一次请求和一次响应,Service 会更加清晰。

如果需求是一个长时间任务,Action 会提供更完整的任务语义。

9.2 使用 Service 执行长时间任务

Service 适合快速完成的操作。如果服务器需要很长时间才能返回,客户端将难以获得任务进度,也无法使用标准方式取消任务。

长时间操作应优先考虑 Action。

9.3 使用 Action 完成所有命令

Action 功能强大,但也比 Service 更复杂。

如果操作只需要几十毫秒就能完成,并且不需要反馈和取消,那么 Service 往往已经足够。

设计接口时不应该追求“功能最多”,而应该选择最符合任务语义的机制。

9.4 将 Parameter 当作控制命令

Parameter 用于描述节点配置,不应该被当作普通消息通道。

例如:

  • max_speed = 0.5:适合作为 Parameter;
  • “开始导航”:不适合作为 Parameter;
  • “立即停止机器人”:通常应通过控制或安全通信机制实现,而不是修改 Parameter。

9.5 认为 Service 一定比 Topic 更可靠

Topic 和 Service 的差别首先是交互语义,而不是简单的“谁更可靠”。

Topic 的具体传输行为与 QoS 配置有关。Service 虽然具有请求和响应关系,但仍然需要处理服务器不可用、请求超时和节点异常等情况。

选择通信方式时,应先判断数据和任务的性质,再考虑可靠性、实时性及网络环境。


十、它们如何共同构成 Nav2?

Nav2 是理解这四种机制如何协同工作的典型案例。

Topic:传递持续数据

Nav2 需要持续接收:

  • 地图;
  • 激光雷达数据;
  • 里程计;
  • TF 坐标变换;
  • 机器人速度;
  • 路径和状态信息。

这些内容会不断更新,因此适合使用 Topic。

Service:执行快速管理操作

Nav2 中的一些管理操作可以通过 Service 完成,例如:

  • 清除代价地图;
  • 查询或修改节点状态;
  • 触发生命周期状态转换;
  • 请求某项快速操作。

Action:管理导航任务

导航到目标位置通常使用 Action。

用户发送目标后,Nav2 可以:

  • 接受或拒绝目标;
  • 在执行期间反馈导航进度;
  • 返回最终结果;
  • 取消当前目标;
  • 接收新的目标并处理任务切换。

Parameter:配置导航行为

Nav2 中存在大量 Parameter,例如:

  • 控制频率;
  • 最大速度;
  • 目标容差;
  • 机器人 footprint;
  • 膨胀半径;
  • Planner 和 Controller 插件;
  • Behavior Tree 文件路径。

这些参数共同决定了 Nav2 的具体运行行为。

因此,一个完整的 Nav2 导航过程不是只依赖某一种通信方式,而是四种机制共同协作:

Topic      提供地图、传感器、位姿和速度数据
Service    执行快速管理操作
Action     管理完整导航任务
Parameter  决定导航系统如何运行

十一、总结

Topic、Service、Action 与 Parameter 分别解决了四类不同的问题:

Topic 负责数据流。

Service 负责快速请求与响应。

Action 负责可以反馈和取消的长时间任务。

Parameter 负责配置节点的运行行为。

它们之间不存在绝对的优劣,关键在于选择符合任务语义的机制。

如果数据是连续产生的,就使用 Topic;如果操作能够快速完成并需要返回结果,就考虑 Service;如果任务执行时间较长,而且需要反馈或取消,就使用 Action;如果需要调整节点的运行方式,就使用 Parameter。

理解这些区别后,再去阅读 SLAM、Nav2、MoveIt 2 或 ros2_control 的架构,会发现许多接口设计都不再神秘。

当看到一个 Topic、Service、Action 或 Parameter 时,我们不应该只记住它的名称,而应该进一步思考:

这个接口为什么采用这种机制?它表达的究竟是数据、请求、任务,还是配置?

理解这个问题,才是真正开始理解 ROS 2 系统架构。


参考资料

  1. ROS 2 Lyrical:Nodes
  2. ROS 2 Lyrical:Understanding Topics
  3. ROS 2 Lyrical:Tutorials
Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐