四元数(Quaternion)和欧拉角(Eulerangle)
歐拉旋轉、四元數、矩陣旋轉之間的差異
除了歐拉旋轉以外,還有兩種表示旋轉的方式:矩陣旋轉和四元數旋轉。接下來我們比較它們的優缺點。
歐拉角
優點:三個角度組成,直觀,容易理解。
優點:可以進行從一個方向到另一個方向旋轉大于180度的角度。
弱點:死鎖問題。 前面《【Unity編程】歐拉角與萬向節死鎖(圖文版)》已經介紹過萬向節死鎖問題。
四元數
內部由四個數字(在Unity中稱為x,y,z和w)組成,然而這些數字不表示角度或軸,并且通常不需要直接訪問它們。除非你特別有興趣深入了解四元數學,你只需要知道四元數表示三維空間中的旋轉,你通常不需要知道或修改x,y和z屬性。
優點:四元旋轉不存在萬向節鎖問題。
優點:存儲空間小,計算效率高。
弱點:單個四元數不能表示在任何方向上超過180度的旋轉。
弱點:四元數的數字表示不直觀。
矩陣旋轉
優點:與四元數一樣,不存在萬向節鎖問題
優點:可以表示圍繞任意軸的旋轉,四元數的旋轉軸均為通過物體中心點的軸,矩陣則不受限
缺點:矩陣旋轉使用4x4矩陣,記錄16個數值,而四元數只需要4個數值。計算復雜,效率低。
四元數的數學
由于前面兩篇文章均盡可能采用無數字計算的方式,為的是方便理解。而這里由于需要理解四元數的計算,我們還是需要理解一些復數和歐拉旋轉計算方面的基本數學。
復數
首先了解一下復數,上圖中,左右方向的軸(X軸)稱為實數軸,上下的軸(Y軸)稱為虛數軸。
任意一個二維矢量,都可以使用一個復數形式進行表示。也就是:e = a + bi
其中a是實數,i是虛數,i * i=-1。
至于什么是虛數,我的理解它就是個不同維度的后綴標記和符號而已。i標記了實數軸和虛數軸之間的差異,也就是旋轉90度旋轉的差別,乘以i意味著這種旋轉關系。
為什么i * i=-1?也就是兩個虛數i乘積又變成了實數-1?因為從實數軸(1表示)圍繞上圖中逆時針90度(1*i)到達虛數軸(=i),再逆時針旋轉90(1 * i * i)就到達了負實數軸方向(=-1)。所以這里規定i * i=-1。
復數運算
加法: (a+bi)+(c+di)=(a+c)+(b+d)i
減法: (a+bi)-(c+di)=(a-c)+(b-d)i
乘法: (a+bi)(c+di)=ac+bci+adi+bdi^{2}=(ac-bd)+(bc+ad)i
更多復數相關知識,請參考“維基百科-復數_(數學)”
歐拉旋轉定理
為了方便討論旋轉,我們避開矢量長度的影響,也就是假設問題是基于長度為1的矢量去討論。由上圖可以看出,當長度為1時,矢量落在長度為1的圓形上,此時實數軸上的a = cos(φ),虛數軸上的b = sin(φ),其中φ為旋轉角度。
此時的表示形式為 e = cos(φ) + sin(φ)i
那么,使用這樣一種形式到底有什么意義呢?數學從來都是工具,如果沒有用處,它也就不會存在了。我們接下來看它的作用。
當圓上的一個矢量進行了連續的旋轉時時,假設先旋轉φ,再旋轉θ,則結果應該是兩個旋轉的角的和的復數形式,即 e = cos(φ+θ)+sin(φ+θ)i
假設:
e1= cos(φ) + sin(φ)i (表示旋轉了φ角度)
e2= cos(θ) + sin(θ)i (表示旋轉了θ角度)
那么e和e1、e2之間的關系是怎樣的?
根據和差公式可以得知
cos(φ+θ)+sin(φ+θ)i
= (cos(φ)cos(θ)-sin(φ)sin(θ))+(sin(θ)cos(φ)+cos(θ)sin(φ))i
= cos(φ)cos(θ)+cos(φ)sin(θ)i+cos(θ)sin(φ)i- sin(φ)sin(θ)
= (cos(φ) + sin(φ)i)*(cos(θ) + sin(θ)i)
= e1 * e2
=>
e = e1*e2
也就是說,連續的旋轉(例如這里旋轉φ再旋轉θ),可以使用兩個復數的乘積進行表示。在計算機運算中:
如果知道φ=30度,那么計算此單位矢量再旋轉θ=40度是很容易的,只需要直接運算cos(φ+θ)和sin(φ+θ)即可。
如果知道一個矢量(a+bi),不知其φ值,要對其進行旋轉θ=40度,那么也就有了快速的計算方法,即:
(a+bi) * (cos(40)+sin(40)i) = (a * cos(40)-b * sin(40)) + (b * cos(40) + a * sin(40))i
結果:二維向量 x = a * cos(40)-b * sin(40),y= b * cos(40) + a * sin(40)
可以快速計算出二維矢量結果,而不必先求φ。
因此這就是復數和歐拉旋轉定理的作用,它可以使用復數很方便地表示出二維矢量的旋轉變化。
四元數
相對于復數為二維空間,為了解決三維空間的旋轉變化問題,愛爾蘭數學家威廉·盧云·哈密頓把復數進行了推廣,也就是四元數。
以下均為定義,所謂定義,就是我們人為設置的概念和計算方法,它們本身或許沒有什么意義,但是如果按照這些概念和方法計算出某些有意義的結果,那么這些定義也就有了相應的意義。
四元數定義
四元數定義i、j、k三個虛數單位參與運算,并有以下運算規則:
j?k=i,k?j=?i;
j?k=i,k?j=?i;
j?k=i,k?j=?i;
j?k=i,k?j=?i;
k?i=j,i?k=?j;
k?i=j,i?k=?j;
i?i=j?j=k?k=i?j?k=?1
i?i=j?j=k?k=i?j?k=?1
i、j、k仍然理解為旋轉,其中:
i旋轉代表X軸與Y軸相交平面中X軸正向向Y軸正向的旋轉
j旋轉代表Z軸與X軸相交平面中Z軸正向向X軸正向的旋轉
k旋轉代表Y軸與Z軸相交平面中Y軸正向向Z軸正向的旋轉
-i、-j、-k分別代表i、j、k旋轉的反向旋轉
一個普通四元數可以寫成如下形式:
qˉˉ=a+bi+cj+dk
qˉ=a+bi+cj+dk
四元數的i、j、k之間乘法的性質與向量之間的叉積結果形式很類似,于是四元數有了另外一種表示形式:
qˉˉ=((x,y,z)→,w)=(u? ,w)
qˉ=((x,y,z)→,w)=(u→,w)
加法定義
四元數加法,跟復數、矢量和矩陣一樣,兩個四元數之和需要將不同的元素加起來,加法遵循實數和復數的所有交換律和結合律:
qˉˉ1+qˉˉ2=w1+w2+u1→+u2→=(w1+w2)+(x1+x2)i+(y1+y2)j+(z1+z2)k
qˉ1+qˉ2=w1+w2+u1→+u2→=(w1+w2)+(x1+x2)i+(y1+y2)j+(z1+z2)k
格拉斯曼積定義
四元數的乘法有很多種,最常見的一種定義,與數學多項式乘法相同,稱為格拉斯曼積。(注意,下面乘積的式子是由多項式形如a+bi+cj+dk的多項式進行多對多乘法(比如4項x4項=16項)計算后,使用矢量的點積和叉積替代部分計算項后形成):
qˉˉ1qˉˉ2=w1w2?u1→?u2→+w1u2→+w2u1→+u1→×u2→
qˉ1qˉ2=w1w2?u1→?u2→+w1u2→+w2u1→+u1→×u2→
把向量部分和實數部分分開,可以寫成:
qˉˉ1qˉˉ2=((w1u2→+w2u1→+u1→×u2→),(w1w2?u1→?u2→))
qˉ1qˉ2=((w1u2→+w2u1→+u1→×u2→),(w1w2?u1→?u2→))
注意,格拉斯曼積符合結合率,也就是 qˉˉ1qˉˉ2qˉˉ3=(qˉˉ1qˉˉ2)qˉˉ3=qˉˉ1(qˉˉ2qˉˉ3)qˉ1qˉ2qˉ3=(qˉ1qˉ2)qˉ3=qˉ1(qˉ2qˉ3),但不符合交換律,一般來說, qˉˉ1qˉˉ2≠qˉˉ2qˉˉ1qˉ1qˉ2≠qˉ2qˉ1。
點積定義
點積也叫做歐幾里得內積,四元數的點積等同于一個四維矢量的點積。點積的值是 qˉˉ1qˉ1中每個元素的數值與 qˉˉ2qˉ2 中相應元素的數值的一對一乘積(比如4項x4項=4項)的和。這是四元數之間的可換積,并返回一個標量。
qˉˉ1?qˉˉ2=w1w2+u1→?u2→=w1w2+x1x2+y1y2+z1z2
qˉ1?qˉ2=w1w2+u1→?u2→=w1w2+x1x2+y1y2+z1z2
叉積定義
四元數叉積:p × q
四元數叉積也稱為奇積。它和矢量叉積等價,并且只返回一個矢量值:
pˉˉˉ×qˉˉ=pˉˉˉqˉˉ?qˉˉpˉˉˉ2
pˉ×qˉ=pˉqˉ?qˉpˉ2
pˉˉˉ×qˉˉ=u? ×v?
pˉ×qˉ=u→×v→
pˉˉˉ×qˉˉ=(cz?dy)i+(dx?bz)j+(by?xc)k
pˉ×qˉ=(cz?dy)i+(dx?bz)j+(by?xc)k
共軛定義
四元數的共軛的定義。即實部相同,虛部相反。(與復數概念類似)
qˉˉ?=((?x,?y,?z)→,w)=(?v? ,w)
qˉ?=((?x,?y,?z)→,w)=(?v→,w)
定義的推論
從以上三個定義,可以得出一個推論,一個四元數與其共軛的格拉斯曼積等于此四元數與其自身的點積:
qˉˉqˉˉ?=qˉˉ?qˉˉ=qˉˉ?qˉˉ=x2+y2+z2+w2
qˉqˉ?=qˉ?qˉ=qˉ?qˉ=x2+y2+z2+w2
證明: 由格拉絲曼積定義可知
qˉˉ1qˉˉ2=w1w2?u1→?u2→+w1u2→+w2u1→+u1→×u2→
qˉ1qˉ2=w1w2?u1→?u2→+w1u2→+w2u1→+u1→×u2→
而此時,
qˉˉ1=qˉˉ,qˉˉ2=qˉˉ?
qˉ1=qˉ,qˉ2=qˉ?
也就是,
u1→=u? ,u2→=?u? ,w2=w1=w
u1→=u→,u2→=?u→,w2=w1=w
代入
qˉˉ1qˉˉ2=w1w2?u1→?u2→+w1u2→+w2u1→+u1→×u2→
qˉ1qˉ2=w1w2?u1→?u2→+w1u2→+w2u1→+u1→×u2→
得到
qˉˉqˉˉ?=ww+u? ?u? ?wu? +wu? +u? ×u?
qˉqˉ?=ww+u→?u→?wu→+wu→+u→×u→
由于第三四項可以消去,第五項本身為0向量,所以得出
qˉˉqˉˉ?=ww+u? ?u? =qˉˉ?qˉˉ
qˉqˉ?=ww+u→?u→=qˉ?qˉ
于是得證, qˉˉ?qˉˉqˉ?qˉ也可以同理得證,結果是與之相同的。
模的定義
四元數的模的定義。與矢量的模類似,都表示長度或者絕對值的意思。四元數的絕對值是四元數到原點的距離。
|qˉˉ|=x2+y2+z2+w2??????????????√=w2+u? ?u? ????????√=qˉˉ?qˉˉ????√=qˉˉqˉˉ????√
|qˉ|=x2+y2+z2+w2=w2+u→?u→=qˉ?qˉ=qˉqˉ?
逆的定義
四元數的逆通過 qˉˉ?1qˉˉ=1qˉ?1qˉ=1來定義。在此式左右兩端同時乘以 qˉˉ?qˉ?,可以得到:
qˉˉ?1qˉˉqˉˉ?=qˉˉ?
qˉ?1qˉqˉ?=qˉ?
由于格拉絲曼積符合結合率,左式后兩項先乘,得到:
qˉˉ?1(qˉˉqˉˉ?)=qˉˉ?
qˉ?1(qˉqˉ?)=qˉ?
再由上述的推論,可以得出:
qˉˉ?1(qˉˉ?qˉˉ)=qˉˉ?
qˉ?1(qˉ?qˉ)=qˉ?
由于點積是個實數,可以使用除法,所以最后簡化成:
qˉˉ?1=qˉˉ?qˉˉ?qˉˉ
qˉ?1=qˉ?qˉ?qˉ
單位四元數的定義
所謂的單位量,都是指,任意原始量乘以單位量之后保持原始量不變。如對于實數而言,任意原始實數乘以實數1等于原始實數,因此1被定義為單位。
對于四元數同樣,任意原始四元數 qˉˉqˉ乘以某個四元數 qˉˉiqˉi,原始的四元數 qˉˉqˉ保持不變,則稱此四元數 qˉˉiqˉi為單位四元數。注意這里的乘以是指格拉絲曼積。根據格拉絲曼積的定義:
qˉˉqˉˉi=((wui→+wiu? +u? ×ui→),(wwi?u? ?ui→))
qˉqˉi=((wui→+wiu→+u→×ui→),(wwi?u→?ui→))
若希望結果保持不變,也就是結果仍然為:
qˉˉqˉˉi=qˉˉ=(w,u? )
qˉqˉi=qˉ=(w,u→)
可以推測
wi=1,u? i=0
wi=1,u→i=0
也就是,單位四元數為:
qˉˉi=(0? ,1)
qˉi=(0→,1)
四元數的歸一化
歸一化也叫單位化,與矢量的概念一樣,就是為了把長度調整到單位長度。現在單位四元數已經得知,其單位長度顯然是1。我們也知道了模的計算方法,因此把四元數的歸一化方法如下:
qˉˉ,=qˉˉ|qˉˉ|=qˉˉw2+u? ?u? ????????√
qˉ,=qˉ|qˉ|=qˉw2+u→?u→
前述的單位復數表示形式為:e = cos(φ)+ sin(φ)i,因為此時,復數的長度為 cos(φ)2+sin(φ)2=1cos(φ)2+sin(φ)2=1,我們使用類似形式表示歸一化的四元數:
qˉˉ=(s? in(φ)n? ,cos(φ))
qˉ=(s→in(φ)n→,cos(φ))
也就是實部現在使用 cos(φ)cos(φ)表示,虛部使用 sin(φ)n? sin(φ)n→表示,其中 n? n→是歸一化的三維矢量,由于 a? ?b? =|a? ||b? |cos(θab)a→?b→=|a→||b→|cos(θab),因此有 n? ?n? =1n→?n→=1。讓我們嘗試計算此時的模:
|qˉˉ|=w2+u? ?u? ????????√=cos(φ)2+sin(φ)2(n? ?n? )???????????????????√=1
|qˉ|=w2+u→?u→=cos(φ)2+sin(φ)2(n→?n→)=1
四元數映射_實數
我們可以將實數映射到四元數空間,所謂的映射,也就是說1對1的找到相應的存在,并且在不同空間施加施加相對應運算的法則時獲得相同的結果。
例如,對應實數w,嘗試進行如下映射:
qˉˉ=(0? ,w)
qˉ=(0→,w)
那么是否能夠遵守相應的運算法則?也就是說,如果實數 wawa與實數 wbwb均被映射到了四元數空間,那么它們的加法和乘法的結果是否還能映射回去,與原始空間的運算獲得相同的結果?加法顯然可以,這里進行乘法計算測試:
qˉˉa=(0? ,wa)
qˉa=(0→,wa)
qˉˉb=(0? ,wb)
qˉb=(0→,wb)
qˉˉaqˉˉb=(0? ,wa)(0? ,wb)=wawb?0? ?0? +wa0? +wb0? +0? ×0?
qˉaqˉb=(0→,wa)(0→,wb)=wawb?0→?0→+wa0→+wb0→+0→×0→
=>
qˉˉaqˉˉb=wawb+0? =(0? ,wawb)
qˉaqˉb=wawb+0→=(0→,wawb)
顯然,依照映射原則,可以將 (0? ,wawb)(0→,wawb)映射回去變成 wawa wbwb,與實數空間的計算結果相同。因此,此映射法則是可行的:
qˉˉ=(0? ,w)
qˉ=(0→,w)
四元數映射_矢量直接映射
與實數映射類似,我們也可以嘗試將三維矢量映射到四元數。
對于矢量 v? v→映射法則如下:
qˉˉ=(v? ,0)
qˉ=(v→,0)
同樣,加法運算顯然可以映射回去,我們來計算乘法運算。
qˉˉa=(v? a,0)
qˉa=(v→a,0)
qˉˉb=(v? b,0)
qˉb=(v→b,0)
qˉˉaqˉˉb=(v? a,0)(v? b,0)=00?va→?vb→+0vb→+0va→+va→×vb→
qˉaqˉb=(v→a,0)(v→b,0)=00?va→?vb→+0vb→+0va→+va→×vb→
=>
qˉˉaqˉˉb=(va→×vb→,?v? a?v? b)
qˉaqˉb=(va→×vb→,?v→a?v→b)
可以看到,此時出現了之前兩個四元數中均不存在的實部。因此這個映射法則是錯誤的。(本身兩個向量之間如果直接使用多對多的格拉斯曼積式乘法也是沒有意義的,所以結果可想而知。那么,是不是就不能映射矢量了?不是,只是映射法則錯誤。回想之前在在復數中也曾使用過格拉斯曼積式的乘法 如果矢量用 e=cos(φ)+sin(φ)ie=cos(φ)+sin(φ)i表示,那么此時的 ee表示了一個二維旋轉,向量的旋轉可以使用格拉斯曼積形式的復數乘法e1?e2e1?e2表示,因此,映射法則應該與角度相關。)
四元數映射_矢量間接映射
同態
先考慮一個同態概念:假設M,M′是兩個乘集,也就是說M和M′是兩個各具有一個封閉的具有結合律的運算與的代數系統。φ是M射到M′的映射,并且任意兩個元的乘積的像是這兩個元的像的乘積,即對于M中任意兩個元a,b,滿足
φ(a*b)=φ(a)φ(b);
也就是說,當a→φ(a),b→φ(b)時,ab→φ(a)*φ(b),
那么這映射φ就叫做M到M′上的同態。我前面所解釋的可以互相映射大致意思也就是同態。
四元數中的同態函數
為什么我們研究同態?因為這里涉及到我們希望出現的向量的旋轉,一個三維空間的向量被旋轉之后,它應該還是一個三維矢量。這個旋轉函數應該滿足以下要求:
①、旋轉完的矢量長度應該保持不變。也就是
|φ(A)|=|A|
|φ(A)|=|A|
②、假如對向量A和B都執行φ旋轉,那么向量A、B的夾角θ應該與φ(A)、φ(B)的夾角應該相同。由矢量點積我們知道 A?B=|A||B|cos(θ)A?B=|A||B|cos(θ),在滿足①的情況下,也就是模的乘積已經不變,那么如果點積結果相同,也就能保證角度不變,也就是:
φ(A)?φ(B)=A?B
φ(A)?φ(B)=A?B
③、假如對向量A和B都執行φ旋轉,那么旋轉完畢的φ(A)、φ(B)的相對方向關系與A、B應該保持一致,也就是所謂的手向性應該保持一致(比如原來A的正左側恰好B,旋轉完畢應該還是在正左側,僅有夾角是不夠的,正右側也是90度關系)。假如滿足下面的式子,則手向性不變
φ(A)×φ(B)=A×B
φ(A)×φ(B)=A×B
接著,我們詳細了解間接映射的步驟。如下圖所示:
我們通過間接映射將矢量V映射到四元數,先如直接映射那樣,映射成一個純虛四元數,即 (V? ,0)(V→,0),再執行φ()變換。簡寫為
φ(V)
φ(V)
由于
AB=wawb?ua?ub+wa?ub+wb?ua+ua×ub
AB=wawb?ua?ub+wa?ub+wb?ua+ua×ub
此時的 A、BA、B均是純虛四元數,因此 wa=wb=0wa=wb=0,可以簡化為
AB=?ua?ub+ua×ub
AB=?ua?ub+ua×ub
由于 A、BA、B均是純虛四元數,因此 A?B=ua?ubA?B=ua?ub,再由于四元數叉積和矢量叉積等價,因此上式可以轉化為
AB=?A?B+A×B
AB=?A?B+A×B
如果存在這樣的同態函數函數:
φ(A)φ(B)=φ(AB)
φ(A)φ(B)=φ(AB)
也就能滿足②、③的要求。
[此處還可以解釋得更明確,不過太過復雜了]
旋轉四元數
最后,給出旋轉四元數,也就是一直在追求的φ()函數。
qˉˉ=(s? in(θ2)n? ,cos(θ2))
qˉ=(s→in(θ2)n→,cos(θ2))
它的含義是圍繞 n? n→軸旋轉 θθ角度。 具體旋轉的方法使用以下函數:
pˉˉˉ,=qˉˉpˉˉˉqˉˉ?
pˉ,=qˉpˉqˉ?
其中 pˉˉˉpˉ是被旋轉四元數, pˉˉˉ,pˉ,是結果四元數。這里的 qˉˉ?qˉ?寫成 qˉˉ?1qˉ?1也是可以的,因為根據前述對逆的計算,對于此時模為1的 qˉˉqˉ來說,它們結果相同的。 具體推究方法以及證明方法過于復雜,就不在這里給出了。
總結
四元數是高階復數的數學,它用在游戲中的作用主要是計算三維矢量的旋轉,它使用先將矢量映射到純虛四元數,再應用形如 pˉˉˉ,=qˉˉpˉˉˉqˉˉ?,qˉˉ=(s? in(θ2)n? ,cos(θ2))pˉ,=qˉpˉqˉ?,qˉ=(s→in(θ2)n→,cos(θ2))的旋轉函數。最后可以達成旋轉目的。
前面的四元數性質不甚了解也沒有太大關系,大概了解到是如何映射的也就可以了。甚至在Unity編程過程中你對四元數的映射關系不了解都無所謂。后續文章中我再介紹具體的用法。
總結
以上是生活随笔為你收集整理的四元数(Quaternion)和欧拉角(Eulerangle)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 移动平台商家支付宝如何获取商户私钥,支付
- 下一篇: Python中使用pip安装库时提示:远