先交代一下背景。我给不少同事和朋友搭过PX4开发环境,也见过有人折腾了两三天,最后不是卡在源码编译上,而是倒在了最前面那几步:依赖包下载到一半中断,子模块拉取失败,换一台机器又得重来一遍。这篇文章就是围绕PX4开发环境搭建的一次完整复盘,把从版本选型、离线资源准备、依赖安装、首次编译到仿真验证的全过程拆开讲清楚。核心目标只有一个:让你在普通网络条件下、不用反复重试那些下载步骤,也能顺顺当当把环境跑起来,最快把时间压缩到接近标题说的五分钟量级。
适合两类人看:一是刚接触PX4、被各种教程和报错劝退的新手;二是需要在多台电脑上反复重建环境、想节省时间的进阶用户。下文用到的方案和资源我都实际跑过,你可以直接照抄,也可以根据自己场景改。
1. 先想清楚:你需要的不是“装个软件”,而是一套组合拳
很多第一次搭PX4环境的人,最大的误区是把它当成“下载一个安装包双击下一步”。等真正动手才发现,这是一整套工具链的叠加:源码、交叉编译工具链、依赖库、仿真器、地面站,各干各的活,配合起来才能跑。
1.1 PX4开发环境的几个组成部分
我自己在给新人讲解时,习惯把这套环境分成五块:
- PX4源码本体:也就是PX4-Autopilot仓库,所有飞控逻辑、驱动、通信模块都在里面。
- 编译工具链:PX4固件要跑到STM32等ARM平台上,需要ARM交叉编译工具链;PC仿真模式下还需要原生gcc/g++。
- 系统依赖库:CMake、Python、protobuf、Qt、FastRTPS等,具体清单随PX4版本变化,官方在
Tools/setup/目录下提供了自动化安装脚本。 - 仿真器:Gazebo(包括Classic和新的gz sim)、jMAVSim,用于在电脑上模拟无人机飞行。
- 地面站:QGroundControl(QGC),用来与仿真或实物飞控通信、查看状态、调参。
你可以把PX4源码理解为飞机的“大脑程序”,工具链是“编译车间”,仿真器是“虚拟风洞”,地面站是“仪表盘”。缺一样,整套开发流程就转不起来。
1.2 版本选型是环境搭建成败的第一决定因素
我强烈建议:先定版本,再动手安装。很多环境搭不起来的案例,根因就是盲目下了最新main分支,结果依赖脚本、编译器版本和文档全部对不上。
我把常见版本的选择因素列成了一张表:
| 版本 | 工具链复杂度 | 仿真器 | 稳定性 | 适用场景 |
|---|---|---|---|---|
| PX4 v1.12.3 | 低 | jMAVSim、Gazebo Classic | 老牌稳定 | 老机型、旧教程配套 |
| PX4 v1.14.3 | 中 | Gazebo Classic、gz sim | 稳定 | 目前最推荐的入门版本 |
| PX4 main | 高 | 新仿真为主 | 变动频繁 | 想追新特性、不介意踩坑 |
我自己主力使用v1.14.3,原因很直接:它的官方依赖脚本和文档最成熟,Gazebo Classic还能用,网上问题反馈也最多,遇到报错随便搜都能找到解法。v1.12.3虽然老旧,但如果你手头的教程是基于它的,也别纠结,一样能跑通。
1.3 仿真器那点事:Gazebo Classic和gz sim别混为一谈
v1.14.x处于仿真器交接期,官方默认脚本还会装Gazebo Classic,但新的gz sim也开始支持。这两个仿真器不能混用,比如你启动命令用了make px4_sitl gazebo-classic,环境里必须装了对应版本的Gazebo;如果要用make px4_sitl gz_x500,则需要装好gz sim。教程和命令版本对不上,最容易出现“启动仿真后黑屏/闪退/找不到模型”的怪问题。所以这一步虽然不起眼,但前期没确认,后期全是泪。
2. 把最耗时的下载环节提前干掉:离线资源包方案
既然目标是在普通网络条件下快速搭建,核心思路不是祈祷下载速度快,而是干脆把下载环节从“实时进行”改成“前置一次性完成”。这就是离线资源包的价值。
2.1 为什么要把下载环节“前置”
PX4源码是个巨型仓库,子模块极多。我第一次用git clone --recursive拉取v1.14.3完整源码时,光传输就断断续续,最后检查子模块还发现有缺失。依赖安装阶段更头疼,apt和pip要拉几十上百个包,任何一个超时中断都可能导致安装不完全,后续编译报错根本没法看。
把下载环节提前做成离线资源包,相当于把所有外部变量都锁死了。资源包校验没问题,剩下的安装就是本地文件操作,速度自然快,也更可控。
2.2 资源包清单和目录结构
我整理的百度云资源包结构大致如下:
px4_v1.14.3_offline/ ├── sources/ │ └── PX4-Autopilot-v1.14.3-full.tar.gz # 完整源码,含子模块 ├── toolchains/ │ ├── gcc-arm-none-eabi-xxx.tar.bz2 # ARM交叉编译工具链 │ └── cmake ninja protobuf相关deb包 ├── apt_cache/ │ └── archives(apt下载缓存,安装依赖时直接复用) ├── pip_cache/ │ ├── pip_download.tar.gz │ └── requirements.txt └── scripts/ ├── ubuntu.sh(官方依赖脚本) └── setup_offline.sh(封装好的离线安装脚本)关键点:
- 源码包必须是完整版,内含所有submodule和LFS文件,打包前我用
git lfs pull确认过LFS对象都拉到了本地。 - 工具链建议下载官方提供的
gcc-arm-none-eabi压缩包,而非通过apt安装,因为版本可控。 - apt_cache是活宝。你可以在联网条件好的机器上先跑一遍官方依赖脚本,然后把
/var/cache/apt/archives/下的deb导出,拿到另一台机器上离线安装。 - pip_cache同理,用
pip download把依赖下载好,离线安装时指定--find-links即可。
资源包的下载链接我放在评论区,需要的朋友自取。如果你因为某种原因拿不到,也可以按这个方法论,先在一台网络较好的机器上自己攒一套,一劳永逸。
2.3 校验和管理的几个经验
这步别跳过。我自己的习惯是:
- 下载完成后先计算哈希值,和资源包里的
sha256sum.txt对照,避免文件损坏。 - 所有压缩包统一解压到
~/tools和~/PX4-Autopilot,目录一乱,后面环境变量就烦了。 - 把资源包单独存档,下次换电脑直接拷贝,不用重复下载。
如果在线下载遇到中断,建议使用支持断点续传的下载工具,别重新来一遍。
3. 从零搭到能编译:完整实操步骤
这套步骤我在Ubuntu 22.04上完全跑通过,Ubuntu 20.04也没问题。物理机、云主机、WSL均有成功案例,但物理机和云主机更省心,WSL在图形界面上有时需要额外处理。
3.1 系统准备与软件源配置
先把系统更新到最新,避免依赖版本太旧:
sudo apt update && sudo apt upgrade -y接着配置软件源镜像。这一步很关键,直接决定后续安装速度。我习惯把/etc/apt/sources.list里的官方源替换为国内常用镜像源,替换前先备份。如果是全新系统,这一步做完,后续apt install的速度会明显提升。
如果是Python相关依赖,建议同时配置pip源,创建~/.pip/pip.conf:
[global] index-url = https://pypi.tuna.tsinghua.edu.cn/simple trusted-host = pypi.tuna.tsinghua.edu.cn3.2 解压源码并检查子模块
把离线源码包解压到固定位置:
mkdir -p ~/src tar zxvf PX4-Autopilot-v1.14.3-full.tar.gz -C ~/src cd ~/src/PX4-Autopilot然后检查子模块是否完整:
git submodule status如果输出每一行开头不是-,说明子模块齐全。如果某些子模块显示为-,说明打包时没包含完整,需要拉取。这里也提醒一句:检查子模块这一步一定别省,很多人编译报“找不到xx头文件”,查到最后就是子模块缺失导致的。
3.3 依赖安装:优先跑官方脚本,但别当甩手掌柜
进入Tools/setup/目录,找到ubuntu.sh。官方脚本会自动安装一堆系统依赖,命令如下:
bash ./ubuntu.sh --sim--sim参数表示安装仿真相关依赖。我在离线资源包中已经包含脚本和必要的deb缓存,所以跑起来基本不依赖网络。
但我的经验是:不要无脑等脚本跑完,要盯着输出。有几次脚本中途报错退出,原因五花八门,但常见的有:
- 某个deb包没进缓存,导致apt install失败;
- Python包下载超时;
- 系统已有版本冲突。
遇到中途失败,不必从零开始重跑。把命令再执行一遍即可,脚本是幂等的,前面装好的部分会被跳过。
3.4 ARM交叉编译工具链的特殊处理
如果你不打算只是仿真,还要交叉编译真实固件(比如make px4_fmu-v5_default),就需要ARM工具链。我从不直接用apt装,因为版本经常跟PX4要求不一致。
推荐手动安装到~/tools:
cd ~/tools tar xjf gcc-arm-none-eabi-xxx.tar.bz2 export PATH=~/tools/gcc-arm-none-eabi-xxx/bin:$PATH把export写入~/.bashrc,并确认:
arm-none-eabi-gcc --version看到版本号就说明工具链可用。这一步滞后到编译真实固件前再弄也行,但既然离线包都备好了,就顺手装了。
4. 首次编译与Gazebo仿真验证:五分钟切换回来
环境准备完毕,终于到了检验成果的时刻。编译是PX4环境搭建的“期末考”,也是答疑群里提问率最高的一环。
4.1 选对make命令
启动不同仿真器,对应的make命令完全不同。v1.14.3里我常用的组合是:
| 目标 | 命令 |
|---|---|
| Gazebo Classic + 默认飞机 | make px4_sitl gazebo-classic |
| Gazebo(新)+ X500四旋翼 | make px4_sitl gz_x500 |
| jMAVSim | make px4_sitl jmavsim |
| 仅编译SITL,不启动仿真 | make px4_sitl |
| 编译真实固件PMUv5 | make px4_fmu-v5_default |
新手最困惑的就是px4_sitl这个名称。它指“Software In The Loop”,也就是在PC上跑飞控软件,不涉及真实硬件。理解了这个,命令就不会记错。
4.2 编译耗时的心理准备
标题说“5分钟搞定”,这里要交代清楚:如果用的离线缓存包,依赖安装确实可以压缩到几分钟;但首次编译受处理器性能影响很大。我自己的机器(8核16线程)首次编译大概8到12分钟,老双核机器可能要到30分钟以上。这个不是网络问题,是CPU在跑编译任务,急不来。
首次编译影响体验的另一个因素是并发度。默认脚本会根据CPU核数开并行任务,如果你内存只有8GB,并行太猛容易直接OOM。建议在编译前限制一下:
make px4_sitl gazebo-classic -j4-j4表示4个并行任务。内存小的机器用-j2更稳。编译过程输出很长,看到[100%]或Built target字样,说明编译成功。
4.3 启动仿真,验证环境真的通了
编译成功后,命令行会卡在等待模式,同时弹出Gazebo窗口,里面出现一架多旋翼模型。这说明SITL已经跑起来了。
此时可以打开另一个终端,输入:
cd ~/src/PX4-Autopilot source Tools/simulation/gazebo-classic/setup_gazebo.bash export GAZEBO_MODEL_PATH=...(按官方提示) python3 Tools/gazebo/ground_truth_setup.py不过实际上更简单的验证方式是观察Gazebo窗口里的飞机是否出现,以及命令行里是否持续输出PX4飞控日志,比如INFO [commander] Armed by internal command等。
没有图形界面的环境(比如纯WSL命令行)可能弹不出Gazebo窗口,这一节后续单独说。
4.4 用QGC连接,完成闭环验证
环境通不通,最有说服力的验证是让地面站和飞控通信上。启动QGroundControl,它会自动发现SITL进程,在界面上能看到多旋翼的姿态数据、电池状态、GPS信号(仿真数据),甚至可以解锁电机看螺旋奖转动。
这一步的意义在于:它证明从“源码 → 编译 → 仿真 → 地面站”的整条链路全部正常,后面做PX4二次开发、改代码、加模块时,你才有一个可靠的验证平台。
5. 搭建中的高发问题与排查思路
说了这么多顺利的情况,下面聊聊我实际踩过、也看群友反复踩的坑。每个问题我都会写一个完整的排查链路,而不是只给结果。
5.1 Git LFS导致源码不完整,症状极隐蔽
我遇到过最坑的一次:源码能正常解压,编译也不报错,但仿真里飞机模型贴图全白、GPS数据异常。查了很久,最终定位是资源包制作时LFS文件没有拉全,某些二进制模型文件是空的。
排查链路:
- 先看
git lfs ls-files,确认所有LFS文件都已存在; - 在源码目录执行
git status,如果有文件显示被修改,多半是LFS指针文件残留; - 解决办法是重新
git lfs pull后再打包。
经验:做资源包时,git lfs pull的输出也要检查,不能只看有没有报错。
5.2 Python依赖版本冲突,报错却指向编译器
v1.14.3对Python依赖有明确版本要求,但如果你同时装了ROS或其他框架,可能会把系统Python包搞乱。表现是编译到一半,报ModuleNotFoundError或ImportError,但上一行还在出现g++编译指令,非常误导人。
排查链路:
- 先看完整报错,不要只看最后一行;
- 进入
Tools/setup/目录,找到requirements.txt,用pip install -r安装指定版本; - 确认当前环境的Python版本与脚本要求一致。
我之前就是被报错表面前半段骗了,一直在排查编译器版本,浪费了一下午。
5.3 编译内存不足,直接OOM卡死
这种问题最常见于8GB内存的笔记本。现象是编译到一半,系统变卡,然后终端输出Killed,或者直接黑屏重启。
排查和解决:
- 查看内存:
free -h,确认编译时内存使用情况; - 重启后先用
make clean清理,再降低并行度重编; - 最省内存的方式是
make px4_sitl -j1,慢但稳定。
如果连-j1都OOM,可能需要先关掉浏览器等大内存程序,或者换物理机/云主机。
5.4 仿真器启动失败,Gazebo黑屏一直转圈
原因很多,我只说最高频的三种:
- 环境变量没设置:运行
gazebo-classic前必须sourcesetup_gazebo.bash,否则模型路径找不到,Gazebo里空荡荡的。 - 显卡驱动问题:如果是云主机或虚拟机,3D加速往往缺失,会卡在“应用中”。这只影响显示,不影响PX4进程,实在不行可以加
--no-window或使用jmavsim这种轻量仿真。 - 端口被占用:QGC或其他SITL实例占用了14540等端口,起飞前会报连接错误。用
netstat -tunlp | grep 14540检查,杀掉占用进程即可。
5.5 WSL特殊注意事项
WSL2跑PX4仿真,很多人反映Gazebo窗口显示异常。两种常用解决方案:
- 安装WSLg,通常Windows 11直接支持,Ubuntu内图形窗口会自动弹出;
- 如果不行,改用Godot或jMAVSim等轻量仿真。
但我要提醒一句:WSL对USB设备的透传不如物理机方便,如果你后面要接真实飞控开发,建议早点切到物理机或双系统,避免环境返工。
6. 环境跑通后的目录结构:找到二次开发的入口
环境跑通不是终点,对大多数人来说,真正的目标是PX4二次开发:改控制算法、加自定义模块、调参数。这时候熟悉目录结构就非常重要。
6.1 一定会用到的几个目录
我在源码里最关注的目录有这几个:
| 目录 | 作用 |
|---|---|
src/modules/ | 核心功能模块,如mc_pos_control、mc_att_control、navigator |
src/drivers/ | 驱动代码,比如PWM输出、IMU、GPS驱动 |
msg/ | uORB消息定义,改数据结构时必来 |
Tools/setup/ | 环境安装脚本,环境重建时最有用 |
ROMFS/ | 内置参数和启动脚本,PX4启动顺序在里面 |
build/ | 编译产物,出了问题先看这里 |
二次开发的第一步,往往是看某个模块的源码,改完重新编译,然后用仿真验证。所以环境能不能快速重建、编译链路是否清晰,直接影响开发效率。
6.2 常用命令速查
下面这份命令清单,我自己写进了笔记,每次换机器都照做:
# 编译并启动Gazebo Classic仿真 make px4_sitl gazebo-classic # 只编译不启动仿真 make px4_sitl # 编译真实固件 make px4_fmu-v5_default # 清理编译缓存 make clean # 查看当前配置 make list_config_targets # 分布式编译加速(机器多的时候) make px4_sitl gazebo-classic -j$(nproc)环境变量方面,每次新终端建议先source一下相关设置,否则可能出现找不到模型路径之类的怪问题:
source ~/src/PX4-Autopilot/Tools/setup_gazebo.bash6.3 把这套环境固化成你的“开发模板”
我的习惯是:跑通一次之后,立刻做三件事。
- 第一,把整个源码目录打成一个tar包,作为未改动的原始基线,以后改坏了直接解压覆盖;
- 第二,将依赖脚本和pipeline固化成文档,写清楚版本号;
- 第三,把QGroundControl的配置文件导出备份,避免重装后重新配一遍。
这样不管是换电脑、还是给同事搭环境,都能快速交付,不需要每次都经历一遍完整的依赖安装。
另外分享一个小技巧:如果你准备长期做PX4二次开发,建议在虚拟机里留一份快照。每次闯祸了,恢复快照比重新搭环境快得多。把离线资源包也保存在虚拟机共享目录里,双重保险。