4、无人机动力学建模:刚体运动方程、空气动力学简化模型、推力与力矩计算

好,咱们进入正题。无人机动力学建模,说白了就是回答一个问题:这玩意儿到底是怎么飞起来的?

我刚开始做飞控那会儿,总觉得动力学是理论派的事,代码能跑就行。直到有一次,我调了一周的PID参数,飞机就是稳不住——后来才发现,是模型里的转动惯量给错了。嗯,从那以后,我再也不敢轻视建模这一步。

这一节,我会带你从三个层面拆解无人机动力学:

  • 刚体运动方程——描述飞机在空中的位置和姿态变化
  • 空气动力学简化模型——升力、阻力怎么来的
  • 推力与力矩计算——电机和螺旋桨到底给了飞机什么力

咱们先看一张整体框架图,帮你建立全局认知。

无人机动力学建模知识体系 动力学建模 刚体运动方程 空气动力学简化模型 推力与力矩计算 牛顿-欧拉方程 位置与姿态状态方程 升力系数、阻力系数 简化气动模型 电机-螺旋桨模型 力矩分配矩阵 Simulink 模块化实现 → 仿真验证

4.1 刚体运动方程:位置与姿态的数学描述

无人机在空中,本质上就是一个六自由度的刚体。三个平动自由度(x, y, z),三个转动自由度(roll, pitch, yaw)。

我个人习惯把运动方程拆成两部分:

  • 平动动力学:由牛顿第二定律描述,F = m * a
  • 转动动力学:由欧拉方程描述,M = I * α + ω × (I * ω)

你想想看,飞机在空中的加速度,其实来自两个部分:一个是发动机推力,一个是重力。阻力嘛,我们后面再聊。

核心公式(机体坐标系下):

m * dV/dt = F_thrust + F_gravity + F_aero
I * dω/dt = M_thrust + M_gyro - ω × (I * ω)

其中:

  • V = [u, v, w]^T —— 机体坐标系下的速度
  • ω = [p, q, r]^T —— 角速度
  • I —— 转动惯量矩阵(3x3)

我在项目中遇到过一个问题:很多人直接把地面坐标系下的加速度方程拿来用,结果仿真出来的轨迹完全不对。为什么?因为推力方向是随姿态变化的,必须做坐标系旋转。

所以,Simulink里建模时,我建议你这样做:

  1. 旋转矩阵 R 把机体坐标系下的推力转换到地面坐标系
  2. 在地面坐标系下写平动方程
  3. 四元数欧拉角 更新姿态

小技巧: 我个人偏爱用四元数,因为它没有万向锁问题。欧拉角虽然直观,但俯仰角接近±90°时,仿真会崩掉。你可以在Simulink里用“Quaternion”模块,省去手动推导的麻烦。

4.2 空气动力学简化模型:别把简单问题复杂化

说到空气动力学,很多初学者就头大。其实对于多旋翼无人机,我们不需要搞CFD(计算流体力学)。

说白了,我们只需要两个力:升力阻力

升力公式:

L = 0.5 * ρ * v² * S * CL

阻力公式:

D = 0.5 * ρ * v² * S * CD

其中:

  • ρ —— 空气密度(标准大气压下约1.225 kg/m³)
  • v —— 空速(相对空气的速度)
  • S —— 参考面积(机翼面积或桨盘面积)
  • CL, CD —— 升力系数和阻力系数

嗯,这里要注意:对于多旋翼,升力主要来自螺旋桨,而不是机翼。所以S通常取桨盘面积,CL和CD需要查桨叶数据或做实验标定。

避坑指南: 我曾经在仿真里直接用常数CL和CD,结果发现飞机在高速飞行时阻力明显偏小。后来才意识到,CL和CD其实是攻角的函数。如果你做的是高速飞行仿真(比如固定翼),一定要用查表法或多项式拟合。多旋翼低速悬停时,用常数问题不大。

在Simulink里,我习惯把气动模型封装成一个子系统:

  • 输入:空速、攻角、侧滑角
  • 输出:气动力(Fx, Fy, Fz)和气动力矩(Mx, My, Mz)
  • 内部:用MATLAB Function或Lookup Table实现CL、CD曲线

4.3 推力与力矩计算:电机和螺旋桨的配合

这部分是实际工程中最容易出问题的地方。你想想看,四个电机转起来,到底给了飞机多大的推力和力矩?

先看单个电机-螺旋桨模型:

推力: T = kT * ω²
反扭矩: Q = kQ * ω²

其中:

  • ω —— 电机转速(rad/s)
  • kT —— 推力系数
  • kQ —— 扭矩系数

这两个系数通常由桨叶的几何参数决定。我在项目中一般通过静拉力测试来标定,简单说就是:把电机固定在测力台上,测不同油门下的推力和扭矩,然后拟合出kT和kQ。

接下来是力矩分配。对于四旋翼(X型布局),总推力和三个轴的力矩可以写成:

控制量 物理意义 与电机转速的关系
F_total 总推力(z轴) kT * (ω₁² + ω₂² + ω₃² + ω₄²)
M_roll 滚转力矩(x轴) L * kT * (ω₂² - ω₄²)
M_pitch 俯仰力矩(y轴) L * kT * (ω₁² - ω₃²)
M_yaw 偏航力矩(z轴) kQ * (ω₁² - ω₂² + ω₃² - ω₄²)

其中L是电机到重心的距离。你看,偏航力矩靠的是反扭矩差,而不是推力差——这一点很多新手会搞混。

Simulink实现建议:

我一般会建一个“Mixer”模块,输入是期望的[F_total, M_roll, M_pitch, M_yaw],输出是四个电机的转速指令。这个模块本质上就是一个4x4矩阵的逆运算。

% 伪代码示例
% 分配矩阵 (X型四旋翼)
mix_matrix = [1,  1,  1,  1;
              0,  1,  0, -1;
             -1,  0,  1,  0;
              1, -1,  1, -1];
% 注意:这里需要根据实际布局调整符号

个人经验: 电机响应是有延迟的,一般一阶惯性环节就能模拟。时间常数τ大概在0.01~0.05秒之间,具体看电机和电调。别忘了在Simulink里加一个“Transport Delay”或“Transfer Fcn”模块,否则仿真出来的响应会过于理想。

4.4 把模型组装到Simulink里

好了,三个部分都讲完了。怎么把它们拼起来?

我建议的模块结构是这样的:

  1. 输入层:四个电机的PWM指令(0~1归一化)
  2. 电机模型:PWM → 转速(含一阶延迟)
  3. 推力/力矩计算:转速 → 推力和力矩(用上面的公式)
  4. 刚体动力学:推力和力矩 → 加速度、角加速度 → 积分得到速度和位置
  5. 气动模型:速度 → 气动力/力矩(反馈到刚体动力学)
  6. 输出层:位置、姿态、速度、角速度

你想想看,这个结构是不是很清晰?每个模块都可以单独测试,出了问题也好定位。

注意: 仿真步长不要太大。我一般用固定步长1ms,四阶龙格-库塔法。步长太大,刚体动力学积分会发散;步长太小,仿真跑不动。1ms是个不错的折中。

最后,送你一句话:模型是仿真的灵魂,参数是模型的生命。 花时间标定好kT、kQ、I这些参数,比调PID参数重要得多。


公众号:蓝海资料掘金营,微信deep3321