4. ROS2网络发现机制

在ROS2中,节点之间之所以能够“自动找到彼此”,并不依赖中心化的Master,而是由底层DDS中间件通过一套标准化的发现协议完成。理解这套机制,是排查多机通信故障、优化网络配置、控制发现流量的基础。本节围绕简单发现协议、参与者发现、端点发现以及多播/单播配置四个层面展开。

一、核心原理:从SPDP到SEDP的两阶段发现

ROS2默认使用的DDS实现(如Fast DDS、Cyclone DDS)遵循OMG DDSI-RTPS规范,其发现过程分为两个阶段:参与者发现和端点发现。前者解决“网络上有哪些DomainParticipant”,后者解决“这些参与者内部有哪些DataWriter和DataReader,以及它们的数据类型和QoS是否匹配”。

简单发现协议(Simple Discovery Protocol,SDP)是RTPS规范中定义的基础发现机制,它由两个子协议组成:

  • SPDP(Simple Participant Discovery Protocol):负责参与者级别的发现,周期性发送心跳式的公告报文。
  • SEDP(Simple Endpoint Discovery Protocol):负责端点级别的发现,交换话题、服务、数据类型、QoS等信息。

只有SPDP和SEDP都成功匹配后,两个节点之间才会真正建立数据通信通道。因此,多机通信失败时,需要先判断是“参与者没发现”还是“端点没匹配”。

ROS2 发现机制两阶段流程 阶段一:SPDP 参与者发现(多播为主) 节点 A DomainParticipant GUID / 端口 周期发送 SPDP 公告 节点 B DomainParticipant GUID / 端口 周期发送 SPDP 公告 多播地址 239.255.0.1:7400 互相通告:GUID、IP、端口 阶段二:SEDP 端点发现(单播为主) 节点 A 端点 DataWriter /chatter DataReader /status QoS: Reliable / Volatile 节点 B 端点 DataReader /chatter DataWriter /status QoS: Reliable / Volatile 单播交换端点信息 话题名、类型、QoS 匹配 匹配成功 → 建立数据通道

二、参与者发现:SPDP如何工作

SPDP的核心是“周期公告 + 监听响应”。每个DomainParticipant启动后,会周期性地向约定的多播地址发送公告报文,报文中包含:

  • 参与者的GUID(全局唯一标识);
  • 可用的单播IP地址和端口;
  • 协议版本、厂商信息、租约时长(Lease Duration)。

同一网段内的其他参与者监听该多播地址,收到公告后记录对方信息,并回复自己的公告。若在租约时长内未收到对方心跳,则认为对方离线,清理其端点信息。默认租约时长通常为20秒左右,公告周期约为3秒,具体取决于DDS实现。

SPDP只负责“认识人”,不负责“谈业务”。参与者发现成功后,双方只是知道了彼此的存在和单播地址,此时还不能传输话题数据。

三、端点发现:SEDP如何匹配

当两个参与者通过SPDP互相认识后,会通过单播建立可靠通道,进入SEDP阶段。每个参与者把自己内部的DataWriter和DataReader信息发送给对端,包括:

  • 端点GUID、所属参与者GUID;
  • 话题名称、数据类型名称;
  • QoS策略:可靠性、持久性、历史深度、截止时间等;
  • 端点角色:Writer还是Reader。

接收方根据话题名、类型和QoS进行匹配。只有Writer和Reader的话题名一致、类型一致、QoS兼容时,才会建立关联。例如,Writer为Reliable而Reader为BestEffort通常可以匹配;反之则可能不兼容。

四、多播与单播配置

SPDP默认依赖多播,但很多云服务器、跨网段、VPN或企业网络会禁用多播。此时需要配置“初始对等节点列表”(Initial Peers),让参与者直接向指定IP单播发送SPDP公告,从而绕过多播限制。

以Fast DDS为例,可通过XML配置文件指定初始对等节点:

<participant profile_name="peer_profile">
  <rtps>
    <builtin>
      <discovery_config>
        <initialPeersList>
          <locator>
            <udpv4>
              <address>192.168.1.20</address>
              <port>7410</port>
            </udpv4>
          </locator>
        </initialPeersList>
      </discovery_config>
    </builtin>
  </rtps>
</participant>

在ROS2中,可通过环境变量指定配置文件:

export FASTRTPS_DEFAULT_PROFILES_FILE=/path/to/peer_profile.xml
export ROS_DOMAIN_ID=42
ros2 run demo_nodes_cpp talker

对于Cyclone DDS,则使用CYCLONEDDS_URI指定网络接口和Peers。多机场景下,建议明确绑定网卡,避免发现报文从错误接口发出。

配置项 作用 典型值/示例
ROS_DOMAIN_ID 隔离不同ROS2域,避免跨域发现 0~232,多机需一致
多播地址 SPDP默认公告地址 239.255.0.1:7400
Initial Peers 多播不可用时指定单播对端 192.168.1.20:7410
Lease Duration 判定参与者离线的超时时间 默认约20s
网卡绑定 指定发现与数据使用的网络接口 eth0 / wlan0

五、案例与排障复盘

假设两台机器分别运行talker和listener,ros2 node list只能看到本机节点。排查顺序如下:

  1. 确认ROS_DOMAIN_ID一致,且未设置ROS_LOCALHOST_ONLY=1。
  2. 用ros2 multicast send和ros2 multicast receive测试多播是否可达。
  3. 若多播不通,配置Initial Peers,改为单播发现。
  4. 检查防火墙是否放行7400/7410等DDS端口段。
  5. 确认两端话题名、类型和QoS兼容,必要时用ros2 topic info -v查看端点QoS。
常见误区:只配置了Initial Peers却未关闭多播,导致发现报文重复;或两端ROS_DOMAIN_ID不同,SPDP根本不在同一域内公告。多机调试时,先保证“参与者能发现”,再排查“端点能匹配”。

掌握SPDP与SEDP的分工,理解多播与单播的适用边界,就能在多机ROS2系统中快速定位发现层问题,并为后续的QoS调优和网络隔离打下基础。