1. 为什么 MicoAir H743 要配 uXRCE-DDS
1.1 这块板子是什么来头
MicoAir H743 是国产飞控里性价比相当能打的一块板子,主控用 STM32H743,主频跑到 480MHz,相比上一代 F765 那类芯片,算力余量大了不少。接口方面该有的都有:UART 串口、CAN、I2C、SBUS 输入、PPM 输入、多个 PWM 输出通道,IMU 一般是 BMI088 加 ICM20602 的组合,支持双冗余。板子本身兼容 PX4 和 ArduPilot 双生态,因为我主要跑 PX4,所以这篇笔记里所有内容都是基于 PX4 固件来写的。
如果你手里是一台六旋翼或者四旋翼的机器,想在机载电脑上用 ROS 2 直接订阅飞控的姿态、位置、IMU 数据,而不是像传统玩法那样用 Mission Planner 或 QGroundControl 去读 MAVLink 报文,那 uXRCE-DDS 就是绕不开的一环。说白了,它解决的是“飞控怎么把内部消息以 DDS 协议的方式吐给 ROS 2”这个事。
1.2 传统 MAVLink 和 DDS 到底差在哪
先聊一个基础问题,为什么不用 MAVLink 非得折腾 DDS。MAVLink 是个轻量级串行协议,设计哲学就是省带宽、结构简单、适合在 PX4 和地面站之间传控制指令和遥测数据。它的问题也很明显:消息类型是固定的,主题(topic)的概念很弱,自定义数据要手动扩展消息定义,跟 ROS 2 那种真正的发布订阅模型对不上。
DDS 是数据分发服务,本质上是分布式系统里的消息总线。ROS 2 从底层就构建在 DDS 之上,所以最理想的方式是让飞控直接以 DDS 节点的身份出现在 ROS 2 网络里。但飞控上跑的是嵌入式 RTOS,资源有限,没法直接挂一个完整的 DDS 实现,所以 PX4 做了一个折中方案:飞控上跑一个轻量级客户端,机载电脑上跑一个代理,客户端和代理之间通过串口或者 UDP 传输消息,代理再以真正的 DDS 节点身份加入 ROS 2 网络。这就是 uXRCE-DDS 的由来。
1.3 什么人需要这篇配置笔记
我写这篇笔记的定位很明确:给那些已经能飞、正准备上手机载电脑和 ROS 2 的人。你可能已经用 Mission Planner 发过 MAVLink 指令给飞控,也大概知道 PX4 的 offboard 模式怎么切,但对 DDS 这套东西还有点懵。这篇笔记不涉及视觉算法和路径规划的高层设计,专注把 uXRCE-DDS 客户端配置这条链路彻底打通。
配置过程中我踩过不少坑,比如串口波特率不匹配导致客户端反复重启、代理版本和固件版本对不上导致主题没数据、甚至还有因为接线方向搞反导致完全没输出的情况。这些我都会在后面单独开一节讲。
2. 先搞懂 uXRCE-DDS 的工作方式
2.1 客户端和代理的角色划分
uXRCE-DDS 其实是 Micro XRCE-DDS 的缩写,核心思想是把一个完整 DDS 节点拆成两个部分。
飞控这边跑的是 Micro XRCE-DDS Client,它只负责和代理建立连接、收发序列化后的消息。注意,客户端本身不参与课题发现(discovery)、不管理 QoS 策略,这些重活全部甩给代理。代理(Agent)运行在机载电脑上,通常是 Linux 环境,它把客户端串口传过来的二进制数据翻译成标准 DDS 消息,然后以真实 DDS 节点的身份出现在 ROS 2 网络中。
这样拆的好处非常明显:飞控端的资源占用被压到最低,CPU 只要处理串口收发和消息序列化就行。而代理端有完整的 DDS 协议栈,可以做 QoS 匹配、主题注册、类型信息交换这些复杂操作。对飞控这种资源受限的嵌入式设备来说,这是目前兼顾性能和资源消耗的最佳方案。
2.2 传输方式选串口还是 UDP
uXRCE-DDS 的物理传输层支持串口、UDP 和 TCP。我在 MicoAir H743 上主要用串口方式,因为串口连接稳定,不存在局域网延迟抖动问题,而且飞行中机载电脑和飞控之间本来就要用杜邦线或者排线连,顺手就把 DDS 通道放在同一根物理链路上。
UDP 方式适合机载电脑和飞控通过有线以太网连接的情况,但 MicoAir H743 板载没有以太网口,需要额外转接,实际用的人不多。TCP 理论上更可靠但实时性比 UDP 差,实时控制系统里通常不推荐。
我当时的选型逻辑很简单:既然是机载场景,板子和电脑挨得近,串口是最不容易出问题的选择。如果你后续做室内集群之类的应用,飞控和电脑隔得远,再考虑 UDP 也来得及。
2.3 几个关键参数先记下来
配置 uXRCE-DDS 时,最核心的 PX4 参数是 UXRCE_DDS_CFG,它决定客户端跑在哪个串口上。MicoAir H743 上常见的选项有 TELEM1、TELEM2、UART6、UART7 这些,我最后用 TELEM2。另外还有两个配套参数:SER_TEL2_BAUD 控制串口波特率,目前 PX4 官方推荐 921600;老版本固件还有一个 UXRCE_DDS_PTCFG 用于选择物理传输类型,新版本里这个参数被移到了编译层面,后面细说。
这里要特别强调一点:波特率必须和 MicroXRCEAgent 启动命令里的 -b 参数完全一致,两个地方哪怕差一个零,都会导致客户端连接失败。我见过太多人在这里翻车。
2.4 时间同步比你想的重要
uXRCE-DDS 的 Time Synchronization 机制容易被忽略,但实际影响非常大。飞控端和代理端各自维护自己的时间基准,如果不同步,ROS 2 里收到的消息时间戳是漂移的,做数据融合、延时补偿时会出现莫名其妙的偏差。
PX4 的实现是基于 timesync 请求应答机制,客户端定期发时间同步请求,代理应答后客户端校正本地时间偏移。这个机制默认开启,你不用手动配置,但如果发现 ROS 2 消息头里的 stamp 和系统时间对不上,先检查串口波特率是否稳定,再考虑是不是代理版本太老导致同步协议实现有 bug。
3. 固件准备和烧录实操
3.1 编译固件前必须确认的版本问题
PX4 从 v1.14 开始正式支持 uXRCE-DDS,如果你的固件还是 1.13 或者更早版本,那用的是老旧的 micrortps 方案,配置方式完全不同。我建议直接用最新稳定版固件,我自己当前用的是 v1.15 分支。
编译 MicoAir H743 的固件时,需要先确认源码里有没有对应的板级配置。MicoAir 团队一般会维护自己的 PX4 分支,如果没有,可以用兼容的通用目标板替代,但代价是个别板载外设可能无法正确初始化。最稳妥的方式是去 MicoAir 的官方仓库拉代码,然后用它自带的构建脚本编译。
编译命令通常长这样:
make micoair_h743_default upload如果源码里没有这个目标名,可以先执行 make list_config_targets 查一下,或者去 boards 目录下找找 MicoAir 相关的文件夹。
3.2 两种烧录方式实测对比
烧录 PX4 固件到 MicoAir H743,我试过两种方式。
第一种是 QGroundControl 的固件刷写功能。用 USB 线把飞控连到电脑,QGC 识别后选择本地固件文件,点刷写就行。这种方式最简单,适合不想折腾命令行的朋友,但有个前提:你需要先把编译好的 .px4 固件文件准备好。
第二种是命令行烧录,在编译命令后面直接加上传参数,比如上面的 make ... upload。这种方式的好处是编译完自动烧录,不用手动选文件,而且可以通过串口日志实时看烧录进度。我第一次烧的时候因为 USB 驱动没装好,折腾了半天,后来在 Linux 下用命令行一次就成功了。
烧录完成后,连接 QGC 或者 Mission Planner 验证固件版本号,确认目标板信息正确。不要急着配置 uXRCE-DDS,先确认飞控本身跑起来没问题,否则后面排查问题会非常痛苦。
3.3 老版本固件和新版本固件在配置上的差异
如果你因为某些原因只能停留在 PX4 v1.13,那配置方式就不一样了。v1.13 用的是 micrortps 桥接方案,需要在编译固件前修改 fmu.yaml 文件,定义哪些 uORB 主题要被桥接到 DDS 里,然后重新编译固件,再启动一个 micrortps_agent 可执行文件。
这个方法其实也不复杂,但有一个致命问题:fmu.yaml 里配置的主题必须和机载电脑端 ROS 2 的消息类型严格对应,改错一个字段,整个桥接可能就废了。uXRCE-DDS 方案则不需要手动维护主题列表,客户端启动后自动注册飞控上所有 uORB 主题,省去了大量潜在出错点。
所以如果你是刚入门,我强烈建议直接用支持 uXRCE-DDS 的新版本固件,别在旧方案上浪费时间。
4. 客户端配置逐步操作
4.1 硬件接线和串口选型
接线是整个配置过程里最容易出问题的一环。MicoAir H743 的 TELEM2 串口通常是六针或者四针排针,包含电源、地、TX、RX 等。连接机载电脑时,一定要做交叉连接:飞控的 TX 接电脑串口模块的 RX,飞控的 RX 接电脑串口模块的 TX,电源和地直接连通。
我一开始想当然地直连 TX 到 TX,结果一点数据都没有,后来用示波器量了才发现问题。哪怕你用的是 USB 转 TTL 模块,也要确认模块的逻辑电平是 3.3V,H743 的 IO 不是 5V 耐受的,接 5V 电平可能直接烧串口引脚。
如果你手头是一块 USB 转串口芯片做的调试模块,比如 CP2102 或者 CH340,先确认 VCC 跳线帽在 3.3V 档位,再接线。接反了轻则无数据,重则硬件损坏。
4.2 PX4 参数配置的具体步骤
接线完成后,先用 USB 把飞控连到 QGC,进入参数设置界面,搜索并修改以下几个参数:
- UXRCE_DDS_CFG:选择 TELEM2
- SER_TEL2_BAUD:设置为 921600
- SYS_USB_AUTO:保持默认即可,这个不影响串口配置
参数设置完成后需要重启飞控才能生效。重启后如果参数保持住,说明写入成功了。这里有个小细节:很多国产飞控默认会把 TELEM2 用作 MAVLink 遥测输出,所以你在配置完 DDS 后,TELEM2 上不会再出 MAVLink 数据,Mission Planner 连这个口会失败。这是正常现象,不是板子坏了。
如果你还需要同时用地面站,建议要么走 USB 连接,要么把地面站接到 TELEM1 或另一个独立串口。
重启后,在 QGC 的 MAVLink Console 里输入以下命令确认客户端状态:
uxrce_dds_client status正常情况下会输出客户端的开启状态和当前配置的传输方式。如果提示 not running,说明参数没生效或者固件版本不支持。
4.3 启动 MicroXRCEAgent
机载电脑这一侧的代理程序是 MicroXRCEAgent,安装方式有源码编译和二进制包两种。我习惯用源码编译,因为可以保证和固件版本同步:
git clone https://github.com/eProsima/Micro-XRCE-DDS-Agent.git cd Micro-XRCE-DDS-Agent mkdir build && cd build cmake .. make sudo make install编译完成后,启动代理:
MicroXRCEAgent serial --dev /dev/ttyUSB0 -b 921600注意 -b 的参数必须和飞控固件里的 SER_TEL2_BAUD 一致。启动后如果一切正常,终端会显示客户端连接成功的日志,类似 client connected 的提示。
如果日志里出现连接超时或者没有反应,优先检查串口设备路径是否选对。可以用 dmesg | grep tty 查看系统识别的串口设备,或者试一下 ls /dev/ttyUSB*。
4.4 用 ROS 2 验证数据通没通
代理连接成功后,打开一个 ROS 2 环境终端,执行:
ros2 topic list如果你能看到 /fmu/out/vehicle_attitude、/fmu/out/vehicle_odometry 等以 /fmu/out 开头的话题,说明上行数据链路已经通了。这里 /fmu/out 前缀代表从飞控往外发布的消息,/fmu/in 前缀则是从 ROS 2 发往飞控的指令话题。
再执行:
ros2 topic echo /fmu/out/vehicle_attitude能持续输出四元数姿态数据,说明整个链路完全打通。到这一步,uXRCE-DDS 客户端的核心配置就算完成了。
我自己的习惯是再跑一下 ros2 topic hz /fmu/out/vehicle_attitude 看频率,正常情况下姿态消息在 100Hz 左右。如果频率远低于这个值,优先检查波特率是不是设低了,串口线是否需要更换。
5. 常见问题和排查实录
5.1 客户端日志不断显示超时重连
这是最典型的问题。现象是代理终端里日志反复显示 client disconnected,过一会又 connected,循环往复。原因基本有两种。
第一种是波特率不匹配,飞控那边设 921600,代理这边启动忘了加 -b 参数,默认可能就 115200,两边对不上。解决办法很简单:确认两边参数一致。
第二种是串口被其他程序占用。比如 QGC 或者 Mission Planner 还连着同一个串口,代理拿不到权限或者数据冲突。我用 Mission Planner 折腾的时候遇到过这个问题,拔掉地面站连接后立刻就好了。
5.2 波特率设置正确但速度很慢
如果代理日志显示连接成功,但 ros2 topic hz 频率只有 10Hz 左右,通常是波特率虽然设对了,但飞控串口的 DMA 没有开启或者总线负载过高。
PX4 的 uXRCE-DDS 客户端默认发布频率在某些主题上有限制,这是正常的,但 vehicle_attitude 这种高频核心消息应该能到 100Hz 级别。如果上不去,检查一下飞控那边是否还运行着其他不必要的串口驱动,比如同时开了 MAVLink 遥测或者外部 GPS 的同一个 UART。
5.3 主题列表有但 echo 没数据
有时候 ros2 topic list 能看到 /fmu/out/xxx,但 echo 就是没有输出。这个问题我排查了挺久,最后发现是 QoS 设置不匹配。
PX4 的 uXRCE-DDS 客户端发布出来的消息默认 QoS 可能和 ros2 topic echo 默认订阅 QoS 不一致。解决办法是在订阅时显式指定 QoS,或者用 rqt_graph 看看数据链路是否连接上了。如果你是用 Python 写订阅节点,记得在创建订阅时设置合适的 QoS 深度和可靠性策略。
5.4 Mission Planner 连不上飞控了
这个不是 uXRCE-DDS 本身的问题,但很容易让人误判。配置完 DDS 后,TELEM2 被 DDS 客户端占用,Mission Planner 如果还通过 TELEM2 连接,自然连不上。热词里提到的 mission planner 发送 mavlink 信息给飞控,在这个场景下就得换个口。
我自己的解决方案是:调试阶段用 USB 连 Mission Planner,飞行阶段用机载电脑连 DDS,两者互不干扰。如果你必须用数传模块和地面站通信,那就把数传接到 TELEM1,把 TELEM2 留给 DDS。
5.5 固件版本、代理版本和消息类型不匹配
uXRCE-DDS 代理版本和 PX4 固件版本如果差距太大,可能出现主题注册失败或者消息类型对不上的情况。这个没有特别好的自动化排查手段,只能尽量保持两端都更新到较新的稳定版本。
我在一次升级固件后没有同步升级代理,结果 /fmu/out/vehicle_attitude 话题一直不出现,更新代理后立刻恢复正常。所以建议如果有人问你“为什么我升级固件后 DDS 就坏了”,先让他升级代理。
5.6 问题排查速查表
| 症状 | 可能原因 | 排查方式 |
|---|---|---|
| 代理日志显示超时重连 | 波特率不匹配或串口被占用 | 检查 -b 参数,关闭地面站串口连接 |
| 有话题列表但 echo 无数据 | QoS 不匹配或消息类型不兼容 | 显式指定 QoS,升级代理版本 |
| topic list 看不到 /fmu/out 话题 | 客户端未启动,参数配置错误 | uxrce_dds_client status 检查 |
| ROS 2 发指令飞控无响应 | /fmu/in 话题 QoS 不匹配 | 检查发布者的 QoS 设置 |
| 姿态频率过低 | 波特率过低或总线负载高 | 确保 921600,关闭不必要外设 |
| TELEM2 无法用 MAVLink 连 | 串口被 DDS 占用 | 改用 TELEM1 或 USB 连接地面站 |
6. 实操中的一些体会
6.1 我的使用感受
整个配置流程走下来,最大的感受是 uXRCE-DDS 相比旧版 micrortps 方案真的是省心太多了。不用手动维护主题映射表,不用每次改消息类型都重新编译固件,客户端启动后自动把飞控上的 uORB 主题桥接出来,调试效率高了不少。
我手头这台六旋翼,配完 DDS 后在 ROS 2 里跑 offboard 位置控制,姿态数据延迟体感上比原来用 MAVLink 转发然后再解析要低得多。而且重要的是,数据不再是大地坐标系下拼凑出来的,而是直接拿到了飞控内部的估计状态,后续做滤波融合的底子好了很多。
6.2 还可以往哪些方向扩展
如果你已经跑通了 DDS 链路,后面可以尝试的事情很多。比如在 /fmu/in 方向发送 offboard_control_mode 和 trajectory_setpoint 消息,在 ROS 2 侧实现自己的位置控制器;再比如用 /fmu/out/vehicle_local_position 做机载端避障规划;甚至可以把多台 MicoAir H743 飞控都接入同一个 ROS 2 网络,做简单的集群编队原型验证。
我个人目前正在尝试把视觉里程计的数据通过 /fmu/in/vehicle_visual_odometry 反馈给飞控,代替 GPS 做室内定位。这个方向对延迟很敏感,uXRCE-DDS 串口模式的表现值得一试。
最后再分享一个小技巧:调试 uXRCE-DDS 时,别急着上机器人操作系统那一堆工具,先把代理日志研究明白。代理启动时输出的每个警告、每条连接记录都包含大量信息,很多问题光看日志就能定位到根因,比盲目改参数高效得多。