对比三维空间旋转的几种方法——欧拉角、绕轴的旋转、矩阵、四元数、双四元数
三维空间的旋转可以用欧拉角,旋转矩阵,轴-角,四元数,双四元数来表示,本文主要总结这些表示方法的优缺点。像矩阵、四元数等的实现的下载地址,可以参考这里,也可以参考Ogre渲染引擎的内核,都有很高效的实现方法。
一. 欧拉角(Euler-Angles)
1.1 介绍
欧拉角包括3个旋转,根据这3个旋转来指定一个刚体的朝向。这3个旋转分别绕x轴,y轴和z轴,分别称为Pitch,Yaw和Roll,如下图所示。欧拉角可以表示成z-x-z,x-y-x,z-y-z等形式,旋转的顺序影响结果。
Pitch Yaw Roll图1. 欧拉角的表示
欧拉角很重要的一个优点就是直观,容易理解。
欧拉角主要有下面几个缺点:
(1) 欧拉角是不可传递的,旋转的顺序影响旋转的结果,不同的应用又可能使用不同的旋转顺序,旋转顺序无法统一;
(2) 3个旋转的角度可以不受限制,即可以是10000度,也可以是-1500度;
(3) 可能造成万向节死锁(Gimbal Lock)。
1.2 平万向节死锁
当两个环发生重叠的时候,就有丢失了一个*度,如图2所示。对万向节死锁可以参考【1】【2】【3】,特别是【1】提供的视频,对知识点的介绍非常的形象生动。也正是由于锁的存在,无法使用欧拉角实现球面平滑的插值。
图2. 万向节死锁
二. 旋转矩阵
用3*3的矩阵,可以表示三维空间中所有的旋转,设 θ 表示沿着轴的方向望去时,方向是顺时针的旋转角度。则绕着X轴、Y轴、Z轴旋转 θ 角,对应的旋转矩阵表示如下所示:
X=⎛⎝⎜1000cosθsinθ0−sinθcosθ⎞⎠⎟ Y=⎛⎝⎜cosθ0−sinθ010sinθ0cosθ⎞⎠⎟ Z=⎛⎝⎜cosθsinθ0−sinθcosθ0001⎞⎠⎟
旋转矩阵支持传递性,使用起来很简单方便,但是存在下面一些缺点:
(1) 浪费内存,至少需要12个参数,来表示一个6个*度的结构;
(2) 可能就引入不该有的缩放(Scaling)和错切(Sheering)
(3) 矩阵插值的实现难度很大;
(4) 不直观。
三. 轴-角度
绕着单位长度的轴旋转某个角度,使用组合对 (n⃗ ,θ) 。
该方向很直观,避免了欧拉角使用时的万向节死锁;但是实现多个旋转的组合时,比较困难;不能简单的通过对4个元素的线性插值来实现轴-角度的插值,会引起错误。
四. 四元数
参考《四元数》和《双四元数》,也可以参考【5】【6】【7】,这里只简单的描述下该方法的优缺点。
它的缺点就是很不直观,理解起来较费劲。但是存在很多优点:
(1) 更健壮,不会出现欧拉角中出现的万向节死锁。
(2) 更高效,花费更少的空间和时间;当使用有限的精度对矩阵进行大量的操作,就会发生漂移(Drift),实数的四舍五入就会不断累积到矩阵中。由于漂移的存在,旋转的操作就可能发生错误,所以要对矩阵进行归一化操作,重置矩阵,这是很费时的操作。四元数只有4个值,而矩阵有9个,它经历的漂移作用就小,而且归一化时间就更少。
(3) 使用起来很简单
五. 双四元数
双四元数,参考《双四元数》一文。简单来说,就是它使用了两个四元数,8个参数,不仅可以表示旋转,也可以表示位移。
六. 参考
【1】 http://v.youku.com/v_show/id_XNzkyOTIyMTI=.html
【2】 http://www.cnblogs.com/soroman/archive/2008/03/24/1118996.html
【3】 http://www.cnitblog.com/luckydmz/archive/2010/09/07/68674.aspx
【4】 Kenwright, Ben. "A Beginners Guide to Dual-Quaternions."
【5】 http://www.cprogramming.com/tutorial/3d/quaternions.html
【6】 http://isg.cs.tcd.ie/projects/DualQuaternions/
【7】 http://www.gamedev.net/page/resources/_/technical/math-and-physics/quaternion-powers-r1095