3. uXRCE-DDS核心原理
在 PX4 与 ROS 2 的通信链路中,uXRCE-DDS 并不是“把 DDS 直接塞进飞控”,而是把 DDS 的完整能力保留在性能更强的机载计算机侧,在飞控侧只保留一个轻量客户端。理解这一点的关键,是同时看清四件事:DDS-XRCE 协议如何压缩通信开销、客户端与代理如何分工、主题发布订阅如何映射到 PX4 uORB、QoS 如何决定消息的可靠性与时效性。
一、DDS-XRCE:为资源受限设备设计的 DDS 接入协议
标准 DDS 使用 RTPS 作为线上协议,依赖多播发现、较重的参与者状态和较完整的类型系统,对 STM32 这类 MCU 而言负担偏大。DDS-XRCE(DDS for Extremely Resource Constrained Environments)把角色拆成两端:XRCE Client 运行在资源受限设备上,XRCE Agent 运行在资源充足的设备上。客户端不参与 DDS 全局发现,也不直接与其它 DDS 节点建立 RTPS 连接,而是通过一条会话(Session)把“创建实体、注册类型、读写数据”等操作委托给代理。
协议栈自下而上可概括为:传输层(串口/UDP/TCP)→ XRCE 消息层(CREATE、DELETE、WRITE_DATA、READ_DATA、STATUS 等子消息)→ 对象层(Participant、Topic、Publisher、Subscriber、DataWriter、DataReader)→ DDS 类型系统。客户端与代理之间用 Client Key 与 Session Id 标识会话,用 Stream 区分可靠流与尽力而为流。这样,飞控侧只需维护少量对象句柄和紧凑的二进制消息,而代理侧负责把这些对象“翻译”成标准 DDS 实体,接入 ROS 2 的 DDS 域。
二、客户端—代理架构:谁负责什么
很多初学者误以为“飞控里跑了一个 DDS 节点”。实际上,飞控里运行的是 uxrce_dds_client 模块,它只做三件事:把 uORB 主题注册为 XRCE 对象、按配置周期把数据写入对应 DataWriter、按需从 DataReader 读取订阅数据。真正的 DDS 发现、类型匹配、QoS 协商、与其它 ROS 2 节点的互操作,全部由机载计算机上的 Agent 完成。
- Client 侧:资源占用小,无多播发现,依赖 Agent 分配的对象 ID;断链后需要重新建会话。
- Agent 侧:维护 DDS Participant,把 XRCE 对象映射为 DDS Topic 与 DataWriter/DataReader,参与 ROS 2 图发现。
- 传输侧:串口适合飞控直连,UDP 适合机载计算机内部通信,TCP 提供可靠字节流但增加延迟抖动。
三、主题发布订阅模型:uORB 与 ROS 2 主题的映射
PX4 内部使用 uORB 发布订阅,ROS 2 使用 DDS 主题发布订阅。uXRCE-DDS 的桥接规则是:一个 uORB 主题对应一个 ROS 2 主题,消息类型由 PX4 的 .msg 生成对应的 IDL。例如 vehicle_attitude 映射为 /fmu/out/vehicle_attitude,vehicle_command 映射为 /fmu/in/vehicle_command。方向由主题名中的 out 与 in 区分:out 表示 PX4 发布、ROS 2 订阅;in 表示 ROS 2 发布、PX4 订阅。
# 查看当前桥接的主题与频率
uxrce_dds_client status
# 典型输出片段
INFO [uxrce_dds_client] topic: /fmu/out/vehicle_attitude, rate: 100 Hz
INFO [uxrce_dds_client] topic: /fmu/in/vehicle_command, rate: on demand
发布订阅模型的关键在于“解耦”:发布者不需要知道订阅者是谁,代理负责把数据放到 DDS 全局数据空间中。这也意味着,如果 ROS 2 侧没有匹配的订阅者,数据仍然会被写入,但可能因 QoS 不匹配而被丢弃或阻塞。
四、QoS 策略:可靠性与时效性的取舍
QoS 是 uXRCE-DDS 通信中最容易被忽视、却最容易导致“收不到数据”的环节。PX4 默认对高频传感器主题使用 BEST_EFFORT,对命令类主题使用 RELIABLE。如果 ROS 2 订阅者请求 RELIABLE,而发布者只提供 BEST_EFFORT,DDS 的 QoS 兼容性检查会失败,订阅者将收不到任何消息。
| QoS 策略 | 常用取值 | 对通信的影响 | 典型主题 |
|---|---|---|---|
| Reliability | BEST_EFFORT / RELIABLE | 决定是否重传,影响延迟与带宽 | sensor_combined / vehicle_command |
| Durability | VOLATILE / TRANSIENT_LOCAL | 决定晚加入的订阅者能否收到历史数据 | 参数、配置类主题 |
| History | KEEP_LAST / KEEP_ALL | 决定缓存深度与内存占用 | 高频姿态、位置 |
| Depth | 1 ~ 10 | 队列长度,过小会丢帧,过大增加延迟 | vehicle_attitude |
| Deadline | 周期值 | 超时触发回调,用于健康监测 | 心跳、状态主题 |
五、一次完整通信流程
- 飞控启动
uxrce_dds_client,通过串口/UDP 向 Agent 发起会话创建请求。 - Agent 返回会话确认,并为客户端分配 Client Key 与 Session Id。
- Client 发送
CREATE子消息,注册 Participant、Topic、DataWriter/DataReader。 - Agent 在 DDS 域中创建对应实体,完成类型注册与 QoS 匹配。
- PX4 周期发布 uORB 数据,Client 将其封装为
WRITE_DATA发送给 Agent。 - Agent 通过 DDS 将数据分发给 ROS 2 订阅者;反向订阅则通过
READ_DATA回传。 - 链路中断时,Client 检测心跳超时并重建会话,期间数据可能丢失。
ros2 topic list 确认主题是否存在,再用 ros2 topic hz 观察频率,最后用 ros2 topic echo 检查内容。若主题存在但无数据,优先排查 QoS 兼容性与 Agent 是否正常运行。
六、常见误区与复盘
误区二:忽略 QoS 兼容性。订阅者请求 RELIABLE 而发布者只有 BEST_EFFORT 时,DDS 会静默不匹配。
误区三:把串口波特率设得过低。高频主题(如 100 Hz 姿态)在低波特率下会拥塞,表现为数据延迟或丢失。
误区四:认为主题名可以随意改。PX4 的桥接主题名由编译配置决定,ROS 2 侧必须使用
/fmu/out/ 与 /fmu/in/ 前缀。
复盘时建议按“链路分层”排查:先确认物理传输是否通,再确认 XRCE 会话是否建立,然后确认对象是否创建成功,最后检查 DDS QoS 是否匹配。把每一层的状态都看清楚,uXRCE-DDS 的通信问题就不再是黑盒。