四元数Quaternion的概念以及应用领域和处理方法
一、概念
1. 数学定义
四元数是由爱尔兰数学家威廉·卢云·哈密顿(William Rowan Hamilton)在1843年发明的一种超复数结构,用于扩展复数以描述三维空间中的旋转。它的一般形式可以表示为:
q
=
w
+
x
i
+
y
j
+
z
k
q = w + xi + yj + zk
q=w+xi+yj+zk
其中
w
w
w 是实部,
x
x
x、
y
y
y、
z
z
z 是虚部的系数,
i
i
i、
j
j
j、
k
k
k为虚部单位,并且它们遵循以下运算规则:
i
2
=
j
2
=
k
2
=
−
1
i
j
=
k
,
j
i
=
−
k
j
k
=
i
,
k
j
=
−
i
k
i
=
j
,
i
k
=
−
j
\begin{array}{l} i^{2}=j^{2}=k^{2}=-1 \\ i j=k, j i=-k \\ j k=i, k j=-i \\ k i=j, i k=-j \end{array}
i2=j2=k2=−1ij=k,ji=−kjk=i,kj=−iki=j,ik=−j
例如,一个简单的四元数示例可以是
q
=
1
+
2
i
+
3
j
+
4
k
q = 1 + 2i + 3j + 4k
q=1+2i+3j+4k,这里
w
=
1
w = 1
w=1,
x
=
2
x = 2
x=2,
y
=
3
y = 3
y=3,
z
=
4
z = 4
z=4。
2. 几何解释
从几何角度来看,四元数可以被理解为是在四维空间中的一个向量,但它与三维空间的旋转有着紧密联系。单位四元数(满足 w 2 + x 2 + y 2 + z 2 = 1 w^2 + x^2 + y^2 + z^2 = 1 w2+x2+y2+z2=1 的四元数)可以对应到三维空间中的一个旋转操作。具体来说,四元数所表示的旋转是绕着一个通过原点的轴进行的旋转,这个轴的方向由四元数的虚部所确定,而旋转的角度与四元数的实部和虚部都有关系。
例如,若把三维空间想象成一个物体所在的空间,使用四元数就能精确地描述这个物体绕着某个特定轴(比如空间中的某条直线)旋转了多少角度,而不像欧拉角那样可能会出现一些表示上的奇异情况(如万向节锁)。
3. 与其他旋转表示方式对比
- 与欧拉角对比:欧拉角通过三个角度(通常是横滚角、俯仰角、偏航角)来描述三维空间旋转,它比较直观,易于人类理解和手动设置角度。但在进行连续旋转操作时,当俯仰角达到 ±90 度时会出现万向节锁现象,导致旋转失去一个自由度,不能完整地描述所有可能的旋转状态。而四元数不存在这样的问题,能平滑地表示任意的旋转情况。
- 与旋转矩阵对比:旋转矩阵是一个 3×3 的矩阵,同样可以用于表示三维空间中的旋转,它在进行多次旋转组合时需要进行矩阵乘法运算,计算相对复杂且容易出现数值精度问题(比如矩阵元素经过多次乘法后可能会出现舍入误差积累等情况)。四元数在组合旋转时通过乘法运算也能实现,但相对来说计算效率更高,并且更方便进行插值等操作。
二、应用领域
1. 计算机图形学
- 3D 模型动画:在制作 3D 动画时,角色的动作、物体的转动等都涉及旋转操作。四元数用于精确控制模型的旋转姿态,使得动画过渡更加自然平滑。例如在一个游戏中,角色从面向前方转身 90 度去拿物品,通过四元数可以准确地计算出这个旋转过程中每一帧对应的旋转状态,实现流畅的动画效果,而且可以通过四元数插值方便地实现从初始姿态到目标姿态的渐变过渡。
- 摄像机控制:对于游戏或虚拟场景中的摄像机视角切换和跟踪等操作,四元数能很好地描述其旋转变化。比如在第一人称射击游戏中,玩家转动视角观察周围环境,摄像机绕着某个点(比如角色所在位置)旋转的过程就可以用四元数来表示和计算,保证视角旋转的流畅性和准确性,避免出现视角抖动或者突然跳跃等不自然的情况。
2. 机器人学
- 机器人关节运动:多关节机器人在执行任务时,各个关节的旋转运动需要精确控制。四元数可以用来表示每个关节的旋转情况,通过计算四元数的变化来规划机器人手臂的运动轨迹,使得机器人能够准确地抓取物品、完成装配等操作。例如工业机械臂在流水线上进行产品组装,其各个关节按照一定的四元数序列所规定的旋转进行动作,以达到精确的工作位置和姿态。
- 移动机器人导航:对于像扫地机器人、自动驾驶车辆等移动机器人,在调整自身姿态、转向等操作时,四元数可用于表示车体的旋转状态,配合其他位置信息来准确实现导航功能,避免因旋转表示不准确而导致的路径偏差等问题。
3. 航空航天领域
- 飞行器姿态控制:在飞机、无人机等飞行器的飞行过程中,姿态控制至关重要。四元数能够实时准确地描述飞行器的横滚、俯仰、偏航等旋转姿态,控制系统根据目标姿态对应的四元数和当前姿态的四元数进行对比和调整,确保飞行器稳定飞行并按照预定航线飞行,而且在复杂的机动飞行过程中也不会出现像欧拉角那样的万向节锁等影响飞行安全的情况。
- 卫星姿态调整:卫星在太空中需要精确控制自身的姿态,以保证太阳能电池板对准太阳、通信天线对准地面基站等。四元数可以帮助地面控制中心精确地计算并下达姿态调整指令,使卫星维持在正确的工作姿态上,顺利完成通信、观测等任务。
4. 虚拟现实与增强现实
- 头戴式设备姿态跟踪:在 VR(虚拟现实)和 AR(增强现实)设备中,如头戴式显示器,需要实时跟踪用户头部的转动姿态,以便相应地更新虚拟场景的显示视角或者在现实场景上叠加正确的虚拟内容。四元数可以精确地表示头部的旋转情况,为用户提供沉浸式的体验,使得虚拟场景的视角变化与用户实际头部转动高度吻合,避免出现画面延迟、视角偏差等导致的眩晕感等不良体验。
三、处理方法
1. 四元数的构造
通常可以通过给定实部和虚部的值来构造一个四元数。在编程实现中,例如在 C++ 等编程语言中,可能会有对应的类或者结构体来表示四元数,像下面这样简单定义(伪代码示意):
class Quaternion {
public:
float w; // 实部
float x;
float y;
float z;
Quaternion(float _w, float _x, float _y, float _z) : w(_w), x(_x), y(_y), z(_z) {}
};
这样就可以通过 Quaternion q(1.0, 2.0, 3.0, 4.0);
这样的语句构造出一个具体的四元数实例。
2. 四元数的归一化
为了保证四元数能准确表示旋转,需要对其进行归一化操作,使得其模长为 1。计算四元数 q = w + x i + y j + z k q = w + xi + yj + zk q=w+xi+yj+zk 的模长 ∣ ∣ q ∣ ∣ = w 2 + x 2 + y 2 + z 2 ||q|| = \sqrt{w^2 + x^2 + y^2 + z^2} ∣∣q∣∣=w2+x2+y2+z2,然后将四元数的各个分量都除以这个模长,即:
q n o r m a l i z e d = q ∣ ∣ q ∣ ∣ = w + x i + y j + z k w 2 + x 2 + y 2 + z 2 q_{normalized} = \frac{q}{||q||} = \frac{w + xi + yj + zk}{\sqrt{w^2 + x^2 + y^2 + z^2}} qnormalized=∣∣q∣∣q=w2+x2+y2+z2w+xi+yj+zk
在代码中实现可以如下(伪代码示意):
Quaternion normalize(Quaternion q) {
float magnitude = sqrt(q.w * q.w + q.x * q.x + q.y * q.y + q.z * q.z);
return Quaternion(q.w / magnitude, q.x / magnitude, q.y / magnitude, q.z / magnitude);
}
3. 四元数乘法
四元数乘法用于组合多个旋转操作。给定两个四元数
q
1
=
w
1
+
x
1
i
+
y
1
j
+
z
1
k
q_1 = w_1 + x_1i + y_1j + z_1k
q1=w1+x1i+y1j+z1k 和
q
2
=
w
2
+
x
2
i
+
y
2
j
+
z
2
k
q_2 = w_2 + x_2i + y_2j + z_2k
q2=w2+x2i+y2j+z2k,它们相乘的结果
q
=
q
2
×
q
1
q = q_2 \times q_1
q=q2×q1 按照以下规则计算:
q
.
w
=
w
2
w
1
−
x
2
x
1
−
y
2
y
1
−
z
2
z
1
q
.
x
=
w
2
x
1
+
x
2
w
1
+
y
2
z
1
−
z
2
y
1
q
.
y
=
w
2
y
1
−
x
2
z
1
+
y
2
w
1
+
z
2
x
1
q
.
z
=
w
2
z
1
+
x
2
y
1
−
y
2
x
1
+
z
2
w
1
\begin{align*} q.w &= w_2w_1 - x_2x_1 - y_2y_1 - z_2z_1\\ q.x &= w_2x_1 + x_2w_1 + y_2z_1 - z_2y_1\\ q.y &= w_2y_1 - x_2z_1 + y_2w_1 + z_2x_1\\ q.z &= w_2z_1 + x_2y_1 - y_2x_1 + z_2w_1 \end{align*}
q.wq.xq.yq.z=w2w1−x2x1−y2y1−z2z1=w2x1+x2w1+y2z1−z2y1=w2y1−x2z1+y2w1+z2x1=w2z1+x2y1−y2x1+z2w1
在代码中实现四元数乘法运算可以是(伪代码示意):
Quaternion multiply(Quaternion q1, Quaternion q2) {
float new_w = q2.w * q1.w - q2.x * q1.x - q2.y * q1.y - q2.z * q1.z;
float new_x = q2.w * q1.x + q2.x * q1.w + q2.y * q1.z - q2.z * q1.y;
float new_y = q2.w * q1.y - q2.x * q1.z + q2.y * q1.w + q2.z * q1.x;
float new_z = q2.w * q1.z + q2.x * q1.y - q2.y * q1.x + q2.z * q1.w;
return Quaternion(new_w, new_x, new_y, new_z);
}
需要注意的是四元数乘法不满足交换律,即 q 2 × q 1 q_2 \times q_1 q2×q1 一般不等于 q 1 × q 2 q_1 \times q_2 q1×q2。
4. 四元数与旋转矩阵的转换
四元数转旋转矩阵:
给定一个四元数
q
=
w
+
x
i
+
y
j
+
z
k
q = w + xi + yj + zk
q=w+xi+yj+zk,其对应的旋转矩阵
R
R
R 可以通过以下公式计算:
R = [ 1 − 2 y 2 − 2 z 2 2 x y − 2 z w 2 x z + 2 y w 2 x y + 2 z w 1 − 2 x 2 − 2 z 2 2 y z − 2 x w 2 x z − 2 y w 2 y z + 2 x w 1 − 2 x 2 − 2 y 2 ] R = \begin{bmatrix} 1 - 2y^2 - 2z^2 & 2xy - 2zw & 2xz + 2yw\\ 2xy + 2zw & 1 - 2x^2 - 2z^2 & 2yz - 2xw\\ 2xz - 2yw & 2yz + 2xw & 1 - 2x^2 - 2y^2 \end{bmatrix} R= 1−2y2−2z22xy+2zw2xz−2yw2xy−2zw1−2x2−2z22yz+2xw2xz+2yw2yz−2xw1−2x2−2y2
在代码中实现转换(伪代码示意):
Matrix3x3 quaternionToRotationMatrix(Quaternion q) {
Matrix3x3 result;
result.m[0][0] = 1 - 2 * q.y * q.y - 2 * q.z * q.z;
result.m[0][1] = 2 * q.x * q.y - 2 * q.z * q.w;
result.m[0][2] = 2 * q.x * q.z + 2 * q.y * q.w;
result.m[1][0] = 2 * q.x * q.y + 2 * q.z * q.w;
result.m[1][1] = 1 - 2 * q.x * q.x - 2 * q.z * q.z;
result.m[1][2] = 2 * q.y * q.z - 2 * q.x * q.w;
result.m[2][0] = 2 * q.x * q.z - 2 * q.y * q.w;
result.m[2][1] = 2 * q.y * q.z + 2 * q.x * q.w;
result.m[2][2] = 1 - 2 * q.x * q.x - 2 * q.y * q.y;
return result;
}
旋转矩阵转四元数:
若已知一个旋转矩阵
R
R
R,可以通过以下步骤来求解对应的四元数
q
q
q:
首先计算 t r = R 11 + R 22 + R 33 tr = R_{11} + R_{22} + R_{33} tr=R11+R22+R33 ( R i j (R_{ij} (Rij 表示旋转矩阵 R R R 中第 i i i 行第 j j j 列的元素),然后分情况讨论:
-
如果 t r > 0 tr > 0 tr>0:
w = 1 2 1 + t r x = R 23 − R 32 4 w y = R 31 − R 13 4 w z = R 12 − R 21 4 w \begin{align*} w &= \frac{1}{2}\sqrt{1 + tr}\\ x &= \frac{R_{23} - R_{32}}{4w}\\ y &= \frac{R_{31} - R_{13}}{4w}\\ z &= \frac{R_{12} - R_{21}}{4w} \end{align*} wxyz=211+tr=4wR23−R32=4wR31−R13=4wR12−R21 -
如果 t r ≤ 0 tr \leq 0 tr≤0 且 R 11 > R 22 R_{11} > R_{22} R11>R22 和 R 11 > R 33 R_{11} > R_{33} R11>R33:
x = 1 2 1 + R 11 − R 22 − R 33 w = R 23 − R 32 4 x y = R 12 + R 21 4 x z = R 13 + R 31 4 x \begin{align*} x &= \frac{1}{2}\sqrt{1 + R_{11} - R_{22} - R_{33}}\\ w &= \frac{R_{23} - R_{32}}{4x}\\ y &= \frac{R_{12} + R_{21}}{4x}\\ z &= \frac{R_{13} + R_{31}}{4x} \end{align*} xwyz=211+R11−R22−R33=4xR23−R32=4xR12+R21=4xR13+R31
(还有另外两种类似的根据矩阵元素比较来确定四元数各分量的情况,这里省略详细展开)
在代码中实现这个转换(伪代码示意):
Quaternion rotationMatrixToQuaternion(Matrix3x3 R) {
float tr = R.m[0][0] + R.m[1][1] + R.m[2][2];
if (tr > 0) {
float s = 0.5f / sqrt(1 + tr);
return Quaternion(0.5f * sqrt(1 + tr), (R.m[1][2] - R.m[2][1]) * s, (R.m[2][0] - R.m[0][2]) * s, (R.m[0][1] - R.m[1][0]) * s);
} else if (R.m[0][0] > R.m[1][1] && R.m[0][0] > R.m[2][2]) {
float s = 0.5f / sqrt(1 + R.m[0][0] - R.m[1][1] - R.m[2][2]);
return Quaternion((R.m[1][2] - R.m[2][1]) * s, 0.5f * sqrt(1 + R.m[0][0] - R.m[1][1] - R.m[2][2]), (R.m[1][0] + R.m[0][1]) * s, (R.m[0][2] + R.m[2][0]) * s);
}
// 继续补充另外两种情况的代码实现
return Quaternion(0, 0, 0, 0); // 这里只是占位,实际要完整实现所有情况
}
5. 四元数与欧拉角的转换
四元数转欧拉角:
给定一个四元数
q
=
w
+
x
i
+
y
j
+
z
k
q = w + xi + yj + zk
q=w+xi+yj+zk,可以通过以下公式计算对应的欧拉角(这里以常用的横滚角
r
o
l
l
roll
roll、俯仰角
p
i
t
c
h
pitch
pitch、偏航角
y
a
w
yaw
yaw 为例,角度单位假设为弧度制):
r o l l = arctan 2 ( 2 ( w x + y z ) , 1 − 2 ( x 2 + y 2 ) ) p i t c h = arcsin ( 2 ( w y − z x ) ) y a w = arctan 2 ( 2 ( w z + x y ) , 1 − 2 ( y 2 + z 2 ) ) \begin{align*} roll &= \arctan2(2(wx + yz), 1 - 2(x^2 + y^2))\\ pitch &= \arcsin(2(wy - zx))\\ yaw &= \arctan2(2(wz + xy), 1 - 2(y^2 + z^2)) \end{align*} rollpitchyaw=arctan2(2(wx+yz),1−2(x2+y2))=arcsin(2(wy−zx))=arctan2(2(wz+xy),1−2(y2+z2))
在代码中实现(伪代码示意):
void quaternionToEulerAngles(Quaternion q, float& roll, float& pitch, float& yaw) {
roll = atan2(2 * (q.w * q.x + q.y * q.z), 1 - 2 * (q.x * q.x + q.y * q.y));
pitch = asin(2 * (q.w * q.y - q.z * q.x));
yaw = atan2(2 * (q.w * q.z + q.x * q.y), 1 - 2 * (q.y * q.y + q.z * q.z));
}
欧拉角转四元数:
已知横滚角 (roll)、俯仰角 (pitch)、偏航角 (yaw)(同样假设角度单位为弧度制),可以通过以下公式构造对应的四元数 (q):
w
=
cos
(
r
o
l
l
2
)
cos
(
p
i
t
c
h
2
)
cos
(
y
a
w
2
)
+
sin
(
r
o
l
l
2
)
sin
(
p
i
t
c
h
2
)
sin
(
y
a
w
2
)
x
=
sin
(
r
o
l
l
2
)
cos
(
p
i
t
c
h
2
)
cos
(
y
a
w
2
)
−
cos
(
r
o
l
l
2
)
sin
(
p
i
t
c
h
2
)
sin
(
y
a
w
2
)
y
=
cos
(
r
o
l
l
2
)
sin
(
p
i
t
c
h
2
)
cos
(
y
a
w
2
)
+
sin
(
r
o
l
l
2
)
cos
(
p
i
t
c
h
2
)
sin
(
y
a
w
2
)
z
=
sin
(
r
o
l
l
2
)
sin
(
p
i
t
c
h
2
)
cos
(
y
a
w
2
)
−
cos
(
r
o
l
l
2
)
cos
(
p
i
t
c
h
2
)
sin
(
y
a
w
2
)
\begin{align*} w &= \cos(\frac{roll}{2}) \cos(\frac{pitch}{2}) \cos(\frac{yaw}{2}) + \sin(\frac{roll}{2}) \sin(\frac{pitch}{2}) \sin(\frac{yaw}{2})\\ x &= \sin(\frac{roll}{2}) \cos(\frac{pitch}{2}) \cos(\frac{yaw}{2}) - \cos(\frac{roll}{2}) \sin(\frac{pitch}{2}) \sin(\frac{yaw}{2})\\ y &= \cos(\frac{roll}{2}) \sin(\frac{pitch}{2}) \cos(\frac{yaw}{2}) + \sin(\frac{roll}{2}) \cos(\frac{pitch}{2}) \sin(\frac{yaw}{2})\\ z &= \sin(\frac{roll}{2}) \sin(\frac{pitch}{2}) \cos(\frac{yaw}{2}) - \cos(\frac{roll}{2}) \cos(\frac{pitch}{2}) \sin(\frac{yaw}{2}) \end{align*}
wxyz=cos(2roll)cos(2pitch)cos(2yaw)+sin(2roll)sin(2pitch)sin(2yaw)=sin(2roll)cos(2pitch)cos(2yaw)−cos(2roll)sin(2pitch)sin(2yaw)=cos(2roll)sin(2pitch)cos(2yaw)+sin(2roll)cos(2pitch)sin(2yaw)=sin(2roll)sin(2pitch)cos(2yaw)−cos(2roll)cos(2pitch)sin(2yaw)
以下是使用伪代码实现欧拉角转四元数的示例:
Quaternion eulerAnglesToQuaternion(float roll, float pitch, float yaw) {
float halfRoll = roll / 2.0f;
float halfPitch = pitch / 2.0f;
float halfYaw = yaw / 2.0f;
float w = cos(halfRoll) * cos(halfPitch) * cos(halfYaw) + sin(halfRoll) * sin(halfPitch) * sin(halfYaw);
float x = sin(halfRoll) * cos(halfPitch) * cos(halfYaw) - cos(halfRoll) * sin(halfPitch) * sin(halfYaw);
float y = cos(halfRoll) * sin(halfPitch) * cos(halfYaw) + sin(halfRoll) * cos(halfPitch) * sin(halfYaw);
float z = sin(halfRoll) * sin(halfPitch) * cos(halfYaw) - cos(halfRoll) * cos(halfPitch) * sin(halfYaw);
return Quaternion(w, x, y, z);
}