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 知识体系总览
下面这张图是我自己整理的坐标系与姿态表示的知识结构,帮你理清思路:
3.7 实际项目中的选择建议
说了这么多,到底该用哪种?我根据项目经验给个建议:
- 人机交互界面:用欧拉角。操作手看的是"横滚5度、俯仰10度",不是四元数。
- 姿态解算(AHRS):用四元数。IMU数据融合、互补滤波、卡尔曼滤波,四元数是标配。
- 控制律设计:用旋转矩阵。从机体到地球的向量转换,矩阵乘法最直接。
- 轨迹规划:用四元数做插值(Slerp),平滑过渡无抖动。
总结一句话:欧拉角给人看,四元数给计算机算,旋转矩阵做桥梁。三者之间要能自由切换,这是飞控工程师的基本功。
好了,坐标系和姿态表示就讲到这里。下一节咱们会深入Simulink,搭建一个完整的姿态估计模型。到时候你会看到,今天讲的这些知识是怎么串起来的。
公众号:蓝海资料掘金营,微信deep3321