我最早接触PX4那会儿,最头疼的不是飞控逻辑有多复杂,而是环境半天搭不起来。当时照着网上各种帖子折腾Ubuntu、装依赖、拉源码,每一步都可能踩坑,最后好不容易编译通过,又要折腾QGC地面站和IDE调试。尤其是用Qt Creator看代码、打断点调试PX4源码,网上能说清楚的教程很少。这篇文章我就把在Ubuntu 18.04上从零搭建PX4开发环境的完整过程写出来,覆盖固件编译、仿真运行、QGC连接以及Qt Creator工程配置,尽量把你可能遇到的问题一次性讲透。
这篇内容适合两类人看:一类是刚接触PX4、想在PC上跑SITL仿真的新手;另一类是已经能编译固件,但想在Qt Creator里调试PX4代码、搞懂飞控内部逻辑的进阶学习者。我会顺着实际的搭建顺序走,每一步都讲清楚为什么要这么做,而不是只甩一串命令让你复制。
1. 搭建PX4开发环境之前,先搞懂这套工具链是怎么协作的
1.1 PX4固件、QGC地面站、Qt Creator各自扮演什么角色
很多新手上来就急着敲命令,结果环境装到一半就乱了。我建议先花两分钟把工具链的关系理清。
PX4是一个开源的飞控固件项目,平时我们说的“编译PX4”,实际是把PX4 Firmware源码编译成能在仿真环境或真实飞控硬件上运行的固件。在Ubuntu上最常见的编译目标是px4_sitl_default,也就是把PX4编译成计算机上的仿真进程,配合Gazebo或jMAVSim模拟出飞机姿态、传感器数据,让我们的地面站和控制代码像操作真机一样跟它交互。
QGC(QGroundControl)是PX4官方推荐的地面站软件,主要负责飞控状态显示、地图规划、参数调整、航迹规划等。在仿真阶段,QGC会从UDP端口接收PX4仿真进程发出来的MAVLink遥测数据。这样你在QGC上看到的高度曲线、姿态角变化,其实都来自仿真数据。
Qt Creator则是开发调试工具。PX4源码体量不小,纯用vim看代码会很难受,而Qt Creator提供了一套良好的CMake工程支持,可以索引整个PX4源码、跳转定义、打断点调试。把PX4源码导入Qt Creator之后,你才算是真正进入了“能看能改能调”的阶段。
1.2 版本匹配:Ubuntu 18.04和PX4固件分支的兼容性
现在PX4官方对新版本Ubuntu的支持越来越激进,比如Ubuntu 20.04、22.04甚至24.04都有对应的工具链支持脚本。但总有人因为各种原因还在用Ubuntu 18.04,比如实验室里的旧电脑、公司内部指定系统,或者是照着老教程学习。Ubuntu 18.04对应的PX4版本建议控制在v1.13.x及以前,往上更新版本的PX4代码和依赖库可能对CMake、Python版本有更高要求,编译时容易出幺蛾子。
我习惯这样处理:先确定自己用的PX4版本分支,再阅读根目录下的README.md或Tools/setup/目录里的脚本说明。比如PX4 v1.12和v1.13版本的编译工具链要求差异并不大,Ubuntu 18.04都能支持。等环境跑通之后,再考虑要不要切换新版本。
另外要强调的是,Ubuntu 18.04自带的Python版本是3.6,PX4相关的很多工具链脚本对Python版本比较敏感。如果后续要跑Tools/setup/ubuntu.sh,脚本会自动安装一系列依赖,但有时候会因为网络问题或软件源版本过旧而失败。后面我会专门讲这个坑。
2. Ubuntu 18.04系统层面的准备:换源、依赖安装和Python环境
2.1 先更新软件源和基础系统包
我见过太多人在还没更新系统的情况下直接装PX4依赖,结果装到一半报找不到某些包。正确的流程是先把软件源切到国内镜像源(如果你的网络访问官方源速度慢)或者至少确保系统包索引是最新的。
在Ubuntu 18.04上,软件源配置文件是/etc/apt/sources.list。如果你用的是清华源或阿里源,把原来的archive.ubuntu.com和security.ubuntu.com替换成对应镜像地址就行。换完源之后执行:
sudo apt update sudo apt upgrade这一步能避免很多“找不到软件包”的问题。比如PX4编译依赖里有个exiftool,它的Ubuntu软件包名是libimage-exiftool-perl,如果你没更新软件源,可能就搜不到这个包。
2.2 PX4官方依赖脚本与手动安装的取舍
PX4官方在源码仓库的Tools/setup/目录下提供了依赖安装脚本ubuntu.sh。理论上一条命令就能装完所有依赖:
bash ./Tools/setup/ubuntu.sh但实际跑起来经常会遇到两个问题:一是脚本会下载安装Miniconda,用于管理Python环境;二是它默认安装的Gazebo版本可能与你Ubuntu 18.04系统自带的库冲突。所以我自己更倾向于半自动方式:先手动安装基础编译依赖,再用脚本补全特殊依赖。
基础编译依赖包括:
sudo apt install -y \ git zip cmake build-essential ninja-build \ genromfs exiftool astyle libncurses5-dev \ libxml2-utils vim-common libgstreamer1.0-dev \ libgstreamer-plugins-base1.0-dev \ protobuf-compiler libprotoc-dev libprotobuf-dev \ python3-pip python3-dev python3-venv这里ninja-build是PX4推荐使用的构建工具,编译速度快、错误信息可读性好。cmake需要确保版本不低于3.10.2,Ubuntu 18.04自带版本通常满足,但如果你之前手动装过别的版本,要注意路径冲突。
2.3 Python环境的处理:避免pip和系统Python打架
Ubuntu 18.04的默认Python 3.6比较老,PX4的一些工具链脚本虽然能兼容,但如果你用pip给系统Python盲目装包,很容易破坏系统环境。我建议用虚拟环境隔离。
创建一个专门的虚拟环境目录,比如~/px4_venv:
python3 -m venv ~/px4_venv source ~/px4_venv/bin/activate pip install --upgrade pip pip install pyulog pymavlink这里pymavlink是编译和仿真中可能会用到的MAVLink工具库,pyulog用于解析ULog飞行日志。在编译PX4源码时,部分脚本会调用python3,如果你在虚拟环境里编译,需要确保解释器指向正确。
但另一个麻烦是,Gazebo和其他工具链脚本可能依赖系统Python而不是虚拟环境。所以我的做法是:编译PX4时在虚拟环境下执行,如果遇到脚本找不到系统库,再退出虚拟环境用系统Python编译。这种“优先隔离、必要时灵活切换”的方式,比强求一个固定解要省心很多。
3. PX4固件源码的拉取、子模块初始化和第一次编译
3.1 使用git clone拉取PX4源码
PX4固件源码托管在GitHub上。由于历史原因,很多初学者喜欢直接下载ZIP包,这样后期很难管理子模块,也无法切换分支。正确方式是用git clone:
mkdir -p ~/src cd ~/src git clone --recursive https://github.com/PX4/PX4-Autopilot.git -b v1.13.2这里我给了一个具体的版本号v1.13.2。如果你不确定用哪个版本,可以先不指定-b,clone默认主分支,但主分支的代码在Ubuntu 18.04上可能会遇到CMake版本不够的问题。所以建议第一次搭建时选一个明确版本。
--recursive参数会同时拉取所有子模块。PX4有大量子模块,比如固件依赖的mavlink库、各种硬件驱动、图传协议库等。如果网络状态不太好,子模块拉取容易中断,导致后期编译报找不到头文件。
3.2 子模块更新的标准操作
有时候即使用了--recursive,子模块依然可能因为网络问题没有拉全。判断方法很简单:进入PX4源码目录,执行:
git submodule status如果有子模块路径前面是负号-,说明这个子模块没有正确初始化;如果是空格,说明正常同步。针对失败的子模块,单独更新:
git submodule update --init --recursive这个命令可以反复执行,它会自动补录缺失的子模块。在GitHub连接不稳定的情况下,可以试试改用深度较小的clone,比如git clone --recursive --depth 1,只克隆最新一次提交,体积会小不少,但要注意这样无法切换历史版本。
3.3 编译PX4 SITL仿真固件
第一次编译PX4,我建议直接编译仿真目标,因为不需要连接真实硬件,也不涉及交叉编译环境。进入PX4源码目录,执行:
cd PX4-Autopilot make px4_sitl_default gazebo这条命令做了三件事:先配置CMake构建目录,再编译SITL固件,最后启动Gazebo仿真环境。第一次编译耗时比较长,取决于CPU性能,通常在10分钟到30分钟之间,做好心理准备。
编译过程中如果提示缺少某些依赖,比如GStreamer库,就回头检查第2节的基础依赖是否装完。还有一种很常见的提示是cmake版本过低,这时需要手动升级CMake,不能只依赖apt安装。
3.4 编译完成后的启动验证
编译完成后,终端会打印一段启动信息,最后会拉起Gazebo界面,里面出现一架多旋翼模型。这时候PX4仿真进程已经在后台运行,默认监听UDP 14540端口,而QGC需要通过UDP 14550端口接收遥测数据。有人会在这里发懵:明明编译成功了,为什么QGC连不上?
原因在于PX4仿真进程启动时,只默认打开了连接仿真器的本地端口,并不会自动把数据转发给QGC。通常QGC运行在同一台计算机上时,会自动绑定UDP 14550监听端口,而PX4仿真进程默认也会向127.0.0.1:14550发送遥测数据,所以正常情况下QGC是可以直接连上的。如果连不上,到头来往往不是端口配置问题,而是QGC的版本、系统防火墙或者AppImage执行权限出了问题。
4. QGroundControl安装及与SITL仿真的连接
4.1 下载与安装QGC
QGC官方提供的是AppImage格式的Linux可执行文件。下载地址在QGC官网,选择Ubuntu版本的.AppImage文件。下载完成后,首先要给它可执行权限:
chmod +x QGroundControl.AppImage然后点击运行或通过命令行启动:
./QGroundControl.AppImage注意,QGC的AppImage依赖系统的FUSE库。Ubuntu 18.04默认可能没装,或者装了但版本不匹配。如果双击没反应,先到终端执行,看报什么错。如果提示libfuse.so.2找不到,执行:
sudo apt install libfuse2这个问题在Ubuntu 18.04上比较典型,因为我遇到过很多次,而且网上很多人卡在这一步。
还有一个更隐蔽的坑:QGC为了读取USB飞控设备,通常需要加入dialout用户组,否则后续连接真实飞控时会提示没有权限打开串口。即使你当前只是做仿真,我也建议提前执行:
sudo usermod -a -G dialout $USER然后注销重新登录,让用户组生效。
4.2 QGC与SITL仿真之间的连接配置
当你把PX4仿真跑起来,再打开QGC时,QGC会自动发现仿真飞控,界面右上角会显示连接状态为“Simulation”。如果没连上,先检查PX4仿真终端是否还在运行,再查看QGC的通信配置。
QGC的通信配置在“应用设置-通信连接”里,可以看到默认的UDP设置。PX4 SITL仿真时默认通讯链路是:
| 角色 | IP地址 | 端口 |
|---|---|---|
| PX4仿真进程发送遥测数据 | 127.0.0.1 | 14550 |
| QGC接收遥测数据 | 0.0.0.0 | 14550 |
| QGC发送控制指令 | 127.0.0.1 | 14540 |
其中14540是QGC向PX4发送指令的端口,PX4仿真进程会监听这个端口。如果你自己在代码里改过MAVLink配置,就要核对这几个参数是否一致。
常见问题是用QGC连接真实飞控时,切换到串口模式后忘改回UDP模式,导致重新做仿真时始终连不上。这时候去“通信连接”里把串口连接删除,只保留UDP,再重新启动QGC,问题基本就解决了。
4.3 QGC在纯仿真场景下的使用技巧
既然环境已经搭起来,我建议在连接上QGC后试几个关键功能:在“飞行计划”里规划一条航线,然后切到“飞行”页面,把模式改成“自动任务”,飞机会按规划路径飞行。仿真时飞机不会真的飞出去,而是在Gazebo里模拟物理效果,包括姿态变化、传感器噪声、风速干扰等。
如果你想更深入验证PX4逻辑,还可以在QGC的“分析工具”里查看姿态、气压计、加速度计等数据曲线。这些曲线本质上来自PX4的传感器模拟模块,通过MAVLink发送给QGC,和真实飞控的数据链路是一样的。理解了这条链路,之后调试真实飞行时也会更快上手。
5. 在Qt Creator中导入PX4源码并进行代码调试
5.1 Qt Creator的版本选择与安装
Qt Creator是一个独立的IDE,也可以和Qt库一起安装。针对PX4开发,我们可以只安装Qt Creator,不安装完整的Qt SDK,这样体积小、环境干净。
在Ubuntu 18.04上,你可以通过apt安装老版本的Qt Creator:
sudo apt install qtcreator不过这个版本可能比较旧。另一个选择是去Qt官网下载安装器,在安装向导里勾选Qt Creator组件,同时勾选Qt 5.12或以上版本的桌面库。因为我可能在后期还会用Qt开发一些地面站工具,所以更推荐官方安装器,一次性把Qt Creator和Qt库都装好。
安装完成后,打开Qt Creator,在“工具-选项-环境-系统”里确认CMake路径是系统里的CMake。PX4编译会创建一个构建目录,这个目录里保存编译缓存和中间文件,后续我们所有修改和调试都基于这个构建目录。
5.2 在Qt Creator中导入PX4源码
PX4本身是一个CMake项目,Qt Creator可以直接识别和导入。打开Qt Creator,选择“文件-打开文件或项目”,进入PX4源码目录,选择根目录下的CMakeLists.txt文件。
导入过程中,Qt Creator会询问构建方式。这里不要选qmake,要选CMake。然后配置Kit时,编译器需要选择与PX4兼容的GCC版本。Ubuntu 18.04自带的GCC 7基本够用,如果你之前装过GCC 8或更高版本,也可以选,但要注意保持和终端编译时一致的编译器,避免两套构建结果不一致。
配置完成后,Qt Creator会开始加载CMake缓存,这个过程也需要一段时间。加载完成后,左侧的“项目”视图会展示整个源码目录结构,你可以很方便地搜索文件、查看类定义、跳转符号。
5.3 配置构建套件和运行参数
PX4并不像普通Qt程序那样直接点击运行就启动,它需要特定环境变量。在Qt Creator里运行PX4,需要设置自定义环境脚本或添加运行参数。
一种简单方式是借用PX4源码里自带的启动脚本。比如在终端编译时,make px4_sitl gazebo会调用一系列启动步骤,底层执行的命令通常可以拆解为:
make px4_sitl_default ./Tools/gazebo_sitl.sh在Qt Creator里,我们可以把构建目标设置为px4_sitl_default,然后在“运行”设置里添加一个自定义可执行文件,指向PX4构建目录下的px4可执行文件。运行参数可以参考Tools/setup_gazebo.bash里设置的参数,主要是指定Gazebo模型路径、世界文件路径和仿真端口。
不过说实话,在Qt Creator里直接点运行启动整个Gazebo仿真链路不是最省事的做法。我更推荐的方式是:先用终端启动Gazebo仿真环境,让PX4进程跑起来,再用Qt Creator以调试模式附加到PX4进程,这样断点才能稳定命中。
具体做法是:在终端里执行make px4_sitl_default gazebo,等仿真启动后,在Qt Creator里选择“调试-开始调试-附加到运行中的进程”,找到名为px4的进程,附加之后就可以在代码里打断点了。这种方式的好处是不用处理复杂的运行环境变量,调试体验也更接近真实场景。
5.4 添加断点、单步执行和变量监视
当你附加到PX4进程后,打开src/modules/mc_pos_control/MulticopterPositionControl.cpp这类核心控制代码,在比如update()函数里打个断点,再让QGC控制飞机起飞或切换模式,你就会发现程序会停在断点处。
此时你可以在“变量”窗口观察各个参数值,比如期望姿态、当前位置、速度误差等。这对于理解PX4的控制逻辑特别管用。比如看_current_position和_target_position之间的差值,能直观感受到位置控制环在做什么。
有一点要注意:PX4定时循环任务的执行频率非常高,位置控制循环通常是250Hz到1000Hz,如果你随意打断点,可能因为停顿时间过长导致Gazebo仿真报超时。建议在调试时先把仿真暂停,或者选择不那么频繁执行的模块,比如任务状态机的条件分支打断点,会比在紧耦合控制环路里打断点更好用。
6. 编译和联调中的常见问题:从报错信息到最终解决
6.1 虚拟内存不足导致Gazebo启动失败
Gazebo仿真非常吃内存。我在一台4GB内存的旧笔记本上跑PX4 SITL,启动Gazebo后经常直接卡死或闪退。这时候检查系统内存:
free -h如果内存占用接近上限,先把浏览器、其他IDE关掉再试。还可以调整Gazebo的物理步长参数,降低传感器更新频率,减少计算压力。但这个属于优化范畴,建议还是换一台至少8GB内存的电脑进行日常调试。
6.2 “px4: command not found”和PATH变量问题
编译完成后,终端里直接输入px4找不到命令,通常是因为没有执行环境初始化脚本。PX4的make命令启动仿真时,会自动添加构建目录到PATH,但如果你手动运行px4,需要先执行:
source Tools/setup_gazebo.bash source /usr/share/gazebo/setup.sh这两条命令会设置GAZEBO_MODEL_PATH、GAZEBO_PLUGIN_PATH等环境变量。很多人把PATH配置搞混,然后烧录进系统配置文件,导致每次打开终端都需要重新手动设置,非常折腾。
我建议把常用的环境变量写进~/.bashrc里,但要控制好先后顺序,避免被其他脚本覆盖。每次修改完~/.bashrc后记得执行source ~/.bashrc。
6.3 编译时出现“Failed to locate package”或“could not find package”
这类报错多发生在依赖安装阶段。比如编译时提示缺少GStreamer库,但Ubuntu 18.04默认源里对应包名可能是libgstreamer1.0-dev和libgstreamer-plugins-base1.0-dev,和PX4文档里的包名差别不大,但如果软件源没更新,就会找不到。
解决办法是回到第2节的依赖安装,确保所有包都装齐。另外要注意protobuf库版本,PX4编译时会用到protoc编译器,如果你的系统里同时存在多个版本的protobuf,可能会导致生成的C++头文件不一致,出现莫名其妙的编译错误。稳妥做法是用apt统一安装:
sudo apt install protobuf-compiler libprotoc-dev libprotobuf-dev并且不要轻易在/usr/local下手动编译安装更高版本的protobuf。
6.4 Qt Creator调试时断点无效或源码不匹配
这类问题常见于调试时使用了错误的构建目录或者源码目录配置有误。比如你在终端里用make编译,但Qt Creator里配置的是另一个构建目录,那么调试时看到的源码行号和可执行文件里的调试信息可能不一致,断点自然无效。
我的做法是统一构建目录:在Qt Creator里导入工程时,手动指定CMake构建目录为/home/用户名/src/PX4-Autopilot/build/px4_sitl_default,和终端编译使用同一个目录,这样就避免了双份构建结果互相覆盖、缓存冲突的问题。
还有一个细节:PX4很多模块默认编译为优化版本,调试时变量值会被优化掉或者跳变。如果想获得更好的调试体验,可以在CMake配置里增加--debug选项,或者修改cmake/px4_impl.mk等构建配置,关闭-O2优化。不过这样做会增加固件体积和仿真负载,我一般只在需要深入定位算法问题时才这么做。
6.5 QGC无法识别USB飞控设备
这个问题在从仿真切到真实飞控时特别常见。电脑明明通过USB连接了Pixhawk飞控,但QGC就是看不到设备。先检查设备节点是否存在:
ls /dev/ttyACM0如果有设备节点,但QGC没有连接,通常是当前用户不在dialout组里。还有可能是调制解调器管理器ModemManager抢占了USB串口权限,在终端执行:
sudo systemctl stop ModemManager sudo systemctl disable ModemManager这个步骤在不少Linux系统上是连接Pixhawk的隐藏前置条件,我在Ubuntu 18.04和20.04都遇到过类似情况。
7. 最后的实操体会
这套环境我前前后后搭过不下五次,每次在别人的机器上重装时,依然会遇到一些新问题,但总的来说只要把握住三条主线就不会偏:先准备系统和依赖,再编译PX4并跑通仿真,最后才是配置QGC和Qt Creator做联调。很多人一上来就想着用Qt Creator调试PX4,结果连仿真都没跑起来,反而到处碰壁。
如果你只想用PX4做地面站软件测试,那QGC和仿真环境就够用了,不一定非要配置Qt Creator。但如果你打算深入PX4源码,比如修改控制算法、添加新的自定义模块,那Qt Creator是值得花时间配好的工具。我个人一般先用终端跑通常规编译,再用Qt Creator附加调试,这样既能快速验证代码逻辑,又不影响仿真环境的稳定性。
最后分享一个小技巧:如果你在Ubuntu 18.04上编译不同版本PX4固件,建议给每个版本单独建编译目录,比如build_px4_v1.13、build_px4_v1.12这样,免得CMake缓存互相干扰。真要调试某个版本时,直接切分支重新配置构建目录,会比在同一个目录下反复删缓存要省事很多。这套流程跑通之后,后续无论是接真实飞控还是做半实物仿真,都会顺畅不少。