如何使用旋转四元数(翻译:Rotation Quaternions, and How to Use Them)

本文基础性介绍了四元数在三维旋转中的应用。给出四元数定义,展示其与轴 - 角表示、旋转矩阵间的转换方法。还说明了如何用四元数旋转点,包括四元数乘法、逆的定义及旋转步骤,同时介绍了四元数的一些性质。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文:https://danceswithcode.net/engineeringnotes/quaternions/quaternions.html

译者前言

虽然经常使用四元数来处理旋转,但是其底层原理我一直不理解。之前很多次想去学习它,但是每次找到的文档都是在解释欧拉角和“万向锁”,结果看着看着就猪脑过载,最后放弃了。。。

直到这次又有个契机需要学习四元数,我搜到了这一篇文档。看了开头后很庆幸发现自己能看得下去。因此也就想借着翻译的过程去更细节地学习。

需要说明,我暂时省略了原文里“将欧拉角转换为四元数”、“将四元数转换为欧拉角”、“万向锁”这三个小节。因为欧拉角的问题确实比较复杂,也许需要之后再花时间研究作者的另一篇文档《三维旋转:欧拉角和旋转矩阵》后再翻译会更准确。而目前省略掉这些部分也不影响四元数的核心概念。

另外还有几个小节虽然我也翻译了,但我认为就算先不看也不影响了解四元数的核心概念,我使用了星号 * 来做了标记。

摘要

本文基础性地介绍了四元数在三维旋转中的应用。我们给出了四元数的简单定义,并展示了如何在四元数、轴-角表示、欧拉角、旋转矩阵之间来回转换。我们还展示了如何使用四元数向前和向后旋转对象,以及如何将多个旋转操作连接成一个四元数。

介绍

准确来说,一个四元数由四部分组成:
q = q 0 + i q 1 + j q 2 + k q 3 \boldsymbol{q}= q_0+\boldsymbol{i}q_1+\boldsymbol{j}q_2+\boldsymbol{k}q_3 q=q0+iq1+jq2+kq3

其中:
q 0 q_0 q0 q 1 q_1 q1 q 2 q_2 q2 q 3 q_3 q3 都是实数。 i \boldsymbol{i} i j \boldsymbol{j} j k \boldsymbol{k} k 是相互正交的虚数单位向量。 q 0 q_0 q0称为“实部”,其余三项称为“虚部”。在实际应用中(以及本文的其余部分)都隐含了虚数符号,仅使用四个系数来表示一个四元数:
q = ( q 0 , q 1 , q 2 , q 3 ) \boldsymbol{q}= (q_0,q_1,q_2,q_3) q=(q0,q1,q2,q3)

“四元数”是一个复杂的话题。然而在本文中,我们仅讨论 “旋转四元数” 这一四元数的子集。旋转四元数是一种在三维空间中表示旋转的方式,可用于3D图形或其他应用程序中,作为 “旋转矩阵” 的替代方式。想要使用它们,并不需要理解“复数”。

旋转四元数与旋转的“轴-角表示”密切相关。因此,我们将先解释“轴-角表示”,然后展示如何转换为四元数。

3D旋转的 轴-角表示

根据欧拉旋转定理,3D中任何旋转(或旋转的序列)都可以使用两个参数来指定:“表示旋转轴的单位向量” 和 “绕该轴旋转的角度 θ \theta θ”。如图 1 所示:
在这里插入图片描述
因此,一个“轴-角旋转”可以用四个数字表示:
( θ , x ^ , y ^ , z ^ ) (\theta,\hat{x},\hat{y},\hat{z}) (θ,x^,y^,z^)

其中:
( x ^ , y ^ , z ^ ) (\hat{x},\hat{y},\hat{z}) (x^,y^,z^) 是表示旋转轴的单位向量
θ \theta θ 是绕该轴旋转的角度

将“轴-角”转换为“四元数”

“旋转四元数” 类似于“轴-角表示”。如果我们知道了“轴-角表示”中的 ( θ , x ^ , y ^ , z ^ ) (\theta,\hat{x},\hat{y},\hat{z}) (θ,x^,y^,z^),我们就能将其转换为旋转四元数 q \boldsymbol{q} q
q = ( q 0 , q 1 , q 2 , q 3 ) \boldsymbol{q}= (q_0,q_1,q_2,q_3) q=(q0,q1,q2,q3)

其中:
q 0 = cos ⁡ ( θ 2 ) q 1 = x ^ sin ⁡ ( θ 2 ) q 2 = y ^ sin ⁡ ( θ 2 ) q 3 = z ^ sin ⁡ ( θ 2 ) \begin{align*} q_0&=\cos(\frac{\theta}{2})\\ q_1&=\hat{x} \sin(\frac{\theta}{2})\\ q_2&=\hat{y} \sin(\frac{\theta}{2})\\ q_3&=\hat{z} \sin(\frac{\theta}{2}) \end{align*} q0q1q2q3=cos(2θ)=x^sin(2θ)=y^sin(2θ)=z^sin(2θ)

从中我们可以看出,四元数的 实部 q 0 q_0 q0 完全由旋转角决定,其余的三项 虚部( q 1 q_1 q1 q 2 q_2 q2 q 3 q_3 q3)就是旋转轴向量的三个值并且有一个共同的缩放系数。这种表示让旋转四元数的 “大小”(也就是四个分量的平方和) 始终等于 1。

也就是说,“轴-角” 和 “四元数” 表示了完全相同的信息。那么我们就有理由问:为什么我们还要大费周折地使用不直观的四元数呢?答案是:如果使用“轴-角”来执行“旋转3D物体的顶点”等操作,无论如何都必须执行“三角运算”,而大多数四元数运算只需使用“乘/除/加/减运算”即可完成,这节省了计算机运算。

*将“四元数”转换为“轴-角”

给定四元数 q = ( q 0 , q 1 , q 2 , q 3 ) \boldsymbol{q}= (q_0,q_1,q_2,q_3) q=(q0,q1,q2,q3),我们可以用如下方式转换为刚才的“轴-角表示”:

首先,先从 q 0 q_0 q0 中提取出旋转角度:
θ = 2 cos ⁡ − 1 ( q 0 ) \theta=2\cos^{-1}(q_0) θ=2cos1(q0)

然后,如果 θ \theta θ不为0,我们可以用如下算式得到旋转轴的单位向量:
( x ^ , y ^ , z ^ ) = ( q 1 sin ⁡ θ 2 , q 2 sin ⁡ θ 2 , q 3 sin ⁡ θ 2 ) (\hat{x},\hat{y},\hat{z})=(\frac{q_1}{\sin{\frac{\theta}{2}}},\frac{q_2}{\sin{\frac{\theta}{2}}},\frac{q_3}{\sin{\frac{\theta}{2}}}) (x^,y^,z^)=(sin2θq1,sin2θq2,sin2θq3)

在一种特殊情况下不能使用上面算式: q = ( 1 , 0 , 0 , 0 ) \boldsymbol{q}= (1,0,0,0) q=(1,0,0,0) 的四元数称为恒等四元数(identity quaternion),它将不会产生任何旋转。在这种情况下 θ = 0 \theta=0 θ=0,然而,由于在没有旋转时旋转轴是未知的,因此上面算式将产生“除以零的错误”。因此,任何软件实现都应该测试 q 0 q_0 q0 是否等于 “1.0”,如果等于,则应设置 θ = 0 \theta=0 θ=0 并且 ( x ^ , y ^ , z ^ ) = ( 1 , 0 , 0 , 0 ) (\hat{x},\hat{y},\hat{z})=(1,0,0,0) (x^,y^,z^)=(1,0,0,0)

值得注意的是,有多种方法可以将“四元数”转换为“轴-角”。因此如果你看到了和上面的算式不一样的方法,也不要担心。

*将“四元数”转换为“旋转矩阵”

旋转四元数 q = ( q 0 , q 1 , q 2 , q 3 ) \boldsymbol{q}= (q_0,q_1,q_2,q_3) q=(q0,q1,q2,q3) 所对应的旋转矩阵为:
R = ∣ q 0 2 + q 1 2 − q 2 2 − q 3 2 2 q 1 q 2 − 2 q 0 q 3 2 q 1 q 3 + 2 q 0 q 2 2 q 1 q 2 + 2 q 0 q 3 q 0 2 − q 1 2 + q 2 2 − q 3 2 2 q 2 q 3 − 2 q 0 q 1 2 q 1 q 3 − 2 q 0 q 2 2 q 2 q 3 + 2 q 0 q 1 q 0 2 − q 1 2 − q 2 2 + q 3 2 ∣ R= \begin{vmatrix} q_0^2+q_1^2-q_2^2-q_3^2 & 2q_1q_2-2q_0q_3 & 2q_1q_3+2q_0q_2\\ 2q_1q_2+2q_0q_3 & q_0^2-q_1^2+q_2^2-q_3^2 & 2q_2q_3-2q_0q_1\\ 2q_1q_3-2q_0q_2 & 2q_2q_3+2q_0q_1 & q_0^2-q_1^2-q_2^2+q_3^2 \end{vmatrix} R= q02+q12q22q322q1q2+2q0q32q1q32q0q22q1q22q0q3q02q12+q22q322q2q3+2q0q12q1q3+2q0q22q2q32q0q1q02q12q22+q32
或者,等价的:
R = ∣ 1 − 2 q 2 2 − 2 q 3 2 2 q 1 q 2 − 2 q 0 q 3 2 q 1 q 3 + 2 q 0 q 2 2 q 1 q 2 + 2 q 0 q 3 1 − 2 q 1 2 − 2 q 3 2 2 q 2 q 3 − 2 q 0 q 1 2 q 1 q 3 − 2 q 0 q 2 2 q 2 q 3 + 2 q 0 q 1 1 − 2 q 1 2 − 2 q 2 2 ∣ R= \begin{vmatrix} 1-2q_2^2-2q_3^2 & 2q_1q_2-2q_0q_3 & 2q_1q_3+2q_0q_2\\ 2q_1q_2+2q_0q_3 & 1-2q_1^2-2q_3^2 & 2q_2q_3-2q_0q_1\\ 2q_1q_3-2q_0q_2 & 2q_2q_3+2q_0q_1 & 1-2q_1^2-2q_2^2 \end{vmatrix} R= 12q222q322q1q2+2q0q32q1q32q0q22q1q22q0q312q122q322q2q3+2q0q12q1q3+2q0q22q2q32q0q112q122q22

这两种方法都适用于所有有效的旋转四元数,包括恒等四元数。

*将“旋转矩阵”转换为“四元数”

给定旋转矩阵 R R R
R = ∣ r 11 r 12 r 13 r 21 r 22 r 23 r 31 r 32 r 33 ∣ R= \begin{vmatrix} r_{11} & r_{12} & r_{13}\\ r_{21} & r_{22} & r_{23}\\ r_{31} & r_{32} & r_{33} \end{vmatrix} R= r11r21r31r12r22r32r13r23r33
我们可以通过两个步骤找到等效的四元数:

步骤1:求每个分量的“大小”,然而我们并不知道每个分量的正负符号:
∣ q 0 ∣ = 1 + r 11 + r 22 + r 33 4 ∣ q 1 ∣ = 1 + r 11 − r 22 − r 33 4 ∣ q 2 ∣ = 1 − r 11 + r 22 − r 33 4 ∣ q 3 ∣ = 1 − r 11 − r 22 + r 33 4 |q_0|=\sqrt{\frac{1+r_{11}+r_{22}+r_{33}}{4}}\\ |q_1|=\sqrt{\frac{1+r_{11}-r_{22}-r_{33}}{4}}\\ |q_2|=\sqrt{\frac{1-r_{11}+r_{22}-r_{33}}{4}}\\ |q_3|=\sqrt{\frac{1-r_{11}-r_{22}+r_{33}}{4}} q0=41+r11+r22+r33 q1=41+r11r22r33 q2=41r11+r22r33 q3=41r11r22+r33

步骤2:找到 q 0 , q 1 , q 2 , q 3 q_0,q_1,q_2,q_3 q0,q1,q2,q3中最大的,并假设其符号为正。然后使用下表中的算式计算其余分量:(找“最大”的值是为了避免除以太小的数值,因为那样会让数值精度降低)

如果 q 0 q_0 q0最大如果 q 1 q_1 q1最大如果 q 2 q_2 q2最大如果 q 3 q_3 q3最大
q 1 = r 32 − r 23 4 q 0 q_1=\frac{r_{32}-r_{23}}{4q_0} q1=4q0r32r23 q 0 = r 32 − r 23 4 q 1 q_0=\frac{r_{32}-r_{23}}{4q_1} q0=4q1r32r23 q 0 = r 13 − r 31 4 q 2 q_0=\frac{r_{13}-r_{31}}{4q_2} q0=4q2r13r31 q 0 = r 12 − r 21 4 q 3 q_0=\frac{r_{12}-r_{21}}{4q_3} q0=4q3r12r21
q 2 = r 13 − r 31 4 q 0 q_2=\frac{r_{13}-r_{31}}{4q_0} q2=4q0r13r31 q 2 = r 12 + r 21 4 q 1 q_2=\frac{r_{12}+r_{21}}{4q_1} q2=4q1r12+r21 q 1 = r 12 + r 21 4 q 2 q_1=\frac{r_{12}+r_{21}}{4q_2} q1=4q2r12+r21 q 1 = r 13 + r 31 4 q 3 q_1=\frac{r_{13}+r_{31}}{4q_3} q1=4q3r13+r31
q 3 = r 21 − r 12 4 q 0 q_3=\frac{r_{21}-r_{12}}{4q_0} q3=4q0r21r12 q 3 = r 13 + r 31 4 q 1 q_3=\frac{r_{13}+r_{31}}{4q_1} q3=4q1r13+r31 q 3 = r 23 + r 32 4 q 2 q_3=\frac{r_{23}+r_{32}}{4q_2} q3=4q2r23+r32 q 2 = r 23 + r 32 4 q 3 q_2=\frac{r_{23}+r_{32}}{4q_3} q2=4q3r23+r32

正负符号之所以不确定的原因是:任何给定的旋转都可能对应两个四元数,如果已知了其中的一个,那么另一个就可以通过将所有分量取负来得到——这意味着旋转角度和旋转轴都会反转。因此,对于任意旋转四元数, ( q 0 , q 1 , q 2 , q 3 ) (q_0,q_1,q_2,q_3) (q0,q1,q2,q3) ( − q 0 , − q 1 , − q 2 , − q 3 ) (-q_0,-q_1,-q_2,-q_3) (q0,q1,q2,q3) 都将产生相同的旋转。而要将旋转矩阵转换为四元数,我们只能先随便选择两种答案之中的一个。

使用四元数来旋转一个点

本节定义了四元数的 “乘法”和 “逆”,并展示了如何使用四元数来执行旋转。

四元数的乘法

两个四元数相乘:
t = r s ( t 0 , t 1 , t 2 , t 3 ) = ( r 0 , r 1 , r 2 , r 3 ) × ( s 0 , s 1 , s 2 , s 3 ) \begin{align*} \boldsymbol{t}&=\boldsymbol{r}\boldsymbol{s}\\ (t_0,t_1,t_2,t_3)&=(r_0,r_1,r_2,r_3)\times(s_0,s_1,s_2,s_3) \end{align*} t(t0,t1,t2,t3)=rs=(r0,r1,r2,r3)×(s0,s1,s2,s3)

定义为:
t 0 = ( r 0 s 0 − r 1 s 1 − r 2 s 2 − r 3 s 3 ) t 1 = ( r 0 s 1 + r 1 s 0 + r 3 s 2 − r 2 s 3 ) t 2 = ( r 0 s 2 + r 2 s 0 + r 1 s 3 − r 3 s 1 ) t 3 = ( r 0 s 3 + r 3 s 0 + r 2 s 1 − r 1 s 2 ) t_0=(r_0s_0-r_1s_1-r_2s_2-r_3s_3)\\ t_1=(r_0s_1+r_1s_0+r_3s_2-r_2s_3)\\ t_2=(r_0s_2+r_2s_0+r_1s_3-r_3s_1)\\ t_3=(r_0s_3+r_3s_0+r_2s_1-r_1s_2) t0=(r0s0r1s1r2s2r3s3)t1=(r0s1+r1s0+r3s2r2s3)t2=(r0s2+r2s0+r1s3r3s1)t3=(r0s3+r3s0+r2s1r1s2)

四元数的乘法满足结合律,但是不满足交换律(除非某些特殊情况)。也就是说:
( a b ) c = a ( b c ) a b ≠ b a (\boldsymbol{a}\boldsymbol{b})\boldsymbol{c}=\boldsymbol{a}(\boldsymbol{b}\boldsymbol{c})\\ \boldsymbol{a}\boldsymbol{b}\ne\boldsymbol{b}\boldsymbol{a} (ab)c=a(bc)ab=ba

四元数的逆

四元数的通过对虚部取负得到:
q − 1 = ( q 0 , − q 1 , − q 2 , − q 3 ) \boldsymbol{q}^{-1}= (q_0,-q_1,-q_2,-q_3) q1=(q0,q1,q2,q3)

使用四元数来执行旋转

要使用 四元数 q \boldsymbol{q} q 来旋转 点 ( x , y , z ) (x,y,z) (x,y,z),需要以下三个步骤:

步骤1:将要旋转的点转换为四元数 p \boldsymbol{p} p :将点的坐标指定为 p \boldsymbol{p} p的虚部,并将 p \boldsymbol{p} p的实部设置为零。比如 ( x , y , z ) (x,y,z) (x,y,z) 是要旋转的点,那么转换成的四元数 p \boldsymbol{p} p为:
p = ( p 0 , p 1 , p 2 , p 3 ) = ( 0 , x , y , z ) \boldsymbol{p}=(p_0,p_1,p_2,p_3)=(0,x,y,z) p=(p0,p1,p2,p3)=(0,x,y,z)

步骤2:执行旋转。这需要两次乘法

如果是“主动”旋转,则: p ′ = q − 1 p q \boldsymbol{p'}=\boldsymbol{q}^{-1}\boldsymbol{p}\boldsymbol{q} p=q1pq

如果是“被动”旋转,则: p ′ = q p q − 1 \boldsymbol{p'}=\boldsymbol{q}\boldsymbol{p}\boldsymbol{q}^{-1} p=qpq1

其中:
p \boldsymbol{p} p 是步骤1中由要旋转的点所转换的四元数
q \boldsymbol{q} q 是表示旋转的四元数
q − 1 \boldsymbol{q}^{-1} q1 q \boldsymbol{q} q 的逆
p ′ \boldsymbol{p'} p 中包含了执行完旋转后的点的坐标

“主动”旋转是指点相对于坐标系旋转,“被动”旋转是指坐标系相对于点旋转。两个旋转方向相反。

注意,由于四元数乘法满足结合律,所以顺序是 ( q p ) q − 1 (\boldsymbol{q}\boldsymbol{p})\boldsymbol{q}^{-1} (qp)q1还是 q ( p q − 1 ) \boldsymbol{q}(\boldsymbol{p}\boldsymbol{q}^{-1}) q(pq1)都一样。

步骤3:从 p ′ \boldsymbol{p'} p 中提取旋转后的坐标
p ′ = ( 0 , x ′ , y ′ , z ′ ) \boldsymbol{p'}=(0,x',y',z') p=(0,x,y,z)

p ′ \boldsymbol{p'} p 像其他四元数一样有四个分量,但是它的实部总是等于0。而旋转后的点 ( x ′ , y ′ , z ′ ) (x',y',z') (x,y,z) 就是 p ′ \boldsymbol{p'} p 的虚部。

*四元数的性质

以下是四元数一些有用的性质。到目前为止,本文仅讨论了“旋转四元数”。然而,“旋转四元数”只是所有四元数的子集,就像“旋转矩阵”是所有 3x3 矩阵的子集一样。而以下的性质适用于所有四元数,除非特别指明。

  1. 四元数的长度(大小)是 ∣ q ∣ = q q ∗ = q 0 2 + q 1 2 + q 2 2 + q 3 2 |\boldsymbol{q}|=\sqrt{qq^*}=\sqrt{q_0^2+q_1^2+q_2^2+q_3^2} q=qq =q02+q12+q22+q32
  2. 如果 ∣ q ∣ = 1 |\boldsymbol{q}|=1 q=1,则这个四元数是“单位四元数(unit quaternion)
  3. 所有旋转四元数都是“单位四元数”
  4. 如果 q = ( 1 , 0 , 0 , 0 ) \boldsymbol{q}= (1,0,0,0) q=(1,0,0,0),则这个四元数是“恒等四元数(identity quaternion)”。它表示不进行任何旋转。对于任意四元数 q \boldsymbol{q} q 以及单位四元数 i \boldsymbol{i} i,都存在 q i = i q = q \boldsymbol{q}\boldsymbol{i}=\boldsymbol{i}\boldsymbol{q}=\boldsymbol{q} qi=iq=q
  5. 四元数的 共轭(conjugate) q ∗ = ( q 0 , − q 1 , − q 2 , − q 3 ) \boldsymbol{q}^{*}= (q_0,-q_1,-q_2,-q_3) q=(q0,q1,q2,q3)
  6. 四元数的逆为 q − 1 = q ∗ ∣ q ∣ 2 \boldsymbol{q}^{-1}= \frac{\boldsymbol{q}^{*}}{|\boldsymbol{q}|^2} q1=q2q。一个四元数和自己的共轭相乘的结果是恒等四元数: q q − 1 = q − 1 q = ( 1 , 0 , 0 , 0 ) \boldsymbol{q}\boldsymbol{q^{-1}}=\boldsymbol{q^{-1}}\boldsymbol{q}=(1,0,0,0) qq1=q1q=(1,0,0,0)。注意在这个特殊的情况下,这里的乘法是满足交换律的。
  7. 对于旋转四元数,它的逆和共轭是一样的: q − 1 = q ∗ = ( q 0 , − q 1 , − q 2 , − q 3 ) \boldsymbol{q^{-1}}=\boldsymbol{q}^{*}= (q_0,-q_1,-q_2,-q_3) q1=q=(q0,q1,q2,q3)
  8. 旋转四元数的逆/共轭具有反转旋转轴的效果,这会将其修改为沿与原始方向相反的方向旋转。也就是说,如果使用 q \boldsymbol{q} q 将一个点旋转到一个新位置,则使用 q − 1 \boldsymbol{q^{-1}} q1 q ∗ \boldsymbol{q}^{*} q再次旋转它会将其返回到原始位置。
  9. 任何给定的旋转都有两个可能的四元数表示。如果已知其中一个,则可以通过对所有分量取负来找到另一个。这使得旋转角度和旋转轴都反转。因此,如果 q \boldsymbol{q} q 是旋转四元数,则 q \boldsymbol{q} q − q -\boldsymbol{q} q 将产生相同的旋转。
  10. q a \boldsymbol{q_a} qa 随后 q b \boldsymbol{q_b} qb 的旋转可以被合并为一个旋转 q c = q a q b \boldsymbol{q_c}=\boldsymbol{q_a}\boldsymbol{q_b} qc=qaqb。这可以扩展到任意数量的旋转。但请注意,顺序很重要(因为四元数的乘法不满足交换律)。
  11. 四元数的乘法满足结合律: ( a b ) c = a ( b c ) (\boldsymbol{a}\boldsymbol{b})\boldsymbol{c}=\boldsymbol{a}(\boldsymbol{b}\boldsymbol{c}) (ab)c=a(bc)
  12. 四元数的乘法不满足交换律: a b ≠ b a \boldsymbol{a}\boldsymbol{b}\ne\boldsymbol{b}\boldsymbol{a} ab=ba

译者后记

虽然翻译完了除开欧拉角和万向锁的内容,不过文章里的很多公式也值得再去推导一遍。

作者的另一篇文档《三维旋转:欧拉角和旋转矩阵》 之后需要花时间研究。

旋转转换工具 是作者提供的一个可以在欧拉角、四元数、轴-角和旋转矩阵表示形式之间进行转换的工具。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值