3、PX4固件编译环境搭建:Ubuntu环境配置、PX4工具链安装、Firmware源码下载与首次编译

说实话,搭建PX4编译环境这件事,劝退了不少刚入门的朋友。我见过太多人卡在这一步,明明代码逻辑都懂,结果环境没配好,编译报错一整天。其实没那么玄乎,咱们一步步来。

核心思路:Ubuntu 18.04/20.04 LTS → 安装基础依赖 → 安装PX4工具链 → 下载Firmware源码 → 首次编译验证。顺序别乱,否则容易踩坑。

3.1 为什么选Ubuntu?

PX4官方推荐Ubuntu 18.04或20.04 LTS。我个人习惯用20.04,因为软件源更新,兼容性也更好。Windows下虽然能用WSL,但USB设备透传和实时性始终差点意思。你想想看,飞控编译要跟硬件打交道,原生Linux最省心。

如果你手头只有Windows机器,装个双系统或者虚拟机都行。虚拟机记得给4核CPU、8GB内存以上,否则编译时风扇会像飞机起飞一样响。

3.2 Ubuntu环境基础配置

装好系统后,第一件事换源。国内用户不换源,下载速度会让你怀疑人生。

# 备份原源
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak

# 替换为清华源(Ubuntu 20.04为例)
sudo sed -i 's/archive.ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list
sudo sed -i 's/security.ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list

# 更新
sudo apt update && sudo apt upgrade -y

然后安装基础编译工具。这里有个坑——千万别跳过某些看似无关的包,比如python3-pip和ninja-build,后面编译时会用到。

sudo apt install -y \
  git zip cmake build-essential \
  python3 python3-pip \
  ninja-build \
  pkg-config \
  libgstreamer1.0-dev \
  libgstreamer-plugins-base1.0-dev \
  libeigen3-dev \
  libopencv-dev \
  libjsoncpp-dev \
  libcurl4-openssl-dev \
  libprotobuf-dev \
  protobuf-compiler \
  libtinyxml2-dev

小技巧:装完这些后,重启一下系统。我遇到过好几次因为没重启,导致某些库路径没刷新的情况。

3.3 PX4工具链安装

PX4的工具链主要包含编译器、仿真环境和Python工具。官方提供了一个自动化脚本,但我建议你手动分步安装,这样出了问题好排查。

3.3.1 安装GCC交叉编译器

PX4固件编译需要ARM交叉编译器。别用系统自带的gcc,那个是给x86用的。

# 下载ARM GCC 9-2020-q2-update(推荐版本)
wget https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu-rm/9-2020q2/gcc-arm-none-eabi-9-2020-q2-update-x86_64-linux.tar.bz2

# 解压到/opt
sudo tar -xjf gcc-arm-none-eabi-9-2020-q2-update-x86_64-linux.tar.bz2 -C /opt/

# 添加环境变量
echo 'export PATH=$PATH:/opt/gcc-arm-none-eabi-9-2020-q2-update/bin' >> ~/.bashrc
source ~/.bashrc

# 验证安装
arm-none-eabi-gcc --version

输出应该显示9.3.1 20200408之类的版本号。如果提示找不到命令,检查路径写没写对。

3.3.2 安装Gazebo仿真环境

虽然咱们主要做真机编译,但仿真环境能帮你快速验证代码逻辑。PX4官方推荐Gazebo 9或11。

# 安装Gazebo 11
sudo apt install -y gazebo11 libgazebo11-dev

# 安装PX4仿真依赖
sudo apt install -y \
  libeigen3-dev \
  libopencv-dev \
  libgstreamer1.0-dev \
  libgstreamer-plugins-base1.0-dev

注意:Gazebo安装包比较大(约1.5GB),确保磁盘空间充足。我曾经在只有20GB剩余空间的虚拟机上装到一半卡死,最后只能扩容重来。

3.3.3 安装Python工具链

PX4的编译脚本依赖一些Python包。用pip安装时,建议加--user参数,避免污染系统Python环境。

pip3 install --user \
  pyserial \
  pyulog \
  pyyaml \
  numpy \
  matplotlib \
  jinja2 \
  packaging \
  toml

3.4 Firmware源码下载

源码托管在GitHub上。我建议用git clone而不是直接下载zip包,因为后续更新固件时,git pull比重新下载方便得多。

# 创建工作目录
mkdir -p ~/px4_workspace
cd ~/px4_workspace

# 克隆稳定版(v1.13.3为例)
git clone https://github.com/PX4/Firmware.git --branch v1.13.3 --depth 1

# 进入目录
cd Firmware

--depth 1参数只拉取最新提交,能节省大量时间和磁盘空间。完整历史有2GB+,初学者没必要全拉。

如果你网络不好,可以用国内镜像源加速:

git clone https://gitclone.com/github.com/PX4/Firmware.git --branch v1.13.3 --depth 1

3.5 首次编译

终于到这一步了。编译前先初始化子模块,这一步容易被忽略。

cd ~/px4_workspace/Firmware
git submodule update --init --recursive

然后开始编译。以常用的px4_fmu-v5(Pixhawk 4)为例:

make px4_fmu-v5_default

第一次编译会下载大量依赖,耗时约30-60分钟,取决于你的网速和CPU性能。编译过程中终端会滚动输出,看到[100%]就说明成功了。

编译成功标志:最后几行会显示-- Build files have been written to: ...和[100%] Built target px4_fmu-v5_default。生成的固件在build/px4_fmu-v5_default/目录下,文件名是px4_fmu-v5_default.px4。

如果编译报错,别慌。90%的问题出在依赖没装全或版本不对。常见错误及解决方法:

错误信息 原因 解决方法
arm-none-eabi-gcc: not found 交叉编译器未安装或路径未配置 检查~/.bashrc中的PATH,重新source
fatal error: mavlink/v2.0/... 子模块未初始化 执行git submodule update --init --recursive
Could NOT find GStreamer 缺少多媒体库 安装libgstreamer1.0-dev和libgstreamer-plugins-base1.0-dev
Python module not found: em 缺少Python模板引擎 pip3 install --user empy

避坑指南:我曾经在Ubuntu 22.04上编译v1.13.3,结果因为GCC版本太高(11.x)导致链接失败。后来换成Ubuntu 20.04 + GCC 9.3.1,一次通过。所以,环境版本一定要跟官方推荐对齐。

3.6 知识体系总览

下面这张图帮你理清整个搭建流程的脉络:

PX4编译环境搭建流程 PX4编译环境搭建流程 1. Ubuntu系统准备 2. 基础依赖安装 3. PX4工具链安装 ARM GCC编译器 Gazebo仿真 Python工具链 4. Firmware源码下载 5. 首次编译验证 提示:每一步都建议验证通过后再进行下一步,避免问题堆积难以排查

3.7 验证编译结果

编译成功后,可以用以下命令检查固件信息:

# 查看固件大小
ls -lh build/px4_fmu-v5_default/px4_fmu-v5_default.px4

# 查看固件版本信息
strings build/px4_fmu-v5_default/px4_fmu-v5_default.px4 | grep "PX4"

正常输出应该包含固件版本号、编译时间等信息。如果能看到这些,恭喜你,环境搭建成功了。

最后提醒:每次更新源码后,记得重新执行git submodule update --init --recursive,否则编译时会出现莫名其妙的头文件缺失错误。这个坑我踩过不下三次,后来养成了习惯,每次pull完第一件事就是更新子模块。