你是下雨天

你是下雨天

马上订阅 你是下雨天 RSS 更新: https://glooow1024.github.io/atom.xml

三维旋转、欧拉角、四元数

2024年4月16日 22:24

关于三维旋转、欧拉角和四元数,以前只是简单的调用库函数做转换,并没有深入理解,最近在网上找资料发现还是良莠不齐,很多文章写得比较杂乱,这里根据自己学习后的理解整理出一篇文章以供参考。

1. 欧拉角

欧拉角描述了三维空间中的旋转,想象有一架飞机悬在空中朝着正东方向水平静止,现在要将其姿态原地变换到任意一个其他方向,从最接近人的直观来看,在机头原始位置\(A\)和旋转后位置\(A'\)连一条线即为最短路径,沿着该最短路径旋转飞机即可。如果用数学语言描述,那么就是假设飞机中心位置为\(O\),那么\(AOA'\)构成一个平面,以该平面法向量为轴旋转飞机,即可将飞机从原始姿态旋转到新的姿态。尽管这种方法很直观,但是一开始欧拉并没有采用这种表示方法,或许是觉得不够规整,旋转轴的确定和表示稍显麻烦。那么欧拉是如何做的呢?如下图所示[1],我们知道笛卡尔坐标系有\(xyz\)三个轴,那么绕着这三个轴分别做旋转不就可以了吗?这时只需要给出每次旋转的角度即可。

更具体清晰的描述如下:首先假设世界坐标系\(xyz\),飞机自身的局部坐标系为\(XYZ\)(刚体坐标系),世界坐标系始终保持固定不变,而飞机局部坐标系在飞机旋转过程中会发生变化。假设飞机初始坐标系为\(X_1Y_1Z_1(=xyz)\),想要旋转到一个新的姿态\(X_2Y_2Z_2\),那么欧拉给出的一个结论是:任意两个姿态之间,只需要绕\(x,y,z(X,Y,Z)\)轴做3次旋转即可完成。不过,具体到旋转过程中,绕哪几个轴旋转的先后顺序和角度都会对最终结果有影响<spanclass="hint--top hint--rounded" aria-label="欧拉角细节/旋转顺序/内旋外旋- 知乎(zhihu.com) ">[2]

  1. 内旋还是外旋:可以注意到上面动图中首先绕z轴旋转,第一次旋转之后局部坐标系的\(XY\)轴与世界坐标系的\(xy\)轴已经不对齐了,因此第二步是以局部坐标系的轴进行旋转还是以世界坐标系为轴进行旋转?前者被称为内旋,后者为外旋。显然其他参数相同的情况下,两种方式得到的结果不同。
  2. 旋转轴的顺序:欧拉角实际上有两大类,一类是Proper Eulerangles,其旋转顺序包括 (z-x-z, x-y-x, y-z-y, z-y-z, x-z-x,y-x-y),第二类是Tait–Bryan angles,包括 (x-y-z, y-z-x, z-x-y, x-z-y,z-y-x, y-x-z)。可以看到Proper Euler angles只涉及两个转轴.而Tait–Bryanangles涉及三个转轴。目前机器人以及SLAM领域中常用的是Tait–Bryanangles。后面的论述也都采用Tait–Bryan angles。
  3. 旋转的角度:指定绕 \(xyz(XYZ)\)轴三个的旋转角度分别为 \((\alpha,\beta,\gamma)\),需要注意的是如果旋转轴的顺序不同,即使每个轴对应的旋转角度不变,最终的姿态角也可能不同。

最后给一个小的总结,也就是说要想用欧拉角的方式描述一个三维旋转,实际上需要5个参数,即:1)内旋or外旋;2)旋转顺序;3)每次旋转的角度。

另外纠正一个重要的误解:欧拉角并不是描述一个静态的姿态角,而是描述一种过程!(相信很多人和我一样一直没意识到这点)姿态本身是唯一确定的,但是变换到这个姿态的过程是不唯一的,因此欧拉角与内旋/外旋、旋转顺序都密切相关!

2. 旋转矩阵

我们知道旋转可以用矩阵表示,如果考虑外旋的话,那么假设某个点在世界坐标系中的初始位置为\(\boldsymbol{p}_0\),如果跟随世界坐标系按照某个Tait–Bryanangles做外旋,不妨设为 \(x(\alpha)\toy(\beta)\toz(\gamma)\),其旋转后的坐标(在世界坐标系中)是可以表示为 \(\boldsymbol{p}'= \boldsymbol{R} *\boldsymbol{p}_0\),其中 \(\boldsymbol{R}\)为旋转矩阵,那么这个旋转矩阵可以写为 \(\boldsymbol{R}_{\rmextrinsic}=\boldsymbol{R}_z(\gamma)\boldsymbol{R}_y(\beta)\boldsymbol{R}_x(\alpha)\),其中\[\begin{align}\boldsymbol{R}_x(\alpha) &= \left[\begin{array}{ccc}1 & 0 & 0 \\0 & \cos (\alpha) & -\sin (\alpha) \\0 & \sin (\alpha) & \cos (\alpha)\end{array}\right] \\\boldsymbol{R}_y(\beta) &= \left[\begin{array}{ccc}\cos (\beta) & 0 & \sin (\beta) \\0 & 1 & 0 \\-\sin (\beta) & 0 & \cos (\beta)\end{array}\right] \\\boldsymbol{R}_z(\gamma) &= \left[\begin{array}{ccc}\cos (\gamma) & -\sin (\gamma) & 0 \\\sin (\gamma) & \cos (\gamma) & 0 \\0 & 0 & 1\end{array}\right]\end{align}\]外旋比较简单,但内旋的旋转矩阵就比较复杂,首先给出一个结论:如果内旋操作为\(Z(\gamma) \to Y'(\beta)\toX''(\alpha)\),那么其对应的旋转矩阵为 \[\boldsymbol{R}_{\rmintrinsic}=\boldsymbol{R}_{X''}(\alpha)\boldsymbol{R}_{Y'}(\beta)\boldsymbol{R}_{Z}(\gamma)=\boldsymbol{R}_z(\gamma)\boldsymbol{R}_y(\beta)\boldsymbol{R}_x(\alpha)\] 也就是和前面外旋 \(x(\alpha)\toy(\beta)\to z(\gamma)\) 的结果是完全一样的。也就是说:

每种特定顺序的外旋等价于其相反顺序的内旋,例如 \(x(\alpha)\to y(\beta)\to z(\gamma)\) 与\(Z(\gamma) \to Y'(\beta)\toX''(\alpha)\) 的旋转是等价的。

上面 \(\boldsymbol{R}_{\rmintrinsic}\) 的表达式中,第1次旋转绕 \(Z(=z)\) 轴旋转,因此 \(\boldsymbol{R}_{Z}(\gamma)=\boldsymbol{R}_z(\gamma)\),然而在做第2次旋转的时候,此时初始的\(Y\) 轴已经被旋转到了 \(Y'\) 处,因此绕 \(Y'\) 轴的旋转需要根据 \(Y'\) 的方向来确定,\(\boldsymbol{R}_{Y'}(\beta)\)表达式推导较为繁琐,而第3次旋转类似,其旋转轴变为了 \(Z''\),表达式则更为复杂。但是经过推导,会发现他们神奇地和\(\boldsymbol{R}_z(\gamma)\boldsymbol{R}_y(\beta)\boldsymbol{R}_x(\alpha)\)完全等价!实际上这并不是巧合,如何理解呢?下面我将参考博客<spanclass="hint--top hint--rounded" aria-label="Extrinsic& intrinsic rotation: Do I multiply from right or left?...