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 域,最终由上层控制节点按命名空间寻址。理解这张图,就理解了本课程的主干。

PX4 ROS2 多机通信架构 UAV1 实例 PX4 SITL / 飞控 UXRCE_DDS_NS=uav1 micro-ROS Agent 端口 8888 / 域 0 UAV2 实例 PX4 SITL / 飞控 UXRCE_DDS_NS=uav2 micro-ROS Agent 端口 8889 / 域 0 ROS 2 域 DDS Domain 0 /uav1/fmu/out/... vehicle_status, odometry /uav2/fmu/out/... vehicle_status, odometry /uav1/offboard/... 控制指令下行 /uav2/offboard/... 控制指令下行 上层控制节点 编队控制器 任务调度器 状态监控 上行数据 下行控制 UAV1 UAV2 ROS 2 域 控制层

四、实战路线图:从环境搭建到编队飞行

本课程共 30 章,按照“环境准备 → 命名空间隔离 → 通信配置 → 多机协同 → 架构优化”的主线推进。建议你按以下路线学习,每完成一个阶段就在仿真中验证一次。

  1. 阶段一:环境与单机验证(第 1–6 章)。安装 PX4、ROS 2、micro-ROS Agent,跑通单架飞机的 Offboard 控制,理解 uxrce_dds_client 和 MicroXRCEAgent 的基本用法。
  2. 阶段二:命名空间与多实例(第 7–14 章)。掌握 UXRCE_DDS_NS、ROS 2 namespace、PX4_SIM_PORT 的配置方法,实现两架飞机同时启动且话题不冲突。
  3. 阶段三:通信与同步(第 15–22 章)。配置 DDS 域、QoS、TF 树隔离、时钟同步,解决多机 Offboard 控制中的时间戳和坐标系问题。
  4. 阶段四:集群架构与实战(第 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 中会出现坐标系冲突,导致可视化异常。