本文的数学公式、官方文档、NASA 资料、论文和工程接口按 2026-05-09 可访问版本复核。SciPy、Blender、Unity、ROS Rolling、PX4 main、MAVLink generated docs、Drake、MuJoCo、Isaac Lab、Pinocchio、Crocoddyl 等在线文档可能随版本漂移;
准备工作
建议先自行搜索看完下面两个视频,再继续往下读;后文默认你已经理解其中的基础旋转直觉和演示。
- 《Euler (gimbal lock) Explained》
- 《无伤理解欧拉角中的“万向死锁”现象》
欧拉角描述的是变换,而非运动:在给定欧拉角的三个参数和旋转顺序后,它唯一确定了从初始姿态到最终姿态的旋转变换关系,但不包含任何关于中间运动路径的信息
导读:先把结论摆正
万向锁不是三维空间真的少了一个方向,也不一定是机械零件坏了。更准确地说,它是某套旋转结构、姿态坐标或控制映射在特殊姿态附近退化:原本应该独立的三个旋转方向里,有两个在瞬时效果上重合,系统只能提供两个线性独立方向。
本文把“锁住了什么”分成三层:
| 层次 | 出问题的对象 | 典型表现 | 四元数是否解决 |
|---|---|---|---|
| 真实姿态 | S O ( 3 ) SO(3) SO(3) 中的刚体朝向 | 姿态本身仍局部三维 | 不需要“解决”,空间没坏 |
| 姿态表示 | 欧拉角 / Tait-Bryan 角等三参数姿态表示 | 中间角到特殊值时雅可比矩阵降秩 | 可避免这类参数化奇点 |
| 机械与控制 | 三轴万向架、云台、机器人腕部、控制求逆 | 轴线共线、机构雅可比降秩、输入耦合 | 不能消除真实机构限制 |
它到底“锁”住了什么
日常说“锁住”,容易让人误以为物体不能再转了。事实不是这样:
- 物体真实的姿态空间仍然有三个自由度。
- 出问题的是当前机械轴配置、当前坐标表示、传感器接口或控制映射。
- 在锁定姿态附近,两个输入会高度耦合;精确到锁定点时,两个输入产生同一种瞬时旋转效果。
- 对同一真实姿态,欧拉角可能变得不唯一;很小的姿态变化也可能对应很大的角度数值变化。
一个好类比是经纬度。经纬度在大多数地方很好用,但在北极点,“经度”不再唯一。不是北极消失了,而是经纬度这套坐标在极点不好用。万向锁也类似:锁定姿态完全存在,只是某套描述或操纵姿态的方法在特殊位置失灵;接近这个位置时,坐标数值还会对微小噪声和微小运动格外敏感。
先看机械直觉
下面的图用简化三轴万向架说明直觉。正常时,外层、中层、内层提供三个相互独立的旋转方向;当中间轴转到特殊角度时,外层和内层轴线穿过同一中心并落到同一条直线上,两个旋钮在瞬时效果上变成同一类动作。

这里说的“共线”比“平行”更严格。三轴万向架的轴线都穿过同一个中心,所以一旦两轴方向平行,它们实际就是同一条旋转轴。若只是两条不同位置的平行线,它们并不会构成这个意义上的机械万向锁。
本文约定
三维旋转的文字很容易因为约定不同而互相矛盾,所以先把本文的核心约定钉住。
| 项目 | 本文约定 |
|---|---|
| 坐标系 | 右手坐标系 |
| 向量 | 列向量 |
| 矩阵含义 | 主动旋转矩阵,可理解为把物体或向量转过去 |
| 示例序列 | yaw-pitch-roll / roll-pitch-yaw 的 ZYX Tait-Bryan 角 |
| 角度记号 | ϕ \phi ϕ 为 roll, θ \theta θ 为 pitch, ψ \psi ψ 为 yaw |
| 矩阵形式 | R = R z ( ψ ) R y ( θ ) R x ( ϕ ) R = R_z(\psi)R_y(\theta)R_x(\phi) R=Rz(ψ)Ry(θ)Rx(ϕ) |
这个写法可以理解为外禀固定轴旋转:从原始姿态出发,依次绕固定世界 x x x、 y y y、 z z z 轴转 ϕ \phi ϕ、 θ \theta θ、 ψ \psi ψ。矩阵乘法写在左边的旋转最后作用,所以应用到列向量时要从右往左读。
同一个最终矩阵也常称为内禀 ZYX Tait-Bryan 角:按动轴视角看,等价于依次绕随物体转动的机体
z
z
z、
y
y
y、
x
x
x 轴做
ψ
\psi
ψ、
θ
\theta
θ、
ϕ
\phi
ϕ 旋转。简写成一句就是:外禀固定轴 X(φ) -> Y(θ) -> Z(ψ) 等价于内禀动轴 Z(ψ) -> Y(θ) -> X(φ)。不同软件会把“顺序”写成输入顺序、矩阵乘法顺序或实际应用顺序,必须看文档。
本文把“欧拉角”按业界常用宽义使用,泛指三个顺序旋转角;严格区分时,ZXZ、ZYZ 这类首尾轴相同的是 Proper Euler angles,ZYX、XYZ 这类三个轴都不同的是 Tait-Bryan / Cardan angles。
姿态、自由度和欧拉角
一个刚体在空间中的“位置”和“朝向”是两件事。位置可以用三个数表示,例如 x , y , z x,y,z x,y,z;朝向称为姿态,局部来看也需要三个独立参数。
| 类型 | 旋转轴特点 | 例子 | 常见奇点 |
|---|---|---|---|
| Proper Euler angles | 第一轴和第三轴相同,相邻轴不同 | ZXZ, ZYZ, XYX | 中间角为 0 或 180 度附近 |
| Tait-Bryan / Cardan angles | 三个轴都不同 | ZYX, XYZ, ZXY | 中间角为正负 90 度附近 |
航空、机器人、游戏引擎里常说的 yaw-pitch-roll 通常属于 Tait-Bryan 角。许多软件界面仍把它叫 Euler angles,是为了使用方便,不一定严格区分术语。
为什么旋转顺序不能省略
三维旋转不满足交换律。先低头再转身,和先转身再低头,最后的朝向通常不同。因此任何严谨的姿态说明至少要声明:
- 绕哪三个轴转,顺序是什么。
- 是绕固定世界坐标轴转,还是绕随物体转动的局部坐标轴转。
- 使用右手坐标系还是左手坐标系。
- 矩阵是主动旋转物体,还是被动改变坐标描述。
- 四元数分量顺序是
(w, x, y, z)还是(x, y, z, w),乘法约定是 Hamilton 还是 JPL。 - 姿态表示的是“从 A 坐标系到 B 坐标系”,还是“B 在 A 中的姿态”。
这也是为什么不同教材、软件、飞控系统和动画工具里,同样写作 roll, pitch, yaw,含义可能并不完全相同。例如 Unity 6.4 Manual 说明 Unity 使用左手坐标系,Transform 以欧拉角显示,欧拉旋转按固定坐标系 z -> x -> y 顺序执行;ROS 2 tf2 教程使用 fixed/static-frame RPY,geometry_msgs 四元数分量顺序为 (x, y, z, w);MAVLink ATTITUDE 则定义在右手航空坐标系中,采用 X 向前、Y 向右、Z 向下,并标注为 ZYX intrinsic。三者的同名 roll/pitch/yaw 不能脱离坐标帧和旋转顺序直接互换。
万向锁的数学本质
如果把三维旋转看成一个集合,它叫作 S O ( 3 ) SO(3) SO(3),也就是所有 3 × 3 3 \times 3 3×3 正交矩阵且行列式为 1 的集合。欧拉角做的事情,是把三个角映射到一个真实姿态:
F ( α , β , γ ) → R ∈ S O ( 3 ) F(\alpha, \beta, \gamma) \rightarrow R \in SO(3) F(α,β,γ)→R∈SO(3)
在普通位置,三个角的小变化能产生三个线性独立方向上的姿态变化。但在奇点处,这个映射的微分会退化:三个角的变化不再对应三个独立方向。用线性代数说,就是雅可比矩阵失去满秩。
更通俗地说:
三个数字还在,但它们不再能独立控制三种旋转效果。
这里还有一个拓扑层面的原因。 S O ( 3 ) SO(3) SO(3) 局部是三维流形,所以三参数表示可以很好地作为局部坐标;但 S O ( 3 ) ≅ R P 3 SO(3) \cong \mathbb{RP}^3 SO(3)≅RP3,不能被一个单一、全局唯一、连续可逆、处处非奇异的“三个普通实数”坐标系完整表示。多张坐标图、角度边界、跳变或多值约定都可以覆盖更多区域,但那已经不是单张全局无奇点坐标图。
四元数绕开了欧拉角奇点,是因为单位四元数用 S 3 S^3 S3 上的点表示旋转,并以 q q q 与 − q -q −q 表示同一个旋转的方式双覆盖 S O ( 3 ) SO(3) SO(3)。代价是四元数不是一一表示,软件必须处理符号连续性和归一化。
以 yaw-pitch-roll 为例
采用本文约定:先绕固定 x x x 轴横滚 ϕ \phi ϕ,再绕固定 y y y 轴俯仰 θ \theta θ,再绕固定 z z z 轴偏航 ψ \psi ψ。矩阵写为:
R = R z ( ψ ) R y ( θ ) R x ( ϕ ) R = R_z(\psi)R_y(\theta)R_x(\phi) R=Rz(ψ)Ry(θ)Rx(ϕ)
展开后得到:
R = [ c ψ c θ c ψ s θ s ϕ − s ψ c ϕ c ψ s θ c ϕ + s ψ s ϕ s ψ c θ s ψ s θ s ϕ + c ψ c ϕ s ψ s θ c ϕ − c ψ s ϕ − s θ c θ s ϕ c θ c ϕ ] 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} R= cψcθsψcθ−sθcψsθsϕ−sψcϕsψsθsϕ+cψcϕcθsϕcψsθcϕ+sψsϕsψsθcϕ−cψsϕcθcϕ
其中 c c c 表示 cos \cos cos, s s s 表示 sin \sin sin。
当 pitch 角 θ = + 90 ∘ \theta = +90^\circ θ=+90∘ 时, c θ = 0 c_\theta = 0 cθ=0,矩阵只依赖 ϕ − ψ \phi-\psi ϕ−ψ:
R = [ 0 sin ( ϕ − ψ ) cos ( ϕ − ψ ) 0 cos ( ϕ − ψ ) − sin ( ϕ − ψ ) − 1 0 0 ] R= \begin{bmatrix} 0&\sin(\phi-\psi)&\cos(\phi-\psi)\\ 0&\cos(\phi-\psi)&-\sin(\phi-\psi)\\ -1&0&0 \end{bmatrix} R= 00−1sin(ϕ−ψ)cos(ϕ−ψ)0cos(ϕ−ψ)−sin(ϕ−ψ)0
当 θ = − 90 ∘ \theta = -90^\circ θ=−90∘ 时,矩阵只依赖 ϕ + ψ \phi+\psi ϕ+ψ:
R = [ 0 − sin ( ϕ + ψ ) − cos ( ϕ + ψ ) 0 cos ( ϕ + ψ ) − sin ( ϕ + ψ ) 1 0 0 ] R= \begin{bmatrix} 0&-\sin(\phi+\psi)&-\cos(\phi+\psi)\\ 0&\cos(\phi+\psi)&-\sin(\phi+\psi)\\ 1&0&0 \end{bmatrix} R= 001−sin(ϕ+ψ)cos(ϕ+ψ)0−cos(ϕ+ψ)−sin(ϕ+ψ)0
这意味着 roll 和 yaw 不再能被单独区分。更精确地说,在 + 90 ∘ +90^\circ +90∘ 时姿态只依赖 ϕ − ψ ( m o d 2 π ) \phi-\psi \pmod{2\pi} ϕ−ψ(mod2π);在 − 90 ∘ -90^\circ −90∘ 时姿态只依赖 ϕ + ψ ( m o d 2 π ) \phi+\psi \pmod{2\pi} ϕ+ψ(mod2π)。三个角看起来还有三个数,但这套欧拉角参数化在该点只剩两个线性独立的局部变化方向。
也可以从轴线看同一件事。当前机体 x x x 轴在世界系中的方向是 R e x = ( c ψ c θ , s ψ c θ , − s θ ) T R e_x=(c_\psi c_\theta, s_\psi c_\theta, -s_\theta)^T Rex=(cψcθ,sψcθ,−sθ)T。当 θ = + 90 ∘ \theta=+90^\circ θ=+90∘ 时它等于 − e z -e_z −ez;当 θ = − 90 ∘ \theta=-90^\circ θ=−90∘ 时它等于 e z e_z ez。也就是说,机体 roll 轴与世界 yaw 轴共线,方向可能相同也可能相反。
再看角速度关系。对同一约定,可把 R R R 理解为机体系到世界系的姿态矩阵;等价地, R R R 的三列是机体坐标轴在世界系中的方向。机体系角速度满足 ω b o d y = v e e ( R T R ˙ ) \omega_{body}=\mathrm{vee}(R^T\dot R) ωbody=vee(RTR˙)。给定欧拉角变化率 [ ϕ ˙ , θ ˙ , ψ ˙ ] T [\dot\phi,\dot\theta,\dot\psi]^T [ϕ˙,θ˙,ψ˙]T,真实角速度在刚体坐标系轴上的分量 [ p , q , r ] T [p,q,r]^T [p,q,r]T 可以写成:
ω b o d y = [ 1 0 − sin θ 0 cos ϕ sin ϕ cos θ 0 − sin ϕ cos ϕ cos θ ] [ ϕ ˙ θ ˙ ψ ˙ ] \omega_{body}= \begin{bmatrix} 1&0&-\sin\theta\\ 0&\cos\phi&\sin\phi\cos\theta\\ 0&-\sin\phi&\cos\phi\cos\theta \end{bmatrix} \begin{bmatrix} \dot\phi\\ \dot\theta\\ \dot\psi \end{bmatrix} ωbody= 1000cosϕ−sinϕ−sinθsinϕcosθcosϕcosθ ϕ˙θ˙ψ˙
这个矩阵定义的是正向映射:从欧拉角变化率到真实角速度的机体系分量。控制器或估计器如果要从角速度反求欧拉角变化率,就需要对它求逆。该矩阵的行列式是:
det = cos θ \det = \cos\theta det=cosθ
所以当 θ = ± 90 ∘ \theta = \pm90^\circ θ=±90∘ 时,行列式为 0,矩阵不可逆。这就是“接近 90 度时很难稳定控制,精确到 90 度时失去一个独立方向”的数学根源。
把它求逆会更直观地看到病态项:
[ ϕ ˙ θ ˙ ψ ˙ ] = [ 1 sin ϕ tan θ cos ϕ tan θ 0 cos ϕ − sin ϕ 0 sin ϕ / cos θ cos ϕ / cos θ ] [ 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} ϕ˙θ˙ψ˙ = 100sinϕtanθcosϕsinϕ/cosθcosϕtanθ−sinϕcosϕ/cosθ pqr
只要 cos θ \cos\theta cosθ 很小, tan θ \tan\theta tanθ 和 1 / cos θ 1/\cos\theta 1/cosθ 就会很大。下面的“放大因子”不是严格的矩阵条件数,而是这些求逆项的数量级提示。

工程上,接近奇点时常见后果包括:控制输出变大、滤波器对噪声更敏感、动画曲线跳变、UI 显示角度突然换支、求逆和优化对微小扰动变得脆弱。
机械万向架里的万向锁
“万向锁”这个名字来自真实的万向架。三层嵌套环可以让内部平台相对外部支架保持某种朝向,这在早期惯性导航、罗盘平台和摄像稳定器中都很重要。
正常情况下,也就是三轴未共线时,三个环的运动学映射满秩,三个关节输入能提供三个独立的瞬时旋转方向。如果中间环转到某个特殊角度,外环轴和内环轴重合,那么外环和内环不再提供两种独立动作。此时系统不是完全不能动,而是某一个方向的姿态变化无法通过“当前这三个轴的独立控制”直接实现。
机械系统还会遇到软件姿态表示以外的问题,例如关节限位、线缆缠绕、电机速度和力矩上限、传感器安装方向、控制回路延迟、结构弹性、摩擦、载荷和装配误差。因此“用四元数”只能解决欧拉角表示奇点,不能让真实机构摆脱轴线共线、限位、线缆和载荷带来的物理限制。
Apollo 和航天惯导中的案例
Apollo 飞船的主制导、导航与控制系统使用惯性测量单元 IMU。Apollo PGNCS 的 IMU 属于稳定平台式惯导,平台姿态通过三轴万向架管理,因此必须认真管理万向锁风险。
严谨地说,Apollo 的情况不应被讲成“飞船差点因为万向锁失败”。更准确的是:万向锁是设计和操作中必须规避的已知风险。工程团队会通过任务阶段的 IMU 对准、万向架角监测、告警/显示提示、操作规程和必要时的姿态重整,尽量避免中间万向架角进入危险区域。具体阈值和步骤应以任务手册、飞行计划和 G&N 操作文档为准,不宜用流行故事里的单一数字替代。
NASA NTRS 中的 Apollo 导航资料把 PGNCS IMU 管理和姿态管理作为导航技术的一部分讨论;Klumpp 的 Apollo lunar descent guidance 的 NTRS 摘要提到,altitude maneuver routine 使用了使 gimbal lock “inherently impossible”的概念。该条目没有可下载全文,因此适合作为补充证据,而不宜作为具体操作规程的唯一依据。
在惯性平台设计中,增加冗余万向架是一种降低轴线对齐风险的思路,但它也会带来重量、体积、伺服系统、可靠性、热设计和计算接口复杂度。在航天工程里,避免一个风险往往意味着引入另一组成本和故障模式,不能把“加一个轴”理解成无代价的万能方案。
现代许多航天器、导弹和无人机采用捷联式惯导;手机和机器人中的 IMU 姿态估计也常采用捷联式测量架构:传感器固定在机体上,姿态由计算机积分和融合。全姿态积分通常用单位四元数或方向余弦矩阵;在滤波、优化或误差状态建模中,姿态误差常在 S O ( 3 ) SO(3) SO(3) 的李代数/切空间里处理,而不是直接用欧拉角做全姿态积分。
动画、游戏和 3D 软件里的表现
动画师和游戏开发者很容易遇到万向锁,因为很多工具界面会显示欧拉角,很多动画曲线也按三个角来编辑。
典型表现包括:角色骨骼转到某个姿态后某个旋转轴突然“消失”;摄像机抬头接近垂直时,左右旋转变成类似横滚的效果;关键帧插值突然翻转;曲线编辑器里的三个角度曲线变得难以理解。
几个官方资料给出的提醒很有代表性:
- Blender Manual 5.1:Euler 模式的轴有层级关系;中间轴接近 90 度或等效角时,底层轴会与顶层轴对齐,失去一个旋转轴。动画编辑时要选择合适的 rotation order,必要时改用 Quaternion 模式。
- Unity Manual 6.4:Unity 使用左手坐标系,Transform 显示欧拉角,内部用四元数存储;脚本中转换到欧拉角再计算可能遇到万向锁;欧拉旋转按
z -> x -> y外禀顺序执行。因此内部累积和插值尽量用四元数或向量构造,不要反复读写欧拉角。 - SciPy
Rotation.as_euler:欧拉角在 gimbal lock 处第一角和第三角不能唯一确定;SciPy 会警告并把第三角设为 0,但返回姿态仍正确。工程代码要把警告视为坐标分支问题,不要误判姿态本身错误。
很多引擎采用折中方案:内部计算、插值和姿态累积用四元数或矩阵;编辑器、日志和 UI 为了让人看懂,显示成欧拉角;导出或手工编辑动画时,再仔细处理 rotation order、关键帧路径和跨软件约定转换。
机器人和无人机里的相似问题
机器人里常说“奇异位形”。这和万向锁很像,但要小心区分:机器人奇异性本质上是机械臂运动学映射退化,通常表现为机械臂雅可比矩阵降秩;欧拉角万向锁则是姿态参数化退化。
例如,许多采用球形腕部的 6R 工业机械臂会出现腕部奇异性:当某些腕部旋转轴线对齐时,末端执行器某个姿态方向的控制可能需要极高关节速度,甚至在该瞬间无法独立实现。这与三轴万向架的轴线重合相似;但即使目标姿态用四元数或旋转矩阵表示,机械臂本身的奇异位形仍然存在。
| 对比项 | 欧拉角万向锁 | 机器人奇异位形 |
|---|---|---|
| 退化对象 | 姿态参数化 ( ϕ , θ , ψ ) → S O ( 3 ) (\phi,\theta,\psi) \rightarrow SO(3) (ϕ,θ,ψ)→SO(3) | 机械结构运动学 q → S E ( 3 ) q \rightarrow SE(3) q→SE(3) |
| 典型数学表现 | 欧拉角雅可比降秩 | 机械臂雅可比降秩 |
| 换四元数是否解决 | 可以避免这类参数化奇点 | 不能消除真实机构奇异性 |
| 常见处理 | 换表示、换旋转序列、局部坐标切换 | 路径重规划、阻尼最小二乘、冗余自由度、速度限制 |
为什么人形机器人通常不把欧拉角作为内部姿态状态
更准确地说,人形机器人不是“完全不用欧拉角”。界面显示、日志阅读、人工调参、遥操作输入、示教动作、报警阈值都可能出现欧拉角;带 roll、pitch、yaw 名称的单轴关节坐标也常见,但它们是关节角,不等同于整机姿态的欧拉角。工程上通常避免的是:把欧拉角当作浮动基座、状态估计、全身控制、动力学仿真和优化里的全姿态主状态。
原因是人形机器人通常是 floating-base 系统:骨盆或躯干基座在空间中同时平移和旋转。算法关心的状态更接近
(
p
,
R
,
v
,
ω
,
q
j
,
q
˙
j
)
(p, R, v, \omega, q_j, \dot q_j)
(p,R,v,ω,qj,q˙j),其中
R
∈
S
O
(
3
)
R\in SO(3)
R∈SO(3),完整基座位姿在
S
E
(
3
)
SE(3)
SE(3) 上;IMU 陀螺仪、刚体动力学、接触雅可比、角动量和全身控制直接使用角速度
ω
\omega
ω 或 6 维 twist。若把
R
R
R 换成三个全局欧拉角,积分和线性化就必须频繁在角速度与欧拉角率之间转换;对 ZYX 约定,反求欧拉角率会出现
tan
θ
\tan\theta
tanθ 和
1
/
cos
θ
1/\cos\theta
1/cosθ,接近奇点时会放大噪声、bias 和控制误差。
一个具体例子是起身或跌倒恢复:假设状态估计把骨盆姿态直接存成 ZYX 的 roll-pitch-yaw,并用 IMU 角速度反算欧拉角率。当躯干 pitch 接近
90
∘
90^\circ
90∘ 时,微小陀螺噪声会被
1
/
cos
θ
1/\cos\theta
1/cosθ 放大成很大的 roll/yaw 角率;在奇点上 roll 和 yaw 本身也不可分。若全身控制器再把 roll_des - roll_now、yaw_des - yaw_now 当作姿态误差,QP 或逆动力学会把这个坐标造成的突变当成真实误差去分配关节力矩和接触力。使用四元数、旋转矩阵或
S
O
(
3
)
SO(3)
SO(3) 切空间误差,避免的是这个坐标奇点问题,而不是改变机器人真实的力矩、摩擦和接触限制。
因此,控制和估计里更常见的是把名义姿态保存在四元数、旋转矩阵或刚体变换上,把误差写成局部三维小量,例如误差四元数、
log
(
R
d
T
R
)
\log(R_d^T R)
log(RdTR)、
1
2
(
R
d
T
R
−
R
T
R
d
)
∨
\frac12(R_d^T R-R^T R_d)^\vee
21(RdTR−RTRd)∨,或
R
+
=
R
exp
(
δ
θ
∧
)
R^+=R\exp(\delta\theta^\wedge)
R+=Rexp(δθ∧) 这样的切空间更新。这样保留了三维误差的紧凑性,也避免用 roll_des - roll_now 直接表示全局姿态误差所带来的角度换支、旋转顺序和奇点问题。
这不是某一家机器人的特殊习惯,而是主流接口的一致取舍。ROS REP 103 把旋转表示推荐顺序列为 quaternion、rotation matrix、fixed-axis RPY,最后才是 Euler yaw-pitch-roll,并提醒欧拉角有 24 种有效约定。Drake 明确警告 RpyFloatingJoint 这类三参数姿态必有奇点;如果不能保证避开奇点,应考虑 QuaternionFloatingJoint。MIT Robotic Manipulation 笔记也提醒,角速度不是 roll、pitch、yaw 的时间导数;floating-base 的
q
q
q 可用单位四元数,而
v
v
v 使用角速度和线速度。MuJoCo 允许用 euler 输入建模姿态,但编译后转成单位四元数,且 free/ball joint 的 qpos 与 qvel 维度不同;Isaac Lab 的根状态采用 [pos, quat, lin_vel, ang_vel];Pinocchio 和 Crocoddyl 把多体构型视为流形上的点,把速度和差分放在切空间里。腿足机器人状态估计文献也常在
S
O
(
3
)
SO(3)
SO(3)/
S
E
(
3
)
SE(3)
SE(3) 或四元数框架下处理 IMU 与接触约束,而不是把基座姿态或整机位姿估计建立在一组三个全局欧拉角上。
所以,“人形机器人不用欧拉角”的准确说法是:内部估计、控制、动力学、仿真和优化通常不把欧拉角作为全姿态主状态;欧拉角仍可作为人机界面、日志和有限范围命令的外层表达。换成四元数、旋转矩阵或 S E ( 3 ) SE(3) SE(3) 也不是消灭所有问题,它只是避开欧拉角参数化奇点;真实机器人仍要处理关节限位、接触切换、摩擦、力矩上限、执行器带宽、机械雅可比奇异,以及四元数归一化和 q q q 与 − q -q −q 等价等工程细节。
无人机和云台系统通常有两层问题:飞控内部姿态估计通常用四元数或旋转矩阵,避免欧拉角奇点;真实三轴云台仍可能受到机械限位、线缆、驱动器速度上限、轴序设计下的轴线趋同等限制。危险位置不一定在所有硬件上都叫 pitch 垂直。
MAVLink 协议很好地展示了工程取舍:
ATTITUDE消息使用右手航空坐标系(X向前、Y向右、Z向下)下的 roll、pitch、yaw,并明确为ZYXintrinsic。ATTITUDE_QUATERNION、SET_ATTITUDE_TARGET、多种云台消息使用(w, x, y, z)顺序的四元数,其中SET_ATTITUDE_TARGET的四元数表示从MAV_FRAME_LOCAL_NED到MAV_FRAME_BODY_FRD的目标姿态。HIL_STATE被标注为因缺少空速字段和欧拉角奇异性而被HIL_STATE_QUATERNION取代;HIL_STATE_QUATERNION明确说明它避免了HIL_STATE的奇异性。- 云台相关消息还把硬件角度范围、是否支持无限 yaw、yaw 是相对机体还是相对地球北向等内容作为接口的一部分,这说明真实云台问题远不止一个姿态表示。
PX4 的 VehicleAttitude uORB 消息也体现了类似约定要求:页面导语说明四元数使用 Hamilton convention,顺序为 q(w, x, y, z);字段表说明 q 表示从 FRD 机体系到 NED 地球系的旋转。这里要注意:Hamilton 是乘法/代数约定,wxyz 是字段顺序;两者相关但不能混成同一个概念。
四元数为什么常被推荐
单位四元数用四个数表示三维旋转。它常被推荐,是因为它作为单位 S 3 S^3 S3 上的嵌入表示,没有欧拉角那种中间角特殊值处的局部参数奇点,适合连续积分、姿态组合和 SLERP 等插值。
但四元数不是魔法。
| 四元数能帮什么 | 四元数不能自动解决什么 |
|---|---|
| 避免欧拉角参数化奇点 | 机械万向架或机器人关节的真实奇异构型 |
| 稳定做姿态连续积分 | 关节限位、线缆缠绕、电机力矩和速度上限 |
| 比 3 × 3 3 \times 3 3×3 矩阵更紧凑 | 坐标系、帧方向、左乘/右乘约定错误 |
| 容易归一化修正数值漂移 | q q q 与 − q -q −q 表示同一旋转带来的符号连续性 |
| 适合姿态间平滑插值 | 转回欧拉角显示后的奇点和分支跳变 |
严谨说法应该是:四元数可以避免欧拉角参数化带来的万向锁,不是消灭所有机械奇异性和姿态工程问题。
常见姿态表示对比
| 表示法 | 优点 | 代价与适合用途 |
|---|---|---|
| 欧拉角 / Tait-Bryan 角(3 参数) | 直观,适合人读和 UI | 有奇点、顺序敏感;适合设置界面、日志和小范围姿态输入 |
| 旋转矩阵 / DCM(9 参数) | 直接变换向量,无欧拉角奇点 | 参数冗余,需保持正交归一;适合坐标变换、工程推导和控制系统 |
| 单位四元数(4 参数加单位约束) | 稳定、紧凑,适合插值和积分 | 不直观,需归一化,且 q q q 与 − q -q −q 等价;适合游戏引擎、机器人、飞控和姿态滤波 |
| 轴角(轴 + 角) | 概念清楚:绕某轴转某角 | 0 度时轴不唯一,接近 180 度时需处理符号和分支;适合几何解释和局部姿态差 |
| 旋转向量(3 参数) | 紧凑,适合小姿态误差 | 大角度处有边界和不连续约定;适合优化、滤波和误差状态 |
无论选择哪种表示,工程接口都应声明坐标系、旋转顺序、角度单位、帧方向、主动/被动含义、四元数分量顺序和乘法约定。
| 表示或结构 | 典型奇点 / 病态位置 | 影响 |
|---|---|---|
ZYX Tait-Bryan 角 | 中间角 θ = ± 90 ∘ \theta = \pm90^\circ θ=±90∘ | roll 与 yaw 不能唯一分离 |
Proper Euler 角,如 ZXZ、ZYZ | 中间角为 0 或 180 度 | 第一角与第三角不能唯一分离 |
| 单位四元数 | 没有欧拉角式中间角奇点 | 需要归一化,且 q q q 与 − q -q −q 等价 |
| 旋转矩阵 / DCM | 没有欧拉角式奇点 | 需要维护正交性和行列式为 1 |
| 三轴万向架 / 机器人腕部 | 机械轴共线或雅可比降秩 | 某些瞬时运动方向不可独立控制 |
怎样避免或管理万向锁
万向锁通常不是靠一句“别用欧拉角”解决,而是按场景管理。
按场景看,常见处理方式是:
- 飞控、机器人、惯导:先问核心状态是否需要穿越全姿态。全姿态状态用四元数或方向余弦矩阵;误差状态滤波可用小角度或李代数增量;欧拉角只用于显示或有限接口。
- 动画制作:先问动作最大幅度落在哪个轴。选择合适 rotation order;把动作幅度最大的轴放到不易触发奇点的位置;必要时改用四元数插值。
- 摄像机控制:先问是否直接累加欧拉角。用四元数、方向向量或轨道相机构造视角;限制俯仰角接近垂直。
- 机械云台:先问是否会穿越轴线共线或硬限位。可增加冗余轴、设计限位、使用滑环或无限 yaw、规划路径,并避免穿越锁定姿态。
- 机械臂:先问机构雅可比是否接近降秩。常用奇异性检测、阻尼最小二乘、路径重规划、冗余自由度和靠近奇异构型的速度限制。
- 欧拉角提取和显示:先问是否接近奇点或跨角度分支。接近奇点时警告;必要时固定第一角或第三角;避免把显示角度再作为积分状态。
- 数据接口:先问对方系统的约定是否完全一致。明确旋转顺序、坐标系、单位、四元数分量顺序、帧方向和乘法约定。
- 教学和科普:先问是否混淆了表示退化和物理结构退化。区分欧拉角奇点、机械万向架和机器人奇异性;避免把四元数说成万能解。
工程上最重要的问题通常不是“有没有万向锁”这个词,而是当前姿态表示在任务范围内有没有奇点、控制器是否要在奇点附近求逆、角速度和角度变化率是否被混用、UI 显示是否会把同一姿态写成跳变角度,以及机械结构是否存在轴线重合、限位或不可达区域。
常见误解
误解一:万向锁意味着物体不能转了
不准确。物体本身仍然可以有三维姿态。锁住的是当前机械轴配置、当前坐标表示或当前控制映射的独立控制能力。
误解二:只要用四元数,所有万向锁都消失
不准确。四元数避免欧拉角表示奇点,但不能消除机械万向架、机器人关节、线缆、限位、载荷和电机速度上限。
误解三:欧拉角完全没用
不准确。欧拉角很适合人类理解、手动输入、日志阅读和小范围姿态控制。问题在于不要把它当成无约束三维姿态的唯一内部状态。
误解四:yaw-pitch-roll 到处都是同一个定义
不准确。必须声明坐标系、旋转顺序、内禀或外禀、主动或被动旋转。Unity、ROS、MAVLink、航空 NED(North-East-Down,北-东-地)、数学右手坐标系的约定并不总是一样。
误解五:三个参数一定不够表示三维旋转
也不准确。三维旋转局部就是三维的,所以三个参数可以很好地表示一片局部区域。真正做不到的是用一个单一三参数坐标图全局唯一、连续可逆、处处无奇点地覆盖所有旋转。
误解六:人形机器人完全不能用欧拉角
不准确。人形机器人常会把欧拉角用于显示、日志、配置、调参、小范围命令和人类可读接口。真正不推荐的是把欧拉角作为浮动基座和全身控制里的全姿态主状态,或者把三个角直接相减当作全局姿态误差。
术语表
| 术语 | 含义 |
|---|---|
| 万向锁 / Gimbal lock | 两个旋转轴共线或参数化退化,导致少一个独立旋转方向的现象 |
| 万向架 / Gimbal | 允许物体绕轴旋转的支架结构,常见于云台、惯导平台和仪表结构 |
| 姿态 / Orientation / Attitude | 物体在空间中的朝向,不是位置 |
| S O ( 3 ) SO(3) SO(3) | 三维旋转群,所有 3 × 3 3 \times 3 3×3 正交且行列式为 1 的旋转矩阵构成的集合 |
| S E ( 3 ) SE(3) SE(3) | 三维刚体位姿群,同时包含平移和旋转 |
| 自由度 / Degree of Freedom | 可独立变化的方向或参数数量 |
| 欧拉角 / Euler angles | 用三个按顺序执行的旋转角描述三维姿态的方法;业界常宽义使用 |
| Proper Euler angles | 第一轴和第三轴相同的三次旋转,如 ZXZ、ZYZ |
| Tait-Bryan / Cardan angles | 三个轴都不同的三次旋转,常见 yaw-pitch-roll 属于这一类 |
| 偏航 / Yaw | 常指绕竖直轴或机体相关轴的转向 |
| 俯仰 / Pitch | 常指抬头或低头 |
| 横滚 / Roll | 常指绕自身前后轴翻滚 |
| 奇点 / Singularity | 某种数学表示、映射或机械构型失去正常可逆性的位置 |
| 雅可比矩阵 / Jacobian | 描述输入小变化如何引起输出小变化的矩阵 |
| 旋转矩阵 / Rotation matrix | 用 3 × 3 3 \times 3 3×3 正交矩阵表示旋转 |
| 方向余弦矩阵 / DCM | 旋转矩阵在导航、航姿领域的常用叫法 |
| 单位四元数 / Unit quaternion | 用四个数和单位长度约束表示三维旋转的方法 |
| 李代数 / 切空间 | 在当前姿态附近描述小姿态误差的局部线性空间,常用于滤波和优化 |
| NED / FRD | 导航和飞控常见坐标系;NED 是北-东-地,FRD 是前-右-下 |
| Hamilton 约定 | 四元数乘法/代数约定之一,不等同于 (w, x, y, z) 分量顺序 |
| SLERP | 球面线性插值,常用于四元数姿态平滑过渡 |
参考资料与延伸阅读
官方文档与工程接口
- SciPy 文档,
scipy.spatial.transform.Rotation.as_euler和from_euler:说明欧拉角存在 gimbal lock,第一和第三角在奇点处不能唯一确定;SciPy 会发出警告并把第三角设为 0,但返回的角仍表示正确旋转。from_euler还说明大写轴序表示 intrinsic,小写轴序表示 extrinsic,且不能混用。当前页面源码指向 SciPy v1.17.0。https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.transform.Rotation.as_euler.html https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.transform.Rotation.from_euler.html - Blender Manual 5.1,Rotation Modes:解释 Euler 模式中的层级轴关系,中间轴接近 90 度时底层轴会与顶层轴对齐,从而丢失一个独立旋转轴并影响动画插值。页面显示 Last updated on 2026-05-08,长期引用可用其 5.1 permanent link。https://docs.blender.org/manual/en/latest/advanced/appendices/rotations.html
- Unity Manual 6.4,Quaternion and Euler rotations in Unity:说明 Unity 使用左手坐标系,Transform 显示欧拉角,内部用四元数存储旋转;脚本中转换到欧拉角再计算可能遇到万向锁;欧拉旋转按
z -> x -> y外禀顺序执行。页面构建时间为 2026-05-06。https://docs.unity3d.com/Manual/QuaternionAndEulerRotationsInUnity.html - ROS 2 文档,Quaternion fundamentals:介绍 ROS 2 中四元数分量顺序
(x, y, z, w)、归一化、fixed/static-frame RPY 以及与 RPY 的转换。该链接指向 Rolling 开发版;长期引用时应优先查最新发布版,例如页面提示的 Kilted。https://docs.ros.org/en/rolling/Tutorials/Intermediate/Tf2/Quaternion-Fundamentals.html - ROS REP 103,Standard Units of Measure and Coordinate Conventions:说明 ROS 坐标约定、右手系、旋转表示优先级,并提醒欧拉角因 24 种有效约定而通常不推荐作为通用接口。https://www.ros.org/reps/rep-0103.html
- Drake C++ 文档,
RollPitchYaw、RpyFloatingJoint和QuaternionFloatingJoint:说明 RPY 的 space-fixedXYZ/ body-fixedZYX含义、pitch 接近 n π + π / 2 n\pi+\pi/2 nπ+π/2 时的 gimbal lock 和除零风险;RpyFloatingJoint明确警告三参数姿态表示必有奇点,不能保证避开奇点时应考虑QuaternionFloatingJoint。Drake 在线 Doxygen 会随主分支更新,冻结引用时应固定 release 或源码 commit。https://drake.mit.edu/doxygen_cxx/classdrake_1_1math_1_1_roll_pitch_yaw.html https://drake.mit.edu/doxygen_cxx/classdrake_1_1multibody_1_1_rpy_floating_joint.html https://drake.mit.edu/doxygen_cxx/classdrake_1_1multibody_1_1_quaternion_floating_joint.html - MIT Robotic Manipulation, Chapter 3 Basic Pick and Place:说明 RPY 到旋转矩阵的逆映射在 pitch 为 π / 2 \pi/2 π/2 时有奇点,roll 与 yaw 不可分;这些奇点在求导和写运动方程时会成为问题。该课程笔记还说明 spatial velocity 中的角速度不是 RPY 的时间导数,floating-base 的 q q q 可用单位四元数而 v v v 用角速度和线速度,因此通常 q ˙ ≠ v \dot q\ne v q˙=v。https://manipulation.csail.mit.edu/pick.html
- MuJoCo 文档,Modeling 与 Computation:MJCF 可用
euler输入帧姿态,但编译后帧姿态会转为单位四元数;含 ball/free joint 时,qpos的位置坐标数会大于自由度数qvel,因为四元数表示姿态而速度属于三维切空间, q ˙ \dot q q˙ 不等同于通常意义的速度。链接指向 stable 文档;长期引用仍应标注 MuJoCo 版本。https://mujoco.readthedocs.io/en/stable/modeling.html https://mujoco.readthedocs.io/en/stable/computation/index.html - Isaac Lab API 文档,
isaaclab.assets:刚体和 articulation 的 root/body state 常以[pos, quat, lin_vel, ang_vel]表示,四元数顺序为(w, x, y, z),同时提供heading_w等派生 yaw 信息。该链接指向main文档,版本冻结引用时应固定 Isaac Lab 版本。https://isaac-sim.github.io/IsaacLab/main/source/api/lab/isaaclab.assets.html - Pinocchio 文档,SE(3) operations 与 practical exercises:展示机器人库中用
SE3表示刚体位姿、用Motion/Force表示空间速度和空间力,并说明关节速度属于关节坐标流形的李代数/切空间。该链接通过 ROS Rolling 生成,长期引用应固定 Pinocchio 版本或官方源码文档。https://docs.ros.org/en/rolling/p/pinocchio/doc/c-maths/se3.html https://docs.ros.org/en/rolling/p/pinocchio/doc/d-practical-exercises/1-directgeom.html - Crocoddyl 文档,
StateMultibodyTpl与 free forward dynamics:多体状态由构型点和切向速度组成,diff()、integrate()、Jdiff()、Jintegrate()等操作定义在状态流形及其切空间上;free dynamics 文档把 q q q 描述为 configuration point,把 v v v 描述为 generalized velocity / tangent vector。该链接指向 devel Doxygen,长期引用应固定 Crocoddyl 版本或源码 commit。https://gepettoweb.laas.fr/doc/loco-3d/crocoddyl/devel/doxygen-html/classcrocoddyl_1_1StateMultibodyTpl.html https://gepettoweb.laas.fr/doc/loco-3d/crocoddyl/devel/doxygen-html/classcrocoddyl_1_1DifferentialActionModelFreeFwdDynamicsTpl.html - PX4 文档,VehicleAttitude uORB message:页面导语说明四元数使用 Hamilton convention,顺序为
q(w, x, y, z);字段表说明q表示从 FRD 机体系到 NED 地球系的旋转。该链接指向main开发文档,版本冻结引用时应查 release 文档或源文件。https://docs.px4.io/main/en/msg_docs/VehicleAttitude.html - MAVLink Common Message Set:
ATTITUDE明确采用右手航空坐标系和ZYXintrinsic;HIL_STATE标注因缺少空速字段和欧拉角奇异性而被HIL_STATE_QUATERNION取代;多种姿态和云台消息使用(w, x, y, z)四元数。generated HTML 会随common.xml演进,冻结引用时应固定mavlink/mavlink仓库 commit 或 tag。https://mavlink.io/en/messages/common.html - MathWorks 文档,
eul2quat:欧拉角到四元数转换应明确旋转序列;未显式指定时默认序列为ZYX。输入行形如[zAngle yAngle xAngle],应用到点时按x -> y -> z执行,输出四元数为[w x y z]。https://www.mathworks.com/help/nav/ref/eul2quat.html
航天、导航与历史资料
- NASA NTRS,Apollo Onboard Navigation Techniques:Apollo 导航、PGNCS IMU 管理和姿态管理相关背景资料。https://ntrs.nasa.gov/citations/20090016292
- NASA NTRS,Klumpp, A. R. 1974. Apollo lunar descent guidance:NTRS 摘要提到 altitude maneuver routine 使用了让 gimbal lock “inherently impossible”的概念;该条目无可下载全文,适合作为补充来源。https://ntrs.nasa.gov/citations/19740044219
- Henderson, D. M. 1977. Shuttle Program. Euler angles, quaternions, and transformation matrices working relationships. NASA-TM-74839 / JSC-12960 / REPT-77-FM-37:欧拉角、四元数和变换矩阵的工程参考资料,NTRS 提供 PDF。https://ntrs.nasa.gov/citations/19770024290
- NASA Apollo Journals:Apollo Lunar Surface Journal 和 Apollo Flight Journal 的历史资料入口,适合作为任务记录和背景资料,不宜单独支撑具体 PGNCS 操作规程。https://www.nasa.gov/history/alsj/
论文、教材与机器人资料
- Bernardes, E. and Viollet, S. 2022. Quaternion to Euler angles conversion: A direct, general and computationally efficient method. PLOS ONE 17(11): e0276302. 论文讨论 12 种 Proper Euler 与 Tait-Bryan 序列的四元数到欧拉角直接转换及奇点处理。https://doi.org/10.1371/journal.pone.0276302
- Hartley, R., Ghaffari Jadidi, M., Grizzle, J. W. and Eustice, R. M. 2018. Contact-Aided Invariant Extended Kalman Filtering for Legged Robot State Estimation. Robotics: Science and Systems. 论文为 3D 双足机器人推导接触辅助惯性导航观测器,基于 invariant observer / InEKF 处理 IMU 与接触约束,并与 quaternion-based EKF 对比。https://arxiv.org/abs/1805.10410 https://doi.org/10.15607/RSS.2018.XIV.050
- Sommer, H., Gilitschenski, I., Bloesch, M., Weiss, S., Siegwart, R. and Nieto, J. 2018. Why and how to avoid the flipped quaternion multiplication. Aerospace 5(3):72. 讨论 Hamilton/JPL、乘法顺序和四元数约定差异。https://doi.org/10.3390/aerospace5030072
- Lynch, K. M. and Park, F. C. Modern Robotics, Chapter 3.2.3 Exponential Coordinates of Rotation 与 Chapter 5.3 Singularities:前者介绍 s o ( 3 ) so(3) so(3) 指数坐标和旋转的局部三维表示,后者从机器人雅可比矩阵角度解释奇异性和末端速度空间退化。https://modernrobotics.northwestern.edu/nu-gm-book-resource/3-2-3-exponential-coordinates-of-rotation-part-1-of-2/ https://modernrobotics.northwestern.edu/nu-gm-book-resource/5-3-singularities/
- Malcolm D. Shuster, A Survey of Attitude Representations, Journal of the Astronautical Sciences, 1993:航天姿态表示的经典综述。
- John Stuelpnagel, On the Parametrization of the Three-Dimensional Rotation Group, SIAM Review, 1964:三维旋转群参数化的经典论文。
- Shuster, M. and Markley, F. L. 2006. General Formula for Extracting the Euler Angles, Journal of Guidance, Control, and Dynamics:从旋转表示中提取欧拉角的一般公式。
- Jack B. Kuipers, Quaternions and Rotation Sequences, Princeton University Press, 1999:四元数与旋转序列的系统教材。
- F. Landis Markley and John L. Crassidis, Fundamentals of Spacecraft Attitude Determination and Control, Springer, 2014:航天器姿态确定与控制的权威教材。
- Siciliano, B., Sciavicco, L., Villani, L. and Oriolo, G. Robotics: Modelling, Planning and Control, Springer, 2009:机器人运动学、雅可比矩阵和奇异性的权威教材。

1万+

被折叠的 条评论
为什么被折叠?



