Quaternion

Quaternion


Introduction

Quaternion 中文稱作四元數,是一種用來表示角度與用來旋轉的代數系統

我們一般認識的座標系統為 Euler 角,假設在三維空間下就是 (x, y, z) 表示對三個座標軸旋轉多少角度

這個表示法不好嗎?

由於我們的旋轉是動態的,因此在某些情況下會造成 Gimbal lock,簡單來說 Gimbal lock 就是歐拉角在旋轉到某些位置時會造成某一軸的遺失,無法再進行那軸旋轉的問題。而此問題是無法解決的,因此才會設計出 Quaternion 的代數系統。


Description

Quaternion 是由 a + bi + cj + dk 所組成,其中 a, b, c, d 為實數 i, j, k 為虛數且

  • i2 = j2 = k2 = ijk = -1

很神奇吧 我也不知道為什麼呢 不過他就是這樣 所以接受吧 XD
另外還有

  • ij = k, jk = i, ki = j
  • ji = -k, kj= -i, ik = -j
  • ii = jj = kk = -1

Operation

Q0 = w0 + ix0 + jy0 + kz0
Q1 = w1 + ix1 + jy1 + kz1

Addition

Q0 + Q1 = (w0 + w1) + i(x0 + x1) + j(y0 + y1) + k(z0 + z1)

Q0 + Q1 = Q1 + Q0

Multiplication

Q0 * Q1 = (w0 + ix0 + jy0 + kz0)(w1 + ix1 + jy1 + kz1)

= (w0w1 - x0x1 - y0y1 - z0z1)

+ i(w0x1 + x0w1 + y0z1 - z0y1)

+ j(w0y1 + y0w1 - x0z1 + z0x1)

+ k(w0z1 + z0w1 - y0x1 + x0y1)

Q0 * Q1 != Q1 * Q0

Conjugate

Q0* = (w0 - ix0 - jy0 - kz0)

Norm

||Q|| = N(Q) = sqrt(w2 + x2 + y2 + z2)

Inner Product

<q0, q1> = w0w1 + x0x1 + y0y1 + z0z1


Vector vs Quaternion

接下來就是要將我們平常用的三維 vector 轉成 quaternion
而他們的關係為 vector 屬於 quaternion 的 subspace
如果我們有一個向量 v 要轉成 quaternion 要記成 v = (0, v) ,其中 0 為實部
然後再運用 quaternion 的運算

如果要旋轉的話則使用

q = (cos(Θ/2), sin(Θ/2)u)
v’ = qvq*


Reference


Extra Problem

如果你看完 Quaternion 還是用歐拉角寫 code 再往下看 XD



這個額外的問題是關於歐拉角旋轉的時候由於軸是有順序性的,所以會被旋轉的順序互相影響,因此在 coding 時會因為旋轉軸順序不同造成不當的亂轉(如果你實作的方法是只記錄旋轉角度然後在每一個 frame 都重新由原位開始轉的話)

歐拉角是有順序性的,想想如果我們只記錄角度且在每一個 frame 重新旋轉會有甚麼問題?

一般來說,我們每次做旋轉的時候應該是以當前姿態去做旋轉但如果只記錄角度而每一個 frame 重新轉會變成初始的姿態做旋轉

比方說我們有架飛機,我們請他 x 軸旋轉 30° y軸 旋轉 30° x軸再旋轉 30°
我們累積下來的角度為 x = 60° y = 30°
這時如果我們直接用這角度做出旋轉矩陣去旋轉是不會跟我們原本所期望的姿態 x 30°, y 30°, x 30°不一樣的!!

這就是因為歐拉角的順序性

Solution

這方法算是碰巧在亂試之下試對的,當時也不知道為什麼,現在才仔細地想清楚原因 XD

  • 每一個 frame 在旋轉的時候都將旋轉的角度累積到一個旋轉矩陣上,最後 model matrix 再乘以這個旋轉矩陣,取代每一個 frame 重新計算的旋轉矩陣

How it works?

由於我們是在每一個 frame 上累積旋轉的角度在我們的旋轉矩陣上,因次我們每次旋轉的角度都是代表著當前那個 frame 的姿態,因次我們是維持我們旋轉的順序將矩陣累積起來,最後再將 model matrix 乘上他,他就是依照我們的所旋轉的順序做旋轉了!!