SLAM 之四元数转欧拉角再理解

   我们知道在SLAM中,经常会用到旋转,平移等坐标变换,平移的话,相对来说比较好理解,但是旋转就会比较复杂,通常旋转可以有很多种表示方法,像是旋转矩阵,四元数,欧拉角,欧拉轴角,李代数(SO3)等,但是万变不离其宗,都是为了表达两个坐标系之间的相对角度关系。最近重新回顾欧拉角这些基础知识的时候有了一些新的体会,这篇博文主要是为了记录一下最近的总结。首先,参考了网上很多博客和资源,以前在脑子里记得的欧拉角都是Z-Y-X这种常用的欧拉角转换,但是都知道欧拉角可以有12种组合,就是不知道到底是怎么个意思,所以这里记录一下。以下内容仅自己总结,如需转载请著名出处,如有错误,欢迎指出,谢谢!若文中缺少了对相关文章或链接的引用,请指出,我会添加上去的,尊重原创!

欧拉角定义

   总结之前还是要回顾一下,欧拉角的定义,欧拉角定义分为两种,一种是静态欧拉角,也称外旋/固定轴,另一种是动态欧拉角,也称内旋/动态轴,参考weiki百科的内容,静态和动态可以从下面两幅图来理解

静态欧拉角,每次都绕着固定参考系的某一个轴转动

动态欧拉角,每次都绕着自身参考系的某一个轴转动

总之一句话,静态欧拉角是绕着固定坐标系旋转的角度,动态欧拉角是绕着刚体自身坐标系的旋转,且内旋是右乘,外旋是左乘变换
在SLAM中其实经常用的是内旋的形式,所以下面的内容也是按照内旋来计算说明的。

四元数到旋转矩阵

   都知道四元数是可以转换为旋转矩阵的,但实际上怎么转换的呢,网上也有很多直接给公式的,但是只要花点时间去推,很快就能推出来的:

假设有点p1和p2,满足对应的旋转关系,p1=R∗p2p1 = R*p2p1=R∗p2,其中RRR表示旋转矩阵
R=[r00r01r02r10r11r12r20r21r22]R=\left[\begin{matrix} r00 & r01 & r02 \\ r10 & r11 & r12 \\ r20 & r21 & r22\end{matrix} \right] R=⎣⎡​r00r10r20​r01r11r21​r02r12r22​⎦⎤​
而对四元数q=[qw,qx,qy,qz]T=[qw,qv]\bold q = [qw,qx,qy,qz]^T = [qw,\bold {qv}]q=[qw,qx,qy,qz]T=[qw,qv]而言,有
[0p1xp1yp1z]=q∗[0p2xp2yp2z]∗q∗\left[\begin{matrix}0\\ p1_x \\ p1_y \\ p1_z\end{matrix}\right] = \bold q *\left[\begin{matrix}0\\ p2_x \\ p2_y \\ p2_z\end{matrix}\right]*\bold q^* ⎣⎢⎢⎡​0p1x​p1y​p1z​​⎦⎥⎥⎤​=q∗⎣⎢⎢⎡​0p2x​p2y​p2z​​⎦⎥⎥⎤​∗q∗
其中q∗\bold q^*q∗表示共扼四元数q∗=[q0,−qx,−qy,−qz]T\bold q^* = [q0,-qx,-qy,-qz]^Tq∗=[q0,−qx,−qy,−qz]T。
另外,四元数的乘法也可以写成矩阵的形式,上面的内容可以转换为:
[0p1xp1yp1z]=[q]L∗[q∗]R[0p2xp2yp2z]其中,[q]L=qwI+[0−qvTqv[qv]×],表示左乘四元数q然后,[q∗]R=qwI+[0−q∗vTq∗v−[q∗v]×],表示乘右乘四元数q∗[qv]×=[0−qzqyqz0−qx−qyqx0]表示反对称矩阵\left[\begin{matrix}0\\ p1_x \\ p1_y \\ p1_z\end{matrix}\right] = \bold [\bold q]_L *[\bold q^*]_R\left[\begin{matrix}0\\ p2_x \\ p2_y \\ p2_z\end{matrix}\right] \\ 其中,[\bold q]_L = qw\bold I + \left[\begin{matrix}0 & -\bold {qv}^T \\ \bold {qv} & [\bold {qv}]_\times\end{matrix}\right],表示左乘四元数\bold q \\ 然后,[\bold q^*]_R = qw\bold I + \left[\begin{matrix}0 & -\bold {q^*v}^T \\ \bold {q^*v} & -[\bold {q^*v}]_\times\end{matrix}\right],表示乘右乘四元数\bold q^* \\ [\bold {qv}]_\times=\left[\begin{matrix} 0 & -qz & qy \\ qz & 0 & -qx \\ -qy & qx & 0 \end{matrix}\right]表示反对称矩阵 ⎣⎢⎢⎡​0p1x​p1y​p1z​​⎦⎥⎥⎤​=[q]L​∗[q∗]R​⎣⎢⎢⎡​0p2x​p2y​p2z​​⎦⎥⎥⎤​其中,[q]L​=qwI+[0qv​−qvT[qv]×​​],表示左乘四元数q然后,[q∗]R​=qwI+[0q∗v​−q∗vT−[q∗v]×​​],表示乘右乘四元数q∗[qv]×​=⎣⎡​0qz−qy​−qz0qx​qy−qx0​⎦⎤​表示反对称矩阵
所以,这就可以计算出对应的转换关系:
[q]L∗[q∗]R=qw2∗I+[0002∗qw∗[qv]×]+[qvT∗qv−qvT∗[qv]×−[qv]×∗qvqv∗qvT+[qv]×∗[qv]×]又因为,对向量而言,[a]×∗b=a×b,所以[qv]×∗qv=qv×qv=0T则[q]L∗[q∗]R=[∣∣q∣∣20T0qv∗qvT+qw2I+2∗qw∗[qv]×+[qv]×∗[qv]×]\bold [\bold q]_L *[\bold q^*]_R= qw^2*\bold I + \left[\begin{matrix} 0 & 0 \\ 0 & 2*qw* [\bold {qv}]_\times \end{matrix}\right] + \left[\begin{matrix} \bold {qv}^T*\bold {qv} & -\bold {qv}^T*[\bold {qv}]_\times \\ -[\bold {qv}]_\times*\bold {qv} & \bold {qv}*\bold {qv}^T + [\bold {qv}]_\times*[\bold {qv}]_\times \end{matrix}\right] \\又因为,对向量而言,[\bold {a}]_\times*\bold {b} = \bold a \times\bold b,\\所以[\bold {qv}]_\times*\bold {qv} = \bold {qv} \times\bold {qv} = \bold 0^T \\则 \\\bold [\bold q]_L *[\bold q^*]_R=\left[\begin{matrix} ||\bold {q}||^2 & \bold {0}^T \\ \bold {0} & \bold {qv}*\bold {qv}^T + qw^2\bold I + 2*qw*[\bold {qv}]_\times + [\bold {qv}]_\times*[\bold {qv}]_\times\end{matrix}\right] [q]L​∗[q∗]R​=qw2∗I+[00​02∗qw∗[qv]×​​]+[qvT∗qv−[qv]×​∗qv​−qvT∗[qv]×​qv∗qvT+[qv]×​∗[qv]×​​]又因为,对向量而言,[a]×​∗b=a×b,所以[qv]×​∗qv=qv×qv=0T则[q]L​∗[q∗]R​=[∣∣q∣∣20​0Tqv∗qvT+qw2I+2∗qw∗[qv]×​+[qv]×​∗[qv]×​​]
所以,综上所述,可以得到:
[0p1]=[∣∣q∣∣20T0qv∗qvT+qw2I+2∗qw∗[qv]×+[qv]×∗[qv]×]∗[0p2]即:p1=(qv∗qvT+qw2I+2∗qw∗[qv]×+[qv]×∗[qv]×)∗p2=[qx2+qw2−qy2−qz22∗qx∗qy−2qw∗qz2∗qx∗qz+2∗qw∗qy2∗qx∗qy+2∗qw∗qzqw2+qy2−qx2−qz22∗qy∗qz−2∗qw∗qx2∗qx∗qz−2∗qw∗qy2∗qy∗qz+2∗qw∗qxqw2+qz2−qx2−qy2]\left[\begin{matrix}0\\ \bold p1 \end{matrix}\right] = \left[\begin{matrix} ||\bold {q}||^2 & \bold {0}^T \\ \bold {0} & \bold {qv}*\bold {qv}^T + qw^2\bold I + 2*qw*[\bold {qv}]_\times + [\bold {qv}]_\times*[\bold {qv}]_\times\end{matrix}\right]*\left[\begin{matrix}0\\ \bold p2 \end{matrix}\right] \\ 即: \bold p1 = ( \bold {qv}*\bold {qv}^T + qw^2\bold I + 2*qw*[\bold {qv}]_\times + [\bold {qv}]_\times*[\bold {qv}]_\times)*\bold p2 \\ =\left[\begin{matrix} qx^2 + qw^2-qy^2 - qz^2 & 2*qx*qy-2qw*qz & 2*qx*qz + 2*qw*qy \\ 2*qx*qy+2*qw*qz & qw^2+qy^2-qx^2-qz^2 & 2*qy*qz - 2*qw*qx \\ 2*qx*qz-2*qw*qy & 2*qy*qz+2*qw*qx & qw^2+qz^2-qx^2-qy^2\end{matrix}\right] [0p1​]=[∣∣q∣∣20​0Tqv∗qvT+qw2I+2∗qw∗[qv]×​+[qv]×​∗[qv]×​​]∗[0p2​]即:p1=(qv∗qvT+qw2I+2∗qw∗[qv]×​+[qv]×​∗[qv]×​)∗p2=⎣⎡​qx2+qw2−qy2−qz22∗qx∗qy+2∗qw∗qz2∗qx∗qz−2∗qw∗qy​2∗qx∗qy−2qw∗qzqw2+qy2−qx2−qz22∗qy∗qz+2∗qw∗qx​2∗qx∗qz+2∗qw∗qy2∗qy∗qz−2∗qw∗qxqw2+qz2−qx2−qy2​⎦⎤​
完成了上面的推导之后,就可以根据四元数转换到旋转矩阵了。

旋转矩阵到欧拉角

讲解完了上面的内容,接下来就是怎么根据旋转矩阵转换出欧拉角了,正如前面所言,SLAM中常用的其实是内旋的形式,正如我们对旋转矩阵求偏导的时候会采用右扰动的方式一样,也就是说,假如相机/Lidar坐标系经过三次旋转之后,其方位(不考虑平移)能够转到和世界坐标系重合,这三次旋转分别为Rz(α),Ry(β),Rx(γ)Rz(\alpha),Ry(\beta),Rx(\gamma)Rz(α),Ry(β),Rx(γ),则旋转矩阵表示的形式为:
R=[cos(α)−sin(α)0sin(α)cos(α)0001]∗[cos(β)0sin(β)010−sin(β)0cos(β)]∗[1000cos(γ)−sin(γ)0sin(γ)cos(γ)]=[cos(α)cos(β)−sin(α)cos(γ)+cos(α)sin(β)sin(γ)sin(α)sin(γ)+cos(α)sin(β)cos(γ)sin(α)cos(β)cos(α)cos(γ)+sin(α)sin(β)sin(γ)−cos(α)sin(γ)+sin(α)sin(β)cos(γ)−sin(β)cos(β)sin(γ)cos(β)cos(γ)]=R=[r00r01r02r10r11r12r20r21r22]R = \left[\begin{matrix} cos(\alpha) & -sin(\alpha) & 0 \\ sin(\alpha) & cos(\alpha) & 0 \\ 0 & 0 & 1 \end{matrix}\right]* \left[\begin{matrix} cos(\beta) & 0 & sin(\beta) \\ 0 & 1 & 0 \\ -sin(\beta) & 0 & cos(\beta) \end{matrix}\right]* \left[\begin{matrix} 1 & 0 & 0 \\ 0 & cos(\gamma) & -sin(\gamma)\\ 0 & sin(\gamma) & cos(\gamma) \end{matrix}\right] \\ = \left[\begin{matrix} cos(\alpha)cos(\beta) & -sin(\alpha)cos(\gamma)+cos(\alpha)sin(\beta)sin(\gamma) & sin(\alpha)sin(\gamma)+cos(\alpha)sin(\beta)cos(\gamma) \\ sin(\alpha)cos(\beta) & cos(\alpha)cos(\gamma)+sin(\alpha)sin(\beta)sin(\gamma) & -cos(\alpha)sin(\gamma) + sin(\alpha)sin(\beta)cos(\gamma)\\ -sin(\beta) & cos(\beta)sin(\gamma) & cos(\beta)cos(\gamma)\end{matrix}\right] \\=R=\left[\begin{matrix} r00 & r01 & r02 \\ r10 & r11 & r12 \\ r20 & r21 & r22\end{matrix} \right] R=⎣⎡​cos(α)sin(α)0​−sin(α)cos(α)0​001​⎦⎤​∗⎣⎡​cos(β)0−sin(β)​010​sin(β)0cos(β)​⎦⎤​∗⎣⎡​100​0cos(γ)sin(γ)​0−sin(γ)cos(γ)​⎦⎤​=⎣⎡​cos(α)cos(β)sin(α)cos(β)−sin(β)​−sin(α)cos(γ)+cos(α)sin(β)sin(γ)cos(α)cos(γ)+sin(α)sin(β)sin(γ)cos(β)sin(γ)​sin(α)sin(γ)+cos(α)sin(β)cos(γ)−cos(α)sin(γ)+sin(α)sin(β)cos(γ)cos(β)cos(γ)​⎦⎤​=R=⎣⎡​r00r10r20​r01r11r21​r02r12r22​⎦⎤​
由此可得到,在内旋,Z-Y-X的旋转顺序下对应欧拉角所构成的旋转矩阵是上面的这个样子,要想反解出对应的角度,只要对矩阵做一定的操作即可:
sy=sqrt(r21∗r21+r22∗r22)γ=atan2(r21,r22)β=atan2(−r20,sy)α=atan2(r10,r00)sy=sqrt(r21*r21+r22*r22) \\ \gamma = atan2(r21,r22) \\ \beta = atan2(-r20,sy) \\ \alpha = atan2(r10,r00) sy=sqrt(r21∗r21+r22∗r22)γ=atan2(r21,r22)β=atan2(−r20,sy)α=atan2(r10,r00)
这样,就可以得到三轴的欧拉角为(γ,β,α)(\gamma,\beta,\alpha)(γ,β,α)
但是,上面的计算是不考虑了Gimbol Lock(万向锁)的情况的,具体Gimbol Lock是啥这里不做详细的解释,一句话概括,就是假如第二次旋转的角度为+90度或-90度的时候,会出现绕第三个轴旋转和绕第一个轴旋转的效果是一样的情况,也就是少了一个自由度,这个大家可以用自己的右手做一个测试即可,设食指朝前是x轴,中指朝左是y轴,大拇指朝上是z轴,当先绕z轴旋转一定水平角度α\alphaα之后,再绕此时的中指旋转90度,会惊奇的发现,食指和原来的大拇指方向重合了,这个时候,再去绕食指转动γ\gammaγ,实际上相当于一开始就绕z轴旋转α+γ\alpha + \gammaα+γ角度,然后再绕此时的中指旋转90度,所以说是少了一个自由度。
从矩阵上看,还是以Z-Y-X的旋转顺序,就是第二角度β=90\beta = 90β=90,那么cos⁡β=0,sinβ=1\cos\beta = 0,sin\beta = 1cosβ=0,sinβ=1,这个时候,再去反解算欧拉角的时候,就会出现0/0的情况,这是明显不对的,所以需要再做个判断,
由于在计算机中,都是浮点数,所以基本上不会完全等于0,一般认为a<ϵa<\epsilona<ϵ的时候就认为是0了,所以假如前面的sy < 1e-6之类的,就可以认为是遇到了万向锁了,这个时候,其实对角度解算就没有太大意义了,因为有两个轴α,γ\alpha,\gammaα,γ在同一个方向上了,可以假定其中一个为0,然后再带回去算就好了,完整的判断如下:
sy=sqrt(r21∗r21+r22∗r22)ifsy<1e−6:γ=atan2(r01,r02)β=atan2(−r20,sy)α=0.0esleγ=atan2(r21,r22)β=atan2(−r20,sy)α=atan2(r10,r00)sy=sqrt(r21*r21+r22*r22) \\ if \quad sy <1e-6: \\ \quad \quad \quad \gamma = atan2(r01,r02) \\ \quad \quad \quad \beta = atan2(-r20,sy) \\ \quad \quad \quad \alpha = 0.0 \\esle \quad \quad \quad\quad \quad \quad \\ \quad \quad \quad \gamma = atan2(r21,r22) \\ \quad \quad \quad \beta = atan2(-r20,sy) \\ \quad \quad \quad \alpha = atan2(r10,r00) sy=sqrt(r21∗r21+r22∗r22)ifsy<1e−6:γ=atan2(r01,r02)β=atan2(−r20,sy)α=0.0esleγ=atan2(r21,r22)β=atan2(−r20,sy)α=atan2(r10,r00)
最后得到的结果就是上面所述的情况了,至于其它的旋转顺序,同样可以这么分解,先通过内旋的形式把对应欧拉角的旋转矩阵乘起来,然后再和四元数推出来的旋转矩阵对比,注意一下Gimbol Lock的情况,就可以解出来了,大家可以用在线转换工具测试一下

需要注意的是:以上解法只适用于内旋的反解,目前好像大多的库比如Eigen,Ros tf 都是这么解的,根据旋转矩阵解外旋欧拉角还不清楚有哪些,但是外旋和内旋满足:
(Riz(α)∗Riy(β)∗Rix(γ))−1=(Rex(γ)∗Rey(β)∗Rez(α))其中Ri表示内旋,Re表示外旋,且:Riz(α)=[cos(α)−sin(α)0sin(α)cos(α)0001]Rez(α)=[cos(α)sin(α)0−sin(α)cos(α)0001](Riz(\alpha)*Riy(\beta)*Rix(\gamma))^{-1} =(Rex(\gamma)*Rey(\beta)*Rez(\alpha)) \\其中Ri表示内旋,Re表示外旋,且: \\ Riz(\alpha)=\left[\begin{matrix} cos(\alpha) & -sin(\alpha) & 0 \\ sin(\alpha) & cos(\alpha) & 0 \\ 0 & 0 & 1 \end{matrix}\right] \\Rez(\alpha)=\left[\begin{matrix} cos(\alpha) & sin(\alpha) & 0 \\ -sin(\alpha) & cos(\alpha) & 0 \\ 0 & 0 & 1 \end{matrix}\right] (Riz(α)∗Riy(β)∗Rix(γ))−1=(Rex(γ)∗Rey(β)∗Rez(α))其中Ri表示内旋,Re表示外旋,且:Riz(α)=⎣⎡​cos(α)sin(α)0​−sin(α)cos(α)0​001​⎦⎤​Rez(α)=⎣⎡​cos(α)−sin(α)0​sin(α)cos(α)0​001​⎦⎤​

参考

特别感谢以下参考,其实还看了很多,记不全了,如有遗漏,也请指出!
<< Quaternion kinematics for the error-state Kalman filter >>
https://en.wikipedia.org/wiki/Euler_angles
https://blog.csdn.net/qq_38288618/article/details/77195271
https://quaternions.online

SLAM 之四元数转欧拉角再理解相关推荐

  1. matlab和Eigen库中的一些旋转矩阵(方向余弦矩阵)、四元数和欧拉角之间的转换和绘图的注意事项

    最近用matlab和Eigen库中的一些旋转矩阵(方向余弦矩阵).四元数和欧拉角之间的转换和绘图,弄得我有些头疼,把遇到的问题记录一下,以防以后又脑阔疼....有不同的理解可以再评论区批评指正- 主要 ...

  2. 转换矩阵、平移矩阵、旋转矩阵关系以及python实现旋转矩阵、四元数、欧拉角之间转换

    文章目录 1. 转换矩阵.平移矩阵.旋转矩阵之间的关系 2. 缩放变换.平移变换和旋转变换 2. python实现旋转矩阵.四元数.欧拉角互相转化 由于在平时总是或多或少的遇到平移旋转的问题,每次都是 ...

  3. eigen 编译_头条 | 使用eigen实现四元数、欧拉角、旋转矩阵、旋转向量间的转换...

    点击上方蓝字,关注本公众号,获得更多资源上一篇文章介绍了四元数.欧拉角.旋转矩阵.轴角如何相互转换,本篇文章介绍如何用eigen来实现. 旋转向量 1,初始化旋转向量:旋转角为alpha,旋转轴为(x ...

  4. 四元数,欧拉角,旋转矩阵相互转换

    #include <TransForms3d/TransForms.h>/*---------------------------------------角度弧度转换----------- ...

  5. 【飞控理论】【惯性导航基础】二维平面的旋转如何用代数表示?三维平面的旋转如何用代数表示?什么是四元数?四元数、欧拉角、方向余弦之间有什么关系?

    上一篇欧拉角 由于欧拉角在描述三维空间物体旋转问题时存在万向节死锁问题(详情戳这里),所以引入四元数概念. 目录 1.二维平面的旋转 2.三维平面的旋转(什么是四元数) 3.<捷联惯性导航> ...

  6. Matlab ——旋转矩阵,四元数,欧拉角之间的转换

    最近要用这方面的东西,整理,记录,分享一下 基于Matlab现有函数下的内容 Matlab --旋转矩阵,四元数,欧拉角之间的转换 旋转矩阵 dcm R 四元数 quat q = [q0 q1 q2 ...

  7. unity中的四元数,欧拉角,方向向量之间的相互转换方法。

    四元数: 到欧拉角:quaternion.eulerAngles 到方向向量:(quaternion * Vector3.forward).normalized 欧拉角: 到四元数:Quaternio ...

  8. 【Unity3D 灵巧小知识点】☀️ | Unity 四元数、欧拉角 与 方向向量 之间转换

    Unity 小科普 老规矩,先介绍一下 Unity 的科普小知识: Unity是 实时3D互动内容创作和运营平台 . 包括游戏开发.美术.建筑.汽车设计.影视在内的所有创作者,借助 Unity 将创意 ...

  9. 在matlab和python if中的旋转变换(四元数、欧拉角、旋转矩阵)等

    在matlab和python tf中的旋转变换(四元数.欧拉角.旋转矩阵等) 目录 1. 基本的认识 2. 变换矩阵 3. 欧拉角 4. 四元数 5. matlab中相互转换 6. python tf ...

  10. 再理解RankNet算法

    再理解RankNet算法 前面的一篇博文介绍了学习排序算法(Learning to Rank)中的RankNet算法.如下:http://blog.csdn.net/puqutogether/arti ...

最新文章

  1. 求从第一列走到第n列的最短路径
  2. 使用Skywalking实现全链路监
  3. 平台积分体系设计方案
  4. 将Python源码编译成pyc和pyo文件
  5. 获取当前时间的天、周、月、季度、半年度、年度开始和结束时间
  6. 点、圆和线的转化关系
  7. Linux嵌入式开发_修改机器码
  8. 概率论与数理统计图解
  9. Java IO流常用操作方法总结
  10. 语法分析:自下而上分析
  11. 有些CAD通过Arcgis程序读取后,发现面积不对
  12. [物联网+云存储]-关于人工智能开关的学习思路
  13. selenium基础②:模拟QQ空间登录
  14. C PrimerPlus 第五章程序示例
  15. C语言-qsort函数详解及使用例
  16. 格式化字符串漏洞利用 一、引言
  17. STM32 SPI TX FIFO处理
  18. 微软OFFICE在线预览
  19. 【FSB总线、HT总线、QPI总线、DMI总线】
  20. 修改/dev/shm大小

热门文章

  1. 图扑软件数字孪生民航飞联网,构建智慧民航新业态
  2. vue-Observe、Dep、Watcher
  3. 太阳辐射最少的地区_读中国年太阳辐射总量分布图,寻找年太阳辐射量最多和最少的地方...
  4. Linux efi分区被删除了,恢复删掉的 MSR 和 EFI 分区
  5. QQ界面的MSN聊天软件
  6. hapi入门之Authentication篇
  7. 《中国传统文化》慕课期末试题及答案
  8. 电脑断网情况下,自动连接wifi
  9. 用互联网大脑模型分析滴滴的战略意图和战术失误
  10. 毕业设计之 ---- 基于深度学习图像识别的垃圾分类系统