3. 源码获取与编译:从GitHub克隆ArduPilot主仓库,配置编译环境,编译Copter固件,验证编译产物(.px4文件)
好,到了真正动手的环节了。前面两章我们把环境搭好、工具链装齐,现在终于可以拉代码、编译固件了。这一章我会带你走完整个流程:从GitHub上把ArduPilot源码拿下来,配置好编译环境,然后编译出Copter固件,最后验证那个.px4文件是不是对的。
说实话,我第一次编译ArduPilot的时候,踩了不少坑。那时候文档还没现在这么全,光一个依赖库装错版本就折腾了半天。嗯,现在好多了,但有些细节还是得注意。跟着我来,别跳步。
本章核心目标:从零开始,在本地获得一个可用的Copter固件(.px4文件),并验证其完整性。
3.1 从GitHub克隆ArduPilot主仓库
先打开终端,找个你习惯放代码的目录。我个人习惯在 ~/workspace 下面放所有项目,你随意,别放桌面就行。
克隆命令很简单:
cd ~/workspace
git clone https://github.com/ArduPilot/ardupilot.git
cd ardupilot
这里有个小细节——不要用SSH方式克隆,除非你配好了GitHub SSH Key。HTTPS方式最省事,输一次密码就行。我见过不少新手卡在这一步,明明配了Key但权限不对,折腾半天。
小技巧:如果你网络不好,可以加个 --depth=1 参数只克隆最新版本,省流量也省时间。不过后续更新子模块时可能要多跑一次 git fetch --unshallow。
3.2 切换分支与更新子模块
克隆下来后,默认在 master 分支。但说实话,master分支有时候不太稳定,我建议你切到最新的稳定版。写这篇文章时,稳定版是 Copter-4.5.x。
git checkout Copter-4.5.7
然后是最关键的一步——更新子模块。ArduPilot依赖很多第三方库,比如AP_Param、AP_Math这些,都是以子模块形式管理的。不更新子模块,编译必报错。
git submodule update --init --recursive
这个过程会下载所有依赖库,大概几百兆。我第一次跑的时候等了快十分钟,还以为卡死了。其实它在后台拉东西,耐心等就好。
注意:子模块更新失败是最常见的坑。如果你遇到网络超时,可以试试 git submodule update --init --recursive --depth=1,或者换个时间段再试。我曾经在下午三点怎么都拉不下来,换到晚上十点一次成功——你想想看,GitHub的CDN有时候就是这么玄学。
3.3 配置编译环境
子模块更新完后,需要安装一些Python依赖。ArduPilot的编译脚本依赖 future、pyserial 这些库。
pip install --user future pyserial
python Tools/environment_install/install-prereqs-ubuntu.py -y
这个脚本会自动检测你的系统,安装必要的工具链。如果你用的是Ubuntu 20.04或22.04,基本一路绿灯。但如果你跟我一样用Ubuntu 24.04,可能会遇到Python版本兼容问题——别慌,后面我会讲怎么处理。
装完之后,记得重新加载一下环境变量:
. ~/.profile
这一步很多人会忘,然后发现 arm-none-eabi-gcc 找不到。嗯,我也忘过。
3.4 编译Copter固件
环境配好了,终于可以编译了。ArduPilot的编译系统基于waf,用法很简洁。
先配置目标板型。以Pixhawk1为例:
./waf configure --board Pixhawk1
配置成功后,开始编译Copter:
./waf copter
第一次编译会下载工具链并编译所有依赖,大概需要10-20分钟。后面再编译就快多了,只编译改动的文件。
常用板型对照表:
| 板型名称 | 适用硬件 | Flash大小 | RAM大小 |
|---|---|---|---|
| Pixhawk1 | Pixhawk 1/2.4.x | 1MB | 256KB |
| Pixhawk4 | Pixhawk 4 / FMUv5 | 2MB | 512KB |
| CubeOrange | Cube Orange / FMUv5 | 2MB | 512KB |
| sitl | 软件在环仿真 | N/A | N/A |
编译过程中,你会看到终端刷刷地滚日志。如果一切正常,最后会显示 Build complete 或者类似信息。如果报错,别慌——90%的情况是子模块没更新全,或者Python依赖没装对。
3.5 验证编译产物(.px4文件)
编译成功后,固件文件在哪?在 build/Pixhawk1/bin/ 目录下。你会看到类似这样的文件:
ls -la build/Pixhawk1/bin/
# 输出示例:
# arducopter.apj
# arducopter.px4
# arducopter.hex
我们要验证的是 .px4 文件。这个文件是Pixhawk系列飞控的标准固件格式,包含了引导加载器和固件镜像。
怎么验证它是不是对的?我一般做三步检查:
- 检查文件大小:正常编译出来的.px4文件应该在500KB-1.5MB之间。如果只有几KB,那肯定有问题。
- 检查文件头:用
hexdump或xxd看一眼文件头,应该能看到PX4或APJ魔数。 - 检查编译时间戳:用
stat命令看文件修改时间,确认是你刚才编译的时间。
# 检查文件大小
ls -lh build/Pixhawk1/bin/arducopter.px4
# 检查文件头(前4个字节)
xxd -l 4 build/Pixhawk1/bin/arducopter.px4
# 检查编译时间戳
stat build/Pixhawk1/bin/arducopter.px4
我的经验:如果你编译的是SITL(软件在环仿真)版本,产物是 arducopter 可执行文件,不是.px4。SITL固件是给仿真环境用的,后面章节我们会专门讲。这里先记住:实物飞控用.px4,仿真用SITL可执行文件。
3.6 常见编译问题与避坑指南
编译过程中可能会遇到一些问题,我把最常见的几个列出来:
| 错误现象 | 原因 | 解决方法 |
|---|---|---|
fatal error: AP_Common/AP_Common.h: No such file or directory |
子模块未更新 | 运行 git submodule update --init --recursive |
arm-none-eabi-gcc: command not found |
工具链未安装或环境变量未加载 | 运行 . ~/.profile 或重新安装工具链 |
Python module future is not installed |
Python依赖缺失 | pip install --user future pyserial |
configure failed 且日志中有 No such file or directory |
系统缺少某些库 | 重新运行 install-prereqs-ubuntu.py |
我曾经在编译时遇到一个特别诡异的问题——编译到一半报 internal compiler error。查了半天,发现是内存不够了。虚拟机只分了1GB内存,编译大型C++项目根本不够用。后来加到4GB,问题解决。所以如果你用虚拟机,记得给够资源。
重要提醒:不要用root用户编译!ArduPilot的编译脚本会检测当前用户,如果检测到root会直接退出。用普通用户,但确保该用户有sudo权限(安装依赖时需要)。
3.7 本章小结
到这里,你应该已经拿到了一个可以用的Copter固件。总结一下我们做了什么:
- 从GitHub克隆了ArduPilot主仓库
- 切换到了稳定分支并更新了子模块
- 配置了编译环境(工具链+Python依赖)
- 编译了Copter固件(以Pixhawk1为例)
- 验证了.px4文件的完整性和正确性
这个.px4文件就是后面章节要烧录到飞控里的固件。当然,在仿真联调场景下,我们更多是用SITL模式,但先学会编译实物固件,能帮你理解整个编译流程。后面讲SITL时,你会发现流程几乎一样,只是板型参数从 Pixhawk1 换成 sitl 而已。
好,固件有了,下一件大事就是——怎么把它烧到飞控里?或者怎么用SITL跑起来?别急,我们一步步来。