旋转矩阵、旋转向量、欧拉角、四元数的关系

摘要:
{b_3})]交叉乘法的结果表示一个向量,[overridararowaimesoverlightarrow{m{b}}=左|{egin{array}{*{20}{{c}}{{e1}}}&
  • 向量的矩阵形式

有两个向量:
[overrightarrow { m{a}} = ({a_1},{a_2},{a_3})]

[overrightarrow { m{b}} = ({b_1},{b_2},{b_3})]

叉乘的结果表示一个向量,这个向量向量垂直于a,b向量构成的平面。

[overrightarrow a imes overrightarrow { m{b}} = left| {egin{array}{*{20}{c}}
{{e_1}}&{{e_2}}&{{e_3}}\
{{a_1}}&{{a_2}}&{{a_3}}\
{{b_1}}&{{b_2}}&{{b_3}}
end{array}} ight| = left[ {egin{array}{*{20}{c}}
{{a_2}{b_3} - {a_3}{b_2}}\
{{a_3}{b_1} - {a_1}{b_3}}\
{{a_1}{b_2} - {a_2}{b_1}}
end{array}} ight] = left[ {egin{array}{*{20}{c}}
0&{ - {a_3}}&{{a_2}}\
{{a_3}}&0&{ - {a_1}}\
{ - {a_2}}&{{a_1}}&0
end{array}} ight]left[ {egin{array}{*{20}{c}}
{{b_1}}\
{{b_2}}\
{{b_3}}
end{array}} ight] = {a^ wedge }b]

将向量a对应的矩阵表示出来,为一个反对称矩阵,每一个向量都对应着一个反对称矩阵。这就引出向量的矩阵形式。

[{a^ wedge } = left[ {egin{array}{*{20}{c}}
0&{ - {a_3}}&{{a_2}}\
{{a_3}}&0&{ - {a_1}}\
{ - {a_2}}&{{a_1}}&0
end{array}} ight]]

  • 坐标变换的易混点

在齐次变换中

[{{ m{p}}_1} = {T_{12}} ullet {p_2}]

[{{ m{p}}_2} = {T_{23}} ullet {p_3}]

T12表示,把坐标系{2}的向量变换到坐标系{1}中,T23同理,如果把坐标系{3}下的向量变换到坐标系{1}中为:

[{{ m{p}}_1} = {T_{12}} ullet {T_{23}} ullet {p_3}]

  • 旋转向量和欧拉角:

  SO(3)的旋转矩阵有9个量,但是只有3个自由度,同理SE(3)有16个量,但是也只有6个自由度。在实际的旋转中,任意的旋转都可用一个旋转轴和一个旋转角来表示,我们使用一个向量,方向与旋转轴一致,长度等于旋转角,这样只需要一个三维向量即可描述旋转。对于SE(3),用一个旋转向量和一个平移向量即可表达,恰好自由度为6.如果用旋转向量来描述R:旋转轴为一个单位长度的向量n,角度为$ heta $,那么$ heta { m{n}}$可以表示这个旋转。旋转矩阵R和旋转向量$ heta { m{n}}$的转换过程为罗德里格斯变换:

[R = cos heta I + (1 - cos heta )n{n^T} + sin heta {n^ wedge }]

此处末尾的${{ m{n}}^ wedge }$ 如上面所示,代表矩阵表示的向量。那么反过来通过旋转矩阵获取转角 $ heta $;

$$ heta { m{ = arccos}}frac{{tr(R) - 1}}{2}$$

tr(R)为矩阵R的迹。对于转轴n,Rn=n;表示为转轴绕自身转动不生改变,从数学来说n是矩阵R特征值为1时对应的特征向量。从现在来看旋转轴和旋转角来表示的旋转是紧凑的,没有冗余性,但是欧拉角RPY的空间中,当一个旋转达到$underline { m{ + }} 90^circ $是就出现了奇异性。相当于地球的经纬度中当纬度为$underline { m{ + }} 90^circ $时,经度无意义。

旋转矩阵、旋转向量、欧拉角、四元数的关系第1张

  那么如何解决冗余性和奇异性呢,于是又提出了四元数,既不冗余有没有奇异性。

  • 四元数

  $q = {q_0} + {q_1}i + {q_2}j + {q_3}k$其中i,j,k 为四元数的三个虚部,关系为:

[left{ {egin{array}{*{20}{c}}
{{i^2}{ m{ = }}{j^2}{ m{ = }}{k^2}{ m{ = }}; - 1}\
{ij = k,ji = - k}\
{jk = i,kj = - i}\
{ki = j,ik = - j}
end{array}} ight.]

i,j,k的关系就像三维坐标系一样,用单位四元数可以表示空间中的任意一个旋转,与复数有一些不同,在复数中,乘以i代表旋转90°,但在四元数中,乘以i对应着旋转180°,保证$ij = k$,对应着绕i旋转180°,在绕j旋转180°等于绕k旋转180°。${i^2} = - 1$意味着绕i轴旋转360°得到一个相反的东西。四元数之间的运算满足上面四个关系。

  • 用四元数表示旋转

空间的一个三维点$p = [x,y,z] in {R^3}$,由一个单位四元数q指定的旋转,三维点$p$经过旋转之后变为$p'$,在原始的矩阵描述为$p' = Rp$,在四元数中描述时:$p = {[0,x,y,z]^T} = {[0,u]^T}$,相当于把四元数的三个虚部与空间中的三个轴对应,旋转后的$p'$可以表示为:$p' = qp{q^{ - 1}}$(不用纠结为什么左乘一个q右乘一个q的逆,运算规则就是这样),结果仍然为四元数。把$p'$的虚部取出得到旋转之后的坐标。

  •  说千道万落到实践是关键:
 1 Matrix3d R_mat = Matrix3d::Identity();//初始化为单位阵
 2     AngleAxisd R_vec(M_PI/4,Vector3d(0,0,1));//用旋转角和旋转轴表示的旋转向量
 3     cout.precision(3);//输出精确到三位小数
 4     R_mat = R_vec.toRotationMatrix();//旋转向量转化为旋转矩阵
 5     cout << "旋转矩阵1:
"<<R_vec.matrix() << endl //旋转向量转化为旋转矩阵
 6          << "旋转矩阵1:
" << R_mat << endl;
 7     
 8     Vector3d v(1, 0, 0);
 9     Vector3d v_r = R_vec * v;//用旋转轴和角表示的坐标变换
10     cout << "旋转向量2:
" << v_r.transpose() << endl;//transpose()为转置
11     v_r = R_mat * v;//用旋转矩阵表示的坐标变换
12     cout << "旋转向量2:
" << v_r.transpose() << endl;
13 
14     Vector3d eul_ang = R_mat.eulerAngles(2, 1, 0);//ZYX顺序,RPY
15     cout << "欧拉角rpy为:
" << eul_ang << endl;//绕Z旋转π/4
16 
17     Isometry3d T = Isometry3d::Identity();//欧氏变换,4x4矩阵
18     T.rotate(R_vec);//按照R_vec旋转向量来旋转
19     T.pretranslate(Vector3d(1, 2, 3));//平移向量为(1.2.3)
20     cout << "变换矩阵为:
" <<T.matrix() << endl;
21 
22     Vector3d v_transform = T * v;//就是通常的R*v+t,旋转和平移都包括进去了对于坐标第四个数默认补1
23     cout << "变换后的坐标为:
" << v_transform << endl;
24 
25     Quaterniond q = Quaterniond(R_vec);//用四元数表示旋转向量
26     cout << "四元数表示的旋转向量为:
" << q.coeffs().transpose() << endl;//(i,j,k,w),前三个为虚部,最后一个为实部
27      q = Quaterniond(R_mat);//用四元数表示旋转矩阵
28     cout << "四元数表示的旋转矩阵为:
" << q.coeffs().transpose() << endl;//(i,j,k,w),前三个为虚部,最后一个为实部      
29     
30     v_r = q * v;//用四元数表示的旋转变换,数学中是q*v*q.inverse()
31     cout << "四元数旋转向量为:
" << v_r.transpose() << endl;

旋转矩阵、旋转向量、欧拉角、四元数的关系第2张

免责声明:文章转载自《旋转矩阵、旋转向量、欧拉角、四元数的关系》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇C11中的Unicodevue2.0模拟锚点实现定位平滑滚动下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

vuex : 模块化改造

我们知道,vuex是vue技术栈中很重要的一部分,是一个很好用的状态管理库。 如果你的项目没有那么复杂,或者对vuex的使用没有那么重度,那么,是用不着modules功能的。 但如果你写着写着就发现你的vuex 代码过于臃肿,那么就可能需要modules功能来进行模块化改造了。 由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂...

C++编译器符号表有哪些内容?(转帖)

原帖地址:http://blog.csdn.net/abortexit/archive/2007/04/24/1583306.aspx很早就想写一篇关于符号表的学习小结,可是迟迟不能下笔。其一是因为符号表在编译器的设计中占有举足轻重的地位【我们在学习编译原理的时候更多的是注重principles,而没有关心一个编译器的实现,所以符号表讲解的也比较少】,编译...

Nginx 下配置SSL证书的方法

1、Nginx 配置 ssl 模块 默认 Nginx 是没有 ssl 模块的,而我的 VPS 默认装的是 Nginx 0.7.63 ,顺带把 Nginx 升级到 0.7.64 并且 配置 ssl 模块方法如下: 下载 Nginx 0.7.64 版本,解压 进入解压目录:  复制代码代码如下: wget http://sysoev.ru/nginx/ng...

Tensorflow:ImportError: DLL load failed: 找不到指定的模块 Failed to load the native TensorFlow runtime

配置: Windows 10 python3.6 CUDA 10.1 CUDNN 7.6.0 tensorflow 1.12 过程:import tensorflow as tf ,然后报错: Traceback (most recent call last): File "<ipython-input-6-64156d691fe5>...

iframe用法总结

<p><iframe>是框架的一种形式,也比较常用到。 </p><div class="blogstory"><p><span style="font-size:18px;"><span style="color:#0000ff;"><span style="font...

【深度学习系列】用Tensorflow实现经典CNN网络Vgg

  上周我们讲了经典CNN网络AlexNet对图像分类的效果,2014年,在AlexNet出来的两年后,牛津大学提出了Vgg网络,并在ILSVRC 2014中的classification项目的比赛中取得了第2名的成绩(第一名是GoogLeNet,也是同年提出的)。在论文《Very Deep Convolutional Networks for Large...