四元数学习中。

来源:互联网 发布:文件夹隐藏加密软件 编辑:程序博客网 时间:2024/05/16 11:25

http://blog.sina.com.cn/s/blog_4b700c4c0102e30g.html

转载自:

http://blog.csdn.net/chenlanjie842179335/article/details/8039031


http://baike.baidu.com/link?url=vaXfsVpSGNdfKJTG1BPcWUamwWCAX5KI3jZfYSAmjPfNpviuvHYxZp-1EgZZfstidhA3Rjkv2rjTvNpZYP_lIa


四元数是由爱尔兰数学家威廉·卢云·哈密顿1843年发现的数学概念。四元数的乘法不符合交换律

明确地说,四元数是复数的不可交换延伸。如把四元数的集合考虑成多维实数空间的话,四元数就代表着一个四维空间,相对于复数为二维空间

基础

定义

复数是由实数加上元素 i 组成,其中

i^2 = -1 \,

相似地,四元数都是由实数加上三个元素 ijk 组成,而且它们有如下的关系:

i^2 = j^2 = k^2 = ijk = -1 \,

每个四元数都是 1、ij 和 k 的线性组合,即是四元数一般可表示为a + bi + cj + dk \,

要把两个四元数相加只需将相类的系数加起来就可以,就像复数一样。至于乘法则可跟随以下的乘数表:

×1ijk11ijkii-1k-jjj-k-1ikkj-i-1

四元数的单位元的乘法构成了八阶四元群Q_8

例子

假设:

x = 3 + i \,
y = 5i + j - 2k \,

那么:

x + y = 3 + 6i + j - 2k \,
xy = \left( {3 + i} \right)\left( {5i + j - 2k} \right) = 15i + 3j - 6k + 5i^2 + ij - 2ik
= 15i + 3j - 6k - 5+ k + 2j = - 5 + 15i + 5j - 5k \,

性质

四元数不像实数复数那样,它的乘法是不可交换的,例如

i \, j = k, \, j \, i = -k
j \, k = i, \, k \, j = -i
k \, i = j, \, i \, k = -j

四元数是除法环的一个例子。除了没有乘法的交换律外,除法环与是相类的。特别地,乘法的结合律仍旧存在、非零元素仍有唯一的逆元素。

四元数形成一个在实数上的四维结合代数(事实上是除法代数),并包括复数,但不与复数组成结合代数。四元数(以及实数和复数)都只是有限维的实数结合除法代数。

四元数的不可交换性往往导致一些令人意外的结果,例如四元数的 n-阶多项式能有多于 n 个不同的。例如方程式 h^2 + 1 = 0 \,  就有无数多个解。 只要是符合 b^2 + c^2 + d^2 = 1 \,  的实数,那么 h = b \, i + c \, j + d \, k就是一个解。

一个四元数 h = a + b \, i + c \, j + d \, k 的共轭值定义为:

h^* = a - b \, i - c \, j - d \, k

而它的绝对值则是非负实数,定义为:

\left| h \right| = \sqrt {h \cdot h^ * } = \sqrt {a^2 + b^2 + c^2 + d^2 }

注意(h \, k)^* = k^* \, h^*,一般状况下不等于h^* \, k^*

四元数的乘逆可以h^{ - 1} = \frac{{h^* }}{{\left| h \right|^2 }}算得。

透过使用距离函数 d(h, k) = |h - k| \,  ,四元数便可成为同胚于 \mathbb{R}^4 的度量空间,并且有连续算术运算。另外,对于所有四元数h \, k \, 皆有 |h \, k| = |h| \, |k| 。 若以绝对值为,则四元数可组成一实数 巴拿赫空间

群旋转

四元数和空间转动条目所释,非零四元数的乘法群在R3的实部为零的部分上的共轭作用可以实现转动。单位四元数(绝对值为1的四元数)若实部为cos(t),它的共轭作用是一个角度为2t的转动,转轴为虚部的方向。四元数的优点是:

  1. 表达式无奇点(和例如欧拉角之类的表示相比)
  2. 矩阵更简炼(也更快速)
  3. 单位四元数的对可以表示四维空间中的一个转动。

所有单位四元数的集合组成一个三维球S3和在乘法下的一个群(一个李群)。S3行列式为1的实正交3×3正交矩阵的群SO(3,R)的双重复盖,因为每两个单位四元数通过上述关系对应于一个转动。群S3SU(2)同构,SU(2)是行列式为1的复2×2矩阵的群。令A为形为a + bi + cj + dk的四元数的集合,其中abcd或者都是整数或者都是分子为奇数分母为2的有理数。集合A是一个,并且是一个。该环中存在24个四元数,而它们是施莱夫利符号为{3,4,3}的正二十四胞体的顶点。

以矩阵表示四元数

有两种方法能以矩阵表示四元数,并以矩阵之加法、乘法应用于四元数之加法、乘法。

第一种是以二阶复数矩阵表示。若 h = a + bi + cj + dk 则它的复数形式为:

\begin{pmatrix} a-di & -b+ci \\ b+ci & \;\; a+di \end{pmatrix}

这种表示法有如下优点:

  • 所有复数 (c = d = 0) 就相应于一个实矩阵。
  • 四元数的绝对值的平方就等于矩阵的行列式
  • 四元数的共轭值就等于矩阵的共轭转置
  • 对于单位四元数 (|h| = 1) 而言,这种表示方式给了四维球体SU(2)之间的一个同型,而后者对于量子力学中的自旋的研究十分重要。(请另见泡利矩阵

第二种则是以四阶实数矩阵表示:

\begin{pmatrix}\;\;a&-b&\;\;d&-c\\ \;\;b&\;\;a&-c&-d\\-d&\;\;c&\;\;a&-b\\ \;\;c&\;\;d&\;\;b&\;\;a\end{pmatrix}

其中四元数的共轭等于矩阵的转置

四元数运算

四元数运算在电动力学广义相对论中有广泛的应用。四元数可以用来取代张量表示。有时候采用带有复数元素之四元数会比较容易,导得结果不为除法代数之形式。然而亦可结合共轭运算以达到相同的运算结果。

此处仅讨论具有实数元素之四元数,并将以两种形式来描述四元数。其中一种是矢量与标量的结合,另一形式两个创建量(constructor)与双矢量(bivector;i、j与k)的结合。

定义两个四元数:

q = a + \vec{u} = a + bi + cj + dk
p = t + \vec{v} = t + xi + yj + zk

其中\vec{u}表示矢量<b, c, d>,而\vec{v}表示矢量<x, y, z>.

加、乘和一般函数

四元数加法:p + q
复数矢量矩阵一样,两个四元数之和需要将不同的元素加起来:
p + q = a + t + \vec{u} + \vec{v} = (a + t) + (b + x)i + (c + y)j + (d + z)k

加法遵循实数复数的所有交换律和结合律。

四元数乘法:pq
两个四元数之间的非可换乘积通常被格拉斯曼称为积,这个积上面已经简单介绍过,它的完整型态是:

pq = at - \vec{u}\cdot\vec{v} + a\vec{v} + t\vec{u} + \vec{v}\times\vec{u}

pq = (at - bx - cy - dz) + (bt + ax + cz - dy)i + (ct + ay + dx - bz)j + (dt + za + by - xc)k \,

由于四元数乘法的非可换性,pq并不等于qp。格拉斯曼积常用在描述许多其他代数函数。qp乘积的矢量部分是:

qp = at - \vec{u}\cdot\vec{v} + a\vec{v} + t\vec{u} - \vec{v}\times\vec{u}

四元数点积: p · q
点积也叫做欧几里得内积,四元数的点积等同于一个四维矢量的点积点积的值是p中每个元素的数值与q中相应元素的数值的乘积的和。这是四元数之间的可换积,并返回一个标量

p \cdot q = at + \vec{u}\cdot\vec{v} = at + bx + cy + dz

点积可以用格拉斯曼积的形式表示:

p \cdot q = \frac{p^*q + q^*p}{2}

这个积对于从四元数分离出一个元素有用。例如,i项可以从p中这样提出来:

p \cdot i = x

四元数外积:Outer(p,q)

欧几里得外积并不常用; 然而因为外积内积格拉斯曼积形式的相似性.它们总是一同被提及:

\operatorname{Outer}(p,q) = \frac{p^*q - q^*p}{2}

\operatorname{Outer}(p,q) = a\vec{u} - t\vec{v} - \vec{v}\times\vec{u}

\operatorname{Outer}(p,q) = (ax - tb - cz + dy)i + (ay - tc - dx + bz)j + (az - td - by + xc)k

四元数偶积:Even(p,q)

四元数偶积也不常用,但是它也会被提到,因为它和奇积的相似性。它是纯对称的积;因此,它是完全可交换的。

\operatorname{Even}(p,q) = \frac{pq + qp}{2}

\operatorname{Even}(p,q) = at - \vec{u}\cdot\vec{v} + a\vec{v} + t\vec{u}

\operatorname{Even}(p,q) = (at - bx - cy - dz) + (ax + tb)i + (ay + tc)j + (az + td)k

四元数叉积:p × q

四元数叉积也称为奇积。它和矢量叉积等价,并且只返回一个矢量值:

p \times q = \frac{pq - qp}{2}

p \times q = \vec{u}\times\vec{v}

p \times q = (cz - dy)i + (dx - bz)j + (by - xc)k

四元数转置:p−1

四元数的转置通过p−1p = 1被定义。它定义在上面的定义一节,位于属性之下(注意变量记法的差异)。其建构方式相同于复倒数(complex inverse)之构造:

p^{-1} = \frac{p^*}{p\cdot p}

一个四元数的自身点积是个标量。四元数除以一个标量等效于乘上此标量的倒数,而使四元数的每个元素皆除以此一除数。

四元数除法:p−1q

四元数的不可换性导致了 p−1q 和 qp−1的不同。这意味着除非p是一个标量,否则不能使用q/p这一符号。

四元数标量部:Scalar(p)

四元数的标量部分可以用前面所述的点积来分离出来:

1\cdot p = \frac{p + p^*}{2} = a

四元数矢量部:Vector(p)

四元数的矢量部分可以用外积提取出来,就象用点积分离标量那样:

\operatorname{Outer}(1, p) = \frac{p - p^*}{2} = \vec{u} = bi + cj + dk

四元数模:|p|

四元数的绝对值是四元数到原点的距离。

|p| = \sqrt{p \cdot p} = \sqrt{p^*p} = \sqrt{a^2 + b^2 + c^2 + d^2}

四元数符号数:sgn(p)

一复数之符号数乃得出单位圆上,一个方向与原复数相同之复数。四元数的符号数亦产生单位四元数:

\sgn(p) = \frac{p}{|p|}

四元数辐角:arg(p)

辐角函数可找出一4-矢量四元数偏离单位标量(即:1)之角度。此函数输出一个标量角度。

\arg(p) = \arccos\left(\frac{\operatorname{Scalar}(p)}{|p|}\right)

幂和对数

因为四元数有除法,所以对数可以定义。

  • 自然幂:\exp(p) = \exp(a)(\cos(|\vec{u}|) + \sgn(\vec{u})\sin(|\vec{u}|))
  • 自然对数:\ln(p) = \ln(|p|) + \sgn(\vec{u})\arg(p)
  • 幂:p^q = e^{q\ln(p)} \,

三角函数

  • 正弦:\sin(p) = \sin(a)\cosh(|\vec{u}|) + \cos(a)\sgn(\vec{u})\sinh(|\vec{u}|)
  • 余弦:\cos(p) = \cos(a)\cosh(|\vec{u}|) - \sin(a)\sgn(\vec{u})\sinh(|\vec{u}|)
  • 正切:\tan(p) = \frac{\sin(p)}{\cos(p)}

双曲函数

  • 双曲正弦: \sinh(p) = \sinh(a)\cos(|\vec{u}|) + \cosh(a)\sgn(|\vec{u}|)\sin(|\vec{u}|)
  • 双曲余弦: \cosh(p) = \cosh(a)\cos(|\vec{u}|) + \sinh(a)\sgn(|\vec{u}|)\sin(|\vec{u}|)
  • 双曲正切: \tanh(p) = \frac{\sinh(p)}{\cosh(p)}

反双曲函数

  • 反双曲正弦: \operatorname{arcsinh}(p) = \ln(p + \sqrt{p^2 + 1})
  • 反双曲余弦: \operatorname{arccosh}(p) = \ln(p + \sqrt{p^2 - 1})
  • 反双曲正切: \operatorname{arctanh}(p) = \frac{\ln(1+q)-\ln(1-q)}{2}

反三角函数

将这些被放到最后,是因为需要先定义四元数中的反双曲三角函数。

  • 反正弦函数: \arcsin(p) = -\sgn(\vec{u})\operatorname{arcsinh}(p \sgn(\vec{u}))
  • 反余弦函数: \arccos(p) = -\sgn(\vec{u})\operatorname{arccosh}(p)
  • 反正切函数: \arctan(p) = -\sgn(\vec{u})\operatorname{arctanh}(p \sgn(\vec{u}))


转载自:

http://blog.sina.com.cn/s/blog_557d254601018dfv.html



一、四元数概念及运算
1.
 四元数引入
将实数域扩充到复数域,并用复数来表示平面向量,用复数的加、乘运算表示平面向量的合成、伸缩和旋转变换,这些观念已经在中学课程中学过了。那么,很自然的问题就是,在三维,或更高维空间中是否也有复数的类似物?也就是说,像扩充实数那样,在复数域的基础上添加一个或几个新的元素,并且让它们跟原来的复数做加减乘除,是否就可以得到一个新的数集,并且其中的元素还可以像复数域那样做加、减、乘、除运算,并满足通常复数的那些运算律,包括加法和乘法的交换律与结合律、乘法对加法的分配律等待?更进一步,我们是否可以期望用这样的数来表示三维或更高维空间中的伸缩和旋转,就像用复数表示平面向量的伸缩旋转那样方便?
历史上有很多数学家试图寻找过三维的复数,但后来证明这样的三维复数是不存在的
 ,即使不考虑空间旋转,只从代数角度来说,三维的复数域作为普通复数域的扩张域也是不存在的。
知道了复数不能推广到三维,我们把目光移向四维复数,即四元数。四元数是由爱尔兰数学家威廉·卢云·哈密顿在1843年发现的。复数推广到四元数,必须牺牲掉数域的某一条或几条性质,哈密尔顿抛弃了乘法交换律。
2.
 四元数定义
四元数都是 1、i、j 和 k 的线性组合,一般可表示为 d + ai + bj + ck, a、b、c、d是实数。 如把四元数的集合考虑成多维实数空间的话,四元数就代表着一个四维空间,相对于复数为二维空间。
3.加乘运算
要把两个四元数相加只需将相类的系数加起来就可以,就像复数一样。至于乘法则可跟随以下的乘数表:
四元数与旋转
以上表格中,最左边的列表示被乘数,最上面行表示乘数。
    即 i^2=j^2=k^2=-1,ij=k, ji=-k, jk=i, kj=-i, ki=j, ik=-j
四元数与旋转
可以立即验证加法交换律、结合律,以及等式 p+0=0+p=p,方程 p+x=0 恒有解,乘法结合律,还有乘法对加法的分配律都是成立的,只不过没有乘法交换律。
例如:
假设: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

 四元数也可以表示为:  q=[w,v],  其中v=(x,y,z)是矢量,w是标量。
四元数与旋转
 如果向量部分外积为零,两个四元数的乘积就可交换了。 

4.模的定义
四元数也是可以归一化的,四元数的单位化与Vector类似,首先(a^2+b^2+c^2+d^2)的平方根 称为四元数的模,即||q|| = Norm(q)=sqrt(w2 + x2 + y2 + z2),这里2指平方, 如w2指w的平方。
因为w2 + 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实部相等,向量部分相反的四元数,称为p的共轭。
四元数与旋转
6.逆的定义
如果 四元数与旋转四元数与旋转

二、四元数与三维空间的旋转
我们要关心的是三维空间上任意的伸缩旋转变换是否可用四元数的乘积来表示,而这一点对四元数来说是完全能够胜任的。
如果已知一个三维空间的伸缩旋转的转轴方向、旋转角度和伸缩比例,来求相应的四元数,是比较容易的。
四元数与旋转

特别地,单位化的四元数用来描述旋转:
以原点为旋转中心,旋转的轴是(α, β, γ) α^2 β^2 γ^2 1), 
(右手系的坐标定义的话,望向向量(α, β, γ)的前进方向反时针) θ角的旋转,用四元数表示就是,
(cos(θ/2); α sin(θ/2), β sin(θ/2), γ sin(θ/2)) 
四元数的乘法的意义类似于Matrix的乘法-可以将两个旋转合并,例如:
Q=Q1*Q2 表示Q的是先做Q2的旋转,再做Q1的旋转的结果,而多个四元数的旋转也是可以合并的,当有多次旋转操作时,使用四元数可以获得更高的计算效率。

例子代码

/// 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 在日语里是 乘法的意思
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; 
}  

三、关于插值
    使用四元数的原因就是在于它非常适合插值,这是因为他是一个可以规格化的4维向量,最简单的插值算法就是线性插值,公式如:
   q(t)=(1-t)q1+t q2
一般线性插值由于长度发生变化,不能满足要求,我们需要保持向量长度不变的插值,即球面线性插值。
四元数与旋转


    q(t)=((1-tq1+tq2 )/ ||(1-tq1+tq2||
这样,插值向量v(t)的端点就会沿着v1,v2端点构成的圆弧行进。因为v1,v2是等长的,这个圆弧实际上是位于v1,v2构成的球面上的一段,所以又叫球面线性插值。
但是,由于它的插值不是等角速度的,而是变速的。要想进行等速的球面线性插值,可以用四元数工具:

参考郑军“四元数插值算法实现游戏角色平滑旋转”一文:

四元数与旋转


四元数与旋转

主要程序代码如下所示:
double x0,y0,z0,wO; 
double xl,yl,zl,wl; 
//参数t为插值变量 
double t; 
//在参数t下输出一个四元数,得到一个插值方位 
double x,y,z,w;
//计算开始方位和结束方位的点积 
double cosO=xO*xl+y0*yl+zO*zl+WO*wl;
if(cosO<0){ 
xO=一xO; 
yo=一yO; 
zO=一zO; 
wO=一wo; 
cosO=一eosO; 
//进行插值运算 
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参数下的插值结果
x=xO * kO+xl * kl: 
Z=zO * kO+zl * kl: 
w=wo * kO+wl * kl: 

http://blog.csdn.net/silangquan/article/details/50390570
理解四元数中文:
http://www.qiujiawei.com/understanding-quaternions/


0 0
原创粉丝点击