ROS2 通信机制


前言

本节主要阐述ROS2通信原理并记录自动驾驶开发过程中遇到的一些问题与解决思路。

1. ROS2取消roscore原因

ROS2通信体系的核心价值,不在于把ROS1中的接口重新实现一遍,而在于重新定义了机器人系统中“节点如何发现彼此、数据如何被分发、通信质量如何被约束、系统如何跨机器扩展”的底层范式。ROS1依赖roscore维护全局命名与发现关系,适合实验室原型、单机验证和小规模机器人应用。ROS2面向多机协同、复杂传感器、高频数据流、工业现场部署和长期运行需求,将通信基础迁移到DDS与RTPS之上,通过RMW层实现中间件可插拔,通过DDS动态发现机制实现分布式组网,通过QoS策略将可靠性、时延、带宽与历史数据行为显式暴露出来。

1.1 ROS1通信模型的工程边界

ROS1的通信体系中,roscore承担Master角色,负责节点注册、Topic查询和连接关系建立。一个典型ROS1系统启动后,节点会先向Master登记自身信息,订阅端通过Master查询发布端地址,随后发布端与订阅端之间建立点对点连接。数据真正传输时,Topic数据通常并不经过Master;但连接关系的建立依赖Master。

这种模式具有清晰的工程优点:结构简单、调试直观、入门成本低。在教学、算法验证、单机机器人平台中,roscore提供了足够便利的中心化协调能力。

自动驾驶系统对通信基础有更高要求:

工程需求 ROS1中心化发现的约束
多机协同 Master地址配置、网络环境变化、跨主机解析容易引入额外复杂度
高可用运行 Master异常会影响新节点加入和连接关系重建
高频传感器融合 通信可靠性、队列深度、传输策略需要更细粒度控制
车端/边缘端部署 系统需要在动态拓扑中自动发现、自动恢复、自动隔离
工业网络管理 需要通过域、QoS、发现策略和中间件配置进行工程化治理

ROS2对底层通信进行重构,将系统发现、数据分发和通信质量控制下沉到DDS生态。DDS本身是面向实时系统、分布式系统和数据中心式通信模型设计的中间件标准,ROS2基于DDS获得了分布式发现、QoS配置、跨语言跨平台互操作等能力。

1.2 从节点中心到数据中心

ROS1开发者习惯从“节点连接节点”的角度理解系统。ROS2更适合从“数据在全局数据空间中被发布、匹配和分发”的角度理解通信。

在DDS模型中,系统中的Participant加入某个Domain后,发布者与订阅者围绕Topic、数据类型和QoS进行匹配。应用层并不需要手动维护每个对端节点地址,也不需要显式指定数据要发给哪台机器。只要位于同一通信域、Topic名称一致、类型兼容、QoS匹配,底层中间件就会建立通信关系。

这种设计带来的变化非常关键:

  • 节点生命周期与通信发现过程解耦,后启动节点可以自动加入系统。
  • 多台机器上的节点处于同一DDSDomain时,可以形成统一的逻辑通信空间。
  • 通信质量由QoS策略约束,工程师可以针对传感器、控制指令、状态量、地图数据配置不同传输行为。
  • 底层DDS实现可以替换,应用代码通过rclcpp/rclpy保持相对稳定。

ROS2官方文档说明,ROS2默认使用DDS作为中间件,同时兼容多个DDS或RTPS实现,并支持FastDDS、CycloneDDS、ConnextDDS、GurumDDS等实现;当前ROS2也支持Zenoh等非DDSRMW实现。

2. ROS2通信架构

ROS2通信栈可以理解为从应用API到网络协议的多层封装。每一层都承担明确职责:上层关注自动驾驶开发接口,下层关注发现、序列化、传输和QoS。

2.1 应用层与rcl:开发者直接接触的接口

应用层由rclcpp、rclpy等客户端库组成。开发者创建Node,声明Publisher、Subscription、Service、Client、ActionServer或ActionClient,并通过回调函数处理数据。

以C++Publisher为例,应用层创建发布者:

auto pub = node->create_publisher<std_msgs::msg::String>(
  "/diagnostics/state",
  rclcpp::QoS(10).reliable()
);

这行代码背后实际发生了多层动作:

  1. rclcpp将C++接口转换为rcl层通用调用。
  2. rcl将Topic、类型、QoS信息传递给rmw层。
  3. rmw实现调用具体DDS厂商API创建DataWriter。
  4. DDS参与发现与匹配,找到兼容订阅者。
  5. RTPS将数据样本编码为网络报文并发送。

2.2 RMW层:ROS2架构解耦的关键

RMW即ROSMiddleware接口。它是ROS2通信架构中最关键的解耦层。ROS2并未把应用代码直接绑定到某一个DDS厂商API,而是通过rmw接口抽象出统一的创建节点、创建发布者、创建订阅者、序列化、反序列化、等待集合、服务调用等能力。

这种设计使ROS2具备中间件可插拔能力。使用过程中可以在不修改业务代码的情况下,通过环境变量切换底层RMW实现:

# 查看当前RMW实现
printenv RMW_IMPLEMENTATION
# 切换到FastDDS实现
export RMW_IMPLEMENTATION=rmw_fastrtps_cpp
# 切换到CycloneDDS实现
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp

官方文档说明,安装并正确source新的RMWVendor后,可以在运行时选择使用哪个RMW实现。

在工业现场,这一层解耦非常重要。不同中间件在发现策略、资源占用、共享内存、网络接口选择、跨网段配置、实时性表现上存在差异。开发阶段可以使用默认实现快速验证,部署阶段可以根据网络拓扑和性能测试结果选择更适合的RMW实现。

2.3 DDS标准层:全局数据空间

DDS的核心抽象包括Domain Participant、Topic、Publisher、Subscriber、DataWriter、DataReader和QoS。可以将DDS Domain理解为一个逻辑隔离的通信空间。处于相同Domain中的参与者可以相互发现,处于不同Domain中的参与者默认相互隔离。

在DDS视角中,通信关系围绕数据展开:

DDS概念 ROS2中的近似对应 作用
GDS DDS Domain 全局数据空间
Domain Participant 节点所在进程中的DDS参与者 加入某个通信域,参与发现过程
Topic ROS2Topic 定义数据名称和类型
DataWriter Publisher底层实体 写入数据样本
DataReader Subscriber底层实体 读取数据样本
QoS ROS2QoSProfile 约束可靠性、历史队列、持久性等行为

DDS的设计重点是数据分发,不是远程过程调用。Service和Action在ROS2上层仍然存在,但底层也会映射到DDS通信实体,最终通过数据读写实现请求、响应和状态反馈。

2.4 RTPS协议层:互操作性的线协议

RTPS即Real-Time Publish-Subscribe Protocol,是DDSI-RTPS规范定义的线协议。它规定了DDS数据如何在网络中表达、传输和互操作。DDS厂商可以有不同实现,但只要遵循RTPS协议,就具备跨实现互操作基础。从工程角度看,RTPS解决了三个关键问题:

  1. 发现信息如何表达:Participant、Reader、Writer等实体如何被对端识别。
  2. 数据样本如何传输:Writer如何向匹配Reader发送CacheChange。
  3. 可靠性如何维持:心跳、ACK/NACK、重传等机制如何支持可靠传输。

OMG发布的DDSI-RTPS规范定义了DDS互操作线协议,RTPSWriter负责将HistoryCache中的变更传输给匹配的RTPSReader。

3. DDS动态发现机制

ROS2 在取消 roscore 这一中心节点后,多机系统中节点的互相寻址与连接完全依赖于底层 DDS 的自动发现机制(Discovery Protocol)。以最常用的简单发现协议(Simple Discovery)为例,整个动态发现过程通常分为两个核心阶段:PDP(参与者发现阶段)与 EDP(端点发现阶段)。

3.1 PDP参与者发现

PDP即Participant Discovery Protocol。它负责让DDS Domain中的Participant知道彼此存在。常见实现会使用UDP组播向局域网发送发现公告。参与者启动后,会周期性发送自身标识、Domain信息、地址信息和能力信息。其他参与者收到公告后,会在本地维护远端参与者记录。

CycloneDDS文档说明,SPDP 协议会定期像一组地址发送SPDP样本,默认情况下仅包含多播地址;同时也可以通过Discovery/Peers配置单播地址作为组播发现的补充或替代。

PDP解决的是“系统中有哪些参与者”的问题。此时双方只知道对端参与者存在,还不知道对端发布或订阅了哪些具体Topic。

3.2 EDP端点发现

EDP即Endpoint Discovery Protocol。让Participant各处可以交换底下有哪些端点。端点是收送数据的通讯端点,即数据读取器(DataReader)和数据写入器(DataWriter)。端点信息通常包括:

  • Topic名称。
  • Topic数据类型。
  • Publisher或Subscriber标识。
  • QoS配置。
  • 可用传输地址。
  • 可靠性、持久性、历史队列等策略。

FastDDS文档说明,EDP阶段中,DataWriter和DataReader会相互确认;DomainParticipant通过PDP阶段建立的通信通道交换DataWriter和DataReader信息。

EDP解决的是“参与者内部有哪些具体通信端点”的问题。只有Topic名称、数据类型和QoS兼容的DataWriter与DataReader才会完成匹配。

3.3 从组播发现到单播数据传输

在很多局域网场景中,组播主要用于发现。发现完成并匹配成功后,用户数据通常可以通过点对点单播路径发送。此时数据流不再依赖中心节点,也不需要所有节点都接收所有数据。这也是ROS2多机通信看似“自动”的根源:

  1. 节点加入相同ROS_DOMAIN_ID。
  2. DDS Participant通过PDP发现彼此。
  3. DataWriter和DataReader通过EDP交换端点元数据。
  4. Topic、类型和QoS兼容后建立匹配关系。
  5. RTPS按照QoS和传输配置发送用户数据。

3.4 工业网络中的发现策略取舍

Simple Discovery适合小规模局域网、研发测试环境和节点数量有限的机器人系统。随着节点数量、主机数量和Topic数量增加,发现流量与元数据交换会变得明显。工业现场还经常遇到交换机禁用组播、VLAN隔离、防火墙过滤UDP、无线链路丢包等情况。

因此工程部署时通常需要评估以下策略:

场景 建议策略
单车多进程、多传感器 默认发现通常足够,重点检查QoS和网络接口
多项目、多车辆 使用ROS_DOMAIN_ID隔离不同系统,避免发现风暴
交换机组播受限 配置CycloneDDS Peers或FastDDS Initial_Peers
大规模节点系统 评估FastDDS Discovery Server、静态发现或Zenoh路由方案
跨网段通信 明确路由、组播代理、DDSRouter或ZenohRouter方案

FastDDS文档说明,发现公告可以配置为发送到单播Initial_Peers,也可以配置公告周期;CycloneDDS也支持通过Peers配置单播发现地址。

4. QoS策略深度解析与适配匹配

ROS2将QoS暴露给应用开发者,是其相对ROS1的重要变化之一。QoS不是简单的“可靠”或“不可靠”开关,而是一组控制通信行为的策略组合。ROS2官方文档]说明,QoS策略可以将通信调到类似TCP的可靠状态,也可以调到类似UDP的尽力而为状态。下面列举一些常见 QoS。

4.1 Reliability:可靠性策略

Reliability决定发布端和订阅端如何处理丢包与重传。

策略 行为 适用场景 工程风险
RELIABLE 尽力确保数据送达,底层可能触发确认和重传 控制指令、任务状态、低频关键事件、服务调用 网络拥塞时可能增加延迟和抖动
BEST_EFFORT 尽力发送,不保证每条数据送达 LiDAR点云、相机图像、IMU高频流、临时状态可视化 丢包时应用层必须容忍数据缺口

在100Hz高分辨率LiDAR点云、多路摄像头视频流或车端调试画面中,短暂丢帧通常可以接受。强制使用RELIABLE会引入确认、重传和缓存压力,弱网环境下可能导致带宽拥塞和时延抖动。此时BEST_EFFORT更符合实时感知链路的工程目标。

控制指令、模式切换、紧急停车、任务结果等数据具有较高语义价值,丢失一条消息可能导致状态机不一致。此类链路应优先使用RELIABLE,并配合合理的Deadline、Liveliness和应用层安全机制。

4.2 Durability:持久性策略

Durability决定后加入的订阅者是否可以获取发布者已经发布过的数据。

策略 行为 典型场景
VOLATILE 只接收订阅建立之后的新数据 传感器实时流、控制闭环数据
TRANSIENT_LOCAL 发布端保留一定历史数据,后加入订阅者可获得最近样本 地图、静态配置、标定参数、路径规划初始参考

经典案例是地图Server发布静态地图。导航节点可能在地图发布后才启动。如果地图Topic使用VOLATILE,后启动节点可能无法获得已发布地图;使用TRANSIENT_LOCAL后,发布端可以为后加入订阅者提供最近缓存样本。

4.3 History与Depth:队列行为

History控制历史消息保留策略,Depth控制KEEP_LAST模式下保留多少条样本。

策略 含义 工程建议
KEEP_LAST(N) 保留最近N条消息 ROS2最常用配置,适合资源可控系统
KEEP_ALL 尽量保留全部消息 谨慎使用,需要配合资源限制,避免内存膨胀

Depth并非越大越好。对于高频传感器,如果订阅端处理能力不足,过大的队列会让应用处理过期数据,造成感知结果滞后。对于控制闭环,通常更关注最新状态,Depth可以较小。对于离线记录、低频状态、调试信息,可以适当增加Depth以减少偶发处理延迟带来的数据丢失。

4.4 Deadline:截止时间策略

Deadline用于描述一个Topic在时间维度上的“更新周期契约”。它不是传输层重传策略,也不是实时调度器,而是告诉DDS/RMW:这个Topic理论上应该在多长时间内至少更新一次。对于Publisher来说,Deadline表示两次连续发布之间允许的最大时间间隔;对于Subscriber来说,Deadline表示两次连续接收之间允许的最大时间间隔。

关注点 说明
核心含义 期望Topic按固定或近似固定周期更新
触发条件 超过指定时间没有发布或接收新样本
典型事件 offered deadline missed、requested deadline missed
适用数据 控制周期、底盘状态、定位状态、心跳状态、关键传感器健康状态
不适合误用 不应把Deadline当成“保证准时到达”的实时性承诺

在自动驾驶系统和工业机器人中,Deadline更适合用来做“通信健康监控”。例如底盘状态Topic设计为50Hz更新,理论周期为20ms,可以设置一个略宽松的Deadline,例如40ms或50ms。一旦连续超过该时间窗口没有收到状态,订阅端就可以认为底盘状态链路异常,触发降级、报警或安全停车逻辑。

Deadline的兼容性也需要注意:Subscriber请求的Deadline不能比Publisher提供的能力更严格。更直观地说,如果Publisher承诺最多20ms更新一次,而Subscriber只要求50ms内收到一次,这是兼容的;如果Publisher只能承诺100ms更新一次,而Subscriber要求20ms内必须收到一次,则QoS不兼容。

Deadline要根据真实发布频率、网络抖动、Executor调度延迟和系统负载留出余量。设置过严会导致误报,设置过宽则失去健康监控意义。

4.5 Liveliness:存活性策略

Liveliness用于判断发布实体是否仍然“活着”。它解决的问题不是“数据有没有按周期更新”,而是“发布者是否还存在,是否还具备继续发布的能力”。这在分布式机器人系统中非常重要,因为节点崩溃、进程卡死、网络断开、主备控制器切换,都可能导致系统表面Topic还存在,但实际数据链路已经不可用。

策略 行为 工程含义
AUTOMATIC 由底层RMW/DDS自动维护存活状态 使用简单,适合大多数普通Topic
MANUAL_BY_TOPIC 应用层需要通过发布数据或显式assert liveliness声明该Topic仍然存活 适合关键控制、主备冗余、需要检测应用逻辑卡死的场景
Lease Duration 允许发布者多久不声明存活,超过后认为失活 相当于存活租约或心跳超时时间

Deadline与Liveliness的区别很关键:Deadline关注的是“数据是否按预期周期到达”,Liveliness关注的是“发布者是否还活着”。一个低频事件Topic可能很长时间没有新数据,但发布者仍然存活;反过来,一个周期Topic如果发布者卡死,既可能Deadline Missed,也可能Liveliness Lost。

在自动驾驶和工业控制中,Liveliness常用于关键节点健康判断。例如主控制节点、制动控制节点、状态机节点可以设置较短的Lease Duration。订阅端一旦发现Liveliness丢失,不应继续使用旧控制状态,而应进入安全策略,例如保持、降级、急停或切换备用控制链路。

普通传感器流一般不需要过度配置Liveliness,使用默认AUTOMATIC即可;关键控制链路和主备冗余链路可以考虑MANUAL_BY_TOPIC,但必须保证应用层有稳定的assert逻辑,否则容易出现误判。

4.6 Lifespan:消息寿命策略

Lifespan用于规定一条消息从发布开始,在多长时间内仍然有效。超过该时间后,消息会被认为是过期数据,不应再被交付给订阅端,也不应继续停留在历史缓存中。它的核心价值是避免系统处理“迟到但已经失去意义”的旧数据。

关注点 说明
核心含义 限制消息有效期,防止过期样本被使用
典型对象 图像帧、点云帧、障碍物列表、临时规划结果、短时状态估计
适合场景 高实时性链路、弱网环境、存在缓存或重传的链路
主要风险 时间设置过短会导致消息还未处理就过期,设置过长则可能引入陈旧数据

例如相机图像、LiDAR点云、感知障碍物列表这类数据具有明显时效性。对于高速移动平台,500ms前的障碍物位置可能已经不再可靠。如果系统在网络拥塞或订阅端阻塞后继续处理旧数据,反而会造成错误决策。此时可以通过Lifespan限制消息有效期,让过期数据在进入业务逻辑前被丢弃。

Lifespan和Reliability之间存在一个常见取舍:RELIABLE会尽力重传丢失样本,但如果样本已经超过Lifespan,即使最终重传成功,也不应该再被使用。因此,对强实时数据来说,RELIABLE并不总是更好;需要结合Lifespan、Deadline和业务容忍度综合判断。

传感器数据的Lifespan应略大于正常链路延迟和处理延迟,但小于业务上可接受的最大数据年龄。例如感知链路可以按100ms、200ms、500ms等等级设计,而不是盲目使用无限有效期。

4.7 Ownership:所有权策略

Ownership是DDS层面的QoS策略,用于处理“多个DataWriter同时向同一个Topic实例写数据时,DataReader应该接受谁的数据”。它在ROS2常规应用层接口中不像Reliability、Durability、Deadline那样常被直接配置,很多项目需要通过具体DDS厂商的XML配置或底层能力支持,因此写Ownership更偏DDS高级策略,不是所有RMW实现或ROS2使用方式都适合直接依赖。

策略 行为 典型场景
SHARED 多个Writer的数据都可以被Reader接收 多个节点共同上报告警、日志、观测信息
EXCLUSIVE 同一实例同一时刻只接受一个Owner的数据 主备冗余控制、热备系统、唯一指令源选择
Ownership Strength EXCLUSIVE模式下用于决定哪个Writer是Owner 主控制器强度高,备用控制器强度低

在自动驾驶系统中,Ownership最典型的价值是主备冗余。例如主从机都能发布同一个控制Topic,但系统希望正常情况下只接受主机数据;当主机失活或错过Deadline时,从机自动接管。DDS可以通过EXCLUSIVE Ownership和Ownership Strength实现这种“谁拥有当前Topic实例控制权”的选择。

但是,在自动驾驶中不建议把关键仲裁逻辑完全隐藏在DDS Ownership里。因为ROS2消息通常不是按业务对象精细Keyed建模,很多Topic在DDS视角下可能只有一个实例;同时不同RMW实现、XML配置、调试工具对Ownership的支持和可见性也不完全一致。对于自动驾驶这种安全系数较高的场景,更稳妥的做法通常是:DDS Ownership作为底层冗余能力之一,应用层仍然保留显式的主从状态机、控制权仲裁、日志记录和安全校验。

Ownership还与Liveliness、Deadline有关。EXCLUSIVE模式下,当前Owner如果失去Liveliness,或者违反Deadline,系统可能切换到其他具备更高或可用Ownership Strength的Writer。因此,Ownership不应孤立理解,而应放在“冗余发布者 + 存活检测 + 周期契约 + 应用层安全策略”的组合中设计。

普通ROS2话题默认不需要考虑Ownership;只有在多发布者冗余、主备控制、热切换、唯一数据源选择等场景下,才值得深入评估DDS Ownership。使用前必须确认当前RMW/DDS实现是否支持、配置方式是否可控、故障切换行为是否可测试。

4.8 QoS兼容性原则:请求与提供模型

ROS2 QoS匹配遵循Request/Offered模型。Publisher提供某种服务质量,Subscriber请求某种最低服务质量。只有Publisher提供能力满足Subscriber请求时,通信才能建立。官方文档指出,兼容性由请求端与提供端策略决定;对于Reliability和Durability等策略,不兼容会导致两端即使在线也无法通信。

常见误区如下:

Publisher Subscriber 是否匹配 说明
BEST_EFFORT BEST_EFFORT 匹配 订阅端接受尽力而为
RELIABLE BEST_EFFORT 匹配 发布端能力更强,订阅端要求较低
BEST_EFFORT RELIABLE 不匹配 订阅端要求可靠,发布端无法提供
VOLATILE VOLATILE 匹配 双方只处理新数据
TRANSIENT_LOCAL VOLATILE 匹配 发布端保留历史,但订阅端不强制要求
VOLATILE TRANSIENT_LOCAL 不匹配 订阅端要求历史数据,发布端无法提供

对于时间与存活策略,也要遵循同样的“请求不能高于提供”原则:

策略 兼容性关注点 说明
Deadline Publisher提供的更新周期能力要满足Subscriber请求 可理解为offered deadline period <= requested deadline period
Liveliness Subscriber要求的存活声明粒度和租约不能比Publisher能提供的更严格 Lease Duration过短容易造成误判
Lifespan 更多体现为样本有效期控制,通常不是最常见的匹配失败原因 重点防止过期数据进入业务逻辑
Ownership SHARED/EXCLUSIVE类型需要一致 主要在DDS高级冗余场景中关注

“节点能看到,Topic也能看到,但收不到消息”经常由QoS不兼容引起。排查时优先使用以下命令查看实际QoS:

ros2 topic info /camera/image_raw --verbose
ros2 topic info /points_raw --verbose
ros2 topic echo /map --qos-durability transient_local

4.9 典型数据链路QoS建议

数据类型 Reliability Durability History/Depth 说明
相机图像 BEST_EFFORT VOLATILE KEEP_LAST(1~5) 保持实时性,容忍丢帧
LiDAR点云 BEST_EFFORT VOLATILE KEEP_LAST(1~5) 避免重传造成拥塞
IMU BEST_EFFORT或RELIABLE VOLATILE KEEP_LAST(10~50) 根据频率和丢包容忍度选择
控制指令 RELIABLE VOLATILE KEEP_LAST(1~10) 语义关键,需降低丢失概率
车辆状态 RELIABLE或BEST_EFFORT VOLATILE KEEP_LAST(5~20) 低频关键状态可可靠,高频状态可尽力
静态地图 RELIABLE TRANSIENT_LOCAL KEEP_LAST(1) 支持后启动节点获取地图
参数/配置 RELIABLE TRANSIENT_LOCAL KEEP_LAST(1~10) 强调一致性与后加入可用性
调试可视化 BEST_EFFORT VOLATILE KEEP_LAST(1~5) 优先减少系统扰动

5. ROS2多机通信配置

5.1 基础条件检查

ROS2多机通信首先应满足以下条件:

检查项 要求
网络连通性 多台机器位于可达网络中,IP层可以互通
ROS_DOMAIN_ID 需要通信的节点使用相同Domain ID
RMW实现 推荐同一系统内先使用相同RMW实现降低变量
Topic类型 Publisher与Subscriber消息类型一致
QoS策略 Subscriber请求不能超过Publisher提供能力
防火墙 放行DDS发现和数据传输所需UDP流量
组播 Simple Discovery依赖组播时,交换机与系统需允许组播

官方文档说明,ROS2节点默认使用Domain ID 0;为了避免同一网络中不同计算机组互相干扰,应为不同系统设置不同Domain ID。

# 机器A与机器B使用同一DomainID
export ROS_DOMAIN_ID=10
# 建议写入shell配置,避免重启终端后丢失
echo 'export ROS_DOMAIN_ID=10' >> ~/.bashrc
source ~/.bashrc

5.2 RMW实现切换

不同ROS2发行版默认RMW实现可能存在差异,工程项目中应显式记录部署所用RMW实现。

# 查看当前RMW
printenv RMW_IMPLEMENTATION
# 临时切换到FastDDS
export RMW_IMPLEMENTATION=rmw_fastrtps_cpp
# 临时切换到CycloneDDS
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
# 运行测试节点
ros2 run demo_nodes_cpp talker
ros2 run demo_nodes_cpp listener

建议在项目部署文档中固定以下信息:

export ROS_DOMAIN_ID=23
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
source /opt/ros/humble/setup.bash
source ~/ros2_ws/install/setup.bash

RMW切换后,应重新打开终端或重新source环境,确保所有节点使用一致配置。混合RMW并非一定不能通信,但会引入互操作、默认QoS、发现策略和厂商配置差异,现场排障成本更高。

5.3 组播连通性测试

ROS2提供ros2multicast命令用于测试两端之间UDP组播数据是否可达。官方文档给出的基本用法是在一台机器运行receive,在另一台机器运行send,成功时接收端会输出“HelloWorld!”。

机器A:

ros2 multicast receive

机器B:

ros2 multicast send

如果接收端没有输出,可以检查:

  1. 两台机器是否在同一局域网或组播可达网络中。
  2. 防火墙是否阻止UDP组播。
  3. 交换机是否启用IGMPSnooping且缺少Querier配置。
  4. Wi-FiAP是否隔离客户端或禁用组播转发。
  5. Docker、虚拟机、WSL或容器网络是否阻断组播。

5.4 Topic与QoS排查命令

# 查看Topic列表
ros2 topic list
# 查看Topic发布/订阅端与QoS
ros2 topic info /points_raw -v
# 尝试订阅数据
ros2 topic echo /points_raw
# 指定QoS可靠性订阅
ros2 topic echo /points_raw --qos-reliability best_effort
# 对TRANSIENT_LOCAL地图进行订阅
ros2 topic echo /map --qos-durability transient_local

排查时可以按以下顺序推进:

IP互通 -> ROS_DOMAIN_ID一致 -> RMW一致 -> 组播可达 -> Topic存在 -> 类型一致 -> QoS兼容 -> 应用回调执行 -> CPU/带宽/队列瓶颈

5.5 网络抓包观察RTPS

当命令层面无法解释问题时,可以用tcpdump或Wireshark观察RTPS报文。RTPS常见于UDP传输,端口会受Domain ID、Participant ID和DDS实现配置影响。抓包时不建议只盯固定端口,建议先观察主机间UDP流量,再结合Wireshark的RTPS解析器过滤。

# 抓取某个网卡上的UDP报文
sudo tcpdump -i eth0 udp -w ros2_rtps.pcap
# 限定目标主机,降低抓包噪声
sudo tcpdump -i eth0 host 192.168.1.20 and udp -w ros2_between_hosts.pcap

Wireshark中可以尝试使用以下过滤条件:

rtps
udp
ip.addr == 192.168.1.20

观察重点:

报文现象 可能原因
只有SPDP,没有SEDP Participant发现成功,端点交换异常或被过滤
有发现报文,无用户数据 Topic、类型或QoS不匹配
有大量ACK/NACK RELIABLE链路丢包或订阅端处理不过来
报文只出不进 防火墙、路由、VLAN或组播转发问题
数据突发延迟 队列过深、重传积压、CPU或带宽瓶颈

5.6 容器与多网卡场景

工业部署经常将ROS2节点运行在Docker容器中,也经常存在多网卡:车载以太网、调试网口、5G路由、Wi-Fi、虚拟网桥同时存在。DDS自动选择网络接口时可能选错出口,导致节点在本机正常、多机异常。使用策略:

# Docker中优先使用host网络进行ROS2多机通信验证
docker run --rm -it --net=host ros:humble

对于CycloneDDS,可通过配置文件约束网络接口和Peer;对于FastDDS,可通过XML配置InitialPeers、接口白名单、Discovery Server等能力。正式项目应将DDS配置纳入版本管理,避免现场通过临时环境变量逐台修改。

示例:CycloneDDS单播Peer配置思路。

<CycloneDDS>
  <Domain>
    <General>
      <Interfaces>
        <NetworkInterface name="eth0"/>
      </Interfaces>
    </General>
    <Discovery>
      <Peers>
        <Peer Address="192.168.1.10"/>
        <Peer Address="192.168.1.20"/>
      </Peers>
    </Discovery>
  </Domain>
</CycloneDDS>
export CYCLONEDDS_URI=file:///home/robot/cyclonedds.xml

该配置适用于组播不可用但主机IP固定的场景。对于动态IP或大规模部署,应结合服务发现服务器、路由器或上层编排系统进行治理。

6.常见故障与定位路径

6.1 两台机器互相ping通,但ros2 topic list看不到对方Topic

优先检查:

echo $ROS_DOMAIN_ID
echo $RMW_IMPLEMENTATION
ros2 multicast receive
ros2 multicast send

排查思路:

  1. 保证两端ROS_DOMAIN_ID一致。
  2. 暂时关闭防火墙验证问题边界。
  3. 使用有线网络替代Wi-Fi进行对比测试。
  4. Docker环境使用–net=host复现。
  5. 组播不可用时配置CycloneDDSPeers或FastDDSInitialPeers。

6.2 Topic可见,但echo没有数据

优先检查:

ros2 topic info /topic_name --verbose
ros2 interface show your_msgs/msg/Type

可能原因:

原因 说明
QoS不兼容 最常见,尤其是BEST_EFFORT Publisher与RELIABLE Subscriber
类型不一致 Topic名称相同但消息类型不同
命名空间混乱 Launch文件或remap导致实际Topic不同
发布频率过低 echo期间没有新数据产生
TRANSIENT_LOCAL误用 后加入节点没有按持久性策略订阅

6.3 高频点云或图像导致系统卡顿

定位路径:

ros2 topic hz /points_raw
ros2 topic bw /points_raw
top
htop
nload
iftop

调整思路:

  • 将传感器流QoS从RELIABLE调整为BEST_EFFORT。
  • 减小Depth,避免订阅端处理过期数据。
  • 对图像使用压缩传输或硬件编码链路。
  • 点云进行下采样、ROI裁剪或分通道发布。
  • 记录rosbag时单独评估磁盘写入带宽。
  • 将调试可视化链路与控制链路隔离。

6.4 部分机器可以通信,部分机器不可以

多机系统中应绘制网络矩阵:

源机器 目标机器 ping multicast topic 数据
A B 通过 通过 可见 正常
A C 通过 失败 不可见
B C 通过 失败 不可见

通过这种表格可以快速判断问题位于系统配置、交换机策略、VLAN边界、防火墙或RMW配置层。

7.自动驾驶通信设计思路

7.1 按数据语义划分通信等级

自动驾驶系统中,所有Topic不应套用同一套QoS模板。可以按数据语义分级:

等级 数据 目标 QoS倾向
A级 制动、急停、模式切换、任务状态 降低丢失概率与状态不一致 RELIABLE、较小Depth、应用层确认
B级 定位、车辆状态、规划轨迹 保持连续性和较低延迟 RELIABLE或BEST_EFFORT视频率选择
C级 相机、点云、雷达、调试图像 保持实时性,容忍局部丢帧 BEST_EFFORT、VOLATILE、小Depth
D级 地图、配置、标定、静态信息 后启动节点可恢复状态 RELIABLE、TRANSIENT_LOCAL

7.2 发现平面与数据平面分开治理

DDS通信可以分为发现平面和数据平面。发现平面负责节点、端点和QoS元数据交换;数据平面负责用户消息传输。多机系统常见问题来自二者混淆:发现成功不代表数据可达,Topic可见不代表QoS匹配,组播正常不代表单播数据链路无瓶颈。

在调试项目文档中可分别记录:

  • 发现策略:SimpleDiscovery、StaticDiscovery、DiscoveryServer、Peers、DomainID。
  • 数据链路:Topic频率、消息大小、QoS、网络接口、带宽预算。
  • 故障边界:发现失败、匹配失败、传输失败、应用处理失败。

7.3 现场部署通信调试

部署自动驾驶时使用以下通信基线测试:

# 1.基础发现
ros2 multicast receive
ros2 multicast send
# 2.低频可靠Topic
ros2 run demo_nodes_cpp talker
ros2 run demo_nodes_cpp listener
# 3.高频压力Topic
ros2 topic hz /camera/image_raw
ros2 topic bw /camera/image_raw
# 4.QoS核查
ros2 topic info /camera/image_raw --verbose
ros2 topic info /map --verbose
# 5.抓包留证
sudo tcpdump -i eth0 udp -w baseline_rtps.pcap

通信基线应随软件版本、RMW版本、DDS配置和网络拓扑一起归档。现场问题复现时,先对比基线,再修改配置。

ROS2通信架构的本质,是将系统从中心化命名与连接管理,推进到分布式数据空间与可配置通信质量模型。DDS为ROS2提供了自动发现、发布订阅、QoS、可靠传输、历史数据保留和多厂商实现基础;RMW层则让ROS2应用代码与底层中间件解耦,使工程项目可以在FastDDS、CycloneDDS、ConnextDDS、GurumDDS以及Zenoh等实现之间进行选择。

这种架构也带来了新的工程复杂度。ROS2多机通信问题经常发生在Domain ID、组播、防火墙、多网卡、Docker网络、QoS匹配和RMW默认行为之间。现场调试时可以按照分层排查思路:先验证IP与组播,再检查Domain与RMW,再确认Topic、类型与QoS,最后通过抓包、带宽和CPU监控定位性能瓶颈。

ROS2通信生态正在从单一DDS视角向更灵活的路由化、跨网段、云边协同方向发展。Zenoh、DDSRouter、DiscoveryServer、静态发现和共享内存传输等能力,会在自动驾驶车队、大规模机器人、工厂移动机器人和边缘计算系统中承担更重要角色。


文章作者: LSJune
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 LSJune !
评论
  目录