PX4 + Gazebo + XRCE-DDS + QGC 四件套从零搭建仿真开发环境
发布时间:2026/10/3 12:15:12 锦皓数字建站

做PX4开发的人迟早会把 PX4、Gazebo、XRCE-DDS、QGC 这四样东西串在一条链路上PX4 固件跑 SITL 仿真Gazebo 提供物理环境和传感器数据XRCE-DDS 把 PX4 的 uORB 消息桥接到 ROS2QGC 在另一边做地面站显示、任务规划与参数调整。这套组合对没有实机的人尤其友好——白天在 Gazebo 里飞QGC 里盯状态ROS2 里订阅数据做算法逻辑和真机完全一致等你有实机的那天这套流程基本不需要推倒重来。这篇文章不是“复制粘贴官网教程”而是把我从零搭建到跑通全链路的实际过程写出来。如果你是第一次碰 PX4想搞清楚固件编译、仿真环境、DDS 桥接、地面站连接这几件事之间的先后关系或者你已经能跑起 Gazebo但 ROS2 里死活看不到 PX4 的话题又或者你在纠结 QGC 连接、仿真解锁、内八到底怎么搞——按下面的顺序往下走大概率能少踩一半的坑。1. 为什么把 PX4、Gazebo、XRCE-DDS、QGC 拼在一起1.1 四个组件各管什么PX4 是飞控固件它干的是传感器融合、姿态控制、导航状态机和任务调度的活。在开发阶段大部分人不愿意每次改代码都拿真机冒险所以让 PX4 在 Gazebo 里跑 SITLSoftware In The Loop用仿真模型代替真实无人机。组件在这里的角色PX4飞控固件本体跑姿态估计、控制逻辑、任务状态机Gazebo物理仿真器提供重力、空气阻力、地形、相机和 IMU/GPS 数据XRCE-DDSPX4 与 ROS2 之间的数据桥把 uORB 消息映射成 DDS topicQGC地面站负责连接、显示飞行状态、调参、解锁和任务指令如果你只用 QGC 玩仿真其实不需要 DDS 这一层——PX4 本来就有 MAVLink 可以连 QGC。但一旦你想在 ROS2 里做自主飞行、目标识别、路径规划或者把 PX4 状态和机械臂、导航模块联动MAVLink 就太“飞控专用”了。DDS 是通用的发布订阅中间件ROS2 原生支持消息类型可以自定义所以 XRCE-DDS 就成了连接飞控和机器人生态的“标准接口”。1.2 为什么是 XRCE-DDS而不是让 PX4 直接跑 ROS2这里有个新手常问的问题既然 ROS2 这么好用为什么 PX4 不直接内置 ROS2 客户端原因很实际PX4 跑在嵌入式设备上资源有限。完整 ROS2 客户端rclcpp / rclpy光是运行时依赖就不小对飞控这种对实时性敏感的系统不友好。PX4 内部用的是自己的一套发布订阅机制叫 uORB。要让 uORB 和 DDS 互通最轻量可靠的方式就是加一个 Micro XRCE-DDS Client——它在飞控侧只占很小的资源把 uORB 消息编码后通过网络发给宿主机上的 Micro XRCE-DDS AgentAgent 再转换成完整的 DDS 实体让 ROS2 节点正常订阅。用一个不太严谨但好记的类比PX4 是一个只会说方言的机器人uORB 是它的方言Micro XRCE-DDS Agent 是翻译官把方言翻译成 ROS2 听得懂的普通话。你不需要让机器人学会所有普通话只需要带个翻译官。1.3 这条链路解决的核心问题把四件套放一起本质上解决的是“开发环境和真实运行时不一致”的痛点。第一无硬件也能开发。没有实体无人机没有室外场地也一样能把 PX4 从编译、参数配置到任务飞行全部跑通。Gazebo 里摔机不心疼可以反复改控制参数观察姿态和位置响应。第二双通道并存。MAVLink 通道给 QGC 做地面站DDS 通道给 ROS2 做算法。QGC 负责安全监看、给指令、调参数ROS2 节点同时订阅高频状态量做数据处理两边互不干扰。这种并行结构在实际项目中基本是标准配置。第三从仿真到实机的迁移成本低。仿真里用的 uORB 消息、MAVLink 指令、参数体系和真机上一模一样。你在 Gazebo 里验证过的 offboard 控制代码拿到真机上只需要改传感器话题来源和端口配置大框架可以复用。所以这套组合适合的人群很广刚入门想搞懂 PX4 消息流的学生做无人机算法验证的工程师以及想在其他机器人平台上了解 DDS 桥接思路的开发者。2. 环境准备与基础安装2.1 版本怎么搭配最不容易打架版本搭配是 PX4 仿真环境里最容易翻车的点我见过太多人因为 Ubuntu 版本、Gazebo 版本和 PX4 版本不匹配编译到一半报一堆找不到库的错误。我自己实测比较顺手的组合是软件推荐版本备注操作系统Ubuntu 22.04 LTSROS2 Humble 的原生平台PX4 v1.15 支持最好ROS2Humble官方支持周期长参考资料多PX4v1.15 或当前 stable1.13/1.14 也能跑但 -dds 参数行为有差异GazeboGazebo Classic 11 或 gz sim 8两者选一个不要同时混装QGCv4.4 或 Nightly稳定版足够为什么不太推荐用最新的 ROS2 Jazzy 或者 Ubuntu 24.04不是因为新版本不好而是 PX4 官方工具链对 Humble 的组合测试更成熟Gazebo 插件和 uXRCE-DDS 的文档基本都围绕这个组合写。对学习环境来说稳定比新功能重要。等你在 Humble 上跑通以后再迁移到新版本会轻松得多。2.2 ROS2 Humble 与 PX4 源码准备先把系统基础环境准备好。我习惯只装一个轻量 ROS2 桌面版不需要的东西越少越不容易冲突sudo apt update sudo apt install ros-humble-desktop python3-pip python3-colcon-common-extensions echo source /opt/ros/humble/setup.bash ~/.bashrc source ~/.bashrc装 ROS2 之前要确认 Ubuntu 版本兼容lsb_release -a看一眼是 22.04 再动手。ROS2 装完后先把自带的 demo 跑通一次比如ros2 run demo_nodes_cpp talker确保 DDS 中间件本身没问题。这个自检能帮你把问题隔离在“ROS2 没装好”还是“PX4/DDS 配置不对”。接着拉取 PX4 源码。PX4 仓库自带很多子模块一定要加--recursivegit clone --recursive https://github.com/PX4/PX4-Autopilot.git cd PX4-Autopilot git submodule update --init --recursive --depth 1子模块下载会比较久因为数量多、体积大。网络环境不稳定的时候执行git submodule update可能会中途失败解决办法不是上网找“加速工具”而是把命令拆开重试几次或者用--depth 1浅克隆减少体积。2.3 Gazebo 安装Classic 和 gz sim 怎么选这是我在教程里发现最让人纠结的地方。PX4 支持两套 Gazebo 后端老牌 Gazebo Classic 11和新版 gz sim原 Ignition Gazebo。两者概念很像但启动命令、模型路径、插件接口都不一样。如果你是第一次接触我更推荐先用 Gazebo Classic 11。原因很简单网上资料最多遇到报错能搜到解决方案的概率高。安装命令sudo apt install gazebo11 libgazebo11-dev如果是 Ubuntu 22.04 PX4 v1.15想体验新版 gz sim 8 也可以但你要知道新版 Gazebo 的启动不是通过gazebo命令而是gz sim。PX4 对应的机架名称也不同比如make px4_sitl gz_x500用的是新版 Gazebomake px4_sitl gazebo-classic_iris用的是 Classic。不建议在一个环境里同时装两套 Gazebo。两套系统的插件、环境变量、命令行工具名有交叉编译 PX4 的 Gazebo 插件时CMake 很容易找错库最后出现一些很诡异的问题。如果你已经装了最好有一个独立虚拟机专门跑另一套。2.4 正式编译前的环境自检在编译 PX4 之前花两分钟确认环境是干净的。这一步能省掉后面大把排错时间。source /opt/ros/humble/setup.bash gazebo --version g --version python3 --version which cmake ninja检查项很简单但每一件都可能成为后续编译的定时炸弹。Gazebo 版本要显示 11 而不是旧版编译器要是 GCC 11 或兼容版本Python 版本在 3.10 左右即可。一个容易忽略的坑是不要在已经 source 了 ROS2 Foxy 的终端里再去 source Humble两个 ROS 版本的环境变量会互相污染导致 CMake 找到错误的包。每个终端只 source 当前项目需要的环境。3. XRCE-DDS 配置与 PX4 编译运行3.1 编译安装 uXRCE-DDS AgentXRCE-DDS 分两边飞控侧是 PX4 内置的 client宿主机侧是独立运行的 Agent。我用的 Agent 是 eProsima 的官方实现。git clone https://github.com/eProsima/Micro-XRCE-DDS-Agent.git cd Micro-XRCE-DDS-Agent mkdir build cd build cmake .. make -j4 sudo make install sudo ldconfig编译 Agent 依赖 CMake 和 ASIOUbuntu 22.04 默认环境基本够用。如果 cmake 阶段报缺包先sudo apt install libasio-dev再重试。启动 Agent 的命令很简单MicroXRCEAgent udp4 -p 8888PX4 SITL 默认的 uXRCE-DDS client 端口就是 8888Agent 默认也用 8888两边不需要额外改。启动后终端会停在监听状态看到类似“Waiting for connections...”的输出就说明 Agent 在正常待命。这里有个非常关键的经验Agent 要在启动 PX4 之前就开着否则 PX4 侧会反复重连虽然不影响 MAVLink 功能但会刷大量警告日志让你误以为系统出了问题。Agent 也可以用 ROS2 包micro-rtps-agent启动但我个人更喜欢直接跑官方二进制少一层 ROS2 环境干扰排查起来更清爽。3.2 编译 PX4 SITL 并开启 DDSPX4 编译需要先选机架。我日常调试四旋翼用的是 Iris因为它是官方默认配置电机映射、机架参数、仿真模型都齐最容易跑起来。开启 DDS 的关键就在 make 命令后面加一个-dds参数# 使用 Gazebo Classic 时 make px4_sitl gazebo-classic_iris -dds # 使用新版 gz sim 时 make px4_sitl gz_x500 -dds第一次编译 PX4 会花比较长时间因为要生成 QGC 参数库、编译仿真插件、生成 uORB 消息定义。看到[mavlink]、[logger]这些模块逐个编译就说明一切正常。编译完成后会自动启动 Gazebo 和 PX4 SITL终端会进入 PX4 的 nsh 命令行显示pxh提示符。这里要特别强调-dds参数的意义如果没有这个参数PX4 的 uXRCE-DDS client 不会启用即使 Agent 开着、px4_msgs 也装了ROS2 里依然看不到任何 PX4 话题。我在 v1.14 和 v1.15 上都验证过make px4_sitl gazebo-classic_iris后ros2 topic list是空的加上-dds后话题立刻出现。所以如果你发现 DDS 不通第一件事就是检查 make 命令里有没有这个选项。3.3 构建 px4_msgs 并在 ROS2 侧验证PX4 通过 DDS 发布的是自定义消息类型这些类型定义在px4_msgs包里。你不装这个包ROS2 即使收到数据也不知道怎么反序列化自然看不到具体消息。mkdir -p ~/ws_ros2/src cd ~/ws_ros2/src git clone https://github.com/PX4/px4_msgs.git cd ~/ws_ros2 source /opt/ros/humble/setup.bash colcon build --packages-select px4_msgs source install/setup.bash构建完成后先看话题列表ros2 topic list | grep fmu正常会看到一堆/fmu/out/...开头的话题。最常用的是这三个/fmu/out/vehicle_attitude /fmu/out/vehicle_local_position /fmu/out/timesyncvehicle_attitude是姿态四元数vehicle_local_position是本地位置和速度timesync是时间同步信号。ROS2 echo 的时候要特别注意 QoS 匹配问题。PX4 默认话题大部分是 BEST_EFFORT 可靠性而 ROS2 CLI 默认用 SYSTEM_DEFAULT很多新手直接ros2 topic echo发现没数据问题就出在这。ros2 topic echo /fmu/out/vehicle_attitude --qos-reliability best_effort加了--qos-reliability best_effort后数据就出来了。这也是 DDS 里最典型的“假故障”——链路是通的只是 QoS 策略不匹配。3.4 自定义 DDS topic 映射PX4 不会把所有 uORB 消息都发到 DDS因为那样带宽和实时性都不划算。默认映射文件在 PX4 源码目录src/modules/uxrce_dds_client/dds_topics.yaml打开这个文件你能看到类似这样的配置- topic: /fmu/out/vehicle_attitude type: px4_msgs/msg/VehicleAttitude - topic: /fmu/out/vehicle_local_position type: px4_msgs/msg/VehicleLocalPosition如果你想把某个 uORB 消息也发到 DDS就在这个文件里加一条消息类型名要严格对上。改完后需要重新编译 PX4或者至少重启 SITL 进程才能生效。我个人的建议是刚开始不要乱加先用默认映射跑通等你对消息结构熟悉了再按需扩展。因为每加一个高频话题都会增加 Agent 和飞控侧的 CPU 占用仿真里不明显真机上是要计成本的。4. QGC 地面站连接与整机联调4.1 安装并连接 QGCQGC 是 PX4 生态里最常用的地面站负责参数调整、飞行数据监控、任务规划和固件刷写。在仿真阶段主要用它来看状态和做解锁控制。从 QGC 官方 GitHub Release 页面下载 AppImage 后chmod x QGroundControl.AppImage ./QGroundControl.AppImageQGC 启动后如果 PX4 SITL 还在运行它一般会自动发现并连接。原因是 QGC 默认监听 UDP 14550而 PX4 SITL 默认就是通过 UDP 14550 发 MAVLink 数据。如果没自动连接手动添加一个通信连接QGC 顶部菜单 - 应用设置 - 通信连接 - 添加 - UDP端口填 14550地址填 127.0.0.1。注意这里有个容易迷糊的点QGC 与 PX4 走的是 MAVLink和 ROS2 的 DDS 链路是两回事。你完全可以把 QGC 当成飞控的“驾驶舱仪表盘”ROS2 当成“数据分析后台”。DDS 断了不影响 QGCQGC 关掉也不影响 DDS两套通道并行。4.2 仿真里的解锁、起飞和内八疑问很多从穿越机飞控转过来的朋友一上来就问 PX4 的内八解锁要设置哪个参数。这里必须说清楚PX4 没有“内八解锁”这个逻辑那是 Betaflight 等穿越机飞控的习惯动作。PX4 默认是通过遥控器解锁通道或地面站指令来解锁的你不需要设置什么“内八”参数。在仿真里没有遥控器时最直接的解锁方式是在 QGC 主界面右上角点击“未解锁”按钮。如果弹出“未检测到遥控器”的警告进入“设置 - 安全设置”启用无遥控器解锁选项或者设置COM_RC_IN_MODE参数为“无遥控器”。等 Arming Check 都通过后再次点击解锁按钮。如果你确实想用遥控器解锁需要在 QGC 参数表里设置RC_MAP_ARM_SW把它指向遥控器上负责解锁的那个通道再用RC_ARMSWITCH_IS_MOMENTARY决定是拨动开关还是瞬时开关。但仿真阶段我强烈建议直接用 QGC 解锁少折腾一个变量。起飞也一样别傻乎乎推油门硬飞。最稳的是在 QGC 的“任务”页面里点击“起飞”PX4 会进入 Takeoff 状态机自动控制油门爬升到预定高度。这样你能直观看到 Gazebo 里的模型离地也能在 QGC 的姿态仪表里看到响应曲线。4.3 一套亲测顺手的联调工作流环境全跑通后我日常开发基本固定成下面这个顺序。建议你也把每个阶段拆成独立的终端避免日志混在一起。终端职责命令终端 1启动 DDS AgentMicroXRCEAgent udp4 -p 8888终端 2编译并启动 SITLmake px4_sitl gazebo-classic_iris -dds终端 3ROS2 数据观察ros2 topic echo /fmu/out/vehicle_attitude --qos-reliability best_effort终端 4QGC 地面站运行 QGC AppImage实际操作里我会先启动 Agent再启动 SITL最后开 QGC。等 ROS2 能 echo 到姿态数据后再在 QGC 里解锁、起飞、飞一个小的航线任务。飞行过程中开一个ros2 bag record -a把数据录下来事后用 PlotJuggler 或 Python 分析姿态响应这比在 QGC 仪表盘上肉眼看曲线高效得多。另一个好习惯是在 QGC 里改完参数后去 PX4 源码目录里看生成的build/px4_sitl_default/parameters.json或航点文件。仿真时所有参数持久化都走本地文件不会像真机那样烧写到 EEPROM。你要搞清楚改参数是改在哪个文件里不然下次 make clean 后参数被清空所有调参工作白做。5. 常见问题与排查速查表5.1 DDS 链路常见问题DDS 链路是这套环境里出问题最多的地方我整理成一个速查表现象可能原因解决方法ros2 topic list里没有 /fmu 话题make 命令没加-dds重启 SITL加上-dds参数话题存在但 echo 没数据QoS 可靠性不匹配加--qos-reliability best_effortAgent 一直在等待连接端口不对或 Agent 启动晚于 PX4确认 Agent 用-p 8888重启 PX4有话题但类型显示 unknown没构建 px4_msgscolcon build --packages-select px4_msgs数据偶发中断Agent 版本和 PX4 内置 client 版本不兼容升级/降级 Agent保持一致5.2 Gazebo 模型与渲染问题Gazebo 的问题主要分两类渲染卡死和模型加载失败。如果你打开 Gazebo 后黑屏或者画面闪烁多半是显卡 OpenGL 兼容性问题。可以尝试以软件渲染方式启动LIBGL_ALWAYS_SOFTWARE1 make px4_sitl gazebo-classic_iris -dds软件渲染会卡一些但至少能跑起来。等你确认业务逻辑没问题后再去折腾显卡驱动。很多人会遇到“Gazebo 里看不到模型飞机”的问题。这通常不是编译错误而是模型资源路径没找到。PX4 的 make 脚本会自动设置GAZEBO_MODEL_PATH但如果你手动先开了 Gazebo 再运行 PX4环境变量就可能不对。所以标准做法永远是不要在 PX4 启动前手动打开 Gazebo让 make 脚本自己拉起整个仿真环境。5.3 QGC 连接与解锁问题QGC 连不上的时候先把 SITL 终端的日志往上翻看启动时打印的 MAVLink 端口。如果 QGC 和 SITL 在同一台机器上手动添加 UDP 的时候地址一定要写 127.0.0.1不要写 localhost 或本机局域网 IP有些网络环境下 localhost 解析会出问题。解锁报错也是仿真新手的高频坑。最常见的几种报错提示处理方式Not ready: No RC设置COM_RC_IN_MODE1或 QGC 安全设置里启用无遥控器Preflight check failed检查 IMU、气压计是否有有效数据SITL 中确认仿真模型已加载完成Arming denied看 QGC 状态栏具体失败原因通常是当前模式不允许解锁Motor 无输出确认 Gazebo 里的电机模型是否激活检查机架配置对应的电机输出映射关于内八解锁我再多提醒一句有些人在 QGC 里以为把摇杆右下角拨到底就能解锁结果发现没反应其实是概念理解反了。PX4 的解锁条件是“通道满足指定状态”或者“地面站发出 ARM 指令”和你摇杆手势无关。如果你就是要模拟穿越机的操作习惯那得在遥控器端做混控把一个解锁通道映射到摇杆组合动作上——但那已经不是 PX4 的配置问题了。5.4 这套思路可以平移的领域PX4、Gazebo、DDS、QGC 这四件套看着是无人机专用但其实把里面任何一块拿走换成对应领域的组件整个思路依然成立。比如现在热度很高的机械臂仿真Panda 机械臂在 Gazebo 里跑MoveIt2 负责运动规划RViz2 负责可视化它们之间就是靠 DDS 同步状态。和 PX4 场景最大的区别是机械臂没有飞控不会出现 MAVLink 和 QGCDDS 是唯一的通信主干。再比如嵌入式 ARM 开发板上跑 PX4像 RK3588 这类平台核心架构完全一致。你可以在 ARM 板子上启动 AgentQGC 通过 UDP 连接板子上跑的 SITLROS2 节点直接在板子本地订阅话题。唯一需要关注的只是算力分配RK3588 跑 Gazebo 的物理渲染会比较吃力但跑 Agent 和轻量 ROS2 节点完全没有问题。理解了这套架构的通用性你以后遇到任何“仿真器中间件控制端”的项目都能快速映射出对应的组件和通信关系。6. 一些容易被忽略的实践建议最后分享几个我踩过坑后总结出来的习惯不一定写在官方文档里但对提升开发效率很有帮助。第一先把 DDS 打通再接 QGC。很多人一上来先开 QGC看到飞机动了就以为万事大吉结果后面做 ROS2 算法时才来排查 DDS容易把问题混淆在一起。我自己的顺序是先启动 Agent再启动带-dds的 SITL然后用ros2 topic echo验证话题数据确认链路稳定后再开 QGC。这样一旦出现问题你能清楚地判断是哪一层出的故障。第二花时间读dds_topics.yaml。这个文件决定了飞控和 ROS2 之间的数据边界。看懂它你就知道 PX4 默认发出来的高频话题有哪些、哪些消息类型可以订阅、哪些需要自己补充。很多人只会ros2 topic echo那几条默认话题遇到自定义任务需求就抓瞎往往是因为没吃透这个映射文件。第三仿真到真机的过渡期别忽略端口和话题差异。SITL 里所有通信都走 localhost到了真机上Agent 要连飞控的串口或 WiFi 地址端口可能完全不一样。MAVLink 和 DDS 的 topic 名称倒是基本一致但传感器数据的噪声特性、时延都会变。所以仿真跑通只是第一步真机上必须重新做一次完整的链路验证——这跟能力没关系是硬件世界本来就更复杂。这套环境我第一次完全跑通花了两天大部分时间都耗在版本不匹配和不知道要加-dds这类细节上。希望这篇记录能帮你把这个时间压缩到一个小时以内。等你在 Gazebo 里看着 QGC 解锁、ROS2 里实时刷出姿态、飞机稳稳起飞的那一刻就会觉得前面所有折腾都值了。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。