4. DDS发现机制

在ROS2中,两个节点即使运行在同一台机器上,也必须先“互相认识”才能开始通信。这个“认识”的过程就是DDS的发现机制(Discovery)。ROS2默认使用DDS作为中间件,而DDS的发现协议由RTPS(Real-Time Publish-Subscribe)规范定义,核心是SPDP与SEDP两个协议。理解它们,是排查“节点看不到对方”“话题连不上”“QoS不匹配”等问题的关键。

一、核心原理:SPDP与SEDP的分工

DDS发现分为两个阶段:参与者发现(Participant Discovery)和端点发现(Endpoint Discovery)。前者由SPDP完成,后者由SEDP完成。

  • SPDP(Simple Participant Discovery Protocol):负责发现“域参与者”(DomainParticipant)。每个ROS2节点在启动时都会创建一个DomainParticipant,并周期性地向网络发送“我在这里”的公告(Announcement),同时监听其他参与者的公告。SPDP只交换参与者的基本信息,如GUID、IP、端口、协议版本,不涉及具体的话题或服务。
  • SEDP(Simple Endpoint Discovery Protocol):在SPDP建立参与者之间的连接后,SEDP负责交换端点信息。端点包括DataWriter(发布者)和DataReader(订阅者),以及它们绑定的话题名、类型名、QoS策略。只有端点信息匹配成功,数据流才会真正建立。

简单来说:SPDP让节点“找到人”,SEDP让节点“找到话题”。两者配合,构成DDS的“简单发现协议”(Simple Discovery Protocol)体系。

二、方法流程:ROS2节点发现全流程

下面以两个ROS2节点(一个发布者、一个订阅者)为例,描述完整的发现流程:

  1. 节点启动:每个节点创建DomainParticipant,加入指定的ROS_DOMAIN_ID域。
  2. SPDP公告:参与者周期性地通过多播(默认239.255.0.1)发送SPDP公告,包含自身GUID、可用端口、租约时长。同时监听多播地址,接收其他参与者的公告。
  3. 参与者匹配:当两个参与者互相收到公告后,建立单播连接,进入“已发现”状态。
  4. SEDP交换:双方通过单播通道交换SEDP消息,列出自己拥有的DataWriter和DataReader,包括话题名、类型名、QoS。
  5. 端点匹配:DDS根据话题名、类型名和QoS策略进行匹配。若发布者的DataWriter与订阅者的DataReader匹配成功,则建立数据通道。
  6. 数据传输:匹配完成后,发布者开始发送数据,订阅者接收数据。
提示:SPDP公告默认周期为5秒,租约时长默认20秒。如果节点异常退出,其他节点最多需要20秒才能感知到它已离线。
ROS2 DDS 发现流程:SPDP + SEDP 节点 A(发布者) DomainParticipant DataWriter /chatter · std_msgs/String QoS: Reliable SPDP 公告 节点 B(订阅者) DomainParticipant DataReader /chatter · std_msgs/String QoS: Reliable SPDP 公告 SPDP 多播公告(239.255.0.1) SEDP 单播交换端点信息 端点匹配成功 话题名 + 类型名 + QoS 一致 匹配

三、案例场景:为什么我的节点看不到对方?

假设你在两台机器上分别运行一个发布者和一个订阅者,使用默认配置,但ros2 topic list看不到对方的话题。常见原因如下:

现象 可能原因 排查命令
SPDP公告收不到 多播被禁用、ROS_DOMAIN_ID不同、防火墙拦截 ros2 multicast receive
参与者发现但端点不匹配 话题名不一致、类型名不一致、QoS不兼容 ros2 topic info /chatter --verbose
节点列表为空 RMW实现不同(Fast DDS vs Cyclone DDS) echo $RMW_IMPLEMENTATION
发现延迟大 SPDP周期长、网络拥塞、租约未过期 ros2 daemon stop && ros2 daemon start

例如,发布者使用Reliable,订阅者使用Best Effort,两者QoS不兼容,SEDP交换后端点匹配失败,数据不会传输。此时ros2 topic info会显示“Publisher count: 1, Subscription count: 1”,但实际收不到数据。

# 查看端点QoS详情
ros2 topic info /chatter --verbose

# 输出示例
Type: std_msgs/msg/String
Publisher count: 1
  QoS: Reliability: RELIABLE, Durability: VOLATILE
Subscription count: 1
  QoS: Reliability: BEST_EFFORT, Durability: VOLATILE

四、误区与复盘

误区一:认为“节点启动就能通信”。实际上,SPDP公告有周期,SEDP交换需要时间,通常需要几百毫秒到数秒。若在启动后立即发送数据,可能因发现未完成而丢失。
误区二:忽略ROS_DOMAIN_ID。不同域ID的节点使用不同的多播端口,SPDP公告互不可见,自然无法发现。ROS2默认域ID为0,多机通信时必须显式设置相同域ID。

复盘要点:发现机制是ROS2通信的“第一公里”。排查通信问题时,应按照“SPDP是否通 → SEDP是否交换 → 端点是否匹配 → QoS是否兼容”的顺序逐层检查。常用工具包括ros2 node list、ros2 topic list、ros2 topic info --verbose、ros2 doctor以及Wireshark抓包分析RTPS报文。

理解SPDP与SEDP的分工,不仅能帮助你快速定位“节点看不见”的问题,还能在配置QoS、设计多机系统时做出更合理的决策。例如,在大型系统中,可以通过调整SPDP公告周期和租约时长来平衡发现速度与网络开销;在跨网段场景中,可以配置单播发现列表(Unicast Discovery)替代多播,提升可靠性。