四元數和旋轉矩陣

2021-07-01 21:00:01 字數 3615 閱讀 5654

quaternion(四元數)

quaternion 的定義

四元數一般定義如下:

q=w+xi+yj+zk

其中 w,x,y,z是實數。同時,有:

i*i=-1

j*j=-1

k*k=-1

四元數也可以表示為:

q=[w,v]

其中v=(x,y,z)是向量,w是標量,雖然v是向量,但不能簡單的理解為3d空間的向量,它是4維空間中的的向量,也是非常不容易想像的。

通俗的講,乙個四元數(quaternion)描述了乙個旋轉軸和乙個旋轉角度。這個旋轉軸和這個角度可以通過 quaternion::toangleaxis轉換得到。當然也可以隨意指定乙個角度乙個旋轉軸來構造乙個quaternion。這個角度是相對於單位四元數而言的,也可以說是相對於物體的初始方向而言的。

當用乙個四元數乘以乙個向量時,實際上就是讓該向量圍繞著這個四元數所描述的旋轉軸,轉動這個四元數所描述的角度而得到的向量。

四元組的優點

有多種方式可表示旋轉,如 axis/angle、尤拉角(euler angles)、矩陣(matrix)、四元組等。 相對於其它方法,四元組有其本身的優點:

四元數不會有尤拉角存在的 gimbal lock 問題

四元數由4個數組成,旋轉矩陣需要9個數

兩個四元數之間更容易插值

四元數、矩陣在多次運算後會積攢誤差,需要分別對其做規範化(normalize)和正交化(orthogonalize),對四元數規範化更容易

與旋轉矩陣類似,兩個四元組相乘可表示兩次旋轉

quaternion 的基本運算

normalizing a quaternion

// normalising a quaternion works similar to a vector. this method will not do anything

// if the quaternion is close enough to being unit-length. define tolerance as something

// small like 0.00001f to get accurate results

void quaternion::normalise()

}vector3 quaternion::operator* (const vector3 &vec) const

how to convert to/from quaternions1

quaternion from axis-angle

// convert from axis angle

void quaternion::fromaxis(const vector3 &v, float angle)

quaternion from euler angles

// convert from euler angles

void quaternion::fromeuler(float pitch, float yaw, float roll)

quaternion to matrix

// convert to matrix

matrix4 quaternion::getmatrix() const

quaternion to axis-angle

// convert to axis/angles

void quaternion::getaxisangle(vector3 *axis, float *angle)

quaternion 插值

線性插值

最簡單的插值演算法就是線性插值,公式如:

q(t)=(1-t)q1 + t q2

但這個結果是需要規格化的,否則q(t)的單位長度會發生變化,所以

q(t)=(1-t)q1+t q2 / || (1-t)q1+t q2 ||

球形線性插值

儘管線性插值很有效,但不能以恆定的速率描述q1到q2之間的曲線,這也是其弊端,我們需要找到一種插值方法使得q1->q(t)之間的夾角θ是線性的,即θ(t)=(1-t)θ1+t*θ2,這樣我們得到了球形線性插值函式q(t),如下:

q(t)=q1 * sinθ(1-t)/sinθ + q2 * sinθt/sineθ

如果使用d3d,可以直接使用 d3dxquaternionslerp 函式就可以完成這個插值過程。

用 quaternion 實現 camera 旋轉

總體來講,camera 的操作可分為如下幾類:

沿直線移動

圍繞某軸自轉

圍繞某軸公轉

下面是乙個使用了 quaternion 的 camera 類:

class camera ;

void camera::rotate(const quaternion& q)

void camera::rotate(const vector3& axis, const radian& angle)

void camera::roll (const glfloat angle) //in radian

void camera::yaw (const glfloat angle)  //in degree

rotate(yaxis, angleinradian);

}void camera::pitch (const glfloat angle)  //in radian

void camera::glulookat()

用 quaternion 實現 trackball

用滑鼠拖動物體在三維空間裡旋轉,一般設計乙個 trackball,其內部實現也常用四元數。

class trackball

;void trackball::move(const qpointf& p)

每乙個單位四元數都可以對應到乙個旋轉矩陣

單位四元數q=(s,v)的共軛為q*=(s,-v)

單位四元數的模為||q||=1;

四元數q=(s,v)的逆q^(-1)=q*/(||q||)=q*

乙個向量r,沿著向量n旋轉a角度之後的向量是哪個(假設為v),這個用四元數可以輕鬆搞定

構造兩個四元數q=(cos(a/2),sin(a/2)*n),p=(0,r)

p`=q * p * q^(-1) 這個可以保證求出來的p`也是(0,r`)形式的,求出的r`就是r旋轉後的向量

另外其實對p做q * p * q^(-1)操作就是相當於對p乘了乙個旋轉矩陣,這裡先假設 q=(cos(a/2),sin(a/2)*n)=(s,(x, y, z))

兩個四元數相乘也表示乙個旋轉

q1 * q2 表示先以q2旋轉,再以q1旋轉

則這個矩陣為

同理乙個旋轉矩陣也可以轉換為乙個四元數,即給你乙個旋轉矩陣可以求出(s,x,y,z)這個四元數,

方法是:

旋轉矩陣 尤拉角 四元數比較

旋轉矩陣 尤拉角 四元數主要用於 向量的旋轉 座標系之間的轉換 角位移計算 方位的平滑插值計算。旋轉矩陣 尤拉角 四元數比較 不同的方位表示方法適用於不同的情況。下面是我們對合理選擇格式的一些建議 1.尤拉角最容易使用。當需要為世界中的物體指定方位時,尤拉角能大大的簡化人機互動,包括直接的鍵盤輸入方...

Eigen 四元數 尤拉角 旋轉矩陣 旋轉向量

一 旋轉向量 1.0 初始化旋轉向量 旋轉角為alpha,旋轉軸為 x,y,z eigen angleaxisd rotation vector alpha,vector3d x,y,z 1.1 旋轉向量轉旋轉矩陣 eigen matrix3d rotation matrix rotation ma...

unity3d四元數和旋轉矩陣

quaternion中存放了x,y,z,w四個資料成員,可以用下標來進行訪問,對應的下標分別是0,1,2,3。主要介紹幾個函式 1 根據兩個向量計算出旋轉量,計算出來的旋轉量為從fromdirection旋轉到todirection的旋轉量 static quaternion fromtorotat...