Skip to content

DDS RTPS 协议:模块构成与自动发现 ​

RTPS 规范(The Real-Time Publish-Subscribe Protocol DDS Interoperability Wire Protocol Specification,也称 DDSI-RTPS)定义了 DDS 底层的报文格式与行为,解决的是不同厂商 DDS 产品之间的互操作问题:各家都实现了 DCPS 接口规范,但只有把线上的报文格式和交互行为统一定义,不同实现才能互联互通。本文整理 RTPS 的四大模块(结构、报文、行为、发现),重点展开发现模块的 SPDP/SEDP 两阶段协议与常见实现提供的发现模式。读完可以理解 DDS"纯分布式架构"在协议层是如何落地的。

为什么需要 RTPS ​

RTPS 产生的因果链:

  • DDS 接口(DCPS)规范定义了应用看到的 API 与语义;
  • 不同厂家按接口规范实现出各自的 DDS 产品;
  • 使用不同 DDS 产品的系统需要集成,对跨厂商互操作、互联互通提出了需求;
  • RTPS 规范据此定义 DDS 底层的报文格式、行为等内容。

主流开源 DDS 都基于 RTPS 协议实施:Fast DDS 支持直接调用 RTPS 接口,embeddedRTPS 专注嵌入式场景下的 RTPS 协议实现。

四大模块 ​

RTPS 规范分为四个模块:

模块 职责
结构模块 定义概念和数据结构
报文模块 定义报文格式
行为模块 定义不同配置下传输的行为,即什么情况下发送什么报文、如何响应接收的报文
发现模块 综合使用以上三个模块,定义简单发现协议,用于通信实体之间的自动发现与匹配

结构模块 ​

结构模块描述了作为通信参与者的 RTPS 实体的结构。RTPS 实体是应用程序可见的 DDS 实体相互通信而使用的协议级端点,各概念如下:

概念 说明
Entity 实体,包括参与者以及通信实体(写者、读者)的共用属性,包括唯一标识。
Participant 参与者,作为通信实体(写者、读者)的父实体,存储协议版本、供应商 ID 以及默认的地址信息。
Endpoint 通信实体,作为写者以及读者的父类抽象,存储两端共有的信息,包括使用的通信地址、可靠性等级以及主题等级。
Writer 写者,用于发送数据,每个写者关联一个 HistoryCache,用于维护发送的数据,并提供接口发送数据。
Reader 读者,用于接收数据,每个读者关联一个 HistoryCache,用于维护接收的数据列表。
HistoryCache 历史数据缓存队列,提供增、删、查的功能,队列中的元素为 CacheChange。
CacheChange 描述一个样本数据,包括发送方标识、序列号、所属数据实例以及负载。

报文模块 ​

报文模块描述了 RTPS Writer 端点和 Reader 端点之间交换的消息的总体结构和逻辑内容:

  • Message:RTPS 消息,包含一个消息头(Header)以及 1 个到多个子消息(SubMessage);
  • Header:RTPS 消息头;
  • SubMessage:子消息,作为不同子消息的抽象结构,包括一个子消息头(SubmessageHeader)以及每种不同子消息各自的一个到多个子消息元素(SubmessageElement)。按功能可以分为三类:
    • 可靠型:Heartbeat、AckNack、NackFrag;
    • 信息型:InfoDestination、InfoTimeStamp、InfoReply、InfoSource;
    • 数据型:Data、Gap、DataFrag;
    • 此外还有 Pad(填充)、HeartbeatFrag(分片心跳)等辅助子消息。

行为模块 ​

行为模块进一步定义了 Writer/Reader 的接口及其行为,按可靠性配置对应四类端点:

  • StatelessWriter:对应 BEST_EFFORT 类型的数据写者;
  • StatelessReader:对应 BEST_EFFORT 类型的数据读者;
  • StatefulWriter:对应 RELIABLE 类型的数据写者;
  • StatefulReader:对应 RELIABLE 类型的数据读者。

其中 StatelessWriter 的状态机如下:

IDLE 状态下匹配新的远程数据读者后保持 IDLE;有未发送的样本数据时进入 PUSHING 状态,在该状态下循环发送未发送的样本数据(仅涉及 DATA 与 GAP 两类子消息),发送完成后回到 IDLE。

发现模块 ​

发现模块是 DDS"纯分布式架构"的基础:每个应用上的 DDS 实体通过纯分布式的方式获取系统内其他 DDS 实体的信息,并根据这些信息进行基于主题的按需分发。发现模块定义了两个协议:

  1. 参与者发现协议(PDP):发现网络中其他 DDS 参与者;
  2. 端点发现协议(EDP):在已发现的参与者之间,发现彼此拥有的、可能匹配的 DataWriter 和 DataReader。

参与者发现协议(PDP) ​

核心功能:

  • 创建内置的参与者发现端点(SPDP Writer/Reader);
  • 周期性广播本地参与者信息;
  • 接收并处理远程参与者信息;
  • 维护参与者代理数据(ParticipantProxyData);
  • 触发端点发现过程。

工作流程:

  1. 启动阶段:每个 DomainParticipant 启动时,创建一对内置端点(SPDP Writer 和 Reader);
  2. 广播机制:周期性在预定义的多播地址和端口上发送 SPDPdiscoveredParticipantData 消息(周期因实现而异:Fast DDS 默认 3 秒,RTPS 规范建议值为 30 秒);
  3. 消息内容:包含自身 Participant 的 GUID、QoS、定位信息(Locator,IP/Port)等;
  4. 接收与处理:接收其他 Participant 的 SPDP 消息,更新参与者代理数据;
  5. 连接建立:收到新 Participant 公告后,尝试建立与对方 Participant 的通信通道;
  6. 离开检测:通过停止接收公告(租约超时)或收到明确的 dispose 消息检测 Participant 离开。

发现模式:

  • 多播发现:节点加入预定义多播组,无需预知其他节点地址,适用于局域网;
  • 单播发现:节点需预先配置对端地址,通过点对点通信交换信息,适用于广域网或跨子网场景。

端点发现协议(EDP) ​

核心功能:交换 DataWriter 和 DataReader 的信息,匹配可能通信的端点,确认匹配成功后建立数据传输通道。

工作流程:

  1. 信息交换:通过 PDP 建立的通信信道,共享 DataWriter 和 DataReader 的信息;
  2. 匹配条件:主题(Topic)和数据类型必须一致;
  3. 确认机制:通过 Heartbeat、AckNack 等消息确认数据样本。例如 B 的 SEDPbuiltinSubscriptionWriter 发送 Heartbeat 给 A 的 SEDPbuiltinSubscriptionReader,A 收到后若发现缺少样本,会发送 AckNack 告知丢失的样本,B 发送缺失的样本并更新 Heartbeat;
  4. 匹配完成:当双方确认数据一致后,DataWriter 和 DataReader 可以开始发送/接收用户数据。

实现提供的其他发现机制 ​

以 Fast DDS 为例,除标准发现外还提供多种机制以适应不同应用场景:

  1. 简单发现(Simple Discovery):默认机制,支持 PDP 和 EDP 的 RTPS 标准,使用 SPDP 和 SEDP 协议自动完成发现过程,与任何其他 DDS 和 RTPS 实现兼容。
  2. 静态发现(Static Discovery):跳过 EDP 阶段,通过 XML 文件预先配置对端信息,无需自动发现。
  3. 发现服务器(Discovery Server):集中式发现体系结构,DomainParticipant(称为服务器)充当元流量发现的集线器,适用于大规模分布式系统,可减少网络广播流量。
  4. 手动发现(Manual Discovery):禁用 PDP,用户使用外部元信息信道手动匹配和取消匹配 RTPS 实体,适用于特殊网络环境或需要高度定制化的系统。

要点 ​

  • RTPS 是 DDS 的互操作线协议:统一报文格式与行为,使不同厂商实现可以互通
  • 四大模块:结构(协议级端点与 HistoryCache)、报文(Header + SubMessage 三类)、行为(四类端点按可靠性划分)、发现(SPDP/SEDP 两阶段)
  • 发现分两步:PDP 发现参与者(周期广播,Fast DDS 默认 3 秒、RTPS 规范建议 30 秒),EDP 在参与者间匹配端点(Topic 与类型一致 + Heartbeat/AckNack 确认)
  • 大规模系统可用发现服务器(集中式元流量)或静态发现(XML 预配端点)替代全广播的简单发现
最近更新

基于 VitePress 构建