
I. Preface在多个ubuntu22.04设备中都部署了ROS2然后它们之间互相通信功能是基础不然没办法体现分布式节点的优势。同时也会遇到很多奇怪的问题这些都跟ROS2的通信框架有关系与ROS1的最大不同就是取中心化不需要roscore了使用DDS来去中心化DDS (Data Distribution Service) 是现在ROS2实现分布式通信和部署的底层架构需要先了解清楚才知道怎么解决问题。ROS 1 是 节点 → roscore → 节点 而 ROS 2 没有 roscore节点之间靠 DDS 自动发现 节点 A ← DDS 发现与通信 → 节点 BII. Solutions接下来就是排查的过程先检查防火墙在terminal输入sudo ufw status verbose如果是如下输出则正常说明防火墙是关闭状态。adminadminpc:~$ sudo ufw status verbose [sudo] password for admin: Status: inactive但如果是激活状态就需要关闭它sudo ufw disable检查一下网卡是否支持MULTICAST在设备上输入ipaddr找到你们局域网使用的网卡例如 enp3s0、wlp2s0看是否有MULTICAST也可以执行iplinkshow如果没有 multicast会影响 ROS 2 自动发现。也可以用multicast工具做测试在设备A运行ros2 multicast receive在设备B运行ros2 multicast send如果两边成功通信了会收到Hello world的信息这就说明通信完全没问题的。但如果不通没收到消息就说明防火墙按第一步检查的方法关闭路由器Wi-Fi是否有 AP 隔离进入wifi的管理员界面可以查看不过这种一开始ping一下就知道了如果用隔离是ping不了的DDS 绑定到了错误接口这个很有可能是多网卡造成的下一个检查步骤会说。检查以下四项先说头三项echoROS_DOMAIN_ID$ROS_DOMAIN_IDechoROS_LOCALHOST_ONLY$ROS_LOCALHOST_ONLYechoRMW_IMPLEMENTATION$RMW_IMPLEMENTATION其中ROS_DOMAIN_ID只要几台设备之间是一样的就行ROS_LOCALHOST_ONLY需要是0如果有的设备设置了1就说明它的ROS通信只在本地端实现RMW_IMPLEMENTATION就是中间件接口RMW (ROS Middleware Interface)其实不设也可以默认使用的是 Fast DDS通过rmw_fastrtps_cpp实现。这是因为在 ROS 2 的默认安装配置中Fast DDS 通常作为首选的中间件。然而依赖默认设置在多机通信中有时会带来不确定性原因如下环境一致性确保所有参与通信的设备使用相同的 RMW 实现至关重要。如果一台设备默认使用 Fast DDS而另一台由于历史安装或配置原因实际使用了 CycloneDDS即使ROS_DOMAIN_ID相同它们也无法发现彼此。Fast DDS 的共享内存Shared Memory传输在某些系统配置或虚拟机环境中Fast DDS 默认启用的共享内存传输可能无法正常工作导致进程间甚至本机内的节点通信失败。这常表现为“奇怪的”或间歇性的连接问题。网络发现Discovery配置默认的 Fast DDS 配置可能未针对复杂的局域网拓扑进行优化。例如它可能默认绑定到错误的网络接口或者在多网卡环境下选择非预期的 IP 地址进行组播通信。因此虽然不设置RMW_IMPLEMENTATION可以快速开始但在部署到多台设备进行分布式通信时显式地、统一地设置此变量是一个推荐的最佳实践。这消除了一个潜在的不确定源使得网络问题的排查范围更集中。例如你可以统一设置为rmw_cyclonedds_cpp因为 CycloneDDS 在某些网络环境下表现出更稳定和可预测的发现行为。但是注意在某些机器上 Fast DDS 的 shared memory 会导致奇怪问题。RMW有几种的如果没有特别设置的话默认是Fast DDS常见的类型如下RMW底层 DDS说明rmw_fastrtps_cppFast DDSROS 2 Humble 默认常见选择rmw_cyclonedds_cppCycloneDDS多机通信中经常比较好排查rmw_connextddsRTI Connext DDS商业 DDS特定场景使用在bashrc里我设置了exportROS_DOMAIN_ID2exportRMW_IMPLEMENTATIONrmw_cyclonedds_cpp我遇到的问题就是在局域网内互相ping通DOMAIN IDRMWros版本都一样但还是没办法互相接收对方的topic也包括其他ros的信息。因此还需要检查最后一项RMW的配置链接不同的RWM接口用不同的指令CycloneDDS:echoCYCLONEDDS_URI$CYCLONEDDS_URIFast DDS:echo$FASTRTPS_DEFAULT_PROFILES_FILE正常来说如果没有设置的话会没有返回值。这也是正常的因为一般DDS会自动选择一张网卡的ip进行通信。没有的情况下也需要后面留意的。先进行下一步检查看看当前的设备里有几张网卡输入ip -brief addr会有如下类似的返回robrobnuc:~$ ip -brief addr lo UNKNOWN 127.0.0.1/8 ::1/128 enp86s0 UP 192.168.1.5/24 fe80::d754:6db5:4faf:8609/64 wlp87s0f0 UP 192.168.0.12/24 fe80::aae8:c70:e8c4:829f/64 enx426f491da532 DOWN可以看到这台设备上有两个up状态的网卡一个是无线的网卡wlp87s0f0另一个是有线网卡enp86s0特别要注意这种多网卡的设备很多通信失败都是因为DDS选择了错误的网卡进行通信导致的。所以我们需要加入一个DDS的配置文件告诉ROS2系统应该使用哪一张网卡进行通信在有多网卡的设备中以cyclonedds为例创建一个xml格式的配置文件并写入内容的指令如下直接复制到terminal中运行即可cat ~/cyclonedds.xml EOF CycloneDDS Domain General Interfaces NetworkInterface namewlp87s0f0/ /Interfaces AllowMulticasttrue/AllowMulticast /General /Domain /CycloneDDS EOF注意里面的参数wlp87s0f0根据自己当前局域网对应的端口名称来填写。然后可以做一组测试在terminal输入export CYCLONEDDS_URIfile://$HOME/cyclonedds.xml然后运行一个节点发布些消息如ros2 run demo_nodes_cpp talker这时再到另一台设备中检查是否能检测到topic和node如果有那就说明问题解决了可以互相接收到ros的信息了。下一步就是把这个RMW的配置文件写到bashrc里面就可以了不同的RWM接口用不同的指令CycloneDDS: export CYCLONEDDS_URIfile://$HOME/cyclonedds.xml Fast DDS: export FASTRTPS_DEFAULT_PROFILES_FILE$HOME/fastdds.xml这样以后这台设备就会一直使用指定的网卡进行通信了。