RTPS(Real-Time Publish-Subscribe Protocol)是 DDS 标准体系的基石,也是 ROS2 能够实现高性能、高可靠、即插即用通信的核心技术。
一、RTPS 概述
1.1 定义
RTPS 全称为 DDS Interoperability Wire Protocol (DDSI-RTPS),是 OMG 组织于 2002 年制定的标准有线协议,专门解决不同厂商 DDS 实现之间的互操作性问题。
它定义了 DDS 数据在网络上传输的精确二进制格式、通信行为规则和状态机,是 DDS 世界中唯一的"通用网络语言"。我们可以用三层模型清晰理解它的定位:
- CDR:定义数据"长什么样"(二进制序列化格式)
- RTPS:定义数据"怎么传"(网络传输规则与协议)
- DDS:定义应用"怎么用"(上层 API 接口与语义)
1.2 设计目标与优先级
OMG 官方明确规定了 RTPS 的设计目标,并按优先级从高到低排序:
- 性能:最小化延迟和开销,支持微秒级延迟和百万级消息吞吐量
- 可配置性:细粒度 QoS 控制,可在可靠性、实时性和资源消耗之间灵活平衡
- 容错性:无单点故障,支持节点动态加入/离开,网络中断后自动恢复
- 可扩展性:支持从几个节点到数千个节点的大规模分布式系统
- 即插即用:完全自动发现,无需手动配置任何 IP 地址和端口
- 类型安全:编译时和运行时双重类型检查,确保数据类型一致性
- 可移植性:与底层传输无关,支持 UDP、TCP、TSN、5G 等多种网络技术
1.3 DDS 与 RTPS
| 维度 | DDS (Data Distribution Service) | RTPS (Real-Time Publish-Subscribe) |
|---|---|---|
| 层级 | 应用层标准 | 传输层标准 |
| 定义 | 数据中心发布-订阅(DCPS)模型、API 接口、QoS 语义 | 网络包格式、通信行为、状态机 |
| 解决问题 | 应用程序如何与中间件交互 | 不同 DDS 实现如何在网络上交换数据 |
| 提供能力 | 应用可移植性 | 实现互操作性 |
| 类比 | HTTP 协议(定义请求/响应语义) | TCP/IP 协议(定义数据包传输规则) |
DDS 是接口规范,RTPS 是 wire 协议规范。所有符合 DDS 标准的实现(如 Fast DDS、Cyclone DDS、RTI Connext)都必须支持 RTPS 协议,才能实现跨厂商互操作。
二、RTPS 架构:PIM 与 PSM 分离
RTPS 采用 OMG 模型驱动架构(MDA),严格分离平台无关模型(PIM)和平台特定模型(PSM),这是它能够支持多种传输技术并保持高度可扩展性的关键。
2.1 平台无关模型(PIM,Platform Independent Model)
PIM 定义了 RTPS 的核心逻辑和行为,与任何具体传输技术无关。它只描述业务逻辑、功能规则和数据结构,完全不绑定任何编程语言、操作系统或网络协议。
PIM 包括以下核心内容:
- 实体模型(Participant、Writer、Reader、Topic)
- 消息类型和二进制格式
- 通信状态机定义
- 自动发现协议(SPDP、SEDP)
- 可靠传输机制(心跳-确认-重传)
- QoS 策略执行逻辑
- 数据序列化规则
2.2 平台特定模型(PSM,Platform Specific Model)
PSM 将抽象的 PIM 映射到具体的传输技术,在 PIM(平台无关抽象模型) 的基础上,绑定具体技术平台、框架、语言、中间件、系统,带上所有落地细节的可直接落地实现模型。OMG 官方定义了两种标准 PSM:
- UDP/IP PSM:最原始、最广泛使用的 PSM,利用 UDP 的无连接、低延迟和多播特性,是实时系统的首选
- TCP/IP PSM:RTPS v2.2 新增,用于穿越防火墙和利用现有 TCP 基础设施,适合跨网段通信
这种分离架构使得 RTPS 可以轻松扩展到其他传输技术。目前已有多个厂商实现了:
- RTPS over TSN(时间敏感网络):用于工业自动化领域的确定性通信
- RTPS over 5G:用于车联网和移动机器人
- RTPS over 串口:用于嵌入式设备和低带宽场景
三、RTPS 实体模型:构建通信的基本单元
RTPS 定义了四个核心实体,构成了整个协议的基础。所有通信都是通过这些实体之间的交互完成的。
3.1 Domain:通信隔离的边界
- 最高级别的隔离单元,不同域之间完全独立,不能通信
- 由一个唯一的 Domain ID 标识(范围 0-232)
- 所有属于同一域的 RTPS 实体可以相互发现和通信
- 在 ROS2 中,可以通过
ROS_DOMAIN_ID环境变量设置域 ID
设计目的:允许在同一物理网络上运行多个独立的 DDS 系统,互不干扰。例如,在一个工厂里,可以用域 0 运行机器人控制系统,用域 1 运行环境监测系统。
3.2 RTPSParticipant:应用的网络代表
- 应用程序在 RTPS 域中的唯一代表
- 每个应用程序在一个域中只能有一个 Participant
- 负责创建和管理所有 Writer 和 Reader 端点
- 包含一个全局唯一的 GUID,用于标识自身
- 维护本地参与者列表和端点列表
- 处理自动发现和通信连接建立
Participant :一个应用程序在 DDS 网络中的"身份证"和"通信门户"。
3.3 RTPSWriter 与 RTPSReader:数据的发送与接收
- RTPSWriter:负责发送数据的端点,每个 Writer 关联一个主题(Topic)和一个数据类型
- RTPSReader:负责接收数据的端点,每个 Reader 关联一个主题(Topic)和一个数据类型
- 两者都维护一个历史缓存(HistoryCache),用于存储最近的消息
- 当 Writer 和 Reader 的主题、数据类型匹配且 QoS 兼容时,自动建立通信连接
3.4 GUID 与 Locator:实体的唯一标识与地址
GUID 结构
每个 RTPS 实体(Participant、Writer、Reader)都有一个 16 字节的全局唯一标识符(GUID),结构如下:

- GuidPrefix(12 字节):标识 Participant,同一 Participant 下的所有实体共享相同的 GuidPrefix
- EntityId(4 字节):标识 Participant 内的具体实体
EntityId 详细结构:
- 前 2 字节:实体类型(如 Participant、Writer、Reader、内置端点)
- 后 2 字节:实体实例 ID
例如:
- Participant 的 EntityId:
0x00000001 - BuiltinPublicationWriter 的 EntityId:
0x00000002 - BuiltinSubscriptionReader 的 EntityId:
0x00000003
Locator
Locator 完整标识了一个特定传输协议上的一个特定端口 ,Locator以 24 字节 标准结构封装了传输协议、IP 地址和端口号 ,支持 UDPv4/v6、TCPv4/v6、共享内存等多种类型。
RTPS 采用两级 Locator 体系:
- Participant 级 Locator 用于 SPDP/SEDP 自动发现阶段交换元数据
- 端点级 Locator 用于匹配成功后的端到端用户数据传输,实现流量隔离与性能优化。
Locator天然支持多网卡自动切换、IP 地址动态更新和多协议同时通信,端口号按标准公式计算。
Locator 是 RTPS 实体的网络地址,格式为:
<协议>://<地址>:<端口>
<protocol>://<ip_address>:<port>
例如:udp://192.168.1.100:7410、tcp://10.0.0.5:7420
关键特性:
- 每个 Participant 可以有多个 Locator,支持同时在多个网络接口上通信
- 每个 Writer 和 Reader 也有自己的 Locator,用于直接通信
- Locator 可以动态更新,支持网络地址变化
四、RTPS 四大核心机制
RTPS 的强大功能来自于它的四大核心机制:自动发现 、可靠传输 、QoS 服务质量 和数据序列化。
4.1 自动发现:即插即用的核心
RTPS 的即插即用特性完全依赖于自动发现机制。OMG 标准定义了两个层次的发现协议,按顺序执行:
SPDP(Simple Participant Discovery Protocol)
参与者级别的发现,负责找到同域内有哪些节点。
- 每个 Participant 启动后,立即向多播地址
239.255.0.1:7400+DomainID发送参与者宣告消息 - 宣告消息包含:Participant 的 GUID、Locator 列表、支持的协议版本和厂商 ID
- 其他同域 Participant 收到后,将对方加入本地参与者列表
- Participant 会周期性(默认 30 秒)重新发送宣告消息,更新存活状态
- 如果在 3 个周期内没有收到某个 Participant 的宣告,就认为它已经下线,从本地列表中删除
SEDP(Simple Endpoint Discovery Protocol)
端点级别的发现,负责找到每个节点里有哪些发布者和订阅者。
- 在 SPDP 发现参与者之后,通过单播交换端点信息
- 每个 Participant 有两个内置端点:
BuiltinPublicationWriter:发布本地所有 Writer 和 Reader 的信息BuiltinSubscriptionReader:接收远程所有 Writer 和 Reader 的信息
- 端点信息包含:主题名称、数据类型、QoS 配置和 Locator 列表
- 当 Writer 和 Reader 的主题、数据类型匹配且 QoS 兼容时,自动建立通信连接
发现流程:
- 节点 A 启动,发送 SPDP 多播宣告
- 节点 B 收到宣告,将 A 加入本地参与者列表
- 节点 B 向 A 的单播地址发送自己的 SPDP 宣告
- 节点 A 收到宣告,将 B 加入本地参与者列表
- 节点 A 通过 BuiltinPublicationWriter 发布自己的端点信息
- 节点 B 通过 BuiltinSubscriptionReader 收到 A 的端点信息
- 节点 B 发布自己的端点信息
- 双方匹配主题和 QoS,建立通信连接
4.2 可靠传输:在 UDP 上实现可靠通信
RTPS 在不可靠的 UDP 传输之上实现了比 TCP 更适合实时系统的可靠传输机制 ,其核心是基于序列号的心跳-确认-重传机制。
基本工作流程
- 消息序列号:每个 Writer 为每个消息分配一个唯一的、单调递增的序列号
- 历史缓存:Writer 和 Reader 都维护历史缓存,存储最近的消息
- 心跳消息(Heartbeat):Writer 周期性地向所有关联的 Reader 发送心跳,告知当前最高序列号
- 确认-否定消息(ACKNACK) :Reader 收到心跳后,回复 ACKNACK 消息,指出哪些序列号已经收到,哪些丢失
- 重传:Writer 收到 ACKNACK 后,立即重传丢失的消息
优化
- NACK 合并:Reader 将多个丢失的序列号合并到一个 ACKNACK 消息中,减少网络开销
- 心跳抑制:当 Writer 没有新数据时,自动降低心跳发送频率
- 负向确认:Reader 可以主动请求重传丢失的消息,而不必等待心跳
- 选择性重传:只重传真正丢失的消息,而不是重传整个窗口
与 TCP 的区别:
- RTPS 支持一对多可靠多播,而 TCP 只能一对一
- RTPS 可以独立控制每个 Reader 的可靠性级别
- RTPS 没有 TCP 的队头阻塞问题,更适合实时系统
- RTPS 的重传延迟更低,因为它不需要等待超时
4.3 QoS 服务质量:平衡可靠与实时
RTPS 支持 20 多种 QoS 策略,允许用户精确控制通信的各个方面。OMG 标准将它们分为以下几类:
| QoS 类别 | 关键策略 | 作用 |
|---|---|---|
| 可靠性 | RELIABILITY | 选择 BEST_EFFORT(尽力而为)或 RELIABLE(可靠)模式 |
| 时间性 | DEADLINE, LATENCY_BUDGET | 限制数据传输的最大延迟和截止时间 |
| 资源 | HISTORY, RESOURCE_LIMITS | 控制历史缓存大小和资源使用 |
| 生命周期 | LIFESPAN, DURABILITY | 控制数据的有效期和持久性 |
| 所有权 | OWNERSHIP | 解决多个 Writer 发布同一主题的冲突 |
| 存活性 | LIVELINESS | 检测节点是否存活 |
| 表示 | DATA_REPRESENTATION | 指定数据序列化格式 |
QoS 匹配规则 :Writer 和 Reader 的 QoS 必须兼容才能建立连接。一般来说,Writer 提供的 QoS 级别必须高于或等于 Reader 要求的 QoS 级别。
例如:
- 如果 Writer 配置为 RELIABLE,Reader 可以配置为 RELIABLE 或 BEST_EFFORT
- 如果 Writer 配置为 BEST_EFFORT,Reader 只能配置为 BEST_EFFORT
- 如果 Writer 配置为 TRANSIENT_LOCAL 持久性,Reader 可以配置为 TRANSIENT_LOCAL 或 VOLATILE
4.4 数据序列化:CDR 与 XCDR2
RTPS 使用 CDR(Common Data Representation) 作为标准数据序列化格式,确保跨平台和跨语言的一致性。
CDR 的主要特点:
- 支持所有基本数据类型和复杂数据类型(结构体、数组、序列、联合)
- 支持大端和小端字节序
- 编码效率高,开销小
RTPS v2.5 新增了对 XCDR2(Extensible CDR version 2) 的支持,解决了传统 CDR 不支持数据类型演进的问题。XCDR2 支持:
- 可选字段
- 默认值
- 类型扩展(添加新字段不会破坏兼容性)
- 更高效的编码
五、RTPS 消息格式:网线上的二进制语言
RTPS 消息由 RTPS 头 和子消息列表组成,所有字段都采用网络字节序(大端)传输。
5.1 RTPS 头(20 字节)
| 字节偏移 | 比特范围 | 长度 | 字段名称 | 说明 |
|---|---|---|---|---|
| 0 ~ 3 | 0 ~ 31 bit | 4 Byte | RTPS | 固定 RTPS 4个字符 |
| 4 ~ 7 | 32 ~ 63 bit | 4 Byte | ProtocolVersion | 高16bit主版本,低16bit次版本 |
| 8 ~ 11 | 64 ~ 95 bit | 4 Byte | VendorId | 厂商标识 |
| 12 ~ 19 | 96 ~ 159 bit | 8 Byte | GuidPrefix | RTPS 全局唯一标识前缀 |
- 前 4 字节:固定为"RTPS",用于快速识别 RTPS 消息
- ProtocolVersion:协议版本,当前为 2.5
- VendorId:厂商 ID,用于标识 DDS 实现(如 eProsima 为 0x0101,RTI 为 0x0102)
- GuidPrefix:发送方 Participant 的 GUID 前缀
5.2 子消息格式
RTPS 头后面跟着一个或多个子消息,每个子消息有一个 4 字节的子消息头:
| 字节偏移 | 比特范围 | 字段长度 | 字段名称 | 字段说明 |
|---|---|---|---|---|
| 0 | 0~7 bit | 1 Byte | SubmessageId | 子消息类型ID |
| 1 | 8~15 bit | 1 Byte | Flags | 标志位 |
| 2~3 | 16~31 bit | 2 Byte | SubmessageLength | 子消息长度 |
| 4~n | 32bit 往后 | 可变长度 | Submessage Contents | 子消息实际载荷内容 |
- SubmessageId:子消息类型 ID
- Flags:子消息标志位,用于控制子消息的行为
- SubmessageLength:子消息内容的长度(不包括子消息头)
5.3 常见子消息类型
OMG 标准定义了 16 种不同的子消息类型,最常用的有:
- DATA:携带用户数据,包含序列号、时间戳和数据载荷
- HEARTBEAT:Writer 告知 Reader 当前最高序列号
- ACKNACK:Reader 向 Writer 确认收到的消息和请求重传
- INFO_TS:携带时间戳信息
- INFO_DST:指定消息的目标 Participant
- GAP:告知 Reader 某些序列号的消息已经被删除,不需要重传
六、RTPS 在 ROS2 中的应用
ROS2 的所有通信功能,包括发布/订阅、服务、动作和参数,都是基于 RTPS 实现的。
6.1 ROS2 实体到 RTPS 实体的映射
ROS2 的上层实体直接映射到 RTPS 的底层实体:
| ROS2 实体 | RTPS 实体 |
|---|---|
| Node | RTPSParticipant |
| Publisher | RTPSWriter |
| Subscription | RTPSReader |
| Service Server | RTPSReader(请求) + RTPSWriter(响应) |
| Service Client | RTPSWriter(请求) + RTPSReader(响应) |
| Action Server | 多个 RTPSWriter 和 RTPSReader |
| Action Client | 多个 RTPSWriter 和 RTPSReader |
6.2 ROS2 QoS 与 RTPS QoS 的对应关系
ROS2 的 QoS 配置直接映射到 RTPS 的 QoS 策略:
cpp
// ROS2 QoS 配置示例
rclcpp::QoS qos(10);
qos.reliability(RMW_QOS_POLICY_RELIABILITY_RELIABLE);
qos.durability(RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL);
qos.history(RMW_QOS_POLICY_HISTORY_KEEP_LAST);
qos.deadline(std::chrono::milliseconds(100));
qos.liveliness(RMW_QOS_POLICY_LIVELINESS_AUTOMATIC);
6.3 ROS2 中 RTPS 的调试工具
ROS2 提供了多个工具来调试 RTPS 通信:
ros2 doctor:检查 ROS2 环境和网络配置,诊断常见问题ros2 topic info:查看主题的详细信息,包括 QoS 配置和端点信息ros2 node info:查看节点的详细信息,包括发布和订阅的主题ros2 service info:查看服务的详细信息- Wireshark:抓包分析 RTPS 消息,Wireshark 已经内置了 RTPS 解析器
fastdds或cyclonedds命令行工具:查看 DDS 层的详细信息
七、RTPS 性能优化
7.1 传输层优化
- 优先使用 UDP/IP PSM,它比 TCP/IP PSM 延迟更低、开销更小
- 对于大数据传输(如点云、图像),启用分片传输
- 对于跨网段通信,可以使用 TCP/IP PSM 或配置多播路由
- 启用 UDP 校验和,确保数据完整性
7.2 多播的合理使用
- 对于一对多通信,使用多播可以显著减少网络带宽
- 避免在不支持多播的网络中使用多播(如某些云环境)
- 合理配置多播 TTL,防止消息扩散到不必要的网段
- 对于大规模系统,可以使用多播分区(Multicast Partition)减少网络流量
7.3 历史缓存与资源限制配置
- 根据数据的重要性和频率配置合适的历史缓存大小
- 使用
RESOURCE_LIMITSQoS 限制内存使用,防止内存溢出 - 对于高频数据,使用
KEEP_LAST历史策略,只保留最新的 N 条消息 - 对于不需要历史数据的场景,使用
KEEP_ALL历史策略
7.4 分片传输与大数据处理
- 当消息大小超过 MTU(通常为 1500 字节)时,RTPS 会自动进行分片传输
- 对于非常大的消息(如 10MB 以上的点云数据),可以考虑使用压缩或分块传输
- 合理配置分片大小,平衡传输效率和重传开销
- 启用异步发送和接收,提高吞吐量
八、常见问题
Q1:RTPS 为什么用 UDP 而不是 TCP?
A:UDP 具有无连接、低延迟和多播支持的特性,这些对于实时系统至关重要。RTPS 在 UDP 之上实现了可靠传输,同时保留了 UDP 的优点。TCP 的滑动窗口机制和队头阻塞问题不适合实时系统的一对多通信场景。
Q2:ROS2 节点无法发现对方怎么办?
A:这是最常见的问题,通常由以下原因引起:
- Domain ID 不匹配 :确保所有节点使用相同的
ROS_DOMAIN_ID - 多播不通:检查防火墙是否阻止了多播流量,网络交换机是否支持多播
- 网络接口问题:确保节点绑定到正确的网络接口
- 防火墙规则:允许 UDP 端口 7400-7450 的入站和出站流量
Q3:如何解决 ROS2 跨网段通信问题?
A:有两种主要方法:
- 配置多播路由:在路由器上配置多播路由,使多播消息能够跨网段传输
- 使用 TCP/IP PSM:将 DDS 实现配置为使用 TCP/IP PSM,它支持单播跨网段通信
- 使用 Discovery Server:使用 Fast DDS 的 Discovery Server 功能,通过单播进行发现
Q4:RTPS 支持加密吗?
A:是的,RTPS v2.3 及以上版本支持 DDS 安全规范,可以对消息进行加密、认证和访问控制。ROS2 Humble 及以上版本已经集成了 DDS 安全功能。
Q5:不同 DDS 实现之间可以互操作吗?
A:是的,只要它们都符合 RTPS 标准,就可以实现互操作。例如,使用 Fast DDS 的节点可以与使用 Cyclone DDS 或 RTI Connext 的节点通信。