2. 飞控系统概述

在进入姿态控制源码之前,必须先建立对飞控系统整体架构的认知。飞控系统是无人机的大脑,它由硬件平台(传感器、处理器、执行机构接口)和软件框架(实时操作系统、状态估计、控制律、任务管理)共同构成。PX4 和 ArduPilot 是目前最主流的开源飞控软件,它们虽然目标一致,但在架构设计、代码组织、调度方式上存在显著差异。理解这些差异,是后续阅读姿态控制源码、进行二次开发或移植的基础。本章将带你梳理硬件架构的典型组成、两大软件框架的设计哲学,并给出源码目录的导航地图。

飞控系统软硬件架构总览 硬件层 (Hardware) 传感器组 (Sensors) • IMU: 加速度计 + 陀螺仪 • 磁力计 (Compass) • 气压计 (Barometer) • 空速计 / GPS / 测距仪 计算单元 (MCU) • STM32F4/F7/H7 系列 • 主频 168-480 MHz • 硬件浮点单元 (FPU) 接口与执行 • PWM / DShot 输出 • UART / I2C / SPI / CAN • SBUS / DSM 接收机 • 电调 (ESC) 与舵机 软件框架 (Software) 实时操作系统 (RTOS) • NuttX (PX4) • ChibiOS/ArduPilot 状态估计 • EKF2 / LKF (PX4) • EKF3 (ArduPilot) 姿态控制律 • 角度环 (外环) • 角速度环 (内环) 任务与通信 • MAVLink 协议 • 任务规划器 • 日志记录 源码结构 (Source) PX4 核心目录 • src/modules/ - mc_att_control/ - mc_pos_control/ • src/lib/ (EKF, math) • platforms/nuttx/ ArduPilot 核心目录 • libraries/AP_AttitudeControl/ • libraries/AP_NavEKF3/ • libraries/AP_Math/ • ArduCopter/ (主程序) 构建系统 • CMake (PX4) • Makefile / WAF (ArduPilot) 驱动 数据 编译 配置

上图展示了飞控系统从硬件到软件再到源码的整体映射关系。硬件层提供物理感知与执行能力,软件框架负责调度算法与逻辑,源码结构则是具体实现的载体。下面我们分层展开。

2.1 主流飞控硬件架构

核心原理:飞控硬件围绕“感知-决策-执行”闭环设计。感知层由 IMU(惯性测量单元,包含加速度计与陀螺仪)、磁力计、气压计等组成,它们以不同频率(通常 100Hz-1000Hz)产生原始数据。决策层是 MCU(微控制器),它运行实时操作系统,执行状态估计与控制律计算。执行层通过 PWM 或 DShot 协议驱动电调与舵机。硬件架构的关键在于传感器数据同步、MCU 算力余量以及接口电气可靠性。

典型硬件组成:

模块典型器件通信接口关键参数
主控 MCUSTM32F427 / F765 / H743内部总线主频 168-480MHz,FPU,2MB Flash
IMUICM-20689 / BMI088SPI(从模式)加速度计 ±16g,陀螺仪 ±2000dps
磁力计IST8310 / RM3100I2C 或 SPI精度 0.3° 典型
气压计MS5611 / BMP388I2C / SPI分辨率 10cm,更新率 100Hz
外部存储MicroSD / FlashSDIO / SPI用于黑匣子日志
电源管理PMU + BEC模拟 / I2C5V/3.3V 供电,电流检测

操作流程(硬件选型与检查): 在动手写代码前,先确认硬件平台。第一步,查看飞控板的原理图,确认 MCU 型号与传感器型号;第二步,检查传感器在 SPI/I2C 总线上挂载的片选引脚与中断引脚;第三步,用示波器或逻辑分析仪抓取上电瞬间传感器数据,确认 IMU 数据在 SPI 时钟 10MHz 下无丢帧。对于姿态控制开发,建议使用带有硬件浮点单元且主频不低于 168MHz 的 MCU,否则控制律在 500Hz 下可能占用过高 CPU。

风险提示: 很多飞控板将 IMU 与磁力计放在同一 SPI 总线上,但磁力计对噪声敏感。若在源码调试中发现磁力计数据跳变,优先检查 PCB 布局中是否有大电流走线靠近磁力计,而非急于修改软件滤波参数。

2.2 软件框架对比:PX4 与 ArduPilot

核心原理: PX4 采用微内核 + 模块化架构,每个功能(如姿态控制、位置控制、传感器驱动)都是独立进程,通过 uORB 消息总线通信。这种设计隔离性好,一个模块崩溃不会拖垮整个系统,且方便单独重启。ArduPilot 则采用单进程多线程模型,所有库函数直接链接到主程序中,通过调度器(Scheduler)按优先级和时间片执行。ArduPilot 的优点是代码紧凑、资源占用低,但模块间耦合度较高。

对比分析:

维度PX4ArduPilot
操作系统NuttX (POSIX 兼容)ChibiOS / 裸机
进程模型多进程,uORB 通信单进程,函数调用
姿态控制源码位置src/modules/mc_att_control/libraries/AP_AttitudeControl/
状态估计器EKF2 / LKFEKF3
构建方式CMakeMakefile / WAF
适合人群研究者、二次开发者整机集成、传统航模

案例拆解(如何选择框架): 假设你需要在开源飞控上实现一种新型姿态控制算法(例如基于模型预测控制 MPC)。在 PX4 中,你可以新建一个模块,订阅传感器数据,发布姿态控制量,不影响原有模块。而在 ArduPilot 中,你需要修改 AP_AttitudeControl 库中的核心函数,并重新编译整个固件,测试周期更长。因此,若以算法研究为主,PX4 更合适;若目标是稳定可靠的整机产品,ArduPilot 的成熟度更高。

经验之谈: 阅读源码时,不要一开始就钻进控制算法文件。先找到消息定义(PX4 的 uORB 主题,ArduPilot 的参数表),理解数据流如何从传感器进入估计器,再从估计器进入控制器。这比直接看 PID 公式更重要。

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() 函数,这是姿态控制的核心入口。

实战要点: 在 PX4 中,姿态控制模块的运行频率由 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 以上),以便随时查阅。