先介绍一下四元数与旋转的关系,之后在Unity中进行仿真看是否和理论一致。
四元数
先介绍一下四元数的概念: 首先四元数的定义与复数非常相似: 复数的定义为:
z
=
a
+
b
i
z=a+bi
z=a+bi 其中:
i
2
=
?
1
,
a
、
b
∈
R
i^2=-1,a、b\in\mathbb{R}
i2=?1,a、b∈R 我们对四元数的定义为:
q
=
a
+
b
i
+
c
j
+
d
k
q=a+bi+cj+dk
q=a+bi+cj+dk 其中:
i
2
=
j
2
=
k
2
=
i
j
k
=
?
1
,
a
、
b
、
c
、
d
∈
R
i^2=j^2=k^2=ijk=-1,a、b、c、d\in\mathbb{R}
i2=j2=k2=ijk=?1,a、b、c、d∈R 这里的四元数仅仅只是这样定义的,只需要记住四元数的定义和他的几个性质即可。理解旋转不需要理解四元数在高维空间的意义,也不需要知道四元数的其他性质。 同时我们也采用另一种方式(向量、矩阵)的形式来存储四元数。 比如
q
=
[
s
,
v
]
.
(
v
=
[
x
,
y
,
z
]
,
s
,
x
,
y
,
z
∈
R
)
q=[s,\mathbf v].(\mathbf v=[x,y,z],s,x,y,z\in\mathbb{R})
q=[s,v].(v=[x,y,z],s,x,y,z∈R) 其中s,x,y,z分别对应我们的a,b,c,d
四元数的性质
四元数的加法和减法
四元数的加法和减法与复数的加法与减法类似: 加法:
q
1
=
a
1
+
b
1
i
+
c
1
j
+
d
1
k
q_1=a_1+b_1i+c_1j+d_1k
q1?=a1?+b1?i+c1?j+d1?k
q
2
=
a
2
+
b
2
i
+
c
2
j
+
d
2
k
q_2=a_2+b_2i+c_2j+d_2k
q2?=a2?+b2?i+c2?j+d2?k
q
1
+
q
2
=
(
a
1
+
a
2
)
+
(
b
1
+
b
2
)
i
+
(
c
1
+
c
2
)
j
+
(
d
1
+
d
2
)
k
q_1+q_2=(a_1+a_2)+(b_1+b_2)i+(c_1+c_2)j+(d_1+d_2)k
q1?+q2?=(a1?+a2?)+(b1?+b2?)i+(c1?+c2?)j+(d1?+d2?)k 可以看到我们的四元数的加法和减法是符合各分量相加的,减法同理:
q
1
=
a
1
+
b
1
i
+
c
1
j
+
d
1
k
q_1=a_1+b_1i+c_1j+d_1k
q1?=a1?+b1?i+c1?j+d1?k
q
2
=
a
2
+
b
2
i
+
c
2
j
+
d
2
k
q_2=a_2+b_2i+c_2j+d_2k
q2?=a2?+b2?i+c2?j+d2?k
q
1
?
q
2
=
(
a
1
?
a
2
)
+
(
b
1
?
b
2
)
i
+
(
c
1
?
c
2
)
j
+
(
d
1
?
d
2
)
k
q_1-q_2=(a_1-a_2)+(b_1-b_2)i+(c_1-c_2)j+(d_1-d_2)k
q1??q2?=(a1??a2?)+(b1??b2?)i+(c1??c2?)j+(d1??d2?)k 根据四元数的第二种表示形式,我们有:
q
1
=
[
s
1
,
t
1
]
,
q
2
=
[
s
2
,
t
2
]
q_1=[s_1,\mathbf t_1],q_2=[s_2,\mathbf t_2]
q1?=[s1?,t1?],q2?=[s2?,t2?] 则有:
q
1
±
q
2
=
[
s
1
±
s
2
,
t
1
±
t
2
]
q_1 \pm q_2=[s_1 \pm s_2,\mathbf t_1 \pm \mathbf t_2]
q1?±q2?=[s1?±s2?,t1?±t2?]
四元数的乘法
四元数的乘法是比较特殊的,首先四元数的乘法不遵循交换律。 我们先推导一下四元数的乘积,以及他的表示:
q
1
=
a
1
+
b
1
i
+
c
1
j
+
d
1
k
q_1=a_1+b_1i+c_1j+d_1k
q1?=a1?+b1?i+c1?j+d1?k
q
2
=
a
2
+
b
2
i
+
c
2
j
+
d
2
k
q_2=a_2+b_2i+c_2j+d_2k
q2?=a2?+b2?i+c2?j+d2?k
q
1
q
2
=
(
a
1
+
b
1
i
+
c
1
j
+
d
1
k
)
?
(
a
2
+
b
2
i
+
c
2
j
+
d
2
k
)
=
a
1
a
2
+
a
1
b
2
i
+
a
1
c
2
j
+
a
1
d
2
k
+
a
2
b
1
i
+
b
1
b
2
i
2
+
b
1
c
2
i
j
+
b
1
d
2
i
k
+
a
2
c
1
j
+
b
2
c
1
j
i
+
c
1
c
2
j
2
+
c
1
d
2
j
k
+
a
2
d
1
k
+
b
2
d
1
k
i
+
c
2
d
1
k
j
+
d
1
d
2
k
2
q_1q_2=(a_1+b_1i+c_1j+d_1k)* (a_2+b_2i+c_2j+d_2k)\\=a_1a_2+a_1b_2i+a_1c_2j+a_1d_2k\\+a_2b_1i+b_1b_2i^2+b_1c_2ij+b_1d_2ik\\+a_2c_1j+b_2c_1ji+c_1c_2j^2+c_1d_2jk\\+a_2d_1k+b_2d_1ki+c_2d_1kj+d_1d_2k^2
q1?q2?=(a1?+b1?i+c1?j+d1?k)?(a2?+b2?i+c2?j+d2?k)=a1?a2?+a1?b2?i+a1?c2?j+a1?d2?k+a2?b1?i+b1?b2?i2+b1?c2?ij+b1?d2?ik+a2?c1?j+b2?c1?ji+c1?c2?j2+c1?d2?jk+a2?d1?k+b2?d1?ki+c2?d1?kj+d1?d2?k2 此处的推导要注意顺序因为例如:
i
j
=?
j
i
ij\not=ji
ij=ji 我们根据
i
2
=
j
2
=
k
2
=
i
j
k
=
?
1
i^2=j^2=k^2=ijk=-1
i2=j2=k2=ijk=?1 可以推导出:
i
2
=
j
2
=
k
2
=
?
1
i
j
=
k
j
k
=
i
i
k
=
?
j
i^2=j^2=k^2=-1\\ij=k\\jk=i\\ik=-j
i2=j2=k2=?1ij=kjk=iik=?j 因此我们可以化简:
q
1
q
2
=
a
1
a
2
?
b
1
b
2
?
c
1
c
2
?
d
1
d
2
+
(
a
1
b
2
+
a
2
b
1
+
c
1
d
2
?
c
2
d
1
)
i
+
(
a
1
c
2
?
b
1
d
2
+
a
2
c
1
+
b
2
d
1
)
j
+
(
a
1
d
2
+
b
1
c
2
?
b
2
c
1
+
a
2
d
1
)
k
q_1q_2=a_1a_2-b_1b_2-c_1c_2-d_1d_2\\+(a_1b_2+a_2b_1+c_1d_2-c_2d_1)i\\+(a_1c_2-b_1d_2+a_2c_1+b_2d_1)j\\+(a_1d_2+b_1c_2-b_2c_1+a_2d_1)k
q1?q2?=a1?a2??b1?b2??c1?c2??d1?d2?+(a1?b2?+a2?b1?+c1?d2??c2?d1?)i+(a1?c2??b1?d2?+a2?c1?+b2?d1?)j+(a1?d2?+b1?c2??b2?c1?+a2?d1?)k 经过整理有:
=
(
a
1
a
2
?
b
1
b
2
?
c
1
c
2
?
d
1
d
2
)
+
(
b
1
a
2
+
a
1
b
2
?
d
1
c
2
+
c
1
d
2
)
i
+
(
c
1
a
2
+
d
1
b
2
+
a
1
c
2
?
b
1
d
2
)
j
+
(
d
1
a
2
?
c
1
b
2
+
b
1
c
2
+
a
1
d
2
)
k
=(a_1a_2-b_1b_2-c_1c_2-d_1d_2)\\+(b_1a_2+a_1b_2-d_1c_2+c_1d_2)i\\+(c_1a_2+d_1b_2+a_1c_2-b_1d_2)j\\+(d_1a_2-c_1b_2+b_1c_2+a_1d_2)k
=(a1?a2??b1?b2??c1?c2??d1?d2?)+(b1?a2?+a1?b2??d1?c2?+c1?d2?)i+(c1?a2?+d1?b2?+a1?c2??b1?d2?)j+(d1?a2??c1?b2?+b1?c2?+a1?d2?)k 我们可以将上述的式子看成是矩阵相乘的形式。(这里不再赘述) 同时我们推导一下四元数的一些性质如下: 我们如果将上文的分量作为向量则有:
v
=
[
b
1
,
c
1
,
d
1
]
,
u
=
[
b
2
,
c
2
,
d
2
]
\mathbf v=[b_1,c_1,d_1],\mathbf u=[b_2,c_2,d_2]
v=[b1?,c1?,d1?],u=[b2?,c2?,d2?] 那么我们可以推导出来
v
?
u
=
b
1
b
2
+
c
1
c
2
+
d
1
d
2
\mathbf v \cdot \mathbf u=b_1b_2+c_1c_2+d_1d_2
v?u=b1?b2?+c1?c2?+d1?d2? 同时我们也有
v
×
u
=
(
c
1
d
2
?
d
1
c
2
)
i
?
(
b
1
d
2
?
d
1
b
2
)
j
+
(
b
1
c
2
?
c
1
b
2
)
k
\mathbf v \times \mathbf u=(c_1d_2-d_1c_2)i-(b_1d_2-d_1b_2)j+(b_1c_2-c_1b_2)k
v×u=(c1?d2??d1?c2?)i?(b1?d2??d1?b2?)j+(b1?c2??c1?b2?)k 则我们可以将其写成:
q
1
q
2
=
[
a
1
a
2
?
v
?
u
,
a
1
u
+
a
2
v
+
v
×
u
]
q_1q_2=[a_1a_2-\mathbf v \cdot \mathbf u,a_1 \mathbf u+a_2 \mathbf v+\mathbf v \times \mathbf u]
q1?q2?=[a1?a2??v?u,a1?u+a2?v+v×u] 这个就是四元数的乘积的另一种表示形式。
纯四元数
对于一个纯四元数(只有虚部的四元数)来说,我们可以将其与三维世界一一对应,即我们的x,y,z坐标对应的正是i,j,k的数值。 这时对我们两个纯虚数来说:
v
=
[
0
,
v
]
,
u
=
[
0
,
u
]
v=[0,\mathbf v],u=[0,\mathbf u]
v=[0,v],u=[0,u] 则我们有根据上文可以推导:
v
u
=
[
?
v
?
u
,
v
×
u
]
vu=[-\mathbf v \cdot \mathbf u,\mathbf v \times \mathbf u]
vu=[?v?u,v×u]
四元数的逆、共轭
四元数的逆
我们规定
q
?
1
q^{-1}
q?1是
q
q
q的逆,因此我们可以规定有:
q
q
?
1
=
q
?
1
q
=
1
(
q
=?
0
)
qq^{-1}=q^{-1}q=1(q\not = 0)
qq?1=q?1q=1(q=0) 这里要注意左乘与右乘的区别。
四元数的共轭
我们规定
q
?
q^{*}
q?是
q
q
q的共轭。 其中假设:
q
=
a
+
b
i
+
c
j
+
d
k
q=a+bi+cj+dk
q=a+bi+cj+dk则
q
?
=
a
?
b
i
?
c
j
?
d
k
q^{*}=a-bi-cj-dk
q?=a?bi?cj?dk 因此根据四元数的另一种定义形式我们有:
q
=
[
a
,
v
]
q
?
=
[
a
,
?
v
]
q=[a,\mathbf v]\\q^{*}=[a,-\mathbf v]
q=[a,v]q?=[a,?v]
四元数共轭的性质
q
?
q
=
[
a
2
?
v
?
v
,
a
v
+
a
(
?
v
)
?
v
×
v
]
=
[
a
2
+
v
?
v
,
0
]
=
∣
q
∣
2
q^{*}q=[a^2-\mathbf v \cdot \mathbf v,a\mathbf v+a(-\mathbf v)-\mathbf v \times \mathbf v]\\=[a^2+\mathbf v \cdot \mathbf v,0]=|q|^2
q?q=[a2?v?v,av+a(?v)?v×v]=[a2+v?v,0]=∣q∣2 四元数共轭的乘法是满足交换律的:
q
?
q
=
q
q
?
q^{*}q=qq^{*}
q?q=qq? 当四元数是一个单位四元数的时候,会有好性质如下:
q
q
?
=
1
q
?
1
q
q
?
=
q
?
1
q
?
=
q
?
1
qq^{*}=1\\q^{-1}qq^{*}=q^{-1}\\q*=q^{-1}
qq?=1q?1qq?=q?1q?=q?1
旋转
我们先看一下三维空间的旋转,以四元数应用的角度来看: 假设一个向量
v
\mathbf v
v要绕
u
\mathbf u
u旋转
θ
\theta
θ度。则我们可以分解为
v
/
/
,
v
⊥
\mathbf v_{//},\mathbf v_{\bot}
v//?,v⊥?绕
u
\mathbf u
u旋转再求和。 接下来的推导均假设
u
\mathbf u
u为单位向量,如果不是单位向量就单位化再进行将其作为轴进行旋转。
v
/
/
\mathbf v_{//}
v//?的旋转
我们知道
v
/
/
=
(
u
?
v
)
u
\mathbf v_{//}=(\mathbf u \cdot \mathbf v)\mathbf u
v//?=(u?v)u 并且
v
/
/
\mathbf v_{//}
v//?旋转过程中并不变, 因此有:
v
/
/
′
=
v
/
/
\mathbf v_{//}^{'}=\mathbf v_{//}
v//′?=v//?
v
⊥
\mathbf v_{\bot}
v⊥?的旋转
根据上文我们有:
v
⊥
=
v
?
v
/
/
\mathbf v_{\bot}=\mathbf v-\mathbf v_{//}
v⊥?=v?v//? 我们知道
v
⊥
\mathbf v_{\bot}
v⊥?是在图上的圆中的,也就是
v
⊥
\mathbf v_{\bot}
v⊥?绕圆旋转
θ
\theta
θ度。如果我们想要用一个向量来表示
v
⊥
′
\mathbf v_{\bot}^{'}
v⊥′?的话我们需要构建一个单位向量通过叉乘的形式构建一个与
v
⊥
\mathbf v_{\bot}
v⊥?的向量。 这个向量我们称之为:
w
\mathbf w
w
w
=
u
×
v
⊥
\mathbf w=\mathbf u\times \mathbf v_{\bot}
w=u×v⊥? 方向由右手定则确定。 如果其中的
u
\mathbf u
u为单位向量,那么
∣
w
∣
=
∣
v
⊥
∣
|\mathbf w|=|\mathbf v_{\bot}|
∣w∣=∣v⊥?∣ 此时如果旋转
θ
\theta
θ度。 则有:
v
⊥
′
=
c
o
s
(
θ
)
v
⊥
+
s
i
n
(
θ
)
w
=
c
o
s
(
θ
)
(
v
?
v
/
/
)
+
s
i
n
(
θ
)
(
u
×
v
⊥
)
\mathbf v_{\bot}^{'}=cos(\theta)\mathbf v_{\bot}+sin(\theta)\mathbf w\\=cos(\theta)(\mathbf v- \mathbf v_{//})+sin(\theta)(\mathbf u \times \mathbf v_{\bot})
v⊥′?=cos(θ)v⊥?+sin(θ)w=cos(θ)(v?v//?)+sin(θ)(u×v⊥?) 其中有:
u
×
v
⊥
=
u
×
v
\mathbf u \times \mathbf v_{\bot}=\mathbf u \times \mathbf v
u×v⊥?=u×v 则可以推导:
v
′
=
v
/
/
′
+
v
⊥
′
=
v
/
/
+
c
o
s
(
θ
)
(
v
?
v
/
/
)
+
s
i
n
(
θ
)
(
u
×
v
⊥
)
=
c
o
s
(
θ
)
v
+
(
1
?
c
o
s
(
θ
)
)
(
u
?
v
)
u
+
s
i
n
(
θ
)
u
×
v
\mathbf v^{'}=\mathbf v_{//}^{'}+\mathbf v_{\bot}^{'}\\=\mathbf v_{//}+cos(\theta)(\mathbf v- \mathbf v_{//})+sin(\theta)(\mathbf u \times \mathbf v_{\bot})\\=cos(\theta)\mathbf v+(1-cos(\theta))(\mathbf u \cdot \mathbf v)\mathbf u +sin(\theta)\mathbf u \times \mathbf v
v′=v//′?+v⊥′?=v//?+cos(θ)(v?v//?)+sin(θ)(u×v⊥?)=cos(θ)v+(1?cos(θ))(u?v)u+sin(θ)u×v
四元数与旋转的关系
我们将上述旋转的向量转化为四元数则有:
v
=
[
0
,
v
]
v=[0,\mathbf v]
v=[0,v]
v
⊥
=
[
0
,
v
⊥
]
v_{\bot}=[0,\mathbf v_{\bot}]
v⊥?=[0,v⊥?]
v
/
/
=
[
0
,
v
/
/
]
v_{//}=[0,\mathbf v_{//}]
v//?=[0,v//?]
u
=
[
0
,
u
]
u=[0,\mathbf u]
u=[0,u]
v
′
=
[
0
,
v
′
]
v^{'}=[0,\mathbf v^{'}]
v′=[0,v′]
v
⊥
′
=
[
0
,
v
⊥
′
]
v_{\bot}^{'}=[0,\mathbf v_{\bot}^{'}]
v⊥′?=[0,v⊥′?]
v
/
/
′
=
[
0
,
v
/
/
′
]
v_{//}^{'}=[0,\mathbf v_{//}^{'}]
v//′?=[0,v//′?]
u
′
=
[
0
,
u
′
]
u^{'}=[0,\mathbf u^{'}]
u′=[0,u′]
v
/
/
v_{//}
v//?的旋转
v
/
/
=
v
/
/
′
v_{//}=v_{//}^{'}
v//?=v//′?
v
⊥
v_{\bot}
v⊥?的旋转
对于向量来说
v
⊥
′
=
c
o
s
(
θ
)
v
⊥
+
s
i
n
(
θ
)
(
u
×
v
⊥
)
\mathbf v_{\bot}^{'}=cos(\theta)\mathbf v_{\bot}+sin(\theta)(\mathbf u \times \mathbf v_{\bot})
v⊥′?=cos(θ)v⊥?+sin(θ)(u×v⊥?) 如何将上述向量的式子换为四元数呢。 其中
v
⊥
v_{\bot}
v⊥?可以直接替换
v
⊥
\mathbf v_{\bot}
v⊥? 对于
u
×
v
⊥
\mathbf u \times \mathbf v_{\bot}
u×v⊥?可以由
u
v
⊥
uv_{\bot}
uv⊥?替换 因为我们推导过:
v
u
=
[
?
v
?
u
,
v
×
u
]
vu=[-\mathbf v \cdot \mathbf u,\mathbf v \times \mathbf u]
vu=[?v?u,v×u] 因为
u
、
v
⊥
\mathbf u 、\mathbf v_{\bot}
u、v⊥?垂直所以有
v
?
u
=
0
\mathbf v \cdot \mathbf u=0
v?u=0 因此我们可以继续推导
v
⊥
′
=
c
o
s
(
θ
)
v
⊥
+
s
i
n
(
θ
)
(
u
v
⊥
)
=
(
c
o
s
(
θ
)
+
s
i
n
(
θ
)
u
)
v
⊥
v_{\bot}^{'}=cos(\theta) v_{\bot}+sin(\theta)(uv_{\bot})\\=(cos(\theta)+sin(\theta)u)v_{\bot}
v⊥′?=cos(θ)v⊥?+sin(θ)(uv⊥?)=(cos(θ)+sin(θ)u)v⊥? 这里我们的
q
=
(
c
o
s
(
θ
)
+
s
i
n
(
θ
)
u
)
q=(cos(\theta)+sin(\theta)u)
q=(cos(θ)+sin(θ)u)就是用来旋转的四元数,但是只是对垂直与旋转轴的向量是这样的。
q
=
c
o
s
(
θ
)
+
s
i
n
(
θ
)
u
x
i
+
s
i
n
(
θ
)
u
y
j
+
s
i
n
(
θ
)
u
z
k
=
[
c
o
s
(
θ
)
,
s
i
n
(
θ
)
u
]
q=cos(\theta)+sin(\theta)u_xi+sin(\theta)u_yj+sin(\theta)u_zk=[cos(\theta),sin(\theta)\mathbf u]
q=cos(θ)+sin(θ)ux?i+sin(θ)uy?j+sin(θ)uz?k=[cos(θ),sin(θ)u]
接下来我们要旋转
v
\mathbf v
v这个向量 继续推导有:
v
′
=
v
/
/
′
+
v
⊥
′
=
v
/
/
+
q
v
⊥
v'=v_{//}^{'}+v_{\bot}^{'}=v_{//}+qv_{\bot}
v′=v//′?+v⊥′?=v//?+qv⊥? 我们有:
q
=
[
c
o
s
(
θ
)
,
s
i
n
(
θ
)
u
]
q=[cos(\theta),sin(\theta)\mathbf u]
q=[cos(θ),sin(θ)u] 则可以证明
q
2
=
[
c
o
s
(
2
θ
)
,
s
i
n
(
2
θ
)
u
]
q^2=[cos(2\theta),sin(2\theta)\mathbf u]
q2=[cos(2θ),sin(2θ)u] 此处省略证明,其几何意义就是绕一个轴旋转两次
θ
\theta
θ与绕一个轴旋转一次
2
θ
2\theta
2θ相同。 令
p
2
=
q
p^2=q
p2=q 则有
v
′
=
v
/
/
+
q
v
⊥
=
p
p
?
1
v
/
/
+
p
p
v
⊥
=
p
p
?
v
/
/
+
p
p
v
⊥
v'=v_{//}+qv_{\bot}\\=pp^{-1}v_{//}+ppv_{\bot}\\=pp^{*}v_{//}+ppv_{\bot}
v′=v//?+qv⊥?=pp?1v//?+ppv⊥?=pp?v//?+ppv⊥? 这里需要证明
p
?
v
/
/
=
v
/
/
p
?
p^{*}v_{//}=v_{//}p^{*}
p?v//?=v//?p?与
p
v
⊥
=
v
⊥
p
?
pv_{\bot}=v_{\bot}p^{*}
pv⊥?=v⊥?p? 这里省略证明。 则有
v
′
=
v
/
/
+
q
v
⊥
=
p
v
/
/
p
?
+
p
v
⊥
p
?
=
p
(
v
/
/
+
v
⊥
)
p
?
=
p
v
p
?
v'=v_{//}+qv_{\bot}\\=pv_{//}p^{*}+pv_{\bot}p^{*}\\=p(v_{//}+v_{\bot})p^{*}\\=pvp^{*}
v′=v//?+qv⊥?=pv//?p?+pv⊥?p?=p(v//?+v⊥?)p?=pvp? 其中的
p
=
[
c
o
s
(
θ
/
2
)
,
s
i
n
(
θ
/
2
)
u
]
p=[cos(\theta/2),sin(\theta/2)\mathbf u]
p=[cos(θ/2),sin(θ/2)u] 可以让一个向量绕一个轴转
θ
\theta
θ角度。
Unity验证
新建一个立方体,我们通过Unity带的欧拉角转四元数的方式来进行验证,涉及欧拉角的知识请搜索其他文章。 我们可以看到这里的初始立方体的旋转为(0,0,0) 这里通过控制台显示一下绕z轴旋转30度所需要的四元数 根据上述讲解需要的四元数应该是
q
=
[
c
o
s
(
15
°
)
,
s
i
n
(
15
°
)
(
0
,
0
,
1
)
]
q=[cos(15°),sin(15°)(0,0,1)]
q=[cos(15°),sin(15°)(0,0,1)] 因此我们的
q
=
[
0.966
,
0
,
0
,
0.259
]
q=[0.966,0,0,0.259]
q=[0.966,0,0,0.259] 其中Unity中的顺序和之前我们推导的顺序不一致,最后一位才是我们的实数,经过验证是正确的。 将这个四元数施加到我们的物体上我们可以看到: 旋转符合推导,验证成功。
|