第三章 四元数基础:从困惑到通透

说实话,我第一次接触四元数的时候,脑袋是懵的。

什么 i² = j² = k² = ijk = -1?这玩意儿跟控制算法有什么关系?我当时在做一个无人机项目,导师丢给我一句「用四元数代替欧拉角,避免万向锁」。我硬着头皮啃了三天,才勉强搞明白。

今天我就用最直白的方式,把四元数给你讲透。

3.1 四元数的定义

四元数,说白了就是一个四维的复数扩展。你想想看,复数有一个实部和一个虚部(a + bi),四元数则是一个实部和三个虚部:

q = w + xi + yj + zk

其中 w、x、y、z 是实数,i、j、k 是三个虚数单位。它们的关系是:

  • i² = j² = k² = -1
  • ij = k, ji = -k
  • jk = i, kj = -i
  • ki = j, ik = -j

嗯,这里要注意,乘法不满足交换律。也就是说 ij ≠ ji。这在后面的旋转计算中非常关键。

我习惯把四元数写成向量形式:

q = [w, x, y, z]ᵀ

或者拆成标量部分和向量部分:

q = (w, v)  其中 v = (x, y, z)

单位四元数(模长为1)是描述旋转的利器。它的模长定义为:

||q|| = √(w² + x² + y² + z²) = 1

核心要点:只有单位四元数才能表示纯旋转。如果你的四元数模长不是1,记得先归一化。

3.2 四元数与欧拉角的转换

我在项目中遇到过最头疼的事,就是调试时发现姿态数据跳变。查了半天,原来是欧拉角到四元数的转换写错了。

先说说欧拉角转四元数。假设我们用的是 ZYX 顺序(偏航-俯仰-横滚):

// 欧拉角:yaw(ψ), pitch(θ), roll(φ)
// 转换为四元数

double cy = cos(yaw * 0.5);
double sy = sin(yaw * 0.5);
double cp = cos(pitch * 0.5);
double sp = sin(pitch * 0.5);
double cr = cos(roll * 0.5);
double sr = sin(roll * 0.5);

double w = cr * cp * cy + sr * sp * sy;
double x = sr * cp * cy - cr * sp * sy;
double y = cr * sp * cy + sr * cp * sy;
double z = cr * cp * sy - sr * sp * cy;

反过来,四元数转欧拉角:

// 四元数 q = (w, x, y, z)
// 转换为欧拉角

double roll = atan2(2*(w*x + y*z), 1 - 2*(x*x + y*y));
double pitch = asin(2*(w*y - z*x));
double yaw = atan2(2*(w*z + x*y), 1 - 2*(y*y + z*z));

避坑指南:我曾经因为 pitch 接近 ±90° 时,asin 的参数超出 [-1,1] 范围,导致程序直接崩溃。建议加一个 clamp 操作:

double sinp = 2*(w*y - z*x);
if (sinp > 1.0) sinp = 1.0;
if (sinp < -1.0) sinp = -1.0;
double pitch = asin(sinp);

3.3 四元数的优势

为什么我们要用四元数?说白了,欧拉角有三个硬伤:

特性 欧拉角 四元数
万向锁 有(pitch=±90°时丢失自由度)
插值平滑性 差(非线性,容易跳变) 好(球面线性插值SLERP)
计算效率 涉及大量三角函数 仅需乘法和加法
存储空间 3个角度 4个分量

我个人觉得,四元数最大的优势是避免了万向锁。你想想看,在无人机控制中,如果飞机做特技动作时姿态突然锁死,那后果不堪设想。

另外,四元数的旋转组合非常优雅。两个旋转 q₁ 和 q₂ 的复合,直接就是四元数乘法:

q_total = q₂ ⊗ q₁

注意顺序:先应用 q₁,再应用 q₂。乘法公式如下:

q₁ = (w₁, x₁, y₁, z₁)
q₂ = (w₂, x₂, y₂, z₂)

q₁ ⊗ q₂ = (
  w₁w₂ - x₁x₂ - y₁y₂ - z₁z₂,
  w₁x₂ + x₁w₂ + y₁z₂ - z₁y₂,
  w₁y₂ - x₁z₂ + y₁w₂ + z₁x₂,
  w₁z₂ + x₁y₂ - y₁x₂ + z₁w₂
)

我的小技巧:在代码里实现四元数乘法时,我习惯用临时变量存中间结果,避免覆盖原始数据。特别是嵌入式环境,一个不小心就把寄存器搞乱了。

3.4 知识体系总览

下面这张图是我自己总结的四元数知识脉络,你看一眼就能明白整个章节在讲什么:

四元数基础 定义 q = w + xi + yj + zk 与欧拉角转换 ZYX顺序 / 避坑指南 优势 无万向锁 / 平滑插值 单位四元数 乘法不交换 欧拉角→四元数 四元数→欧拉角 旋转复合 SLERP插值

这张图把四元数的三个核心模块串起来了。定义是基础,转换是工具,优势是为什么选它。你顺着这个脉络学,就不会迷路。

好了,四元数的基础就讲到这里。记住:多写代码,多调试,遇到问题别慌。我当年也是从一脸懵逼到逐渐通透的。


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