ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

PX4无人机仿真环境搭建:SITL+Gazebo+QGroundControl完整指南

PX4无人机仿真环境搭建:SITL+Gazebo+QGroundControl完整指南 做无人机开发最怕的不是算法难而是每次改完代码都得往外跑。飞控一崩桨叶换一次钱包瘪一次。我从入坑PX4第二周就开始折腾仿真环境到今天至少在不同Ubuntu版本上搭过五六次踩过的坑比飞过的航线还多。这套Module 6要讲的SITL Gazebo QGroundControl是PX4生态里最经典、也最实用的一套仿真组合不花一分钱硬件成本在电脑上就能把飞控固件、传感器模型、地面站链路全部跑通。这篇我把自己反复验证过的搭建流程、版本匹配逻辑、调试技巧和排错思路完整整理一遍尽量一次说透。1. 这套仿真环境到底在干什么1.1 三个组件的分工很多人第一次接触PX4仿真会被SITL、HITL、Gazebo、QGroundControl这些名词绕晕。我换一种说法来解释仿真本质上是在电脑里“演一出完整的飞行大戏”三个组件各演各的角色。SITL是Software In The Loop的缩写软件在环仿真指的是PX4飞控固件不跑在真实硬件上而是作为一个普通Linux进程直接跑在你的电脑上。固件里的姿态解算、控制回路、任务规划、导航逻辑和真机上是同一份代码只是把传感器数据来源从真实的IMU、GPS模块换成了仿真器注入的虚拟数据。这是SITL最大的价值你调试的逻辑就是将来真机要跑的逻辑不存在“仿真能用、上真机就炸”的代码差异。Gazebo负责提供“物理世界”。它是一个开源机器人仿真器能模拟重力、碰撞、空气阻力这些物理效应也能模拟相机、激光雷达、GPS、IMU等传感器。PX4在Gazebo里加载一个四旋翼模型模型上挂着一堆传感器插件这些插件计算出来的数据就是SITL进程“感知”到的世界。QGroundControl以下简称QGC是地面站负责“人和飞机之间的桥梁”。你在QGC上能看到模拟飞机的姿态、位置、电池电量、飞行模式也可以发指令让飞机起飞、降落、航线飞行。QGC和SITL之间通过MAVLink协议通信这个协议也是真机上飞控和地面站之间的通信协议。三者串起来的数据流是这样的Gazebo计算虚拟传感器数据通过UDP端口发给PX4 SITL进程PX4跑完控制逻辑把电机指令发给Gazebo里的模型同时通过MAVLink把飞行状态发给QGCQGC显示出来你也能从QGC下发指令。整个闭环和真机几乎一致。1.2 为什么这套组合值得折腾直接在真机上开发每个小改动都要烧固件、接电源、找场地、起飞验证。一次悬停测试从准备到收工一小时起步要是撞坏了东西更麻烦。SITL仿真里改完代码重新编译运行只需要几十秒飞机“炸了”也无所谓重启一个进程就回来了。和HITLHardware In The Loop硬件在环相比SITL不需要真实飞控硬件所以可以并行跑多个仿真实例对多机协同、集群编队这类场景特别友好。我就是先在SITL里把所有控制参数调明白了才敢去动真机。不过要提醒一句SITL不能完全替代真机验证。Gazebo里没有真实的风场、没有GPS多径效应、没有磁罗盘干扰电机模型也不够细腻。仿真是第一道验证关口能过滤掉90%的代码级错误但真机是最后一道关口永远不要跳过。1.3 版本匹配是最大的隐性门槛我在社区里看到最多的求助帖不是“这个指令怎么写”而是“按教程做了一切但Gazebo就是黑屏”“编译到一半报错”。十有八九都是版本不匹配。PX4和Gazebo的版本对应关系是这个环境里最需要先搞清楚的底层逻辑。这里我放一张实测过的版本对照表PX4版本默认仿真器常用启动命令备注v1.13及更早Gazebo 9 / Gazebo Classicmake px4_sitl gazebo_iris老系统上常见新系统编译困难v1.14Gazebo ClassicGazebo 11make px4_sitl gazebo-classic_iris目前用得最广泛的稳定组合v1.15GZ Harmonic新gz simmake px4_sitl gz_x500新仿真器模型命名、环境变量都变了main分支GZ Harmonic / Ionicmake px4_sitl gz_x500跟随上游更新API变动频繁v1.15之后PX4把默认仿真器切换成了新一代的gz sim以前叫Ignition Gazebo后来叫Gazebo现在索性叫GZ。很多老教程里的gazebo_iris在新版本里就不好使了启动方式变成了gz_x500这种带gz_前缀的模型名。这不是你操作错了是版本演进过程中命名体系变了。所以动手之前第一件事是选定一个“版本组合”然后所有环节都围绕这个组合来不要混搭。我最推荐的组合是Ubuntu 22.04 PX4 v1.14/v1.15 Gazebo Classic/GZ Harmonic这个组合在网上资料最多遇到问题好查。2. 动手搭建前的环境准备2.1 Ubuntu版本和ROS2怎么选PX4官方对Ubuntu LTS版本支持得最好。当前时间点我推荐两个组合第一种Ubuntu 22.04 ROS2 Humble PX4 v1.15 GZ Harmonic。这个组合是社区用得最多的几乎所有教程都是在类似环境下验证过的。如果用v1.14那就对应Gazebo Classic不要混用新版仿真器。第二种Ubuntu 24.04 ROS2 Jazzy PX4 main分支 GZ Ionic。这个组合比较新适合想体验最新功能的朋友。但要注意main分支天天变今天能编译过明天可能就因为上游改动挂了。如果你不是非要追新特性不建议用main分支做长期开发。ROS2不是PX4仿真必须的但如果你后面要做offboard控制、视觉检测、集群协同这些进阶玩法ROS2是绕不开的。为了省事我在装PX4依赖时会把ROS2一并装上后面不用重复折腾系统。还要强调一个问题如果电脑性能一般别在虚拟机里跑完整仿真。Gazebo的物理引擎加上PX4的实时计算对CPU和内存压力很大虚拟机里图形加速和网络转发都可能成为瓶颈。我见过不少人在VirtualBox里跑Gazebo卡到模型加载都成问题。要么直接装双系统要么用Docker跑仿真都比重度虚拟机体验好。2.2 安装系统依赖PX4官方提供了自动安装脚本在PX4-Autopilot仓库的Tools/setup/目录下。整体流程是git clone --recursive -b v1.14.3 https://github.com/PX4/PX4-Autopilot.git cd PX4-Autopilot bash ./Tools/setup/ubuntu.sh这个脚本会装一大堆东西包括编译工具链、Python依赖、Gazebo和ROS2相关组件。第一次跑通常要二三十分钟取决于网络速度。跑完脚本后我还会手动装两个容易漏掉的包sudo apt install ninja-build pip3 install --user kconfiglibkconfiglib在编译PX4配置菜单时会用到少了它会有莫名其妙的Python报错。ninja-build能显著加快编译速度PX4的CMake默认会找Ninja作为生成器。还有一个容易踩的坑Ubuntu 22.04默认Python是3.10PX4一些老版本的构建脚本对Python版本很敏感。如果你在用v1.12或更老版本编译前先检查python3 --version版本太高反而可能出问题。这也是我建议用v1.14以上版本的原因之一。2.3 安装QGroundControl地面站QGC的安装相对简单官方提供了AppImage格式的免安装包# 下载QGC的AppImage然后赋予执行权限 chmod x QGroundControl.AppImage # Ubuntu 22.04及以后需要先装libfuse2 sudo apt install libfuse2 # 运行 ./QGroundControl.AppImage如果你更习惯apt源安装QGC官方也提供了Debian仓库但版本更新节奏比较慢。我一般用AppImage因为升级只需要换一个文件不影响系统其他部分。QGC启动后第一次运行可能会提示没有串口权限点“Skip”跳过即可仿真环境用不到串口。如果后面要接真机需要把用户加入dialout组sudo usermod -a -G dialout $USER这里插一句QGC的版本一般不需要和PX4严格对应但遇到连接异常时优先考虑换成最新稳定版QGC再试。我遇到过好几次仿真里QGC连不上升级QGC版本后就好了大概率是老版本QGC对新的MAVLink消息兼容有问题。3. 完整实操从源码编译到飞机起飞3.1 拉取PX4源码和子模块PX4是一个大仓库里面用到了很多子模块比如掉电保护、微服务框架、参数定义等。clone的时候要带--recursive参数否则后面编译会缺东西git clone --recursive -b v1.14.3 https://github.com/PX4/PX4-Autopilot.git如果clone过程中断或者子模块没拉全不要重新clone直接进仓库刷新子模块cd PX4-Autopilot git submodule update --init --recursive这个命令可以反复执行不会破坏已有内容。我有一次网络不好子模块拉了四遍才齐靠的就是这个命令。如果你需要checkout老版本比如想用v1.12或者某个历史commit切换版本之后务必再跑一次git submodule update --init --recursive。老版本对应的子模块版本也老如果不更新编译时会报一堆莫名其妙的头文件找不到。3.2 编译SITL固件在源码根目录执行make px4_sitl gz_x500这是v1.15及以上的新启动方式。如果是v1.14用make px4_sitl gazebo-classic_iris首次编译会持续挺久取决于机器配置一般十分钟到半小时。编译过程会生成build/px4_sitl_default/目录里面是编译产物。编译结束后终端会自动进入pxh交互式shell同时Gazebo界面会自动启动屏幕上出现一架四旋翼模型。看到这几个现象环境就算跑通了。这里有个很重要的细节make px4_sitl gz_x500这个指令本质上是“编译固件 启动Simulator 启动Gazebo”的快捷方式。如果你只想编译不想启动仿真可以用make px4_sitl_default或者是先make px4_sitl等编译完进入pxh shell后再手动输入simulator start gz启动仿真器。这种方式方便分段排查问题。3.3 从pxh shell起飞降落pxh shell是PX4的命令行接口类似飞控的调试终端。在这个终端里输入commander takeoff飞机会自动解锁并垂直起飞到默认高度。起飞后你可以在QGC的地图界面看到飞机位置变化。降落指令是commander land飞机会自动降落并锁定。另一个常用指令是查看系统状态status这个命令会打印出当前飞控的模式、电池电压、GPS卫星数、位置估值等。在SITL里这些数据都是仿真生成的但格式和真机完全一样可以提前熟悉这些输出。pxh shell里还能改参数和QGC里的参数面板效果一样param set MIS_DIST_1WP 50这条命令把默认任务距离设成了50米后面跑航线任务时会用到。3.4 QGC连接与界面验证启动SITL后QGC通常会在几秒内自动连接上。连接成功后QGC左上角会变成绿色地图上出现一架橙色的小飞机图案姿态仪表盘开始实时转动。如果QGC没有自动连接在SITL终端里检查MAVLink通信状态mavlink status正常情况下你会看到类似udp port 14540和udp port 14550的信息。14550是默认的地面站通信端口14540是PX4和外部程序通信的端口。这里需要注意一点SITL进程和QGC之间的通信走的是UDP在某些Linux系统上防火墙策略会把UDP广播拦掉。如果你确认端口正常但QGC连不上检查一下系统防火墙sudo ufw status如果防火墙是开启状态可以把14550端口放行或者干脆在开发机上关掉防火墙。我自己的开发机是不开防火墙的毕竟本地回环加家庭局域网没有太大安全风险。4. 仿真里的高频调试技巧4.1 用虚拟摇杆练手SITL里没有真实的遥控器硬件但QGC内置了虚拟摇杆功能。打开QGC的“设置 - 操纵杆”勾选“启用虚拟操纵杆”然后在你键盘上按键就能模拟遥控器输入。默认映射是这样的W/S控制升降A/D控制横滚方向键上下控制油门方向键左右控制航向。实际按键映射可以在“遥控器设置”页面里自定义。虚拟摇杆对练指法很有用但手感上跟真实摇杆差别还是挺大的真机试飞前建议用带USB的遥控器硬件再练一把。虚拟摇杆要真正控制飞机还需要把飞行模式切到“手动模式”或“姿态模式”。在QGC左上角的飞行模式下拉框里选“Position”定点或“Altitude”定高然后用键盘油门缓慢推升飞机才会跟随摇杆指令运动。4.2 模拟GPS失效、风场干扰这些极端情况仿真环境最大的优势之一是可以人为制造传感器故障用来验证飞控的容错逻辑。用param set命令可以直接改参数# 模拟GPS故障断开GPS数据源 param set SYS_FAILURE_EN 1不过更彻底的方式是修改Gazebo模型文件。Tools/simulation/gazebo-classic/models/iris/iris.sdf里定义了各种传感器插件你可以把GPS插件注释掉再启动仿真飞控就会进入无GPS状态。你会发现飞机无法使用“定点”模式只能依赖视觉或光流定位。这一套测试流程真机上做一次要好几天仿真里两分钟搞定。模拟风场也很有用。在Gazebo的world文件比如Tools/simulation/gazebo-classic/worlds/iris.world里可以手动添加风场插件。我在自定义world时会在wind节点里设置不同方向的风速用来测试位置控制器的抗风能力。新版的gz sim环境变量模型库路径有所变化如果你用v1.15的gz_x500对应的模型和world路径在Tools/simulation/gz/目录下。改文件之前先确认你的仿真器版本别找错目录。4.3 多机仿真怎么起PX4官方提供了多机仿真脚本源码目录下的Tools/simulation/gazebo-classic/sitl_multiple_run.sh可以同时启动多架飞机。用法是先编译好固件然后执行cd Tools/simulation/gazebo-classic ./sitl_multiple_run.sh 0 1 2 3这个脚本会启动4个SITL实例每架飞机用不同的端口和模型实例。QGC里会同时看到4架飞机可以分别指挥它们。多机仿真的端口规划是个容易出错的地方。每架飞机除了有独立的Gazebo模型还有独立的MAVLink端口。最稳妥的方式是给每个实例设置不同的PX4_INSTANCE环境变量QGC会自动发现它们。多机仿真对电脑性能要求比较高我建议至少16G内存以上再尝试4机同跑否则Gazebo的物理引擎容易卡顿导致仿真时钟变慢。4.4 自定义机型的入口如果你想在自己的无人机构型上做开发PX4的自定义机型入口在ROMFS/px4fmu_common/init.d-posix/airframes/目录下。每个机型一个文件从1001_iris到6001_hexarok_x这类编号命名。自定义异构飞行器的基本思路是新增一个机型描述文件定义机架类型、电机布局、混控器映射然后在编译时指定这个机型。混合器文件在ROMFS/px4fmu_common/mixers/目录下定义了电机输出和机身几何之间的关系。这个方向比较深不在Module 6的基础范围里但我要提醒一点改自定义机型后先跑SITL验证电机转向、混控方向是否正确再考虑真机。我在自研六旋翼时就是先改了混控器在仿真里发现两个电机转向反了如果直接上真机起飞瞬间基本就翻了。5. ROS2和PX4仿真联动5.1 需要准备哪些组件ROS2和PX4的联动是通过px4_ros_com和px4_msgs这两个仓库实现的。px4_msgs定义了ROS2消息类型px4_ros_com则负责把MAVLink消息翻译成ROS2话题。在PX4 v1.15及以上版本中官方提供了px4_ros_com直接基于uORB的桥接方案和旧版MAVLink转发方案相比延迟更低、消息更丰富。这也是我建议新项目直接用v1.15的原因之一。版本对应关系上Ubuntu 22.04对应ROS2 HumbleUbuntu 24.04对应ROS2 Jazzy。你可以在PX4官方文档的ROS2指南页面看到详细的兼容矩阵。记住一个原则先确定PX4版本再根据PX4版本选择ROS2版本而不是反过来。5.2 一个最简可跑的Demo完整流程是创建工作空间clonepx4_msgs和px4_ros_com用colcon build编译然后启动SITL和ROS2桥接节点。假设你已经按照前面流程启动了一个SITL实例接下来只需要# 在工作空间里编译ROS2接口 cd ~/ws_px4_ros2/src git clone https://github.com/PX4/px4_msgs.git git clone https://github.com/PX4/px4_ros_com.git cd ~/ws_px4_ros2 colcon build # 启动桥接 source install/setup.bash ros2 launch px4_ros_com sensor_combined_listener.launch.py桥接节点启动后另开一个终端订阅PX4的姿态话题source /opt/ros/humble/setup.bash ros2 topic echo /fmu/out/vehicle_attitude如果你能看到姿态四元数在不停更新说明ROS2和PX4仿真之间的数据通路已经打通了。此时你就可以在ROS2侧写节点发布速度设定值或者位置设定值给PX4实现offboard控制。我这里要特别强调fcu_url的配置。PX4 SITL默认会监听UDP 14540端口ROS2桥接节点需要指定正确的连接地址。在offboard_control.launch.py里fcu_url默认可能是udp://:14540127.0.0.1:14557如果你改了SITL的端口这里也要对应修改。6. 实战中高频问题的排查实录6.1 Gazebo启动后黑屏或模型加载不出来这是最经典的问题。表现形式是make命令执行到一半Gazebo窗口出现了但里面空荡荡的没有飞机模型或者只有地面没有飞机。第一步排查思路确认你是用官方标准模型启动的还是自己改过模型。如果改过先恢复默认模型再试。第二步清理缓存。Gazebo会把模型文件缓存在~/.gazebo/models目录下缓存文件损坏会导致模型加载失败rm -rf ~/.gazebo删除后重新启动仿真Gazebo会重新下载模型库。这个操作不会影响PX4源码可以放心执行。第三步检查模型路径环境变量echo $GAZEBO_MODEL_PATH在正常配置下这个变量应该包含PX4源码中模型库的路径比如~/PX4-Autopilot/Tools/simulation/gazebo-classic/sitl_gazebo/models。如果为空说明环境没有正确加载重新执行make px4_sitl gazebo-classic_iris时会自动设置。新版gz sim的路径检查方式略有不同用的是GZ_SIM_RESOURCE_PATH。如果你用的是v1.15检查的是这个变量。6.2 编译报错内存不足和Python依赖问题编译PX4时最常见的报错是internal compiler error: Killed (program cc1plus)。这个错误十有八九是内存不够GCC编译大文件时直接被Linux内核OOM杀了。解决办法有两个一是给系统增加swap空间二是降低并行编译等级。用make px4_sitl gazebo-classic_iris -j4可以把并行任务数降到4降低内存峰值。如果你用的是8G内存的机器我用实测经验告诉你加8G swap能明显改善编译体验。Python相关的编译错误也很常见。PX4的构建系统会用到empy、jinja2、kconfiglib这些Python包。如果你用系统的pip3安装过其他包版本冲突可能导致PX4编译失败。建议在PX4源码目录下单独创建虚拟环境或者直接按官方脚本的依赖列表安装pip3 install --user empy3.3.4 jinja23.0.3 pyyaml numpy rospkg注意empy这个包新版和旧版语法不兼容PX4目前主要适配的是3.x版本。装个4.x版本大概率会报错。6.3 QGC连接不上SITLQGC连接不上SITL时先看SITL终端有没有报错。如果mavlink status显示端口正常问题大概率出在QGC一侧。一个很常见的坑QGC启动时默认只监听本机的MAVLink如果SITL和QGC在同一台机器上通常没有问题。但如果你用了Docker跑SITLQGC在宿主机上就需要把SITL的UDP端口映射到宿主机并且QGC要配置“添加链接”手动指定端口。QGC里手动添加链接的方法是设置 - 通信连接 - 添加 - 选择UDP(监听端口填14550)或者直接填udp://:14550。如果你在Docker里跑PX4记得在docker run参数里加-p 14550:14550/udp。还有一种情况你在终端里先启动了QGC然后启动了SITL。QGC启动时可能没有检测到MAVLink广播。解决办法是重启QGC或者SITL启动后按一下QGC的“重新连接”按钮。6.4 仿真中飞机姿态乱飘或不受控如果飞机在仿真里刚起飞就开始满屏乱飞首先要确认虚拟摇杆有没有输入。在pxh shell里输入listener vehicle_attitude观察姿态数据是不是在持续变化。如果数据正常但飞机就是不受控大概率是Gazebo的物理参数和PX4控制参数不匹配。常用的做法是检查world文件的仿真时间步长在physics节点里确认max_step_size是否为0.001。另外一个容易被忽视的点PX4 SITL默认启动的模型是iris四旋翼但如果你改了PX4_SIM_MODEL环境变量而Gazebo里加载的模型和这个环境变量不匹配飞控的控制分配就会错乱。检查一下环境变量是否残留了之前自定义机型配置unset PX4_SIM_MODEL再重新启动仿真多半就能恢复正常。6.5 老版本代码在24.04上编译失败我遇到过有人用Ubuntu 24.04去编译PX4 v1.12的老版本结果在CMake阶段就报错提示编译器不支持某些参数。原因很简单老版本PX4是在老工具链下开发的新系统的GCC版本、Boost版本、Python版本都变了源码里有些写法在新编译环境下就过不去。解决方案有几个按推荐程度排序一是直接用旧版本的Ubuntu。比如v1.12时代的主流环境是Ubuntu 18.04你如果有旧电脑或者虚拟机装18.04来编译老版本代码问题最少。二是用Docker。PX4官方维护了带完整编译环境的Docker镜像比如px4io/px4-dev-base你可以用对应tag拉取镜像在容器里编译和仿真。Docker的好处是环境隔离不会污染你主系统的工具链。三是尽量升级PX4到新版本。如果你的诉求只是学习老代码的思路建议先看源码了解逻辑实操还是用新版本。老版本里的很多内部API在v1.15里已经改名了花时间纠结老版本的环境配置性价比不高。7. 关于这套环境我最后想说的几点体会折腾PX4仿真这么多年我对它的态度一直在“真香”和“真烦”之间反复横跳。真香的是调试效率提升不是一点半点真烦的是环境本身的复杂度对新手确实不太友好。我的习惯是每搭一套环境就随手记一个环境笔记把PX4版本、Gazebo版本、Ubuntu版本、QGC版本、ROS2版本以及几个关键环境变量都写下来。这样一旦某个环节出问题可以快速定位是不是版本组合变了。这个习惯救过我很多次。另外建议在VSCode里直接打开PX4-Autopilot源码目录配合C/C插件做代码跳转和断点调试。SITL本身就是Linux进程可以像调试普通程序一样打断点。我在调试姿态控制器时直接在src/modules/mc_att_control里打断点变量变化看得清清楚楚比盲调参数效率高太多。最后一个建议把官方文档里的Simulation页面通读一遍。很多人习惯遇到问题先搜中文论坛但PX4迭代很快文档更新往往比论坛帖子及时。官方文档的版本切换按钮在页面左上角一定记得把它切换到和你源码版本一致的档位不然看到的可能是旧接口的用法会让你越看越迷糊。这套环境搭好之后后面无论是做自主航线、机载视觉还是集群协同都有了可以反复折腾的实验田。祝各位起飞顺利少炸机。
返回列表