3、欧拉角:定义、万向锁与旋转顺序

欧拉角这个东西,说实话,是每个做机器人的人都会遇到的「老朋友」。我刚入行那会儿,觉得它直观又好用,后来在项目里被它坑过几次,才真正理解了它的脾气。

简单来说,欧拉角就是用三个角度来描述一个物体的朝向。比如飞机,你可以说它「俯仰了多少度,偏航了多少度,滚转了多少度」。听起来很自然对吧?但这里头藏着不少门道。

3.1 欧拉角的定义

欧拉角的本质,是「绕三个坐标轴依次旋转」。每次旋转都绕着物体当前的某个轴,而不是世界坐标系下的固定轴。这一点很重要,我见过不少新手在这里搞混。

常用的表示方式有几种:

  • ZYX 顺序:先绕 Z 轴转(偏航),再绕 Y 轴转(俯仰),最后绕 X 轴转(滚转)。这是航空领域最常用的。
  • ZYZ 顺序:先绕 Z,再绕 Y,再绕 Z。常见于机械臂的运动学分析。
  • XYZ 顺序:先绕 X,再绕 Y,再绕 Z。有些传感器会这么输出。

每个顺序对应一组不同的旋转矩阵。比如 ZYX 顺序的旋转矩阵可以写成:

R = Rz(yaw) * Ry(pitch) * Rx(roll)

注意乘法的顺序——从右往左读。先转的轴在右边,后转的在左边。我刚开始写代码时总搞反,后来养成了一个习惯:每次写完都拿个手机在手里转一转验证一下。

核心要点:欧拉角用三个角度描述旋转,但旋转顺序决定了最终朝向。同一个角度值,不同顺序会得到完全不同的结果。

3.2 万向锁问题

这是欧拉角最出名的一个坑。什么叫万向锁?说白了,就是当中间那个轴的旋转角度达到 ±90° 时,你会丢失一个自由度。

举个例子。你用 ZYX 顺序控制一个云台。当俯仰角(绕 Y 轴)转到 90° 时,你会发现:不管你怎么转偏航(绕 Z)和滚转(绕 X),云台都只能在一个平面里动。你失去了一个方向的调节能力。

为什么会这样?

因为当俯仰角为 90° 时,第一次旋转的 Z 轴和第三次旋转的 X 轴,在空间中对齐了。两个轴变成了同一个轴。三个自由度变成了两个。

我曾经在一个无人机项目里遇到过这个问题。当时用欧拉角做姿态控制,飞机做大角度俯冲时突然失控了。查了半天,发现就是万向锁导致的。从那以后,我只要做大角度运动,就坚决不用欧拉角。

避坑指南:我曾经在调试一个机械臂时,用欧拉角做逆解,结果在某个奇异点附近怎么都算不对。后来换成四元数,问题立刻解决了。如果你要做全姿态运动,建议直接上四元数或旋转矩阵。

3.3 不同旋转顺序的影响

不同旋转顺序,不仅仅是数学上的差异,在实际应用中影响很大。

旋转顺序 常见应用 特点
ZYX 无人机、飞行器 偏航-俯仰-滚转,直观且符合直觉
ZYZ 机械臂运动学 避免某些奇异点,适合关节型机器人
XYZ IMU 传感器 某些传感器默认输出顺序
YXZ 相机姿态 适合俯仰-偏航-滚转的场景

你想想看,如果你用 ZYX 顺序,偏航角的变化会影响俯仰和滚转的「参考系」。而如果你用 XYZ 顺序,情况又不一样了。所以,在写代码之前,一定要搞清楚你的传感器或算法用的是哪种顺序。

我个人习惯在代码里这样处理:

// 明确指定旋转顺序
enum class EulerOrder {
    ZYX,  // 航空标准
    ZYZ,  // 机械臂
    XYZ   // 传感器
};

// 根据顺序生成旋转矩阵
Matrix3d eulerToMatrix(double roll, double pitch, double yaw, EulerOrder order) {
    Matrix3d R;
    switch(order) {
        case EulerOrder::ZYX:
            R = Rz(yaw) * Ry(pitch) * Rx(roll);
            break;
        case EulerOrder::ZYZ:
            R = Rz(yaw) * Ry(pitch) * Rz(roll);
            break;
        // ... 其他顺序
    }
    return R;
}

嗯,这里要注意:不同库的默认顺序可能不一样。比如 ROS 里的 tf 库,默认用的是 ZYX。而某些数学库可能用 XYZ。我建议你在项目一开始就统一约定好顺序,并在文档里写清楚。

实用技巧:如果你不确定当前用的欧拉角是什么顺序,可以拿一个已知姿态做测试。比如让物体绕某个轴转 90°,看输出值的变化规律,就能反推出顺序。

3.4 知识体系图

下面这张图总结了欧拉角的核心知识点,方便你快速回顾:

欧拉角 定义 • 三个角度描述朝向 • 绕物体当前轴旋转 • 旋转顺序决定结果 万向锁 • 中间轴 ±90° 时发生 • 丢失一个自由度 • 大角度运动需避免 旋转顺序 • ZYX:航空标准 • ZYZ:机械臂常用 • XYZ:传感器输出 建议:全姿态运动用四元数,小角度可用欧拉角 务必在代码中明确标注旋转顺序

欧拉角虽然直观,但用起来要小心。我个人建议:如果你只是做小角度的姿态微调,用欧拉角没问题。但如果你要做全姿态运动,或者你的系统可能经过奇异点,那就老老实实用四元数或者旋转矩阵吧。

好了,关于欧拉角就聊这么多。记住三个关键词:定义、万向锁、旋转顺序。下次写代码时多留个心眼,别在同一个坑里摔两次。

可可精品资料库