1. ArduPilot 概述:从零到一,认识这个开源飞控巨兽
大家好,我是你们的飞控工程师老张。今天咱们正式开讲《ArduPilot飞行模式切换精讲》的第一章。
说实话,我接触 ArduPilot 快十年了。从最早的 APM 2.0 板子开始,一路看着它从一个小众项目长成今天的庞然大物。你想想看,一个开源飞控能支持无人机、无人车、无人船,甚至潜艇,这本身就够传奇的。
这一章,咱们先不急着写代码。先把 ArduPilot 的来龙去脉、它能跑在什么硬件上、软件到底怎么组织的,捋清楚。嗯,磨刀不误砍柴工嘛。
1.1 ArduPilot 发展史:一个社区驱动的传奇
ArduPilot 的故事,得从 2007 年说起。那时候有个叫 Jordi Muñoz 的墨西哥小伙子,跟 Chris Anderson 一起,在 Arduino 平台上搞出了最早的自动驾驶仪。说白了,就是用 8 位单片机控制航模。
我记得第一次看到 APM 1.0 的代码时,差点没笑出来——就那么几百行,连个像样的卡尔曼滤波都没有。但就是这堆简陋的代码,开启了开源飞控的新纪元。
关键时间节点:
- 2007年:APM 1.0 诞生,基于 Arduino,仅支持固定翼
- 2010年:APM 2.0 发布,加入多旋翼支持,社区开始爆发
- 2013年:Pixhawk 项目启动,硬件升级到 32 位 STM32
- 2015年:ArduPilot 从 APM 代码库独立,正式成为顶级开源项目
- 2018年:支持 ChibiOS 实时操作系统,告别裸奔时代
- 2021年至今:全面拥抱 4.0+ 架构,支持多车辆类型、多传感器融合
这里有个坑,我当年踩过。2014 年那会儿,APM 2.5 板子还在用 8 位单片机,我硬要在上面跑复杂的光流算法。结果呢?CPU 满载,炸机。后来才明白,硬件跟不上,软件再牛也白搭。
1.2 支持的硬件平台:从 8 位到 64 位,总有一款适合你
ArduPilot 能支持的硬件,说实话,比市面上任何商业飞控都多。我个人习惯把硬件平台分成三代:
| 代际 | 典型硬件 | 处理器 | RAM | 适用场景 |
|---|---|---|---|---|
| 第一代 | APM 2.x | Atmega2560 (8位) | 8 KB | 教学、简单固定翼 |
| 第二代 | Pixhawk 1 / Cube | STM32F4 (32位) | 256 KB | 多旋翼、主流无人机 |
| 第三代 | Pixhawk 4 / Cube Orange+ | STM32H7 (32位) | 1 MB+ | 工业级、自动驾驶 |
你可能会问:为什么还在支持 8 位机?嗯,这里有个现实问题。很多教育机构和爱好者手里还有大量 APM 板子,ArduPilot 团队一直没放弃它们。我曾经在一个大学实验室里,看到他们用 APM 2.6 带四轴飞了整整两年,虽然功能有限,但稳定得可怕。
我的建议:新手入门直接上 Pixhawk 1 或 Cube 系列。别在 APM 上浪费时间了,那玩意儿连个 SD 卡日志都写不利索。你想想看,调试的时候没有日志,等于瞎子摸象。
除了这些主流板子,ArduPilot 还支持一大堆小众硬件:
- BeagleBone Blue:适合做无人车,GPIO 多
- Raspberry Pi + Navio2:适合搞视觉导航
- STM32F7 系列:适合自己画板子的硬核玩家
- Linux 平台:直接在 Ubuntu 上跑 SITL 仿真
1.3 软件架构概览:分层设计,各司其职
ArduPilot 的软件架构,说白了就是一套分层系统。我画了张图,你一看就明白:
这张图我画了好几次才满意。你看,从下往上,每一层都只干自己的事。我最喜欢的是 HAL 层——当年为了把 ArduPilot 移植到一块国产 STM32 板子上,我只需要重写 HAL 层的传感器驱动,上层代码一行没改。这就是分层设计的好处。
1.3.1 应用层:飞行模式的老家
应用层里藏着所有飞行模式的逻辑。比如你切到 Loiter 模式,应用层就会调用核心层的定位数据,然后生成位置保持指令。我刚开始学的时候,以为飞行模式是写在核心层的,找了好久才发现全在 ArduCopter/mode.cpp 里。
1.3.2 核心层:飞控的大脑
核心层里最牛的就是 EKF(扩展卡尔曼滤波器)。它把 GPS、IMU、磁力计、气压计的数据揉在一起,输出一个干净的状态估计。嗯,这里有个坑——EKF 参数调不好,飞机在天上就跟喝醉了似的。我曾经在项目里因为 EKF 的噪声参数设错了,导致飞机悬停时左右晃了半米,查了三天才找到原因。
1.3.3 HAL 层:硬件的翻译官
HAL 层把不同硬件的差异藏起来了。你写代码的时候,根本不用管底层是 I2C 还是 SPI,直接调用 hal.analog->read() 就行。我个人习惯在移植新硬件时,先跑一遍 HAL 层的单元测试,确保每个传感器都能正常读数。
1.3.4 操作系统层:让一切有序运行
ArduPilot 早期是裸奔的,所有任务在一个大循环里跑。后来换成 ChibiOS,任务调度才规范起来。现在每个传感器读取、控制计算、通信处理都是独立线程,优先级高的任务不会被阻塞。你想想看,如果 GPS 解析卡住了,飞控还能继续控制电机,这就是操作系统的功劳。
注意:虽然 ArduPilot 支持多平台,但不同硬件上的实时性表现差异很大。我曾经在某个国产 STM32F4 板子上遇到过定时器精度不够的问题,导致 PWM 输出抖动。建议量产前做完整的硬件在环测试。