先交代一句背景:我从2018年开始做飞控相关的工作,前几年一直在用开源飞控做二次开发,后来转到自研飞控这条线上,中间踩了无数坑,也积累了不少可以复制的方法论。这篇东西就是打算把这些经验整理出来,围绕“从零到一构建企业级飞控系统”这件事展开,适合正在考虑自研飞控的团队、准备入行飞控算法的工程师、以及想了解无人机底层技术逻辑的产品经理看看。核心关键词就三个:飞控算法、飞控系统、无人机。
1. 先想清楚:开源飞控很好,但“企业级”三个字到底意味着什么
很多研发团队第一次接触无人机的时候,都会从PX4或者ArduPilot开始。这完全没有问题,我自己也是这么过来的。PX4的代码结构清晰,ArduPilot的硬件适配广泛,用它们做原型验证、做科研测试、做小批量定制产品,效率非常高。甚至到今天,很多商业公司的主力产品底层依然是开源飞控的深度魔改版。
但“企业级飞控系统”是一个完全不同的概念。它不是一个能飞起来就行的东西,而是一整套要面对量产、面对交付、面对多年维护的复杂系统。我在跟不少想自研飞控的团队沟通时,最常说的一句话是:不要因为开源飞控“不够好”才自研,而要因为你需要的东西开源飞控“给不了”才自研。
具体来说,企业级飞控和开源方案的核心差异体现在这几个方面:
一是代码可控性和可审计性。开源飞控的代码量非常大,PX4的源码规模动辄上百万行。商业产品如果出了问题,你的团队能不能在最短时间内定位到问题?客户做技术审查的时候,你能不能把每一行关键代码的逻辑讲清楚?这些都是很现实的问题。自研飞控的代码量可以控制在十分之一以内,出问题时能快速定位,这在企业级交付里是极大的优势。
二是深度定制能力。行业用户的无人机通常要带激光雷达、多光谱相机、喊话器、抛投装置这些载荷,还要飞各种复杂航线。开源飞控的设计目标是尽可能通用,所以在特定应用场景里,它的行为不一定最优。比如说,在一个高精度测绘任务里,你希望飞机在航点切换时足够平滑,但开源飞控默认的转弯策略可能就不符合要求。这种时候,改开源代码的边际成本往往比重新写一套更高——因为你得先理解他们整个架构的设计意图。
三是安全机制和认证需求。很多行业对无人机有明确的可靠性和安全性要求。自研飞控可以从底层设计失效保护逻辑,让每一个异常分支都在掌控之中。而深度魔改的开源飞控,往往很难保证“所有”异常分支都被覆盖。
四是长期维护的可持续性。开源飞控的版本更新节奏很快,上游的重大变更可能会让你的魔改工作量剧增。自研飞控虽然前期投入大,但系统的生命周期完全由你掌控,可以按照自己产品的节奏迭代。
从我的经验来看,判断一个团队该不该自研飞控,有几个比较实际的评估维度:
| 评估维度 | 适合继续用开源飞控 | 适合自研飞控 |
|---|---|---|
| 产品形态 | 通用航拍、消费级、科研演示 | 行业应用、定制载荷、特定任务 |
| 量产规模 | 小批量、单机定制 | 有明确量产目标 |
| 安全要求 | 普通飞行场景 | 涉及人员密集区、关键设施巡检 |
| 团队能力 | 无嵌入式底层开发经验 | 有嵌入式、RTOS、控制算法基础 |
| 长期规划 | 快速出原型占市场 | 打算做5年以上产品线 |
如果你看完这个表发现自己确实需要自研,那么下面的内容可以给你一个相对完整的路线参考。
2. 硬件平台选型:主控、传感器和动力系统的搭配逻辑
飞控算法运行在硬件之上,但很多做算法的人容易忽略一个事实:硬件选型直接影响算法的性能和鲁棒性。我先说一下整体架构,再逐项拆解选型逻辑。
一套典型的飞控硬件由这几个部分组成:主控MCU、惯性测量单元IMU、磁力计、气压计、GNSS接收机、空速计(固定翼需要)、以及PWM/DShot信号输出的接口电路。企业级产品通常还会加双IMU冗余、双GNSS冗余、以及独立的看门狗电路。
先说主控MCU。目前行业里最常见的选择是STM32系列,尤其是STM32F405、STM32F427、STM32F7、STM32H7这几个型号。选择STM32的核心原因有几个:生态成熟、参考资料多、硬件抽象层完善、而且很多传感器库和RTOS适配都是现成的。具体到型号选择,我建议根据你的算法复杂度来定。如果是做多旋翼飞行器,F405级别的算力足够跑完整个姿态解算和控制律解算;如果是做垂直起降固定翼,需要同时处理多套控制模式,建议直接上H7,留出足够的算力余量。
我自己在项目里选的是STM32H743,主频480MHz,单精度浮点性能足够。别看很多开源飞控用F4就飞得很好,那是因为人家的代码经过了大量裁剪优化,自己写的话,算力余量充足能省掉很多“抠时间片”的麻烦。
再看IMU选型。IMU包括加速度计和陀螺仪,有些型号还集成磁力计。行业里用得比较多的有博世的BMI088、TDK的ICM-42688-P、以及亚德诺的ADIS系列。这里面有一个容易被忽略的点:IMU的量程和带宽选择。多旋翼飞行的震动环境复杂,如果加速度计量程选得太小,很容易在剧烈机动时饱和,直接导致姿态解算出问题。我一般建议加速度计量程至少选±8g以上,陀螺仪量程至少±1000dps,最好选±2000dps的型号。带宽方面,不要一味追求高带宽,因为宽带宽会把结构震动带进来,反而给滤波增加负担。
IMU的安装位置也有讲究。尽量靠近飞机的几何中心,也就是重心附近,这样可以减小角运动和线运动之间的耦合干扰。减震设计上,不要用太软的减震球,因为太软的减震会在剧烈机动时产生共振。这个需要做模态测试来确定合适的减震结构,后面调试章节我会细说。
GNSS模块这一块,行业应用建议直接用双频RTK模块,比如u-blox的F9P系列或华测、中海达的国产模块。安装位置要尽量远离天线干扰源——尤其是图像传输模块、电源模块、以及大功率的LED灯。GNSS天线尽量朝天安装,必须有完整的接地面,这直接关系到搜星数量和定位稳定性。
电机和电调的选型逻辑也很重要。很多人只看拉力够不够,其实动力系统的响应带宽对飞控的调试非常关键。电机响应延迟大的话,控制器的增益就上不去,飞起来又会“肉”又会“晃”。选型的时候,要注意电机的KV值和桨的尺寸搭配,让系统在最大油门时电流不要超过电调持续电流的80%,保留余量很重要。
最后说一个不太常被提起但特别重要的测量:转动惯量测量。做姿态控制必须知道飞机三个轴上的转动惯量,否则控制器增益完全靠蒙。转动惯量的测量方法有很多,最简单的就是三线摆法或者扭摆法。用三线摆测横滚和俯仰轴惯量很准确,偏航轴的惯量可以用两条线吊起来做扭摆测试。这套测试虽然麻烦,但值得做,因为惯量数据直接决定了你在仿真模型里用到的所有姿态动力学参数,没有它,仿真就没有意义。
3. 软件架构设计:实时任务调度与模块解耦
硬件选完,下一步就是软件架构。很多人做飞控代码的时候喜欢“裸奔”,也就是在主循环里把所有事情都干了。这在开发早期没问题,但一旦系统复杂度上来,各种任务的时序耦合会让人崩溃。企业级飞控强烈建议上RTOS。
目前行业里用得比较多的RTOS有FreeRTOS、RT-Thread、Zephyr。FreeRTOS最普遍,文档多、社区大、而且很多MCU厂商的SDK直接集成好了。我个人用的是FreeRTOS,配合CMSIS-RTOS2接口封装,整体结构很清楚。
飞控软件的任务划分逻辑,核心在于“频率分级”这四个字。不同传感器和控制环节对实时性的要求完全不同,把它们混在一起跑会让最慢的任务拖累最快的任务。我给出一个我常用的任务划分方式:
| 任务模块 | 频率 | 优先级 | 说明 |
|---|---|---|---|
| IMU数据读取与姿态解算 | 1000Hz | 最高 | 姿态控制的基础,必须以最高频率运行 |
| 姿态控制器 | 1000Hz | 最高 | 跟随IMU的节奏,保证控制延迟最小 |
| 位置估计 | 200Hz | 高 | 融合GNSS、气压计、视觉数据 |
| 位置控制器 | 100Hz | 高 | 跟随位置估计,输出姿态期望 |
| 导航与任务管理 | 10~20Hz | 中 | 航线生成、航点切换、任务状态机 |
| 遥测与日志 | 50Hz | 低 | 数据下传和黑匣子记录 |
任务之间通过消息队列或者共享内存通信,但要注意:共享内存必须用互斥锁保护,否则会出现数据竞争导致的间歇性故障。这种故障是最难排查的,因为它不是每次都出现,而是偶发性的。我自己就吃过这个亏,花了整整两周排查一个偶发性的振荡问题,最后发现是一个结构体在多个任务间共享但没有加锁。
传感器数据的时间同步是另一个大坑。IMU数据在t0时刻采样,但实际被主控读取可能已经是t0+几百微秒了。如果所有传感器都用“读取时间”而不是“采样时间”做融合,会产生相位误差,直接限制控制带宽。所以一个合格的飞控系统必须为传感器数据打上时间戳,并且基于时间戳做数据融合。
还有一点容易被忽略的是看门狗机制。除了MCU硬件看门狗,系统层面也建议加一个软件看门狗任务,周期性地检查每个关键任务是否还在正常“报活”。如果某个任务卡死了,软件看门狗要能自动触发安全降落流程,把这个状态通过遥控器和地面站同时推送给飞手。
4. 核心算法实现:状态估计、控制链路与路径规划
现在进入最核心的部分:算法。飞控算法主要分三块:状态估计、姿态控制和位置控制与导航。路径规划、视觉感知这些则是在这个基础之上的扩展。
先说状态估计。姿态解算是整个飞控的基石。目前业界的主流方案有两种:互补滤波和卡尔曼滤波。卡尔曼滤波在理论上更优,但实现复杂、需要调协方差矩阵、而且调试周期长。互补滤波结构简单、计算量小、在调参得当的情况下完全能达到工业级性能。
我做项目时用的是Mahony互补滤波,也就是通过PI控制器把加速度计和磁力计的测量值修正陀螺仪积分漂移。这个方法看起来简单,但有两个关键参数需要仔细调整:比例系数Kp和积分系数Ki。Kp越大,对陀螺漂移的修正越强,但会把加速度计的高频噪声带进来;Ki的作用是消除稳态误差,但如果太大会造成震荡。经验做法是:先调Kp,让姿态在中等机动下能快速回正,再加一点Ki解决静态漂移,最终的效果要让姿态角在静止状态下的波动小于0.5度。
位置和速度的估计也用卡尔曼滤波。传感器融合的对象是GNSS位置、气压计高度、以及IMU加速度。这里面有一点很关键:IMU的加速度数据在做位置融合之前,必须减去重力分量,并且准确校准加速度计零偏。否则,一个0.05g的零偏误差,在积分几秒后就能产生几米的悬浮误差。
再聊姿态控制。几乎所有的商业飞控和开源飞控都采用串级PID架构。串级结构分为内环和外环:内环是角速度环,外环是姿态环。为什么内环一定要是角速度环?因为角速度是姿态的微分,它能比姿态更快反映外界干扰和响应变化。把快的内环包在慢的外环里,整个系统既有姿态层面的精确性,又有角速度层面的快速性。
具体到PID参数整定,我的步骤是:
第一步,只调内环角速度环。把外环全部禁用,直接给角速度期望。从小到大给P值,直到飞机响应出现轻微的高频抖动,然后回退到抖动的80%作为P值。再加一点D值提高阻尼,让角速度响应变得平滑。
第二步,内环调好后,开放外环姿态环。这时候只调P值就够了,从很小的值开始,逐步增加直到飞机姿态响应有一个干净的收敛过程,回退一点余量。如果外环加一点D值,可以增加阻尼感,但D太大会放大噪声,需谨慎。
第三步,做链路延时补偿。实测中发现,从IMU采样到PWM输出的链路总延时,对控制器的最大可用增益有直接影响。测量这个延迟可以用一个简单的办法:在代码里做脉冲信号,从IMU采样的同时翻转一个GPIO,再到PWM输出时计算时间差。把这个延迟时间记下来,在控制器设计时用相位裕度来做补偿,效果很明显。
这里还要重点说说位置控制。位置环的响应频率不需要太高,100Hz足够。位置控制的基本思路是:用位置误差产生期望速度,再用期望速度经过速度环产生期望加速度,然后通过姿态生成器把期望加速度转换到机体坐标系下的期望姿态角。这是PX4和ArduPilot通用的做法。
路径规划方面,在企业级场景下用得比较多的是“航点飞行”和“覆盖式扫描”这两种模式。航点飞行其实就是简单的轨迹插值,关键点在于转弯策略——提前减速、圆弧过渡、以及航线跟踪时用横向偏差和航向偏差做组合修正。覆盖式扫描常见于测绘和巡检任务,这时候要用到Boustrophedon(往复式)路径生成算法,或者更复杂的基于多边形分割的全覆盖路径算法。对于复杂的未知环境,可以引入RRT或者A*做避障路径规划。但要注意,这些复杂的路径规划算法最好在机载计算机上运行,把生成的航点发给飞控执行,不要在MCU上直接跑,算力和确定性都不够。
5. 仿真先行:在代码上真机之前,先让算法在仿真环境里跑够
很多人都问过我一个问题:你们自研飞控,仿真怎么做?
先说结论:仿真不是可选项,而是必选项。没有仿真环境,你的每一项功能直接上真机验证,成本高不说,安全风险也大。一次炸机,物理损坏可能是几千到几万块,但时间损失和项目延期往往才是真正的代价。
我做仿真分两个层面进行。
第一个层面是纯算法仿真,使用MATLAB/Simulink。在这个阶段,把飞行动力学模型搭出来,包括刚体动力学、电机响应模型、传感器模型和噪声模型。把姿态控制、位置控制算法放到里面跑,观察不同参数下的响应曲线。这个层面的好处是调试速度快,可以轻松做蒙特卡洛参数扫描,找到敏感参数。一套好的Simulink仿真模型,能在你写第一行嵌入式代码之前,就把控制律的核心逻辑验证明白。
第二个层面是系统级仿真,也就是软件在环(SITL)仿真。我自己的做法是:把自研的控制算法编译成本地程序,在Ubuntu上运行,通过共享内存或者Socket和一个基于Gazebo或者其他物理引擎的模拟环境通信。这个方法不需要真实飞控,就能跑通完整的“传感器数据输入-控制算法计算-控制指令输出”链路。如果你不想自己搭这一套,PX4的仿真环境可以作为很好的参考——你完全可以用Ubuntu搭建PX4仿真环境来验证动态模型是否正确,再把自己的算法接口对齐到这套体系里。这也是行业里很常见的做法:复用工具链,而不是重复造轮子。
硬件在环(HIL)仿真更接近真实情况。把写好的飞控固件烧进真实的飞控板,再把飞控板跟一个实时仿真机连接。这个阶段要重点验证任务调度有没有问题、传感器通信有没有逻辑错误、以及控制输出和仿真模型之间的闭环延迟是否符合预期。HIL仿真要求仿真机的实时性很高,常用的有Speedgoat、Concurrent等,价格不便宜,但对企业级开发来说,这笔投入绝对值得。
说起仿真和实机的差异,有两个点必须提前有心理准备。第一,模型永远和真实世界有偏差。比如你模型中电机的响应延迟是10ms,但实际可能是18ms,这个偏差会让控制器的整定参数完全失效。第二,传感器的噪声分布和故障模式永远模拟不全。仿真中不会出现的GPS丢星、磁罗盘跳变、IMU饱和,在真实世界里都可能发生。所以仿真的价值不是“验证完了就直接可以上真机”,而是“把所有能预见的逻辑性问题先消灭掉,让真机调试的变量尽可能少”。
6. 真机调试与PID调参:那些文档里不会写的坑
真机这一步,才是真正考验一个飞控团队功底的地方。
第一次上电和自检阶段,就有很多坑。首先是电机转向确认。这个看起来简单,但在多旋翼上,任何一个电机转向错误都会导致起飞瞬间翻转。正确做法是:放电调信号线,然后手动给每个电机一个小的油门指令,确认转向。测试完转向,再把桨装上去。
我建议的第一次真机流程是这样的:
第一步,静态测试。先不上桨,测试电机依次响应遥控器和地面站指令是否正确。同时检查传感器数据:IMU、气压计、磁力计读数要平稳,虚拟仪表要和飞机实际姿态一致。
第二步,姿态内环测试。拿着飞机在手里,小幅度倾斜机身,观察电机转速是否会做出对应响应。注意:这一步测试的响应方向如果反了,飞机会“飞手朝哪边倾斜就朝哪边加速”然后直接翻转。这个检查一定要做细。
第三步,低空悬停。建议在无风环境、草地或者加防护圈的场地上,先用较小的油门目标值测试。第一次离地不需要飞太高,20到30厘米就够。重点观察飞机是否朝某个方向漂移、是否有高频振荡。
讲一下震动问题,这个在真机阶段出现概率极高。螺旋桨的动平衡问题、电机轴承损耗、机身结构共振都可能导致IMU数据被污染。症状就是姿态解算在悬停时出现高频小幅度震荡,或者是控制输入不增加但电机转速忽高忽低。排查思路:先用震动记录模式把IMU原始数据录下来,做FFT频谱分析,看主能量集中在什么频段。如果震动主频接近机架的共振频率,要优先处理机架结构;如果是电机轴承或螺旋桨不平衡,就要更换或者做动平衡。
很多团队在这一步容易犯一个错误:明明机架震动大,却想通过降低滤波器截止频率把震动滤掉。这个办法治标不治本。降低滤波器的截止频率会增加相位的滞后,而相位滞后是姿态控制带宽的天敌,表现出来就是飞机变迟钝、调参总是达不到理想状态。
PID调参这一步,我在上一章已经给了基本步骤,这里补充几个文档中很少提的细节:
第一个细节:内环的D项要放在角速度反馈上,而不是放在姿态误差上。这样做的原因是角速度的微分项包含了对高频噪声的敏感度更低,而且对阻尼的控制更直接。
第二个细节:很多团队在调参的时候只盯着“会不会振荡”这一个指标,忽略了“响应是否干净”这个更深层的问题。一个低增益但不过冲的系统,往往看起来稳定,但抗风能力差。真正的判断标准是:突然给一个姿态目标,飞机的姿态应该在最短时间内到达目标角度,并且只有一次轻微的过冲,随后迅速稳定。如果到达时间太长,说明增益不够,要继续加。
第三个细节:抗风扰测试。低空悬停调稳之后,一定要在稍大的风速下再测试一次。注意观察飞机的横滚角和俯仰角随风速变化的波动幅度,如果波动超过3到5度,就要考虑增加内环的D项或者调整外环的P值。抗风性能是衡量飞控性能的一个重要维度,也是企业级应用(比如电力巡检、桥梁检测)里面最受关注的指标之一。
关于GNSS和磁力计的调试,有一个常见的问题:飞机飞着飞着突然画圈,转速越来越快。这种情况八成是磁力计受到了干扰,导致航向角缓慢漂移。排查方法是:在飞行日志里对比磁力计曲线和GNSS航迹推算的偏航角,看哪边先发生偏移。防止这个问题的根本方法是合理安装GNSS罗盘模块,尽量远离电机电源线和大电流线路。如果磁力计不能远离的话,可以做磁干扰补偿校准,但效果不如物理隔离好。
7. 走向企业级:安全机制、失效保护与全流程验证
最后这一章,讲讲从一套能飞的飞控,变成一套可交付的企业级飞控系统,还需要补哪些东西。
失效保护设计是重中之重。企业级无人机在任何情况下都不允许出现“失控自由落体”这种状态。常见的Failsafe触发条件包括:遥控器信号丢失、GNSS丢失、电量过低、触发电子围栏边界。每个触发条件都要有明确的响应逻辑,而且这些逻辑必须是分层式的:
| 失效等级 | 触发条件 | 响应动作 | 安全原则 |
|---|---|---|---|
| L1 警告 | 电量低于30% | 发出低电量提醒,限制最大加速度 | 不打断任务,但提示返航 |
| L2 保护 | 遥控器信号丢失 | 自动切换为自主返航模式 | 不依赖遥控器也可以完成任务 |
| L3 紧急 | GNSS信号丢失 | 悬停保持,等待恢复或降落 | 防止位置估计漂移导致失控 |
| L4 致命 | 传感器数据异常 | 直接切入紧急降落模式 | 宁可摔机,也不能乱飞伤人 |
这里有一个细节:很多人觉得GNSS丢了第一反应是切换到“返航”。但如果GNSS信号已经丢了,返航点的位置也是不可靠的,所以正确做法是悬停等待恢复,实在恢复不了再降落。
另一块是系统冗余设计。企业级飞控建议至少做双IMU冗余,一个主IMU一个副IMU。软件层面的逻辑是:如果主IMU数据跳变幅度超过阈值,立即切换到副IMU。这个切换逻辑要预先测试,因为有些IMU故障是“温和型”的,数据看起来正常但缓慢漂移,这种情况下单纯靠跳变检测是不够的。所以还要加逻辑比较:两个IMU的数据做交叉验证,偏差超过一定范围就报警。
飞行日志系统就是飞控的“黑匣子”。企业级产品的日志记录频率建议至少50Hz,关键数据(IMU原始数据、控制量、状态量)要100Hz以上。日志要做到掉电不丢失,所以一般需要独立的存储介质或者掉电保护电路。
故障注入测试是很多团队会忽略的环节。它的目的是人为制造故障,验证失效保护逻辑是否真正有效。常见做法包括:
- 在飞行中拔掉GNSS天线,观察是否按预期切换模式
- 用信号发生器模拟IMU数据跳变,验证冗余切换是否及时
- 在代码逻辑里强制让某个任务超时,验证看门狗机制
- 模拟多个传感器同时异常的情况,验证系统是否仍然能做出安全决策
我强烈建议在量产交付之前,做一套完整的故障注入测试矩阵,把每一种可能的故障场景都测试一遍。这比后面出了事故再去补救要划算得多。
从功能级别的角度来看,企业级飞控系统最终的竞争力在于它能不能支撑复杂的行业应用。比如在无人机巡检平台里,飞控需要稳定承载双目视觉传感器进行实时避障;在测绘场景里,飞控需要支持精细的航线执行以便后期做正射拼接;在安防场景里,飞控平台要能稳定悬停并配合机载感知系统完成对低慢小目标的识别与告警。这些上层应用都依赖底层飞控的轨迹精度、抗风能力和安全性。也就是说,飞控不是终点,它是整个无人机智能化的底座。
我自己到现在依然保持一个习惯:每次版本发布前,把上一次试飞的日志拿出来重新翻一遍,看看有没有当时没注意到的小异常。很多时候,那些导致重大事故的隐患,在早期日志里其实已经有微弱的预兆了。做飞控系统,耐心和细致比天赋更重要。
再分享一个连续踩过几次坑之后总结的小技巧:在所有传感器的采样代码里,加一个内存屏障和缓存一致性刷新操作。这个东西听起来是底层常规操作,但在MCU上跑FreeRTOS多任务采集多路传感器数据时,优化器有时会做出错误的指令重排,导致跨任务的数据一致性出问题。在关键数据结构交互时禁用优化,或者在加锁之后做一次数据同步,能规避掉很多莫名奇妙的间歇性故障。
飞控算法开发是一场长跑。从搭好第一版代码框架开始到飞控系统达到可交付的状态,背后需要的不只是理论功底,还有大量试错带来的直觉。如果你的团队也在这条路上,希望这份经验能帮你少走一段弯路。