理解四元數


 

Understanding Quaternions

 轉載自:http://www.qiujiawei.com/understanding-quaternions/

正文

 

在這篇文章中我會嘗試用簡單的方式去解釋四元數的概念,即用可視化的方式解釋四元數以及幾種對四元數的操作。我將把矩陣、歐拉角和四元數放在一起比較,並解釋什么時候該用四元數、什么時候該用歐拉角或矩陣。

 

 

 

介紹

在計算機圖形學中,我們使用轉換矩陣來表示空間中的一個位置以及朝向。一個轉換矩陣還可以表示對一個目標的縮放(scale)或錯切(shear)等。 我們可以把轉換矩陣想象成一個空間,當你用這個矩陣乘以向量、點(甚至矩陣)后, 你就把向量、點、矩陣轉換進這個空間了。

在這篇文章中,我不會討論轉換矩陣的細節。你可以查看我前面的文章,文章中描述了轉換矩陣的細節。

在這篇文章中,我想要討論一個可替代的方案,即用四元數來描述空間里的物體的朝向。

四元數的概念是由愛爾蘭數學家Sir William Rowan Hamilton發明的(1843年,都柏林)。Hamilton當時正和他的妻子前往愛爾蘭皇家研究院,當他從Brougham橋通過皇家運河時,他領悟到了一個激動人心的東西,並立刻把它刻在橋的一個石頭上:

2.jpg

William Rowan Hamilton Plaque on Broome Bridge on the Royal Canal commemorating his discovery of the fundamental formula for quaternion multiplication.

復數

在我們能夠完全理解四元數之前,我們必須先知道四元數是怎么來的。四元數的根源其實是復數

除了知名的數集(自然數、整數、實數、分數)之外,復數系統引入了一個新的數集——虛數。虛數的發明是為了解決一些特定的無解的方程,例如:

要解決這個等式,必須讓 這當然是不行的,因為任意實數的平方都是非負數。

 

一般而言,數學家是不能忍受一個等式是無解的。於是,一個新的術語被發明了,它就是虛數,一個可以解決上面這個等式的數。

虛數有這樣的形式:

不要為這個術語較真,因為邏輯上這個數是不存在的。只要知道i是一個平方等於-1的東西即可。

虛數的集合可以用來表示

復數的集合是一個實數和一個虛數的和,形式如下:

 

可以認為所有實數都是b=0的復數、所有虛數都是a=0的復數。

復數的加減

加法:

 

減法:

 

復數的系數縮放

 

復數的積

 

復數的平方

 

共軛復數

復數的共軛就是指把復數的虛數部分變成負的。共軛復數的符號是

 

復數和它的共軛復數的乘積是:

 

復數的絕對值

我們使用共軛復數來計算復數的絕對值:

 

兩復數的商

 

i的冪

如果的平方等於-1,那么的n次冪也應該存在:

 

如果按照這個順序寫下去,會出現這樣一個模式: (1,\mathbf i,-1,-\mathbf i,1,...)

一個類似的模式也出現在遞增的負數冪:

i

 

你可能已經在數學里頭見過類似的模式,但是是以(x,y,-x,-y,x,...)的形式,這是在2D笛卡爾平面對一個點逆時針旋轉90度時生成的;(x,-y,-x,y,x,...)則是在2D笛卡爾平面對一個點順時針旋轉90度時生成的。

3.png

復數平面

我們也能夠把復數映射到一個2D網格平面——復數平面,只需要把實數映射到橫軸、虛數映射到縱軸。

4.png

如前面的序列所示,我們可以認為,對一個復數乘以i,這個復數就在復數平面上旋轉了90度。

讓我們看看這是不是真的。我們隨機地在復數平面上取一個點:

 

 

t剛好是開始的p。如果我們把這些復數放到復數平面上,就得到下面的圖:

5.png

我們也可以按順時針方向旋轉,只需要把上面的乘數i改成-i。

 

旋轉數(Rotors)

我們也可以在復數平面上進行任意角度的旋轉,只需要定義下面這個復數:

 

這也是一個在復數平面繞原點逆時針旋轉任意點的方法。(譯注:這句話應該是在說旋轉矩陣)

 

四元數

補充:

6.png(\mathbf i \mathbf j, \mathbf j \mathbf k, \mathbf k \mathbf i這幾個性質的可視化)

上圖展示了如何用i、j、k作為笛卡爾坐標系的單位向量。

 

四元數的加減

 

四元數的積

 

再把這個表達式擴展成多個有序對的和:

 

如果把后3個四元數相加,並提取公共部分,就可以把等式改寫成:

 

這個等式是2個有序對的和。第1個有序對是一個四元數,第2個是一個四元數。這兩個四元數也可以合並成一個:

 

如果把下面的表達式代入上面的等式:

 

(譯注:注意,第三條和第四條並不是四元數的點積和叉積,而是向量的點積和叉積)

我們就得到了:

 

這就是四元數乘積的一般式。

實四元數

 

四元數的系數縮放

 

純四元數

 

四元數的加法形式

我們可以把四元數寫成實四元數和純四元數的和:

 

單位四元數

給定任意的向量v,我們可以把這個向量寫成一個系數和一個單位方向向量的乘積:

 

將這個定義和純四元數的定義結合,就得到了:

 

四元數的二元形式

我們現在可以把單位四元數的定義和四元數的加法形式結合到一起,就創造了一種新的四元數的表示法,這種表示法和復數的表示法形似:

 

這就給了我們一種和復數非常相似的四元數表示法:

 

共軛四元數

 

四元數范數

 

四元數規范化

 

四元數的逆

 

四元數的點積

和向量的點積相似,我們也可以計算2個四元數的點積,只需要將各個對應的系數相乘,然后相加:

 

旋轉

前面我們定義了一個特殊的復數:旋轉數。它是用來旋轉2D復數平面的點的:

 

根據四元數和復數的相似性,應該有可能設計一個可以旋轉3D空間的點的四元數:

 

讓我們測試一下這個理論是否可靠,方法就是計算四元數q和向量p的積。第一步,我們把p寫成純四元數的形式:

 

以及單位四元數q:

 

我們可以看到結果是一個同時有系數、有虛向量的四元數。

 

好了,現在計算下qp:

 

這正是我們所期望的!

我們可以用圖像展示旋轉過程:

7.png

現在,讓我們考慮更一般化的四元數,即和p不正交的四元數。現在讓我們把p的向量部分偏移45度:

 

 

我們可以用圖像展示旋轉過程:

8.png

 

然而,還有一線生機。Hamilton發現(但沒有正式宣布),如果對qp右乘q的逆,出來的結果是一個純四元數,並且四元數向量部分的范數可以保持不變。讓我們試試應用在我們的例子里。

 

現在,把前面算出來的qp再次拿出來:

 

下面的圖像展示了旋轉結果:

9.png

所以我們可以看到,這個結果是一個純四元數,並且原四元數的向量的范數也保持住了。但是還有一個問題:向量被旋轉了90度而不是45度。這剛好是我們需要的度數的兩倍!為了正確地讓一個向量繞某個軸向量旋轉某個角度,我們必須以目標角度的一半來計算。因此,我們構造了下面的四元數:

 

這就是旋轉四元數的一般形式!

四元數插值

在計算機圖形學中使用四元數,其中一個重要原因是四元數非常適合用來表示空間中的旋轉。四元數解決了其他3維空間旋轉算法會遇到的惱人的問題,比如使用歐拉角來表示旋轉操作時會遇到的萬向節鎖問題(Gimbal lock)。

使用四元數,我們可以定義好幾種方案來表示3維空間的轉動插值。第一種是SLERP,它被用來把一個點(物體)從一個朝向平滑地插值到另一個朝向。第二個是SLERP的擴展版本,被稱為SQAD,它被用來處理用一系列朝向定義得到的一條路徑的插值。

SLERP

 

四元數的差

 

四元數的冪運算

接下來的目標是干掉上面四元數的差的分數部分,方法是計算四元數的t次冪(就是上面的那個插值參數t,區間是[0,1])。

四元數的冪運算的一般化公式是:

 

(譯注:上述的2次公式推導,其實省略了很多證明過程。具體可以參考:http://bpeers.com/blog/?itemid=861,http://bpeers.com/blog/?itemid=863,http://bpeers.com/blog/?itemid=866http://bpeers.com/blog/?itemid=1001 )

對於t = 0,我們有:

 

而對於t = 1,有:

 

2個四元數的分數差

對於角旋轉的插值計算,我們利用q1和q2的角度分數差來調整原始朝向q1:

 

這也就是使用四元數的球面線性插值的一般形式。然而,這不是slerp函數的常用形式。

我們可以應用類似的用於計算向量的球面插值公式,到四元數里。計算向量的球面插值的一般形式定義如下:

 

用圖像表示如下:

10.png

這個公式可以原封不動地應用到四元數:

 

注意事項

這個方案有2個問題,必須在實現過程中加以考慮。

第一,如果四元數點積的結果是負值,那么后面的插值就會在4D球面上繞遠路,這並不是我們想要的。為了解決這個問題,我們測試點積的結果,當結果是負值時,我們將2個四元數的其中一個取反,取反它的系數和向量部分,並不會改變它代表的朝向。而經過這一步操作,可以保證這個旋轉走的是最短路徑。

q1q1和q2q2的角度差非常小,小到導致sinθ=0sinθ=0 時,會出現第二個問題。如果這個情況出現了,當我們除以sinθsinθ時就會得到一個未定義的結果。在這個情況下,我們可以回退去使用q1q1和q2q2的線性插值。

SQUAD

 

總結

除了特別難理解之外,相比矩陣或歐拉角,四元數在表示旋轉這個事情上,擁有一些明顯的優點。

  • SLERP和SQUAD,提供了一種使得在朝向之間可以平滑過渡的方法。

  • 使用四元數來串聯"旋轉",要比使用矩陣快得多。

  • 對於單位四元數,逆向旋轉可以通過對向量部分取反來實現。而計算一個矩陣的逆矩陣是被認為比較慢的,如果這個矩陣未被標准正交化的話(標准正交矩陣的逆矩陣是它的轉置矩陣)。

  • 從四元數轉換到矩陣,要比從歐拉角轉換到矩陣快一點。

  • 四元數只需要4個數字(如果旋轉四元數已經單位化了那么只需要3個,實數部分可以在運行時計算)來表示一個旋轉,而矩陣需要至少9個數字。

盡管使用四元數有這么多優點,還是有缺點存在的。

  • 因為浮點數的舍入運算錯誤,四元數可能會變無效。不過,這個錯誤可以通過重新單位化四元數來避免。

  • 使用四元數最具威懾性的地方,還是四元數的理解難度大。我希望這個問題可以通過閱讀本文來解決。

存在一些已經實現了四元數、並且是正確的的數學程序庫。在我的個人經驗里,我發現GLM(OpenGL Math Library)是一個優秀的數學庫,它的四元數的實現極其不錯。如果你對在你的程序中使用四元數感興趣,那么我會推薦你使用這個數學庫。

下載Demo

我實現了一個小demo來演示一個四元數如何被用來旋轉一個3維物體。這個demo是用Unity3.5.2實現的,你可以免費下載它和閱讀它的腳本。zip文件也包含了一個Windows版的Unity程序。當然你可以自己構建一個Mac的版本。

Understanding Quaternions.zip

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM