为何使用四元数
转载:http://www.game798.com/html/2007-05/3689.htmhtml
好吧,我必须认可到目前为止我尚未彻底理解四元数,我一度把四元数理解为轴、角表示的4维向量,也就在下午我才从和同事的争辩中理解了四元数不彻底是角、轴这么简单,为此写点心得给那些同我同样搞了2年3D游戏的还不清楚四元数的朋友。
为何使用四元数
为 了回答这个问题,先来看看通常关于旋转(面向)的描述方法-欧拉描述法。它使用最简单的x,y,z值来分别表示在x,y,z轴上的旋转角度,其取值为 0-360(或者0-2pi),通常使用roll,pitch,yaw来表示这些份量的旋转值。须要注意的是,这里的旋转是针对世界坐标系说的,这意味着 第一次的旋转不会影响第2、三次的转轴,简单的说,三角度系统没法表现任意轴的旋转,只要一开始旋转,物体自己就失去了任意轴的自主性,这也就致使了万向 轴锁(Gimbal Lock)的问题。
还有一种是轴角的描述方法(即我一直觉得的四元数的表示法),这种方法比欧拉描述要好,它避免了 Gimbal Lock,它使用一个3维向量表示转轴和一个角度份量表示绕此转轴的旋转角度,即(x,y,z,angle),通常表示为(x,y,z,w)或者 (v,w)。但这种描述法却不适合插值。
那到底什么是Gimbal Lock呢?正如前面所说,由于欧拉描述中针对x,y,z的旋转描述是世界坐标系下的值,因此当任意一轴旋转90°的时候会致使该轴同其余轴重合,此时旋 转被重合的轴可能没有任何效果,这就是Gimbal Lock,这里有个例子演示了Gimbal Lock,点击这里下载。运行这个例子,使用左右箭头改变yaw为90°,此时不论是使用上下箭头仍是Insert、Page Up键都没法改变Pitch,而都是改变了模型的roll。
那么轴、角的描述方法又有什么问题呢?虽然轴、角的描述解决了Gimbal Lock,但这样的描述方法会致使差值不平滑,差值结果可能跳跃,欧拉描述一样有这样的问题。
什么是四元数
四元数通常定义以下:
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维空间中的的矢量,也是很是不容易想像的。
四元数也是能够归一化的,而且只有单位化的四元数才用来描述旋转(面向),四元数的单位化与Vector相似,
首先||q|| = Norm(q)=sqrt(w2 + x2 + y2 + z2)
由于w2 + x2 + y2 + z2=1
因此Normlize(q)=q/Norm(q)=q / sqrt(w2 + x2 + y2 + z2)
说了这么多,那么四元数与旋转到底有什么关系?我之前一直认为轴、角的描述就是四元数,若是是那样其与旋转的关系也不言而喻,但并非这么简单,轴、角描述到四元数的转化:
w = cos(theta/2)
x = ax * sin(theta/2)
y = ay * sin(theta/2)
z = az * sin(theta/2)
其 中(ax,ay,az)表示轴的矢量,theta表示绕此轴的旋转角度,为何是这样?和轴、角描述到底有什么不一样?这是由于轴角描述的“四元组”并非 一个空间下的东西,首先(ax,ay,az)是一个3维坐标下的矢量,而theta则是级坐标下的角度,简单的将他们组合到一块儿并不能保证他们插值结果的 稳定性,由于他们没法归一化,因此不能保证最终插值后获得的矢量长度(通过旋转变换后两点之间的距离)相等,而四元数在是在一个统一的4维空间中,方便归 一化来插值,又能方便的获得轴、角这样用于3D图像的信息数据,因此用四元数再合适不过了。
关于四元数的运算法则和推导这里有篇详细的文章介绍,重要的是一点,相似与Matrix的四元数的乘法是不可交换的,四元数的乘法的意义也相似于Matrix的乘法-能够将两个旋转合并,例如:
Q=Q1*Q2
表示Q的是先作Q2的旋转,再作Q1的旋转的结果,而多个四元数的旋转也是能够合并的,根据四元数乘法的定义,能够算出两个四元数作一次乘法须要16次乘法和加法,而3x3的矩阵则须要27运算,因此当有屡次旋转操做时,使用四元数能够得到更高的计算效率。
为何四元数能够避免Gimbal Lock
在欧拉描述中,之因此会产生Gimbal Lock是由于使用的三角度系统是依次、顺序变换的,若是在OGL中,代码可能这样:
glRotatef( angleX, 1, 0, 0)
glRotatef( angleY, 0, 1, 0)
glRotatef( angleZ, 0, 0, 1)
注意:以上代码是顺序执行,而使用的又是统一的世界坐标,这样当首先旋转了Y轴后,Z轴将再也不是原来的Z轴,而可能变成X轴,这样针对Z的变化可能失效。
而四元数描述的旋转代码多是这样:
TempQ = From Eula(x,y,z)
FinalQ =CameraQ * NewQ
theta, ax, ay, az = From (FinalQ)
glRotatef(theta, ax, ay, az);
其中(ax,ay,az)描述一条任意轴,theta描述了绕此任意轴旋转的角度,而全部的参数都来自于全部描述旋转的四元数作乘法以后获得的值,能够看出这样一次性的旋转不会带来问题。这里有个例子演示了使用四元数不会产生Gimbal Lock的问题。
关于插值
使用四元数的缘由就是在于它很是适合插值,这是由于他是一个能够规格化的4维向量,最简单的插值算法就是线性插值,公式如:
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函数就能够完成这个插值过程。前端
昵称: git
退出 订阅评论 算法
[Ctrl+Enter快捷键提交] 服务器
【活动】华为云普惠季 1折秒杀 狂欢继续
【工具】SpreadJS纯前端表格控件,可嵌入应用开发的在线Excel
【腾讯云】拼团福利,AMD云服务器8元/月
· 关于四元数转载
· 四旋翼姿态解算之理论推导
· 简单VR照片 使用陀螺仪、姿态角(Roll、Pitch、Yaw )、四元数
· 四元数(转载http://www.sineysoft.com/blog/cmd.asp?act=tb&id=57&key=59011)
· 四元数(Quaternions)(转)
· 乐视网回应被王思聪旗下公司追债:将积极应诉
· 红黄蓝2万多学生贡献1亿美圆学费 占净收入超7成
· 次元壁的造成:使用抖音时,抖音也正在定义你
· 连年亏损却执意上市,2亿美金能为蘑菇街续命吗?
· 全国首例:深圳市儿童医院开通支付宝在线刷医保
» 更多新闻...
2014-07-31 pitch yaw roll是什么