日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

四元數(shù)與旋轉(zhuǎn)

 kingwenguang 2015-09-25
一、四元數(shù)概念及運(yùn)算
1.
四元數(shù)引入
將實(shí)數(shù)域擴(kuò)充到復(fù)數(shù)域,并用復(fù)數(shù)來(lái)表示平面向量,用復(fù)數(shù)的加、乘運(yùn)算表示平面向量的合成、伸縮和旋轉(zhuǎn)變換,這些觀念已經(jīng)在中學(xué)課程中學(xué)過(guò)了。那么,很自然的問(wèn)題就是,在三維,或更高維空間中是否也有復(fù)數(shù)的類(lèi)似物?也就是說(shuō),像擴(kuò)充實(shí)數(shù)那樣,在復(fù)數(shù)域的基礎(chǔ)上添加一個(gè)或幾個(gè)新的元素,并且讓它們跟原來(lái)的復(fù)數(shù)做加減乘除,是否就可以得到一個(gè)新的數(shù)集,并且其中的元素還可以像復(fù)數(shù)域那樣做加、減、乘、除運(yùn)算,并滿足通常復(fù)數(shù)的那些運(yùn)算律,包括加法和乘法的交換律與結(jié)合律、乘法對(duì)加法的分配律等待?更進(jìn)一步,我們是否可以期望用這樣的數(shù)來(lái)表示三維或更高維空間中的伸縮和旋轉(zhuǎn),就像用復(fù)數(shù)表示平面向量的伸縮旋轉(zhuǎn)那樣方便?
歷史上有很多數(shù)學(xué)家試圖尋找過(guò)三維的復(fù)數(shù),但后來(lái)證明這樣的三維復(fù)數(shù)是不存在的
,即使不考慮空間旋轉(zhuǎn),只從代數(shù)角度來(lái)說(shuō),三維的復(fù)數(shù)域作為普通復(fù)數(shù)域的擴(kuò)張域也是不存在的。
知道了復(fù)數(shù)不能推廣到三維,我們把目光移向四維復(fù)數(shù),即四元數(shù)。四元數(shù)是由愛(ài)爾蘭數(shù)學(xué)家威廉·盧云·哈密頓在1843年發(fā)現(xiàn)的。復(fù)數(shù)推廣到四元數(shù),必須犧牲掉數(shù)域的某一條或幾條性質(zhì),哈密爾頓拋棄了乘法交換律。
2.
四元數(shù)定義
四元數(shù)都是 1、i、j 和 k 的線性組合,一般可表示為 d + ai + bj + ck, a、b、c、d是實(shí)數(shù)。 如把四元數(shù)的集合考慮成多維實(shí)數(shù)空間的話,四元數(shù)就代表著一個(gè)四維空間,相對(duì)于復(fù)數(shù)為二維空間。
3.加乘運(yùn)算
要把兩個(gè)四元數(shù)相加只需將相類(lèi)的系數(shù)加起來(lái)就可以,就像復(fù)數(shù)一樣。至于乘法則可跟隨以下的乘數(shù)表:
四元數(shù)與旋轉(zhuǎn)
以上表格中,最左邊的列表示被乘數(shù),最上面行表示乘數(shù)。
    即 i^2=j^2=k^2=-1,ij=k, ji=-k, jk=i, kj=-i, ki=j, ik=-j
四元數(shù)與旋轉(zhuǎn)
可以立即驗(yàn)證加法交換律、結(jié)合律,以及等式 p+0=0+p=p,方程 p+x=0 恒有解,乘法結(jié)合律,還有乘法對(duì)加法的分配律都是成立的,只不過(guò)沒(méi)有乘法交換律。
例如:
假設(shè):x = 3 + i, y = 5i + j - 2k
那么:
x + y = 3 + 6i + j - 2k
xy =( {3 + i} )( {5i + j - 2k} ) = 15i + 3j - 6k + 5i^2 + ij - 2ik
= 15i + 3j - 6k - 5 + k + 2j = - 5 + 15i + 5j - 5k

 四元數(shù)也可以表示為:  q=[w,v],  其中v=(x,y,z)是矢量,w是標(biāo)量。
四元數(shù)與旋轉(zhuǎn)
 如果向量部分外積為零,兩個(gè)四元數(shù)的乘積就可交換了。 

4.模的定義
四元數(shù)也是可以歸一化的,四元數(shù)的單位化與Vector類(lèi)似,首先(a^2+b^2+c^2+d^2)的平方根 稱為四元數(shù)的模,即||q|| = Norm(q)=sqrt(w2 + x2 + y2 + z2),這里2指平方, 如w2指w的平方。
因?yàn)閣2 + x2 + y2 + z2=1 所以Normlize(q)=q/Norm(q)=q / sqrt(w2 + x2 + y2 + z2)

5.共軛定義
 若p=w+xi+yj+zk=w+v,則p*=w-xi-yj-zk=w-v 表示與p實(shí)部相等,向量部分相反的四元數(shù),稱為p的共軛。
四元數(shù)與旋轉(zhuǎn)
6.逆的定義
如果 四元數(shù)與旋轉(zhuǎn),四元數(shù)與旋轉(zhuǎn)

二、四元數(shù)與三維空間的旋轉(zhuǎn)
我們要關(guān)心的是三維空間上任意的伸縮旋轉(zhuǎn)變換是否可用四元數(shù)的乘積來(lái)表示,而這一點(diǎn)對(duì)四元數(shù)來(lái)說(shuō)是完全能夠勝任的。
如果已知一個(gè)三維空間的伸縮旋轉(zhuǎn)的轉(zhuǎn)軸方向、旋轉(zhuǎn)角度和伸縮比例,來(lái)求相應(yīng)的四元數(shù),是比較容易的。
四元數(shù)與旋轉(zhuǎn)

特別地,單位化的四元數(shù)用來(lái)描述旋轉(zhuǎn):
以原點(diǎn)為旋轉(zhuǎn)中心,旋轉(zhuǎn)的軸是(α, β, γ) α^2 β^2 γ^2 1), 
(右手系的坐標(biāo)定義的話,望向向量(α, β, γ)的前進(jìn)方向反時(shí)針) 轉(zhuǎn)θ角的旋轉(zhuǎn),用四元數(shù)表示就是,
(cos(θ/2); α sin(θ/2), β sin(θ/2), γ sin(θ/2)) 
四元數(shù)的乘法的意義類(lèi)似于Matrix的乘法-可以將兩個(gè)旋轉(zhuǎn)合并,例如:
Q=Q1*Q2 表示Q的是先做Q2的旋轉(zhuǎn),再做Q1的旋轉(zhuǎn)的結(jié)果,而多個(gè)四元數(shù)的旋轉(zhuǎn)也是可以合并的,當(dāng)有多次旋轉(zhuǎn)操作時(shí),使用四元數(shù)可以獲得更高的計(jì)算效率。

例子代碼

/// Quaternion.cpp 

#include <math.h> 
#include <iostream.h> 
  
/// Define Data type 
typedef struct 

              
double t; // real-component 
              double x; // x-component 
              double y; // y-component 
              double z; // z-component 
quaternion; 
  

//// Bill 注:Kakezan 在日語(yǔ)里是 乘法的意思
quaternion Kakezan(quaternion left, quaternion right) 

              quaternion ans; 
              
double d1, d2, d3, d4; 
  
              d1  left.t right.t; 
              d2 -left.x right.x; 
              d3 -left.y right.y; 
              d4 -left.z right.z; 
              ans.t d1+ d2+ d3+ d4; 
  
              d1  left.t right.x; 
              d2  right.t left.x; 
              d3  left.y right.z; 
              d4 -left.z right.y; 
              ans.x  d1+ d2+ d3+ d4; 
  
              d1  left.t right.y; 
              d2  right.t left.y; 
              d3  left.z right.x; 
              d4 -left.x right.z; 
              ans.y  d1+ d2+ d3+ d4; 
  
              d1  left.t right.z; 
              d2  right.t left.z; 
              d3  left.x right.y; 
              d4 -left.y right.x; 
              ans.z  d1+ d2+ d3+ d4; 
              
              
return ans; 

  
///Make Rotational quaternion 
quaternion MakeRotationalQuaternion(double radian, double AxisX, double AxisY, double AxisZ) 

              quaternion ans; 
              
double norm; 
              
double ccc, sss; 
              
              ans.t ans.x ans.y ans.z 0.0; 
  
              norm AxisX  AxisX  AxisY  AxisY  AxisZ  AxisZ; 
              
if(norm <= 0.0) return ans; 
  
              norm 1.0 sqrt(norm); 
              AxisX *= norm; 
              AxisY *= norm; 
              AxisZ *= norm; 
  
              ccc cos(0.5 radian); 
              sss sin(0.5 radian); 
  
              ans.t ccc; 
              ans.x sss AxisX; 
              ans.y sss AxisY; 
              ans.z sss AxisZ; 
  
              
return ans; 

  
///Put XYZ into  quaternion 
quaternion PutXYZToQuaternion(double PosX, double PosY, double PosZ) 

              quaternion ans; 
  
              ans.t 0.0; 
              ans.x PosX; 
              ans.y PosY; 
              ans.z PosZ; 
  
              
return ans; 

  
///// main 
int main() 

              
double px, py, pz; 
              
double ax, ay, az, th; 
              quaternion ppp, qqq, rrr; 
  
              cout << "Point Position (x, y, z) << endl; 
              cout <<  "; 
              cin >> px; 
              cout <<  "; 
              cin >> py; 
              cout <<  "; 
              cin >> pz; 
              ppp PutXYZToQuaternion(px, py, pz); 
  
              
while(1) 
                            cout << "\nRotation Degree (Enter to Quit) << endl; 
                            cout <<  angle "; 
                            cin >> th; 
                            
if(th == 0.0) break
  
                            cout << "Rotation Axis Direction (x, y, z) << endl; 
                            cout <<  "; 
                            cin >> ax; 
                            cout <<  "; 
                            cin >> ay; 
                            cout <<  "; 
                            cin >> az; 
  
  
                            th *= 3.1415926535897932384626433832795 180.0; 
/// Degree -> radian; 
  
                            qqq MakeRotationalQuaternion(th, ax, ay, az); 
                            rrr MakeRotationalQuaternion(-th, ax, ay, az); 
  
                            ppp Kakezan(rrr, ppp); 
                            ppp Kakezan(ppp, qqq); 
  
                            cout << "\nAnser << ppp.x 
                                          <<  "\n      << ppp.y 
                                          <<  "\n      << ppp.z << endl; 
  
              
  
              
return 0; 
}  

三、關(guān)于插值
    使用四元數(shù)的原因就是在于它非常適合插值,這是因?yàn)樗且粋€(gè)可以規(guī)格化的4維向量,最簡(jiǎn)單的插值算法就是線性插值,公式如:
   q(t)=(1-t)q1+t q2
一般線性插值由于長(zhǎng)度發(fā)生變化,不能滿足要求,我們需要保持向量長(zhǎng)度不變的插值,即球面線性插值。
四元數(shù)與旋轉(zhuǎn)


    q(t)=((1-tq1+tq2 )/ ||(1-tq1+tq2||
這樣,插值向量v(t)的端點(diǎn)就會(huì)沿著v1,v2端點(diǎn)構(gòu)成的圓弧行進(jìn)。因?yàn)?/span>v1,v2是等長(zhǎng)的,這個(gè)圓弧實(shí)際上是位于v1,v2構(gòu)成的球面上的一段,所以又叫球面線性插值。
但是,由于它的插值不是等角速度的,而是變速的。要想進(jìn)行等速的球面線性插值,可以用四元數(shù)工具:

參考鄭軍“四元數(shù)插值算法實(shí)現(xiàn)游戲角色平滑旋轉(zhuǎn)”一文:

四元數(shù)與旋轉(zhuǎn)


四元數(shù)與旋轉(zhuǎn)

主要程序代碼如下所示:
double x0,y0,z0,wO; 
double xl,yl,zl,wl; 
//參數(shù)t為插值變量 
double t; 
//在參數(shù)t下輸出一個(gè)四元數(shù),得到一個(gè)插值方位 
double x,y,z,w;
//計(jì)算開(kāi)始方位和結(jié)束方位的點(diǎn)積 
double cosO=xO*xl+y0*yl+zO*zl+WO*wl;
if(cosO<0){ 
xO=一xO; 
yo=一yO; 
zO=一zO; 
wO=一wo; 
cosO=一eosO; 
//進(jìn)行插值運(yùn)算 
double kO,kl; 
if(cosO>0.9999){ 
kO=1一t; 
kl=t; 
}else{ 
double sinO=Mathf.Sqrt(1一Mathf.Pow(cosO,2)); 
double O=Mathf.Atan2(sinO,cosO); 
float one=1.O/sinO; 
kO=Mathf.Sin((1一t) O)*one; 
kl=Mathf.Sin(t * O) * one; 
//輸出在t參數(shù)下的插值結(jié)果
x=xO * kO+xl * kl: 
Z=zO * kO+zl * kl: 
w=wo * kO+wl * kl: 


    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多