ROS 工作原理
ROS 2 是一个用于编写机器人应用的分布式框架。它提供了一种标准化的方式,让多个进程(即节点,node)可以在同一台计算机或不同计算机之间相互通信、协同工作。ROS 2 的核心设计理念是:将复杂的机器人系统分解为多个各司其职的小型节点,通过消息传递机制实现节点间的数据交换。
与传统单体架构(将所有功能集中在一个程序中)不同,ROS 2 采用松耦合的分布式架构。每个节点只负责单一功能(如读取传感器数据、路径规划、电机控制等),节点之间通过预定义的接口进行通信。这种设计带来了以下优势:
- 模块化:每个节点可以独立开发、测试和替换,而不影响系统的其他部分。
- 语言无关:不同节点可以用不同的编程语言编写(如 C++、Python),只要使用兼容的消息类型即可通信。
- 可复用:已有的节点可以在不同项目之间复用,加速开发。
- 可扩展:可以随时添加或移除节点,而无需重启整个系统。
ROS 图(Graph)
Section titled “ROS 图(Graph)”ROS 2 系统的运行时结构被称为 ROS 图(ROS Graph)。ROS 图是由多个节点通过通信连接构成的网络拓扑结构。
节点是 ROS 图中的基本计算单元。每个节点应当只负责一项逻辑功能。例如:
- 一个节点负责从激光雷达读取数据并发布到话题上
- 另一个节点订阅激光雷达数据,用于构建地图
- 还有一个节点负责根据地图规划机器人路径
节点可以是发布者(publisher)、订阅者(subscriber)、服务端/客户端(service server/client)、动作服务端/动作客户端(Action server/client)的任意组合,这些角色可以同时存在。有关节点的详细介绍,请参见 关于节点。
ROS 2 提供三种主要的通信方式,以适应不同的应用场景:
-
话题(Topic):用于连续数据流的发布/订阅通信。例如传感器数据、机器人状态等。多个订阅者可以同时接收同一个话题的数据。详见 关于话题。
-
服务(Service):用于同步的请求/响应通信。客户端发送请求并等待服务端返回结果,适合短时间的计算任务。详见 关于服务。
-
动作(Action):用于异步的、长时间运行的任务。与服务不同,动作可以在执行过程中提供反馈,并且可以被取消或抢占。详见 关于动作。
ROS 2 的节点之间不需要手动配置连接。当一个节点启动时,它会通过底层的 DDS 中间件自动发现同一 ROS 域中的其他节点,并根据各自的发布者/订阅者关系建立连接。这意味着:
- 节点可以按任意顺序启动,系统会自动适配。
- 新加入的节点可以随时与已运行的节点建立通信。
- 节点退出时,其他节点会自动检测并清理连接。
有关发现机制的详细信息,请参见 关于节点发现。
DDS 中间件
Section titled “DDS 中间件”ROS 2 直接使用 DDS(Data Distribution Service)作为底层通信中间件,并通过 RMW(ROS Middleware)抽象层隔离具体的 DDS 实现。这样 ROS 2 就具备了以下能力:
- QoS(服务质量)控制:可以精确控制消息的可靠性、持久性、截止时间等。详见 QoS 服务质量设置。
- 多播与组播:DDS 支持多种网络传输模式,适用于不同的网络环境。
- 实时通信:通过适当的 QoS 配置和 DDS 实现,ROS 2 可以满足硬实时系统的需求。
用户可以根据应用需求选择不同的 DDS 实现(如 Fast DDS、Cyclone DDS),只需设置 RMW_IMPLEMENTATION 环境变量即可切换。详见 DDS 实现的选用 和 RMW 实现的选用。
命名与命名空间
Section titled “命名与命名空间”ROS 2 使用层次化的命名体系来组织节点、话题、服务和参数。每个实体都有一个名称,该名称可以包含命名空间以形成层次结构。例如:
- 节点名称:
/robot1/lidar_driver - 话题名称:
/robot1/scan - 服务名称:
/robot1/reset_pose
这种命名机制使得多机器人系统中的资源可以清晰地区分开来。
ROS 2 通过 客户端库(client library)为开发者提供编程接口。核心的客户端库包括:
- rclcpp:C++ 客户端库,提供高性能的节点实现,适合对计算效率有较高要求的组件。
- rclpy:Python 客户端库,适合快速原型开发和工具脚本。
这些客户端库都构建在通用的 C 语言核心库 rcl 之上,确保了不同语言之间的行为一致性。社区还提供了 Rust、Java、Node.js 等语言的客户端库。详见 关于客户端库。
坐标变换(TF2)
Section titled “坐标变换(TF2)”机器人系统通常涉及多个坐标系,如机器人的基座坐标系、传感器坐标系、世界坐标系等。ROS 2 通过 tf2 库提供了一种标准化的方式来管理这些坐标系之间的变换关系。tf2 会自动在分布式系统中传播坐标变换信息,使得任何节点都可以查询任意两个坐标系之间的变换。详见 关于坐标变换。
ROS 2 的每个节点都可以拥有 参数(parameter),用于在启动时和运行期间配置节点的行为,而无需修改代码。参数通过节点名称、命名空间和参数名称进行寻址,并支持多种数据类型。详见 关于参数。
ROS 2 与 ROS 1 在架构上的主要区别是什么?
ROS 1 使用自研的 TCPROS/UDPROS 协议和中心化的 rosmaster 进行节点发现。ROS 2 直接使用 DDS 作为中间件,去除了中心化 master,实现了真正的去中心化发现机制,并增加了 QoS 支持。详见 从 ROS 1 迁移。
一个 ROS 2 系统中最多可以有多少个节点?
没有硬性上限,但实际受限于系统资源(CPU、内存、网络带宽)和 DDS 实现的配置。大型机器人系统通常包含数十到数百个节点。
不同编程语言编写的节点能否互相通信?
可以。ROS 2 使用 IDL(接口定义语言)来描述消息类型,各客户端库通过代码生成器为各自的编程语言生成对应的消息代码。只要使用相同的消息定义,不同语言的节点就可以无缝通信。