3、ArduPilot源码编译:从GitHub克隆到固件验证

好,咱们进入正题。上一章我们把仿真环境搭好了,但光有环境没有灵魂——ArduPilot源码才是核心。这一章我就带你走一遍完整的编译流程:从GitHub拉代码、配环境、编译Copter固件,最后验证结果。

说实话,我第一次编译ArduPilot时踩了不少坑。那时候文档没现在全,光依赖问题就折腾了两天。你跟着我走,这些弯路我帮你绕过去。

3.1 从GitHub克隆ArduPilot

先找个干净的工作目录。我个人习惯在 ~/workspace 下放所有项目,你随意,但路径里别带中文和空格。

cd ~/workspace
git clone https://github.com/ArduPilot/ardupilot.git
cd ardupilot

这里有个细节——克隆的是完整仓库,包含所有飞控类型(Copter、Plane、Rover等)和全部历史记录。如果你只想看最新代码,可以加 --depth=1 参数做浅克隆,省时间也省硬盘。

我的习惯:第一次用完整克隆,后面维护用 git pull 更新。浅克隆虽然快,但切分支、查历史时容易受限。

克隆完后,记得初始化子模块。ArduPilot依赖很多第三方库(比如MAVLink、DroneKit),这些是以子模块形式管理的。

git submodule update --init --recursive

这一步别跳过。我曾经遇到过编译到一半报错,查了半天发现是子模块没拉全。嗯,血的教训。

3.2 配置编译环境

ArduPilot支持多种编译工具链。咱们用最主流的——waf 构建系统 + arm-none-eabi-gcc 交叉编译器。为什么选这个?因为Pixhawk系列飞控的STM32芯片全靠它。

3.2.1 安装依赖包

Ubuntu 22.04下,一行命令搞定大部分依赖:

sudo apt update
sudo apt install -y git build-essential g++ python3-pip \
  python3-dev python3-numpy python3-matplotlib \
  libtool autoconf automake pkg-config \
  libusb-1.0-0-dev libxml2-dev libxslt1-dev \
  libssl-dev libffi-dev

然后装Python工具链:

pip3 install --user future pyserial empy pexpect
注意:别用 sudo pip3 装,容易搞乱系统Python。加 --user 装到用户目录下,干净又安全。

3.2.2 安装交叉编译器

ArduPilot官方推荐用 gcc-arm-none-eabi-10.3-2021.10 版本。你可以从ARM官网下载,但我建议直接用脚本:

cd ~/workspace/ardupilot
Tools/environment_install/install-prereqs-ubuntu.sh -y

这个脚本会自动检测系统、装依赖、下编译器。跑完后重启终端或 source ~/.profile 让环境变量生效。

验证一下编译器是否装好:

arm-none-eabi-gcc --version

如果输出类似 arm-none-eabi-gcc (GNU Arm Embedded Toolchain 10.3-2021.10) 10.3.1 20210824,说明成了。

3.3 编译Copter固件

环境配好,咱们开始编译。ArduPilot用waf作为构建系统,和CMake不太一样,但逻辑更直白。

3.3.1 配置编译目标

先看看有哪些板子支持:

./waf list_boards

输出会很长,咱们关注几个常用的:

板子名称 对应硬件 适用场景
Pixhawk1 Pixhawk 1 / 2.4.8 入门调试、教学
CubeBlack CubePilot Cube Black 工业级飞控
sitl 软件在环仿真 无硬件调试
navio2 Raspberry Pi + Navio2 树莓派飞控

咱们先编译SITL版本——这样不用硬件也能跑,方便验证。

./waf configure --board sitl

配置成功后,会看到类似 Configuring for board sitl 的提示。

3.3.2 执行编译

配置完,直接开编:

./waf copter

第一次编译会比较慢,因为要编译整个Copter固件和所有库。我的机器大概要5-8分钟。你可以去泡杯咖啡。

编译过程中,终端会滚动输出编译信息。看到 Waf: Leaving directory 和 Build commands: 0 就表示成功了。

编译加速技巧:用 -j 参数指定并行任务数。比如4核CPU可以跑 ./waf copter -j4,速度能快一倍。但别超过CPU物理核心数,否则反而变慢。

3.4 验证编译结果

编译完,固件在 build/sitl/bin/ 目录下。咱们看看都有啥:

ls -lh build/sitl/bin/

你会看到 arducopter 这个可执行文件。这就是咱们编译出来的SITL固件。

验证它能不能跑:

./build/sitl/bin/arducopter --help

如果输出一堆启动参数说明,说明编译没问题。你也可以直接启动试试:

./build/sitl/bin/arducopter --model quad --speedup 1

看到类似 Starting SITL 和 Waiting for connection 的日志,恭喜你——固件跑起来了!

我的经验:第一次跑SITL时,如果提示端口被占用,八成是之前有残留进程。用 pkill arducopter 杀掉再试。

3.5 本章知识体系

下面这张图把整个编译流程串起来了,你对照着看会更清楚:

ArduPilot 源码编译流程 1. 克隆源码 git clone + submodule 2. 安装依赖 apt + pip3 3. 安装编译器 arm-none-eabi-gcc 4. 配置编译目标 ./waf configure --board 5. 执行编译 ./waf copter 6. 验证结果 运行 arducopter --help 常见编译目标选择 SITL → 无硬件仿真调试(推荐初学者) Pixhawk1 → 实体飞控固件 CubeBlack → 工业级飞控固件 ⚠ 避坑:子模块未初始化、编译器版本不匹配、Python包权限问题 是编译失败三大元凶,按本章步骤逐一排查即可

3.6 常见问题与避坑

编译过程中你可能会遇到一些问题。我把最常见的几个列出来:

  • 子模块拉取失败:网络问题导致 git submodule update 中断。重跑一次,或者用 --depth=1 只拉最新版本。
  • 编译器版本不对:ArduPilot对GCC版本有要求。太新的版本可能不兼容,太老的版本不支持新特性。10.3版本最稳。
  • Python包冲突:如果你同时用系统Python和Anaconda,容易搞混。建议在虚拟环境里操作。
  • 磁盘空间不足:完整编译一次大概占2-3GB。注意你的 /home 分区够不够。
我曾经遇到过:编译到99%报错,提示 arm-none-eabi-gcc: internal compiler error。查了半天发现是内存不够——虚拟机只给了2GB。加到4GB后一次通过。所以编译时尽量别开太多应用。