2. 飞控系统概述
在进入姿态控制源码之前,必须先建立对飞控系统整体架构的认知。飞控系统是无人机的大脑,它由硬件平台(传感器、处理器、执行机构接口)和软件框架(实时操作系统、状态估计、控制律、任务管理)共同构成。PX4 和 ArduPilot 是目前最主流的开源飞控软件,它们虽然目标一致,但在架构设计、代码组织、调度方式上存在显著差异。理解这些差异,是后续阅读姿态控制源码、进行二次开发或移植的基础。本章将带你梳理硬件架构的典型组成、两大软件框架的设计哲学,并给出源码目录的导航地图。
上图展示了飞控系统从硬件到软件再到源码的整体映射关系。硬件层提供物理感知与执行能力,软件框架负责调度算法与逻辑,源码结构则是具体实现的载体。下面我们分层展开。
2.1 主流飞控硬件架构
核心原理:飞控硬件围绕“感知-决策-执行”闭环设计。感知层由 IMU(惯性测量单元,包含加速度计与陀螺仪)、磁力计、气压计等组成,它们以不同频率(通常 100Hz-1000Hz)产生原始数据。决策层是 MCU(微控制器),它运行实时操作系统,执行状态估计与控制律计算。执行层通过 PWM 或 DShot 协议驱动电调与舵机。硬件架构的关键在于传感器数据同步、MCU 算力余量以及接口电气可靠性。
典型硬件组成:
| 模块 | 典型器件 | 通信接口 | 关键参数 |
|---|---|---|---|
| 主控 MCU | STM32F427 / F765 / H743 | 内部总线 | 主频 168-480MHz,FPU,2MB Flash |
| IMU | ICM-20689 / BMI088 | SPI(从模式) | 加速度计 ±16g,陀螺仪 ±2000dps |
| 磁力计 | IST8310 / RM3100 | I2C 或 SPI | 精度 0.3° 典型 |
| 气压计 | MS5611 / BMP388 | I2C / SPI | 分辨率 10cm,更新率 100Hz |
| 外部存储 | MicroSD / Flash | SDIO / SPI | 用于黑匣子日志 |
| 电源管理 | PMU + BEC | 模拟 / I2C | 5V/3.3V 供电,电流检测 |
操作流程(硬件选型与检查): 在动手写代码前,先确认硬件平台。第一步,查看飞控板的原理图,确认 MCU 型号与传感器型号;第二步,检查传感器在 SPI/I2C 总线上挂载的片选引脚与中断引脚;第三步,用示波器或逻辑分析仪抓取上电瞬间传感器数据,确认 IMU 数据在 SPI 时钟 10MHz 下无丢帧。对于姿态控制开发,建议使用带有硬件浮点单元且主频不低于 168MHz 的 MCU,否则控制律在 500Hz 下可能占用过高 CPU。
2.2 软件框架对比:PX4 与 ArduPilot
核心原理: PX4 采用微内核 + 模块化架构,每个功能(如姿态控制、位置控制、传感器驱动)都是独立进程,通过 uORB 消息总线通信。这种设计隔离性好,一个模块崩溃不会拖垮整个系统,且方便单独重启。ArduPilot 则采用单进程多线程模型,所有库函数直接链接到主程序中,通过调度器(Scheduler)按优先级和时间片执行。ArduPilot 的优点是代码紧凑、资源占用低,但模块间耦合度较高。
对比分析:
| 维度 | PX4 | ArduPilot |
|---|---|---|
| 操作系统 | NuttX (POSIX 兼容) | ChibiOS / 裸机 |
| 进程模型 | 多进程,uORB 通信 | 单进程,函数调用 |
| 姿态控制源码位置 | src/modules/mc_att_control/ | libraries/AP_AttitudeControl/ |
| 状态估计器 | EKF2 / LKF | EKF3 |
| 构建方式 | CMake | Makefile / WAF |
| 适合人群 | 研究者、二次开发者 | 整机集成、传统航模 |
案例拆解(如何选择框架): 假设你需要在开源飞控上实现一种新型姿态控制算法(例如基于模型预测控制 MPC)。在 PX4 中,你可以新建一个模块,订阅传感器数据,发布姿态控制量,不影响原有模块。而在 ArduPilot 中,你需要修改 AP_AttitudeControl 库中的核心函数,并重新编译整个固件,测试周期更长。因此,若以算法研究为主,PX4 更合适;若目标是稳定可靠的整机产品,ArduPilot 的成熟度更高。
2.3 源码结构导览
PX4 源码结构: 以 PX4 v1.14 为例,姿态控制相关代码集中在 src/modules/mc_att_control/ 下。其中 mc_att_control_main.cpp 是模块入口,负责参数初始化和循环调度;AttitudeControl.cpp 实现了角度环(外环)与角速度环(内环)的级联 PID 控制。状态估计器在 src/modules/ekf2/ 中,输出四元数姿态和陀螺仪偏置。数学库在 src/lib/mathlib/,包含四元数运算、旋转矩阵、限幅函数等。
PX4 关键路径:
src/modules/mc_att_control/ # 多旋翼姿态控制
├── mc_att_control_main.cpp # 模块入口,uORB 订阅与发布
├── AttitudeControl.cpp # 姿态控制律实现
├── AttitudeControl.hpp # 头文件,参数定义
└── ControlMath.cpp # 辅助数学函数(如推力矢量映射)
src/modules/ekf2/ # 扩展卡尔曼滤波器
src/lib/mathlib/ # 四元数、矩阵、常用数学工具
ArduPilot 源码结构: ArduPilot 的姿态控制库位于 libraries/AP_AttitudeControl/。核心文件是 AP_AttitudeControl.cpp,它提供了角度控制与角速度控制的完整实现。与 PX4 不同,ArduPilot 将多旋翼与固定翼的姿态控制分开,多旋翼使用 AP_Multicopter 相关类。状态估计在 libraries/AP_NavEKF3/ 中,数学工具在 libraries/AP_Math/。
ArduPilot 关键路径:
libraries/AP_AttitudeControl/ # 姿态控制库
├── AP_AttitudeControl.cpp # 角度环 + 角速度环
├── AP_AttitudeControl.h
├── AP_Multicopter.cpp # 多旋翼特有控制(如混控)
libraries/AP_NavEKF3/ # EKF3 状态估计
libraries/AP_Math/ # 四元数、向量、矩阵
ArduCopter/ # 多旋翼主程序(含飞行模式)
操作流程(快速定位姿态控制代码): 第一步,在 PX4 中搜索 vehicle_attitude_setpoint 这个 uORB 主题,它定义了期望姿态;第二步,找到发布该主题的模块,即 mc_att_control;第三步,在 AttitudeControl.cpp 中查找 update() 函数,这就是控制律主循环。在 ArduPilot 中,搜索 attitude_controller_run_quat() 函数,这是姿态控制的核心入口。
MC_ATT_RATE 参数控制,默认 250Hz。角速度环的 PID 增益在 MC_ROLLRATE_P、MC_ROLLRATE_I 等参数中设置。修改这些参数后,无需重新编译,通过 QGroundControl 地面站即可实时调参。而在 ArduPilot 中,对应参数为 ATC_RAT_RLL_P、ATC_RAT_RLL_I 等。2.4 常见误区与总结复盘
误区一:混淆“姿态控制”与“位置控制”。 姿态控制是内环,输出期望力矩;位置控制是外环,输出期望姿态。很多初学者在阅读源码时,从位置控制模块开始,结果陷入大量坐标变换的细节中。建议先从内环(姿态)入手,再逐步向外扩展。
误区二:忽视传感器时间戳同步。 PX4 和 ArduPilot 都要求传感器数据带有精确的时间戳,用于 EKF 融合。如果 IMU 数据延迟或时间戳抖动,即使 PID 参数调得再好,姿态估计也会发散。在源码中,sensor_combined 主题(PX4)或 imu 数据结构(ArduPilot)都包含了时间戳字段。
误区三:直接修改源码而不理解构建系统。 PX4 使用 CMake,ArduPilot 使用 Makefile。如果修改了源码但未正确配置编译选项,可能导致固件无法生成或运行异常。建议先使用默认配置编译一次,确认环境无误后再修改代码。
总结复盘: 本章建立了飞控系统的整体视图。硬件上,关注 MCU 算力与传感器接口;软件上,理解 PX4 的模块化与 ArduPilot 的单体架构差异;源码上,掌握关键目录与核心函数位置。下一阶段,我们将深入姿态控制律的数学基础,从四元数开始,逐步推导出 PX4 和 ArduPilot 中 PID 控制器的具体实现。请务必在本地搭建好编译环境,并准备好一份飞控源码(建议 PX4 v1.13 以上或 ArduPilot 4.1 以上),以便随时查阅。