4、PX4 Autopilot 固件编译:从源码到可执行文件
好,咱们进入正题。这一章要解决的核心问题就一个:怎么把 PX4 的源码变成能刷进飞控板的固件。
说白了,就是搭建编译环境、拉代码、敲命令、处理报错。我刚开始接触 PX4 时,光编译环境就折腾了两天。嗯,现在流程成熟多了,但坑还是有的。咱们一步步来。
本章核心流程:GitHub 克隆源码 → 安装工具链 → 选择目标机型 → 编译 → 处理错误。
4.1 从 GitHub 克隆 PX4 源码
先做第一步:把代码拉到本地。我个人习惯用 git clone 加 --recursive 参数,因为 PX4 依赖很多子模块,一次性拉全省事。
# 克隆最新稳定版(推荐)
git clone https://github.com/PX4/PX4-Autopilot.git --recursive
# 如果你网络不好,可以只拉主仓库,再单独更新子模块
git clone https://github.com/PX4/PX4-Autopilot.git
cd PX4-Autopilot
git submodule update --init --recursive
⚠️ 注意:国内网络环境下,子模块下载经常超时。我曾经遇到过 git submodule 卡住半小时的情况。建议用代理,或者直接下载 GitHub Release 里的源码包(已包含子模块)。
克隆完成后,建议先切到一个稳定的发布版本。我一般用 v1.13.3 或 v1.14.0,这两个版本经过大量验证,坑比较少。
git checkout v1.13.3
git submodule update --init --recursive
4.2 配置编译环境
环境配置是新手最容易翻车的地方。PX4 官方提供了自动化脚本,但说实话,我建议你手动走一遍,这样出了问题知道去哪修。
4.2.1 Ubuntu 环境(推荐)
我主力开发机是 Ubuntu 20.04/22.04。下面是核心依赖安装命令:
# 更新包管理器
sudo apt update
sudo apt upgrade -y
# 安装基础编译工具
sudo apt install -y \
git zip cmake build-essential genromfs ninja-build \
exiftool astyle python3-pip python3-dev python3-venv \
python3-serial python3-numpy python3-jinja2 \
libxml2-dev libxslt1-dev libgstreamer1.0-dev \
libgstreamer-plugins-base1.0-dev
# 安装 ARM 交叉编译器(针对 Pixhawk 等 STM32 飞控)
sudo apt install -y gcc-arm-none-eabi gdb-arm-none-eabi
💡 我的经验:gcc-arm-none-eabi 版本很重要。Ubuntu 20.04 默认源里的是 9.x,够用。如果你用 Ubuntu 22.04,默认是 10.x,也没问题。但千万别用 Ubuntu 18.04 的 7.x 版本,编译 PX4 v1.13+ 会报一堆奇奇怪怪的错误。
4.2.2 Python 依赖
PX4 编译过程中会调用一些 Python 脚本,比如生成参数文件、检查代码格式等。建议创建一个虚拟环境:
cd PX4-Autopilot
python3 -m venv px4_venv
source px4_venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
嗯,这里要注意。如果你不创建虚拟环境,系统全局的 Python 包可能会冲突。我吃过这个亏——有一次装了个新版本的 numpy,结果把 ROS 的依赖搞坏了,折腾了一下午。
4.3 编译固定翼/多旋翼固件
环境配好了,终于可以编译了。PX4 用 make 命令加目标机型来编译。目标机型的命名规则是:制造商_飞控板_应用配置。
4.3.1 多旋翼固件编译
最常用的目标机型是 px4_fmu-v5(对应 Pixhawk 4)和 px4_fmu-v3(对应 Pixhawk 1)。
# 编译多旋翼固件(默认配置)
make px4_fmu-v5_default
# 编译带 RTPS 支持的多旋翼固件(用于和 ROS2 通信)
make px4_fmu-v5_rtps
我第一次编译时,看着终端里刷刷刷滚过的日志,心里还挺激动。整个过程大概 10-20 分钟,取决于你的 CPU 和网络(要下载一些工具链)。
4.3.2 固定翼固件编译
固定翼的编译命令类似,只是目标名不同:
# 编译固定翼固件
make px4_fmu-v5_default
# 注意:px4_fmu-v5_default 默认是多旋翼配置
# 固定翼需要单独指定 airframe
等等,这里有个关键点。很多人以为 px4_fmu-v5_default 就是多旋翼,其实它只是一个基础固件。真正的机型选择是在固件烧录后,通过地面站参数 SYS_AUTOSTART 来设置的。编译时你只需要选对飞控硬件平台。
| 目标机型 | 适用飞控 | 典型应用 |
|---|---|---|
px4_fmu-v2_default |
Pixhawk 1 (FMUv2) | 老款飞控,资源有限 |
px4_fmu-v3_default |
Pixhawk 1 (FMUv3) | 2MB Flash 版本 |
px4_fmu-v5_default |
Pixhawk 4 (FMUv5) | 多旋翼/固定翼通用 |
px4_fmu-v5_rtps |
Pixhawk 4 | 需要 ROS2 通信 |
sitl_default |
PC 仿真 | 软件在环测试 |
🔑 关键理解:编译时选的是硬件平台,不是飞机类型。飞机类型(多旋翼/固定翼/垂直起降)是在地面站里通过参数设置的。你编译一个 px4_fmu-v5_default,既可以飞多旋翼,也可以飞固定翼。
4.4 常见编译错误处理
编译不出错是不可能的,这辈子都不可能的。我整理了几个高频错误,你遇到了直接对照着修。
4.4.1 错误 1:arm-none-eabi-gcc 找不到
/bin/sh: 1: arm-none-eabi-gcc: not found
原因:交叉编译器没装,或者没加到 PATH 里。
解决:
# 检查是否安装
which arm-none-eabi-gcc
# 如果没装,重新安装
sudo apt install gcc-arm-none-eabi
# 如果装了但找不到,手动添加 PATH
export PATH=$PATH:/usr/bin
4.4.2 错误 2:子模块缺失
FATAL: src/modules/uORB is not a git repository
原因:git clone 时没有加 --recursive,子模块是空的。
解决:
git submodule update --init --recursive
我曾经犯过一个低级错误:从 GitHub 网页直接下载了 ZIP 包,结果里面没有 .git 目录,子模块根本拉不下来。后来老老实实用 git clone 了。
4.4.3 错误 3:Python 依赖版本冲突
ModuleNotFoundError: No module named 'jinja2'
原因:Python 包没装全,或者虚拟环境没激活。
解决:
source px4_venv/bin/activate
pip install -r requirements.txt
4.4.4 错误 4:内存不足导致编译崩溃
c++: fatal error: Killed signal terminated program cc1plus
原因:编译时并行任务太多,把内存吃光了。特别是虚拟机用户,2GB 内存很容易挂。
解决:限制并行编译任务数。
# 限制为 2 个并行任务
make px4_fmu-v5_default -j2
# 或者更保守,单线程编译
make px4_fmu-v5_default -j1
💡 我的建议:如果你在虚拟机上编译,至少分配 4GB 内存和 2 个 CPU 核心。我自己的开发机是 16GB 内存 + 8 核,用 -j8 编译大概 5 分钟搞定。
4.4.5 错误 5:固件体积超出 Flash 限制
region 'FLASH' overflowed by 12344 bytes
原因:你启用了太多模块,固件太大了,飞控的 Flash 装不下。FMUv2 只有 1MB,很容易超。
解决:
- 换用更大 Flash 的飞控(如 FMUv5 有 2MB)
- 裁剪不需要的模块:修改
boards/px4/fmu-v2/default.cmake,注释掉不需要的驱动 - 使用优化编译:
make px4_fmu-v2_default RELEASE=1
4.5 编译产物与验证
编译成功后,你会在 build/<目标机型>/ 目录下找到固件文件。最重要的两个:
px4_fmu-v5_default.px4:标准固件包,包含 bootloader,可以直接用 QGroundControl 刷写px4_fmu-v5_default.elf:带调试信息的 ELF 文件,用于 GDB 调试
怎么验证固件对不对?我一般用这个命令:
# 查看固件版本信息
strings build/px4_fmu-v5_default/px4_fmu-v5_default.px4 | grep "PX4"
# 或者用 size 命令查看各段大小
arm-none-eabi-size build/px4_fmu-v5_default/px4_fmu-v5_default.elf
嗯,看到输出里有 PX4 v1.13.3 之类的字样,基本就稳了。