1. 课程导入
当你第一次把两架 PX4 无人机同时接入 ROS 2 时,最常遇到的不是“飞不起来”,而是“分不清谁是谁”。地面站里两个 /fmu/out/vehicle_odometry 话题互相覆盖,ros2 topic list 里出现一堆重名节点,QGC 只能连上一架,MAVROS 或 micro-ROS 的命名空间冲突让控制指令发给了错误的飞机。这些现象背后,是 PX4 与 ROS 2 在多机场景下必须解决的命名空间隔离、通信路由与时钟同步三大问题。本课程的目标,就是让你从“能飞一架”进阶到“能管一群”,并建立一套可复用的多机系统架构思维。
一、学习目标:从单机到集群的四级跃迁
本课程不是简单的命令堆砌,而是围绕“命名空间”这一主线,把 PX4 多机系统的知识拆解为四个可验证的能力层级。你可以对照下表检查自己当前所处的位置,并明确学完本课程后应达到的水平。
| 能力层级 | 典型表现 | 关键知识点 | 验证方式 |
|---|---|---|---|
| L1 单机通信 | 能启动一架 PX4 SITL 并让 ROS 2 节点收发话题 | micro-ROS / MAVROS 基础、QoS 配置 | ros2 topic echo 看到位姿 |
| L2 命名空间隔离 | 两架飞机各自拥有独立话题前缀,互不干扰 | ROS 2 namespace、PX4 UXRCE_DDS_NS |
ros2 node list 显示 /uav1/、/uav2/ |
| L3 多机协同控制 | 能同时向多架飞机发送 Offboard 控制指令 | 多实例启动、TF 树隔离、时钟同步 | 两架飞机按不同航点飞行 |
| L4 集群架构设计 | 能设计可扩展到 10+ 架飞机的通信拓扑 | DDS 域隔离、网桥、分布式部署 | 多机编队仿真稳定运行 |
二、核心挑战:多机系统为什么比单机难
单机系统中,所有话题都在根命名空间下,节点名唯一,通信路径清晰。一旦引入第二架飞机,问题会沿着三个维度同时爆发。
第一是命名冲突。PX4 默认通过 micro-ROS 或 MAVROS 发布的话题名是固定的,例如 /fmu/out/vehicle_status。两架飞机同时运行时,ROS 2 图里会出现两个同名发布者,订阅者无法区分数据来源。解决方式是为每架飞机分配独立的命名空间,如 /uav1/fmu/out/vehicle_status 和 /uav2/fmu/out/vehicle_status。
第二是通信路由。PX4 与 ROS 2 之间的数据通道可以是串口、UDP、共享内存或 DDS。多机场景下,每架飞机需要独立的 UDP 端口或 DDS 域,否则数据包会串流。例如 PX4 SITL 中常用 PX4_SIM_PORT 和 UXRCE_DDS_PORT 来区分实例。
第三是时钟与坐标系。多机系统中,每架飞机的 map、odom、base_link 坐标系必须通过命名空间隔离,否则 TF 树会因 frame_id 重复而断裂。同时,Offboard 控制对时间戳敏感,多机之间的时钟偏差会导致控制指令抖动。
常见误区:很多初学者认为“只要把话题名改掉就能多机运行”。实际上,PX4 端的参数、DDS 域、UDP 端口、TF frame_id、QoS 配置都需要同步修改。只改 ROS 2 侧命名空间,PX4 仍然会向默认话题发布数据,导致“改了但没完全改”的隐蔽故障。
三、整体知识框架:一张图看清多机通信链路
下图展示了 PX4 ROS2 多机系统的核心结构。每架飞机(UAV1、UAV2)拥有独立的 PX4 实例和 DDS 命名空间,通过各自的 micro-ROS 代理接入同一个 ROS 2 域,最终由上层控制节点按命名空间寻址。理解这张图,就理解了本课程的主干。
四、实战路线图:从环境搭建到编队飞行
本课程共 30 章,按照“环境准备 → 命名空间隔离 → 通信配置 → 多机协同 → 架构优化”的主线推进。建议你按以下路线学习,每完成一个阶段就在仿真中验证一次。
- 阶段一:环境与单机验证(第 1–6 章)。安装 PX4、ROS 2、micro-ROS Agent,跑通单架飞机的 Offboard 控制,理解
uxrce_dds_client和MicroXRCEAgent的基本用法。 - 阶段二:命名空间与多实例(第 7–14 章)。掌握
UXRCE_DDS_NS、ROS 2 namespace、PX4_SIM_PORT的配置方法,实现两架飞机同时启动且话题不冲突。 - 阶段三:通信与同步(第 15–22 章)。配置 DDS 域、QoS、TF 树隔离、时钟同步,解决多机 Offboard 控制中的时间戳和坐标系问题。
- 阶段四:集群架构与实战(第 23–30 章)。设计可扩展的多机通信拓扑,完成编队飞行、任务分配和故障排查的综合案例。
学习建议:每学完一个阶段,不要只停留在“命令能跑通”。尝试用 ros2 node list、ros2 topic list -t、ros2 topic info /uav1/fmu/out/vehicle_status --verbose 观察 ROS 2 图的变化,理解命名空间如何影响节点、话题和服务。这种“观察—验证—调整”的习惯,是多机系统调试的核心能力。
五、一个典型场景:两架飞机同时起飞
假设你要让两架 PX4 SITL 飞机同时从不同位置起飞,并各自飞向不同航点。你需要完成以下关键配置:
# 启动 UAV1 的 PX4 SITL
PX4_SIM_PORT=14540 UXRCE_DDS_NS=uav1 ./build/px4_sitl_default/bin/px4 -i 0
# 启动 UAV2 的 PX4 SITL
PX4_SIM_PORT=14560 UXRCE_DDS_NS=uav2 ./build/px4_sitl_default/bin/px4 -i 1
# 启动 micro-ROS Agent(UAV1)
MicroXRCEAgent udp4 -p 8888
# 启动 micro-ROS Agent(UAV2)
MicroXRCEAgent udp4 -p 8889
# 查看 ROS 2 话题,确认命名空间隔离
ros2 topic list | grep fmu
# 输出应包含:
# /uav1/fmu/out/vehicle_odometry
# /uav2/fmu/out/vehicle_odometry
如果此时你看到的是两个同名的 /fmu/out/vehicle_odometry,说明命名空间没有生效。请检查 PX4 端的 UXRCE_DDS_NS 参数是否在启动前正确设置,以及 micro-ROS Agent 是否连接到了正确的端口。这个排查过程,正是本课程要训练的核心能力。
六、复盘与常见误区
在多机系统学习中,以下三个误区最容易导致“看起来配置对了,实际却失败”:
- 只改 ROS 2 侧,不改 PX4 侧。ROS 2 的命名空间只是订阅端的前缀,PX4 发布端仍使用默认话题名。必须通过
UXRCE_DDS_NS让 PX4 在发布时就带上命名空间。 - 忽略端口冲突。两架飞机的 micro-ROS Agent 不能使用同一个 UDP 端口,否则数据会串流。建议为每架飞机分配独立端口,如 8888、8889、8890。
- 忘记 TF 树隔离。多机系统中,每架飞机的
base_link、odom必须加上命名空间前缀,否则 RViz 中会出现坐标系冲突,导致可视化异常。