1. 模型推导的整体思路:为什么四旋翼的数学模型让人又爱又恨
四旋翼无人机这玩意儿,飞行控制圈里人人都说“先建模,再调参”,可真到了自己动手推公式的时候,不少人直接被那堆矩阵、角度、力矩给劝退了。我一开始做飞控时也踩过这个坑:照着论文抄了一版动力学方程,结果扔到真机上,姿态稳不住,稍微打杆就乱飘。后来才明白,不是方程抄错了,是我压根没搞懂每个项对应飞机上的哪个物理部分、哪些项能忽略、哪些项必须精确标定。
聊四旋翼数学模型之前,先说一个最核心的认知:四旋翼本质上是一个欠驱动、强耦合、非线性的系统。它有六个自由度(三个位置方向、三个姿态角),却只有四个电机输入,这意味着你想让飞机往前飞,并不能直接给一个“前进力”,只能通过改变姿态、让升力倾斜,用水平分量去驱动位移。这个“通过姿态间接控制位置”的逻辑,就是整篇数学模型里贯穿始终的主线。
所以推导模型时,我们通常分两层来拆:位置动力学(描述飞机在空间里的平移运动)和姿态动力学(描述飞机绕自身三个轴的旋转运动)。两层之间通过姿态矩阵耦合在一起。写出来就是标准的牛顿-欧拉方程体系。
这套模型能解决什么问题?往小了说,它能告诉你“给定四个螺旋桨转速,飞机会产生多大加速度”,这是仿真模拟、飞控算法开发的基础;往大了说,后面的状态估计、姿态解算、PID控制器设计、甚至故障检测,全都长在这棵树上。适合谁来参考?自己做四旋翼毕设的学生、刚入门飞控开发的工程师、以及想搞无人机仿真验证的爱好者,这篇文章应该能把你们从“能飞”带到“知道为什么能飞”的那一步。
2. 坐标系定义:建模前的必修课,90%的新手都挂在这一步
2.1 机体坐标系与惯性坐标系到底怎么选
做四旋翼建模,第一步不是列方程,而是把“在哪里描述运动”这件事说清楚。这里涉及两个坐标系:地面惯性坐标系和机体坐标系。
地面系一般取起飞点为原点,X轴指向正北(或任意固定方向),Z轴垂直向下或向上,满足右手定则即可。机体系则是固连在飞机上的坐标架,原点在飞机重心,X轴指向机头方向,Y轴指向机右翼,Z轴垂直机体向下。这里特别提醒一下:不同教材Z轴取向可能相反,一种是“北西天”坐标,一种是“东北地”坐标,推导公式前必须统一,否则后面算力矩时符号全乱。
为什么要两个坐标系配合用?因为传感器测量的量分散在两个坐标系里:加速度计和陀螺仪测得的是机体系下的物理量,而GPS、光流传感器测得的是地面系下的位置。控制要的是地面系下的位移误差,而执行机构(电机)是在机体系下出力。没有坐标变换,这两个世界就是割裂的。
2.2 旋转矩阵:连接两个坐标系的桥
从机体系到地面系的旋转,一般用三个欧拉角来描述:滚转角(绕X轴,记为)、俯仰角(绕Y轴,记为)、偏航角(绕Z轴,记为)。三个单轴旋转矩阵相乘,就得到了完整的旋转矩阵,常用的顺序是Z-Y-X(先偏航再俯仰最后滚转),写成教科书里常见的形式:
$$ R = R_z(\psi) \cdot R_y(\theta) \cdot R_x(\phi) $$
展开之后是长这样的东西:
$$ R = \begin{bmatrix} c\psi c\theta & c\psi s\theta s\phi - s\psi c\phi & c\psi s\theta c\phi + s\psi s\phi \ s\psi c\theta & s\psi s\theta s\phi + c\psi c\phi & s\psi s\theta c\phi - c\psi s\phi \ -s\theta & c\theta s\phi & c\theta c\phi \end{bmatrix} $$
这个矩阵的意义很直观:你把它乘上机体系下的任意向量,得到的就是地面系下的表达。比如机体系下的升力方向是垂直机体平面的Z轴负方向,乘以旋转矩阵后,就能算出这个升力在地面系里沿三个轴的分量——这部分直接进入位移方程。
我用一个生活类比帮助理解:机身朝哪个方向,就好比你斜端着一碗水,地面系的Z轴是竖直向下,而机体系的Z轴是垂直于碗底向外。水受重力是沿地面系Z轴的,但你手托碗底感受到的力却是沿机体系Z轴的,这中间的“角度差”,就是旋转矩阵在数学上干的事情。
2.3 欧拉角速率和机体角速度之间的转换关系
建模里另一个容易让人头大的点是:欧拉角随时间的变化率和机体系下的角速度并不相等。机体系下的角速度(p, q, r)是陀螺仪直接测量的量,而我们要的姿态角导数是,两者之间必须有转换矩阵:
$$ \begin{bmatrix} \dot{\phi} \ \dot{\theta} \ \dot{\psi} \end{bmatrix} = \begin{bmatrix} 1 & \sin\phi\tan\theta & \cos\phi\tan\theta \ 0 & \cos\phi & -\sin\phi \ 0 & \sin\phi/\cos\theta & \cos\phi/\cos\theta \end{bmatrix} \begin{bmatrix} p \ q \ r \end{bmatrix} $$
注意这个矩阵在俯仰角接近正负90度时出现奇异值——这就是欧拉角表示法的“万向节锁死”问题。做工程时,如果飞机做特技飞行可能出现倒飞或大角度机动,用欧拉角建模就会失效,这时需要转成四元数表示。四元数没有奇异性,运算也更快,只是直观性稍差。
实操建议:初学者先用欧拉角理解物理意义,写代码时尽早切四元数。我在PX4开源固件里见过姿态估计的代码,内部清一色四元数运算,只在最外层输出欧拉角给上层控制或地面站显示用得着。还有一个细节:姿态解算的0.00001度的误差,经过长时间积分就变成好几米的定位漂移,这也是为什么建模时不能简单用“角度”本身,而要用“角度的变化率”配合传感器融合算法来估计姿态。
3. 力和力矩分量的建模:每一项都对应飞机的真实物理部件
3.1 拉力:模型的主导项,但计算远比想象复杂
四旋翼垂直运动的本质是螺旋桨旋转产生升力。每个螺旋桨产生的拉力F与转速的平方成正比,经验公式写作:
$$ F_i = C_T \cdot \rho \cdot A \cdot R^2 \cdot \omega_i^2 $$
如果飞机尺寸和飞行高度变化不大,空气密度可以算作常数,把所有常系数合并,就得到简化的轴流模型:
$$ F_i = k_T \cdot \omega_i^2 $$
其中就是拉力系数。看起来很简单,但这个系数怎么来,是建模时第一个大坑。理论上可以用螺旋桨叶素理论推导,但实际桨叶形状、桨距、翼型分布都是非线性的,纯理论计算误差在10%以上。我实测过两个不同厂家的1045桨,同样是3000转每分钟,拉力差了近15%,这直接影响后续仿真与实飞的一致性。
更稳妥的方法是台架标定:把电调和电机固定在力传感器上,给定PWM值测转速和拉力,用最小二乘法拟合k_T。具体方法后面会用一整节来讲,这里先记住一个结论:想靠模型精确,拉力系数一定不能用仿真库里的默认值。
3.2 反扭力矩和陀螺效应:两个总被忽略却真实存在的角运动影响
电机旋转除了产生升力,还给机身一个反方向的扭矩。这个反扭力矩同样与转速平方成正比:
$$ M_i = C_M \cdot \omega_i^2 = k_M \cdot \omega_i^2 $$
注意四旋翼的电机是成对反向旋转的:两个顺时针、两个逆时针。当四个电机转速相等时,反扭力矩整体互相抵消,飞机纹丝不动;一旦某对角电机转速差变大,偏航力矩就出现了。这就是四旋翼偏航控制的基本原理。
再看陀螺效应。高速旋转的螺旋桨相当于一个陀螺,当机身旋转时,桨叶会产生抵抗这个旋转的陀螺力矩。完整的高精度模型里,每一项都是:
$$ M_{gyro,i} = I_{prop} \cdot (\Omega_{body} \times \omega_i) $$
也就是螺旋桨的角动量与机体角速度的叉积。很多人做悬停仿真的忽略这一项,但在做快速横滚或剧烈的偏航机动时,陀螺力矩会让飞机出现明显的“进动”现象,姿态响应变得非常奇怪。
3.3 空气阻力与风扰:悬停仿真可以忽略,高速飞行就必须建模
空气在机身平面上产生的阻力,用气动阻力模型来描述:
$$ F_{drag} = \frac{1}{2} \rho C_D A v^2 $$
这个力的方向与速度方向相反。低速(小于3m/s)悬停飞行时,阻力项数值很小,可以当作扰动处理;但如果做高速巡航或抗风试验,这个力就是决定稳态速度上限的关键项,忽略它会导致仿真里的最大速度明显大于实际。
还有一个容易漏掉的项是平动阻力对姿态回路的影响。机身高速飞行时,气流会在机身上产生一个气动力矩,这个力矩在某些攻角下会不稳定,导致飞机抬头或低头。想要做精确的高速飞行模型,就需要查表或风洞数据,这部分已经属于气动辨识的专业领域了。
4. 牛顿-欧拉方程推导:从物理守恒定律到最终的六自由度模型
4.1 平动动力学方程:让位置变化与力直接挂钩
现在可以写核心的动力学方程了。根据牛顿第二定律,在地面惯性坐标系下,四旋翼的平动满足:
$$ m \begin{bmatrix} \ddot{x} \ \ddot{y} \ \ddot{z} \end{bmatrix} = R \cdot \begin{bmatrix} 0 \ 0 \ -T \end{bmatrix} + \begin{bmatrix} 0 \ 0 \ mg \end{bmatrix} + F_{drag} $$
其中是四个螺旋桨升力之和,那个带着旋转矩阵的项就是“机体系升力投影到地面系”的结果。重力项是沿地面系Z轴(按我的坐标约定,Z轴向下为正,重力项为正)。加上气动阻力项之后,就构成了完整的位置动力学。
这个方程解释了四旋翼所有的平移行为:水平方向没有直接的输入力,只能靠倾斜机身(改变R矩阵的俯仰和滚转角),让升力分解出水平分量来驱动运动。这就是为什么四旋翼的“前进”被戏称为“低头往前冲”。
4.2 转动动力学方程:姿态变化的根本原因
姿态动力学用欧拉方程描述,在机体系下:
$$ I \begin{bmatrix} \dot{p} \ \dot{q} \ \dot{r} \end{bmatrix} = - \begin{bmatrix} p \ q \ r \end{bmatrix} \times I \begin{bmatrix} p \ q \ r \end{bmatrix} + \begin{bmatrix} \tau_\phi \ \tau_\theta \ \tau_\psi \end{bmatrix} + M_{gyro} $$
这里I是转动惯量矩阵。对于四旋翼这类近似对称的结构,可以近似为对角阵,也就是I_xx、I_yy、I_zz三个独立参数。其中的叉积项代表陀螺力矩的耦合——当飞机横滚角速度大时,即使没有输入俯仰力矩,俯仰方向也会受到耦合影响。
三个轴的力矩输入分别是:横滚力矩来自左右电机升力差,俯仰力矩来自前后电机升力差,偏航力矩来自反扭力矩差。写成控制关系:
$$ \tau_\phi = l \cdot k_T \cdot (\omega_2^2 - \omega_4^2) $$
$$ \tau_\theta = l \cdot k_T \cdot (\omega_1^2 - \omega_3^2) $$
$$ \tau_\psi = k_M \cdot (\omega_1^2 + \omega_3^2 - \omega_2^2 - \omega_4^2) $$
其中l是电机到飞机重心(质心)的水平距离。这里的电机编号要和你实际装机保持一致,否则就是“控制分配矩阵填错,飞控输出全反”的悲剧。
4.3 从单机功率到模型整体:六自由度的完整状态表达
把平动方程和转动方程组合起来,加上姿态角速率的转换方程,就得到了完整的6自由度模型。用状态空间的形式写出来,状态量是位置x、y、z,速度、,姿态角、和角速度p、q、r,一共12个状态。
完整模型写出来很长,但表达的信息其实就一句话:给定四个电机的转速,就能推算出飞机的位置和姿态随时间的变化。这是仿真器最核心的动力学引擎。反过来,想让飞机按指定轨迹飞行,就需要设计控制律,根据期望的位置和姿态,反解所需的转速——这是后面控制器设计的任务。
5. 实操建模:实物参数测量与辨识技巧
5.1 质量、重心与转动惯量的测量:别再用CAD里的数
模型里的十几个参数,最影响真实度的不是公式形式,而是数值准不准。很多初学者直接用SolidWorks里的估算值,结果仿真和实机飞行状态差了一大截。我个人的经验是:质量和重心一定要实测,转动惯量至少用悬线法测一次。
质量用电子秤直接称,重心位置用两个秤支撑法做一个“找支点”的操作:把飞机平放在一根细杆上,调节细杆位置直到飞机保持平衡,细杆位置所在平面即为重心平面。三个维度都用这个方法做一遍,重心的空间位置就出来了。
转动惯量的测法比较有趣,最常用的是三线摆法:用三根等长的线吊起飞机,让飞机绕垂直轴做小角度扭转摆动,测量摆动周期T,根据公式:
$$ I_{zz} = \frac{m g r^2}{4\pi^2 L} \cdot T^2 $$
就能算出绕垂直轴的转动惯量。绕另外两个轴的测量需要重新调整挂架方向。如果条件不允许,也可以用CAD算出的值做初值,再飞一轮测试,根据实际响应调整。
5.2 拉力系数与扭矩系数的台架标定:一个下午能做完
标定k_T和k_M需要一个简易的台架:力传感器、转速计(或者电调遥测数据)、直流电源、飞控板。把单个电机-电调-桨叶组合固定在力传感器上,依次给不同油门值,记录转速和拉力。我标定一个四轴一般测10个点,从10%油门到90%油门,每个点稳定采集5秒取平均值。再用线性回归去拟合和的关系。
扭矩系数k_M的标定稍微麻烦一点:需要测量电机座上的反扭力。我是用一个L型支架,把电机轴向力传感器压在支架上,记录侧向力乘上力臂得到扭矩,然后同样拟合与转速平方的关系。
这里分享一个注意:电池电压的变化会显著影响拉力系数的标定结果。同一个电机,3S电池满电(12.6V)和接近没电(11.1V)时,相同转速下输出拉力并不会有太大差别(因为转速是闭环控制),但电调的输出特性会变。所以标定时尽量保持输入电压稳定,或者记录电压值,在后续控制里做电压补偿。
5.3 混控矩阵:把期望力与力矩变成四个电机的转速命令
有了参数以后,可以写出完整的控制分配矩阵。常规X型四旋翼,期望的升力T、横滚力矩、俯仰力矩、偏航力矩与四个电机转速平方的关系是:
$$ \begin{bmatrix} T \ \tau_\phi \ \tau_\theta \ \tau_\psi \end{bmatrix} = \begin{bmatrix} k_T & k_T & k_T & k_T \ -k_T l & k_T l & k_T l & -k_T l \ k_T l & k_T l & -k_T l & -k_T l \ -k_M & k_M & -k_M & k_M \end{bmatrix} \begin{bmatrix} \omega_1^2 \ \omega_2^2 \ \omega_3^2 \ \omega_4^2 \end{bmatrix} $$
注意:矩阵的具体数值和正负号,完全取决于你的电机序号排列和旋向定义。装机之后第一件事,就是拿着这个矩阵去对照你的飞机实际构型,把每一行每一列都核对一遍。我见过不少飞友炸机的根源,就是飞控里选的机型跟实际X型还是十字型不一致,导致混控矩阵直接反了。
6. 从数学到控制:模型的具体工程化应用
6.1 在仿真环境里验证你的模型:给控制器当“训练场”
模型建好之后,第一件能做的事就是仿真。以我常用的MATLAB/Simulink为例,可以把第4节的12个状态方程封装进一个S-Function或Stateflow模块里,外面接上控制器作为闭环。这样可以在不上真机的情况下,先验证控制器的稳定性、调节PID参数、做故障模拟(某个电机突然失效)。
做仿真时重要的一点是加入噪声和误差:传感器模型要叠加高斯白噪声,执行器要有响应延迟和饱和限制,否则仿真里效果完美的控制器,搬上真机照样乱来。很多开源仿真器(如AirSim、Gazebo)内部也是用这类动力学模型,只是把空气动力学项做得更细。
6.2 模型在姿态控制器设计中的关键作用:PID参数可以不用再瞎试
有了模型,姿态控制器的设计从“盲调”变成“有据可查”。以角度环为例,外环是姿态角控制,内环是角速度控制。根据模型中的转动方程,角速度回路的被控对象可以近似成一阶惯性环节,增益就是力矩系数除以转动惯量。这告诉你p、q、r三个角速度环比例增益的初值怎么定:
$$ K_p \approx \frac{I_{xx}}{\tau_\phi} $$
用这个初值起调,比纯靠脸盲调省了一个晚上的时间。我自己调试时通常会把模型仿真出来的增益直接作为真机PID的初值,然后根据实际飞行做小范围微调,一般两三轮就能稳住。
6.3 模型验证与误差源分析:为什么模型算出来和真机飞起来不一致
建好模型不等于万事大吉。模型和真机之间的误差来源主要有几类。
首先是参数误差:质量估计不准、重心不在几何中心、转动惯量测得不准,都会导致模型输出与实机响应偏差。这时可以做一个“模型校准飞行”,记录实机舵面激励下的姿态响应,再与仿真对比,用对比结果反过来修正参数。
其次是未建模动态:比如机架的弹性形变、螺旋桨在高速下的气动失速、电机的响应延迟,这些都很难用简单公式描述。处理思路是:先把简单模型建好跑通,再逐个叠加更精细的修正项,千万不要一上来就搞CFD级别的建模,工程上性价比极低。
最后是延迟:从控制器输出到电机转动再到产生拉力的过程,存在几十到上百毫秒的延迟,这个延迟会极大影响控制稳定性。模型里至少要加入一阶惯性环节模拟电机延迟,否则仿真的相位裕度算出来和实际差距很大。
7. 常见问题排查:建模时容易踩的坑和解决办法
7.1 坐标方向搞反:升力符号不对,飞机直接扎地板
这个错误极其常见。很多人在旋转矩阵里用了“Z轴向上”的约定,把升力方向写成正Z,结果跟重力方向一致,仿真里飞机直接加速砸向地面。检查方法非常简单:把飞机水平放置(欧拉角全为0),给一个正升力,看z轴加速度是不是向上(负方向或正方向取决于你的坐标约定)。如果一个简单的悬停命令都让飞机往地上加速,八成是坐标方向或升力符号的问题。
7.2 混控矩阵符号不对:打杆方向全反,翻滚就是翻机
混控矩阵的符号错了,表现是给一个正的横滚指令,飞机往反方向滚。这类问题一定要在系留测试或仿真里先验证——把飞机绑在测试台架上,给一个小的偏航指令,观察四个电机的转速变化是否符合预期。我习惯在混控代码里打印每个电机的转速命令,做一次“地面仿真输出检查”,这比上天试错安全得多。
7.3 转动惯量差太多:姿态振荡的隐形原因
如果你的姿态响应在调参时表现出奇怪的振荡——某些频率下特别容易共振,无论怎么降PID增益都不行——大概率是转动惯量估计偏差太大。此时可以用频率响应法做辨识:给一个扫频激励,测量姿态响应,通过波特图估算实际转动惯量。这一步做完再调PID,你会感觉像是换了架飞机。
8. 一些实操心得和个人的小建议
写到这里,模型推导的全部主线已经走完。最后分享几点我在实际项目中摸爬滚打出来的体会。
关于建模精度:别追求“完全精确”,追求“够用且一致”。控制上需要的不是真实系统的完美复制,而是一个能反映主要动态特性的简化模型。你舍掉陀螺力矩,悬停性能照样很好;你忽略空气阻力,低速飞行问题也不大。但如果你用的模型跟实机的趋势都相反,那再精妙的控制律也白搭。
关于工具链:我强烈建议用一套Python+NumPy/SciPy先快速搭建模型原型,验证模型行为和控制器设计,然后再移植到MATLAB/Simulink做正式仿真或直接生成C代码。Python处理矩阵运算和可视化都比MATLAB轻量不少,而且后期接真机数据做参数辨识也方便。等你需要更复杂的仿真环境时,再考虑Gazebo或AirSim不迟。
关于模型文档化:所有推导的变量定义、坐标约定、参数标定记录,一定要形成文档并写明日期、环境温度、电压等级,因为建模参数跟使用条件强相关。我吃过一个亏:某次做仿真用了一套夏天标定的参数,冬天温度低了电池内阻变大,实际转速-拉力关系变了,飞行性能和仿真对不上,排查了一天才发现是参数标定的环境变了。
四旋翼的数学模型推导,说白了就是三步:定义坐标系、列出力和力矩、代入牛顿欧拉方程。难的是在每个环节都不出错,并把模型参数标得接近真实。只要把这篇文章里面提到的坑都绕过去,后面的控制器设计、状态估计、路径规划再复杂也有一个靠谱的“物理底座”托着。