3、坐标系与姿态表示:地球坐标系、机体坐标系、欧拉角、旋转矩阵、四元数基础、坐标系转换的Simulink实现

做飞控这么多年,我见过太多新手在坐标系上栽跟头。说白了,姿态估计和坐标系转换就是飞控算法的"地基"。地基没打好,上面盖的楼再漂亮也得塌。今天咱们就把这块硬骨头啃下来。

3.1 为什么需要坐标系?

你想想看,无人机在天上飞,它得知道自己"头朝哪"、"往哪去"。但"朝哪"是相对的——相对于地面?相对于机身?还是相对于地磁场?

这就引出了两个最核心的坐标系:

  • 地球坐标系(NED):北东地,固定在地面上。北向为X,东向为Y,指向地心为Z。我习惯叫它"世界坐标系"。
  • 机体坐标系(Body):固定在飞机上。机头为X,右翼为Y,垂直向下为Z。

嗯,这里要注意:不同教材可能定义不同。有的用"东北天"(ENU),有的用"北东地"(NED)。我个人建议飞控领域统一用NED,因为PX4、ArduPilot这些主流开源飞控都是这么干的。

核心思想:传感器测量的是机体坐标系下的数据(比如加速度计测的是机体的加速度),但导航和控制需要在地球坐标系下进行。所以,坐标系转换是绕不开的坎。

3.2 欧拉角——最直观的姿态表示

欧拉角是什么?说白了就是三个角度:横滚(Roll)、俯仰(Pitch)、偏航(Yaw)。我刚开始学飞控时,觉得这玩意儿太直观了——飞机歪了多少度,一目了然。

但欧拉角有个致命问题:万向锁(Gimbal Lock)。当俯仰角接近±90°时,横滚和偏航会"耦合"在一起,丢失一个自由度。我在做固定翼飞控时遇到过这个问题,飞机做筋斗动作时姿态解算直接炸了。

欧拉角 范围 说明
横滚 φ -180° ~ 180° 绕X轴旋转
俯仰 θ -90° ~ 90° 绕Y轴旋转
偏航 ψ -180° ~ 180° 绕Z轴旋转

避坑指南:我曾经在仿真中直接用欧拉角做插值,结果姿态过渡时出现了奇怪的"翻转"。后来才意识到,欧拉角不适合做插值和微分运算。如果你要做平滑的姿态过渡,请用四元数。

3.3 旋转矩阵——数学上的"翻译官"

旋转矩阵就是把一个向量从一个坐标系"翻译"到另一个坐标系。从机体到地球的旋转矩阵记作 C_b^n(或者 R_b^n)。

用欧拉角构建旋转矩阵的公式如下(Z-Y-X顺序):

C_b^n = [cosθ·cosψ,  sinφ·sinθ·cosψ - cosφ·sinψ,  cosφ·sinθ·cosψ + sinφ·sinψ;
         cosθ·sinψ,  sinφ·sinθ·sinψ + cosφ·cosψ,  cosφ·sinθ·sinψ - sinφ·cosψ;
        -sinθ,        sinφ·cosθ,                    cosφ·cosθ]

看着复杂?其实你不需要背。在Simulink里直接用Rotation Matrix模块就行。但我建议你至少手推一次,理解每个元素是怎么来的。

我的经验:旋转矩阵是正交矩阵,它的逆等于它的转置。这个性质在代码实现中非常有用——从地球到机体的转换,直接转置矩阵就行,不用重新计算。

3.4 四元数——飞控的"瑞士军刀"

四元数是个四维复数:q = w + xi + yj + zk,其中 w 是实部,x、y、z 是虚部。它没有万向锁问题,计算效率高,适合做插值。

我刚开始接触四元数时也觉得抽象——四个数怎么就能表示三维旋转了?后来我换了个角度理解:四元数描述的是"绕某个轴转多少度",而不是"绕三个轴依次转多少度"。

欧拉角转四元数的公式(还是Z-Y-X顺序):

w = cos(φ/2)·cos(θ/2)·cos(ψ/2) + sin(φ/2)·sin(θ/2)·sin(ψ/2)
x = sin(φ/2)·cos(θ/2)·cos(ψ/2) - cos(φ/2)·sin(θ/2)·sin(ψ/2)
y = cos(φ/2)·sin(θ/2)·cos(ψ/2) + sin(φ/2)·cos(θ/2)·sin(ψ/2)
z = cos(φ/2)·cos(θ/2)·sin(ψ/2) - sin(φ/2)·sin(θ/2)·cos(ψ/2)

重要提醒:四元数必须归一化!即 w² + x² + y² + z² = 1。数值误差会导致四元数"漂移",我见过有人忘了归一化,结果姿态估计越偏越远。

3.5 坐标系转换的Simulink实现

好了,理论说完了,咱们看看怎么在Simulink里实现。我个人习惯用Aerospace Blockset里的模块,但如果你没有这个工具箱,也可以用基础模块自己搭。

3.5.1 使用Aerospace Blockset(推荐)

Simulink提供了现成的转换模块:

  • Direction Cosine Matrix to Quaternions:旋转矩阵转四元数
  • Quaternions to Direction Cosine Matrix:四元数转旋转矩阵
  • Euler Angles to Quaternions:欧拉角转四元数
  • Quaternions to Euler Angles:四元数转欧拉角

这些模块都在 Aerospace Blockset / Utilities / Axes Transformations 下。

3.5.2 手动搭建(理解原理)

如果你想深入理解原理,可以自己搭。下面是一个欧拉角转旋转矩阵的Simulink模型示例:

% 在MATLAB中定义函数
function R = eulerToRotMat(phi, theta, psi)
    % 输入:phi(横滚), theta(俯仰), psi(偏航),单位:弧度
    % 输出:3x3旋转矩阵
    
    c_phi = cos(phi);
    s_phi = sin(phi);
    c_theta = cos(theta);
    s_theta = sin(theta);
    c_psi = cos(psi);
    s_psi = sin(psi);
    
    R = [c_theta*c_psi,  s_phi*s_theta*c_psi - c_phi*s_psi,  c_phi*s_theta*c_psi + s_phi*s_psi;
         c_theta*s_psi,  s_phi*s_theta*s_psi + c_phi*c_psi,  c_phi*s_theta*s_psi - s_phi*c_psi;
        -s_theta,        s_phi*c_theta,                      c_phi*c_theta];
end

然后在Simulink中用MATLAB Function模块调用这个函数。或者用Fcn模块直接写表达式。

调试技巧:我曾经在Simulink里做坐标系转换时,发现结果总是不对。后来加了个Display模块,把中间变量打印出来,才发现是角度单位搞错了——Simulink默认用弧度,我输入的是度数。

3.6 知识体系总览

下面这张图是我自己整理的坐标系与姿态表示的知识结构,帮你理清思路:

坐标系与姿态表示知识体系 地球坐标系 (NED) 机体坐标系 (Body) 旋转矩阵 / 四元数 欧拉角 (φ, θ, ψ) 旋转矩阵 (3×3) 四元数 (w, x, y, z) ✅ 直观易懂 ❌ 万向锁问题 ❌ 不适合插值 ✅ 无奇异性 ✅ 易于组合 ❌ 9个参数冗余 ✅ 无万向锁 ✅ 适合插值 ✅ 计算高效 Simulink实现:Aerospace Blockset / 手动搭建 MATLAB Function · Fcn模块 · 现成转换模块

3.7 实际项目中的选择建议

说了这么多,到底该用哪种?我根据项目经验给个建议:

  • 人机交互界面:用欧拉角。操作手看的是"横滚5度、俯仰10度",不是四元数。
  • 姿态解算(AHRS):用四元数。IMU数据融合、互补滤波、卡尔曼滤波,四元数是标配。
  • 控制律设计:用旋转矩阵。从机体到地球的向量转换,矩阵乘法最直接。
  • 轨迹规划:用四元数做插值(Slerp),平滑过渡无抖动。

总结一句话:欧拉角给人看,四元数给计算机算,旋转矩阵做桥梁。三者之间要能自由切换,这是飞控工程师的基本功。

好了,坐标系和姿态表示就讲到这里。下一节咱们会深入Simulink,搭建一个完整的姿态估计模型。到时候你会看到,今天讲的这些知识是怎么串起来的。


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