DUDuuu.studio

Back

注意#

本节操作较为复杂,如有不理解的地方可以跳转到文末的配套讲解视频进行辅助学习。

简介#

在前面的仿真系列和 MAVROS2 真机文章中,我们分别介绍了仿真环境搭建和基于 MAVROS2 的 真机Offboard 控制。PX4 从 v1.14 版本开始,官方推荐使用 uXRCE-DDS 中间件替代 MAVROS,作为 ROS2 与 PX4 之间的通信桥梁。

本文以 Pixhawk 6C(官方飞控板)和 Nvidia Jetson Orin NX(机载电脑)为例,完整演示如何在真机上部署 uXRCE-DDS 中间件。内容包括:

  • uXRCE-DDS 架构原理(Client/Agent 模型、DDS 全局数据空间)
  • PX4 固件烧录(命令行 make upload + 地面站两种方式)
  • 飞控端串口参数配置与 uXRCE-DDS Client 启用
  • 机载电脑 WiFi 热点自动启动配置
  • Agent 启动与连通性测试
  • 常见问题排查
PX4 官方推荐 uXRCE-DDS 作为 ROS2 中间件
图 1:PX4 v1.14 版本起官方推荐使用 uXRCE-DDS 中间件,替代传统的 MAVROS 方案

前提条件:本文假设读者已按照 ROS2+PX4 仿真环境开发教程 完成仿真环境搭建,并按 ROS2 真机实践:为机载电脑刷机 完成机载电脑的 Ubuntu 22.04 刷机。如果你是第一次接触 PX4 真机,建议先阅读 使用机载电脑控制 PX4 无人机(MAVROS2) 了解真机操作的基本流程。

uXRCE-DDS 架构原理#

为什么用 DDS 替代 MAVROS?#

在 ROS1 时代和 ROS2 早期,MAVROS 是连接 ROS 与 PX4 飞控的标准方案。但 MAVROS 本质上是一个协议桥接器——它将飞控端的 MAVLink 协议”翻译”成 ROS 话题,这意味着:

  • 你需要发布/订阅 mavros 命名空间下的专用话题(如 /mavros/setpoint_position/local
  • 系统中需要一个中心化的 MAVROS 节点来维护所有通信映射(在ROS1时代的ROS_Master)
  • 在多机场景中扩展性受限

uXRCE-DDS 采用完全不同的思路。它基于 DDS(Data Distribution Service)——一种去中心化的实时数据分发协议,让 PX4 内部的 uORB 话题直接映射为 ROS2 话题。这带来的好处:

  1. 原生 ROS2 话题:飞控的传感器数据直接以 ROS2 标准话题发布,无需 MAVROS 转译层。之前在仿真中写的 Offboard 控制代码可以直接搬到真机上用,话题名都不需要改。
  2. 分布式架构:所有 ROS2 节点在同一个 DDS 数据空间中自动发现彼此,不存在单点瓶颈(没有 ROS1 时代的 Master 节点)。
  3. 低延迟:DDS 使用 UDP 多播和共享内存进行数据传输,延迟远低于 MAVLink 串行化开销。
DDS 全局数据空间中的数据共享示意图
图 2:DDS 全局数据空间中的数据共享——同一 ROS_DOMAIN_ID 下的所有节点自动发现

Client/Agent 通信模型#

uXRCE-DDS 采用 Client-Agent 架构:

uXRCE-DDS Client/Agent 架构图
图 3:uXRCE-DDS Client/Agent 架构——左侧飞控端运行 Client,右侧机载电脑运行 Agent

飞控端(Client):运行在 PX4 内部,负责将 uORB 话题的消息序列化为 DDS 格式。它只做一件事——把飞控内部的 uORB 消息桥接到 Agent。Client 本身不参与 DDS 发现、不维护拓扑。

机载电脑端(Agent):运行 Micro-XRCE-DDS-Agent(之前我们仿真中用 MicroXRCEAgent udp4 -p 8888 启动的那个),负责:

  • 接收来自 Client 的串行化 uORB 消息
  • 将它们发布到 ROS2 的 DDS 全局数据空间
  • 从 DDS 空间接收 ROS2 控制指令并转发给 Client

DDS 全局数据空间(Global Data Space):只要 ROS2 节点运行在同一个 ROS_DOMAIN_ID 下,它们就能自动发现彼此的话题、服务和 action。你不需要手动配置任何连接关系——发布者和订阅者自动匹配。

ROS_DOMAIN_ID 的作用#

DDS 将同一个局域网内使用相同 ROS_DOMAIN_ID 的所有节点视为”在同一数据空间内”。可以用以下命令查看当前 domain ID:

echo $ROS_DOMAIN_ID
bash

如果输出为空,默认值为 0。在多机编队场景中,你可以为每组无人机-机载电脑分配不同的 domain ID 来隔离通信。只要 domain ID 一致且在同一局域网下,ROS2 节点之间就能互相发现——这正是分布式架构的核心优势。

硬件准备#

需要的硬件设备:

  • Pixhawk 6C(或其他 PX4 原生飞控板,固件版本 ≥ v1.14)
  • Nvidia Jetson Orin NX(或其他机载电脑,已刷 Ubuntu 22.04)
  • USB-TypeC 线(连接飞控到本地电脑,用于烧录和参数配置)
  • 杜邦线 ×3(连接飞控 TELEM2 到机载电脑 UART)
  • 机载电脑供电线(12V)
  • 飞控供电电池
  • 数传模块(用于地面站,可选但强烈建议保留)

飞控固件版本要求:uXRCE-DDS 中间件在 PX4 v1.14 及以上版本的源码中才包含。目前最新稳定版已到 v1.16(26年7月已出现v1.17),建议使用最新版本。

PX4 固件烧录#

确保飞控固件版本 ≥ v1.14。如果已有的固件版本满足要求可以跳过本节,否则选择以下两种方式之一重新烧录。

方式一:命令行编译上传(推荐)#

克隆 PX4 源码并编译上传。这种方式适合已经搭建好 PX4 开发环境的读者。

cd ~/PX4-Autopilot
bash

在烧录之前,先确认飞控板对应的编译目标(board target)。Pixhawk 6C 的目标为 px4_fmu-v6c

# 查看所有可用的编译目标
make list_config_targets | grep -i "v6c"
bash

确认飞控通过 USB-TypeC 连接到电脑后,查看串口:

ls -l /dev/ttyACM*
# 应输出类似 /dev/ttyACM0
bash
查看串口信息
图 4:确认飞控 USB 连接后查看串口设备

使用 make upload 一键编译并烧录:

make px4_fmu-v6c upload
bash
烧录成功
图 5:make upload 烧录成功,飞控自动重启
烧录过程中终端会显示进度,完成后飞控会自动重启。可以通过串口查看飞控的 NSH(NuttShell)消息确认烧录成功:
# 查看串口参数,确认波特率为 115200
stty -F /dev/ttyACM0 115200 raw -echo
cat /dev/ttyACM0
# 按回车后出现 nsh> 提示符表示飞控正常运行
bash

常见问题:如果 make upload 报权限错误,执行 sudo usermod -a -G dialout $USER 后重新登录。

方式二:QGroundControl 地面站烧录#

如果不想通过命令行编译,也可以用 QGC 直接烧录预编译固件。

  1. 打开 QGroundControl,通过 USB 连接飞控
  2. 进入 “Vehicle Setup” → “Firmware” 页面
  3. 拔掉 USB 再重新插入,QGC 会自动识别飞控型号
  4. 确认显示的版本号 ≥ v1.14,点击 “OK” 开始烧录
  5. 等待进度条完成

注意:地面站烧录会重置所有参数,如果之前配置过参数请先导出备份。

通过地面站烧录
图 6:通过 QGroundControl 地面站烧录固件

飞控端串口参数配置#

这一节是部署中最容易出错的环节——我们需要准确理解飞控内部串口的命名映射关系。

串口映射关系#

Pixhawk 6C 有三个 TELEM 端口,每个端口在飞控 NSH 内部对应不同的 TTY 设备:

物理端口飞控内部 TTY默认用途默认波特率
TELEM1/dev/ttyS5数传(MAVLink)57600
TELEM2/dev/ttyS3机载电脑921600
TELEM3/dev/ttyS0备用

本文使用 TELEM2 连接机载电脑。TELEM2 的六针引脚排列为:VCC(5V)、TX、RX、PWM、GPIO、GND。我们只需要接三根线:

TELEM2 引脚连接到Jetson Orin NX UART2 引脚
TXPin 10 (RX)
RXPin 8 (TX)
GNDPin 6 (GND)

不要连接 VCC!飞控和机载电脑各自独立供电。

不同机载电脑的 UART 引脚和 TTY 设备名不同。以 Jetson Orin NX 为例:

UARTTX 引脚RX 引脚GND 引脚TTY 设备
UART1(默认调试口)Pin 8Pin 10Pin 6/dev/ttyTHS0
UART2Pin 12Pin 14Pin 6/dev/ttyTHS1

本文使用 UART2(/dev/ttyTHS1),以保留 UART1 作为调试口。读者请根据自己的机载电脑型号查阅对应引脚图。

Jetson NX 对应的 UART 引脚
图 7:Jetson Orin NX 的 UART 引脚对应关系
### 使用 NSH 进入飞控终端

飞控通过 USB 连到本地电脑后,使用 mavlink_shell 工具进入飞控的 NSH 终端:

cd ~/PX4-Autopilot
./Tools/mavlink_shell.py /dev/ttyACM0:9600
bash

注意:进入 NSH 的波特率是 9600(不是 115200 也不是 921600)。如果之前 QGC 占用了串口,需要先关闭地面站。

进入后出现 nsh> 提示符。先用 mavlink status 查看当前 MAVLink 实例分配情况:

nsh> mavlink status
instance #0:
    TX queue: ...
    ...
    UART: /dev/ttyS5, 57600 baud    ← TELEM1 (数传)
instance #1:
    ...
    UART: /dev/ttyS3, 921600 baud   ← TELEM2 (机载电脑)
instance #2:
    ...
    UART: /dev/ttyACM0, 9600 baud   ← USB (当前连接)
plaintext

可以看到飞控已自动为 TELEM2 分配了 MAVLink 实例 #1,波特率 921600。但我们需要让 TELEM2 走 uXRCE-DDS 而不是 MAVLink,否则两者会冲突。

mavlink status 查看串口实例
图 8:在 NSH 中输入 mavlink status,查看不同串口设备对应的 MAVLink 实例
### 停用 TELEM2 上的 MAVLink 实例

查看当前 MAVLink 参数配置:

nsh> param show MAV_1_CONFIG
MAV_1_CONFIG = 102    ← 102 对应 TELEM2

nsh> param show MAV_1_MODE
MAV_1_MODE = 0        ← 0 = Normal (MAVLink)
plaintext

参数 102 是 TELEM2 的硬件端口编号。我们需要:

  1. MAV_1_CONFIG 设为 0(禁用该 MAVLink 实例)
  2. 停止当前已在 TELEM2 (ttyS3) 上运行的 MAVLink 实例
# 1. 禁用 TELEM2 上的 MAVLink
param set MAV_1_CONFIG 0

# 2. 停止正在运行的 ttyS3 上的 MAVLink 实例
mavlink stop -d /dev/ttyS3
bash

再次检查 mavlink status,应只剩两个实例(TELEM1 + USB),TELEM2 的 MAVLink 已停下。

配置 MAV_1_CONFIG 参数
图 9:将 MAV_1_CONFIG 设为 0,卸任 TELEM2 上的 MAVLink

启用 uXRCE-DDS Client#

现在在 TELEM2 上启动 uXRCE-DDS Client:

nsh> uxrce_dds_client start -d /dev/ttyS3 -b 921600
plaintext

参数说明:

  • -d /dev/ttyS3:指定 TELEM2 对应的串口设备
  • -b 921600:波特率,需与 MAV_1_RATE 保持一致

可选的命名空间参数:加 -n <namespace> 可在所有发布的话题前添加命名空间前缀(如 /px4_1/fmu/...),这在多机场景中区分不同飞控实例时非常有用。单机可以不指定。

设置 DDS 配置参数,确保 DDS Client 绑定正确的端口:

nsh> param set UXRCE_DDS_CFG 102
plaintext

为什么设为 102? 这个参数指定 uXRCE-DDS Client 应该绑定到哪个硬件端口。102 = TELEM2(与 MAV_1_CONFIG=102 对应同一个端口)。默认值为 0(未配置),需要显式设置。

验证 Client 已启动:

nsh> uxrce_dds_client status
# 输出应显示 running 状态,但此时尚未连接到 Agent("not connected" 是正常的)
plaintext
飞控端启用 uXRCE-DDS Client
图 10:在飞控 NSH 中启动 uXRCE-DDS Client
至此,飞控端配置完成。以下回顾关键命令:
# 飞控 NSH 中执行的完整命令序列
param set MAV_1_CONFIG 0                                             # 禁用 MAVLink on TELEM2
mavlink stop -d /dev/ttyS3                                           # 停止现有 MAVLink 实例
uxrce_dds_client start -d /dev/ttyS3 -b 921600                       # 启动 uXRCE-DDS Client
param set UXRCE_DDS_CFG 102                                          # 绑定 DDS 到 TELEM2
uxrce_dds_client status                                              # 验证状态
bash

硬件接线#

将飞控 TELEM2 的 TX、RX、GND 三根杜邦线连接到机载电脑 UART2 对应引脚:

TELEM2 引脚连接到Jetson Orin NX UART2 引脚
TXPin 10 (RX)
RXPin 8 (TX)
GNDPin 6 (GND)

如果你使用 USB-TTL 转接线(方式类似 MAVROS 文章中的方法一),则机载电脑端走 /dev/ttyUSB0。下面以 UART 直连(/dev/ttyTHS1)为例。

机载电脑 WiFi 热点配置#

在实际飞行中,我们无法给机载电脑接显示器和键鼠,必须通过远程 SSH 操作。这就要求机载电脑和本地电脑在同一个局域网内。最可靠的方式是让机载电脑自己创建一个 WiFi 热点,本地电脑连接这个热点后通过固定 IP SSH 过去。

创建热点#

在机载电脑(Jetson Orin NX)上打开终端:

nm-connection-editor
bash

在弹出的图形界面中:

  1. 点击 ”+” → 选择 “Wi-Fi” → 点击 “Create”
  2. Connection name:任取,如 北航中法工程师学院是XX
  3. SSID:与 Connection name 相同即可
  4. Mode:选择 Hotspot(热点模式)
  5. Wi-Fi Security:选择 “WPA & WPA2 Personal”,设置一个 8 位以上密码
  6. 切换到 IPv4 Settings 选项卡,Method 选择 “Manual”:
    • Address: 192.168.10.1
    • Netmask: 24
    • Gateway: 192.168.10.1
  7. IPv6 Settings:Method 选择 “Ignore”
  8. 点击 “Save”
配置机载电脑 WiFi 热点
图 11:通过 nm-connection-editor 配置机载电脑 WiFi 热点

设置开机自动启动热点#

首先删除之前保存的 WiFi 连接记录(防止上电后自动连到其他 WiFi):

# 列出所有已保存的连接
nmcli connection show

# 删除不需要的连接(保留刚创建的热点)
sudo nmcli connection delete "<旧 WiFi 名称>"
bash

将热点设为自动连接:

nmcli connection modify "北航中法工程师学院是XX" connection.autoconnect yes
nmcli connection modify "北航中法工程师学院是XX" connection.autoconnect-priority 10
bash

激活热点:

nmcli connection up "北航中法工程师学院是XX"
bash

此时在本地电脑上搜索 WiFi,应能看到 北航中法工程师学院是XX 信号。连接后验证:

ping 192.168.10.1
bash

之后每次飞控上电 → 机载电脑供电 → 自动启动热点 → 本地电脑连接 → SSH:

ssh jetson@192.168.10.1
bash

启动 Agent 与连通测试#

连接前检查#

在 SSH 进入机载电脑后,先不要给飞控上电。执行以下准备步骤:

# 1. 将用户加入 dialout 组(防止串口权限问题)
sudo usermod -a -G dialout $USER
# 重新登录使生效

# 2. 查看可用的串口设备
ls -l /dev/ttyTHS*
# 应输出 /dev/ttyTHS1(UART2)
bash

确认机载电脑上已安装 Micro-XRCE-DDS-Agent(仿真环境中应该已装好,若未安装参考 ROS2+PX4 仿真环境开发教程 中 MicroXRCE-DDS Agent 安装部分)。

验证硬件连通性#

先测试飞控 → 机载电脑的串口通信是否正常。给飞控上电后,用 cat 检测是否有数据流:

stty -F /dev/ttyTHS1 921600 raw -echo
cat /dev/ttyTHS1
bash

如果出现乱码(MAVLink 或 uXRCE-DDS 二进制数据),说明物理连接和串口配置正确:

cat 串口测试收到乱码
图 12:cat 收到乱码表示飞控与机载电脑串口通信正常

如果没有任何输出,请检查:

  • 飞控 TELEM2 TX ↔ 机载电脑 UART RX 是否正确交叉连接
  • 波特率是否匹配(飞控端和机载电脑端都应为 921600)
  • 飞控端 uxrce_dds_client start 是否已执行
  • 是否被其他进程(如地面站)占用了串口

启动 Micro-XRCE-DDS-Agent#

# 激活 ROS2 环境
source /opt/ros/humble/setup.bash

# 启动 Agent,通过串口连接飞控
MicroXRCEAgent serial --dev /dev/ttyTHS1 -b 921600
bash

成功连接时,终端会输出类似以下信息:

[info] Serial agent starting...
[info] Connect to serial device: /dev/ttyTHS1, baudrate: 921600
[info] Connection established
[info] Client connected: 0x00000001
[info] Topic created: /fmu/out/vehicle_odometry
[info] Topic created: /fmu/out/imu
[info] Topic created: /fmu/out/...
...
plaintext
Agent 成功连接
图 13:Agent 成功连接后终端输出——Client connected,自动创建 /fmu/out/ 话题

至此,uXRCE-DDS 中间件部署完成。 Agent 会自动将飞控的 uORB 话题发布为 ROS2 话题。在另一个终端中验证:

source /opt/ros/humble/setup.bash
ros2 topic list | grep fmu
bash

应看到大量 /fmu/out/... 开头的飞控数据话题。现在你的 ROS2 Offboard 控制代码可以直接在机载电脑上运行,话题名和仿真环境完全一致!

完整启动流程#

每次真机飞行前,按以下顺序操作:

  1. 本地电脑连接机载电脑热点 北航中法工程师学院是XX
  2. 确认本地电脑能 ping 通 192.168.10.1
  3. 给飞控上电(通过电池),等待飞控启动完成
  4. 确认地面站(QGC)通过数传连接到飞控
  5. SSH 进入机载电脑:ssh jetson@192.168.10.1
  6. 在 SSH 终端中启动 Agent:
source /opt/ros/humble/setup.bash
MicroXRCEAgent serial --dev /dev/ttyTHS1 -b 921600
bash
  1. 开另一个 SSH 终端,运行 ROS2 控制节点:
source /opt/ros/humble/setup.bash
source ~/ros2_ws/install/setup.bash
ros2 run offboard_control simple_offboard   # 以之前的 Offboard 节点为例
bash

重要提示:根据经验,Agent 第一次连接成功后尽量保持飞控通电不断开。如果在飞行中反复断开重连串口,有时会导致后续连接失败。建议准备好后一次连通,中间不要改动。

参数速查表#

参数说明
MAV_1_CONFIG0(禁用)将 TELEM2 上的 MAVLink 卸任
MAV_2_CONFIG101(TELEM1)数传保留在 TELEM1
UXRCE_DDS_CFG102(TELEM2)DDS Client 绑定 TELEM2
SER_TEL2_BAUD921600TELEM2 波特率

uXRCE-DDS vs MAVROS 对比#

uXRCE-DDSMAVROS
PX4 官方推荐v1.14+ 推荐旧方案,仍在维护
话题命名原生 ROS2 话题/mavros/ 命名空间
架构去中心化 DDS中心化桥接
多机扩展DDS 自动发现需手动配置
仿真/真机代码复用话题完全一致,代码无需修改需替换话题前缀
稳定性仍在活跃开发成熟稳定(ROS1 时代积累)
真机延迟低(UDP 多播)较低(MAVLink 串行化)

建议:新项目优先选择 uXRCE-DDS。如果飞控固件版本 < v1.14 无法升级,或有大量遗留 MAVROS 代码需要兼容,可以继续使用 MAVROS。参考 使用机载电脑控制 PX4 无人机(MAVROS2)

常见问题排查#

现象可能原因排查方法
NSH 终端连接不上,串口被占用QGC 或其他进程占用了 ACM0关闭 QGC 地面站后重试
uxrce_dds_client start 报错波特率不匹配或 TELEM2 仍被 MAVLink 占用确认 MAV_1_CONFIG=0,确认 mavlink stop -d /dev/ttyS3 已执行
Agent 启动后一直是 “not connected”UXRCE_DDS_CFG 未正确设置param set UXRCE_DDS_CFG 102
cat /dev/ttyTHS1 无输出接线错误或波特率不对检查 TX/RX 是否交叉连接,波特率是否 921600
Agent 连上但 ros2 topic list/fmu/ 话题ROS2 环境未 source 或 domain ID 不匹配source /opt/ros/humble/setup.bash,检查 echo $ROS_DOMAIN_ID
串口设备名不是 ttyTHS1使用了 UART 编号不同ls /dev/ttyTHS* 查看可用设备

总结#

本文完整演示了 Pixhawk 6C + Jetson Orin NX 上部署 uXRCE-DDS 中间件的全流程——从固件烧录、飞控 NSH 终端操作、MAVLink 卸任与 DDS Client 启用、硬件接线,到机载电脑热点配置和 Agent 启动。uXRCE-DDS 作为 PX4 官方推荐的 ROS2 通信方案,在代码复用性(仿真代码直接上真机)、扩展性(DDS 自动发现)和延迟方面都有显著优势。

当然,MAVROS 作为久经考验的老方案,在稳定性和社区文档积累上仍有其价值。读者可以根据自己的飞控固件版本和项目需求灵活选择。如果你同时使用两种方案进行对比测试,欢迎在评论区分享经验。

最后,感谢大家的耐心阅读,如有错漏请批评指正!

完整讲解视频#

如果下方视频加载较慢,可前往知乎观看:https://www.zhihu.com/zvideo/1981084557504701099

参考资料#

ROS2+PX4 真机部署:UXRCE-DDS 中间件的部署(以 Pixhawk 6C 为例)
https://duduuu.xyz/zh/posts/px4-ros2-uxrce-dds
Author dudu
Published at 2026年7月16日
阅读
总访问