zoukankan      html  css  js  c++  java
  • 旋转矩阵---数学理论

           旋转矩阵是姿态的一种数学表达方式,或者笼统说变换矩阵是一种抽象的数学变量。其抽象在于当你看到数据,根本无法断定其正确性;往往只有转换为较为直观的欧拉角,然后大概目测估算(总不能拿着量角器去测量精度吧)。

    我们知道,姿态的数学形式有旋转矩阵(满足RTR=E)、欧拉角旋转向量(角轴)、四元数(norm(x y z w) = 1)等。今天这里要讨论的是旋转矩阵相关理论基础。

           旋转矩阵常用于以下三种场景:

    • 描述一个frame(坐标系)相对于另一个frame间的位姿;(如:描述相邻两帧间的相机运动)
    • 描述一个point从一个frame变换到另一个frame;(其实点没动,只是在两个frame观测时,坐标不一样而已;如:;路标点点P在不同相机坐标系下坐标值不同,但在世界坐标系下是固定的)
    • 描述一个point在同一个frame中的运动;(这里的点是运动了的,在VSLAM中应用较少)

            绕三个轴的旋转矩阵请按以下形式进行记忆,可能有些地方是下面的转置形式。

     (本博客和大多数论文资料一样,都是左乘原则)

    一、固定旋转(Fix Angles)

           所谓固定旋转,就是按照物体外部固定轴旋转。这种旋转在工程中很常见,用的相对多一些(相对于下面的欧拉旋转),例如:旋转次序为X-Y-Z,那么旋转矩阵的形式为:RZRYRX。如下图,其实没什么好说。

          已知旋转矩阵,怎么求解欧拉角呢?下图便是一种比较好的求解办法。我们知道,顺时针旋转180°和逆时针旋转180°是等效的(让机械臂旋转190°其实是走远路,因为旋转170°似乎更快),所以求解出来的欧拉角其取值范围最好是:[0°,180°] or [0°,-180°] 或者[-90°,90°],这里采用的后者。

           下图中的atan2是matlab中的api,我们在这里简单验证下其与tan的区别:可以看到,当一个点在第三象限,如(-1, -1),在欧拉角中,其角度为:-135°,但是atan(-1/-1)算出来是45°,显然是错的。

     1 >> atan(1) * 180 / pi
     2 
     3 ans =
     4 
     5     45
     6 
     7 >> atan2(1, 1) * 180 / pi
     8 
     9 ans =
    10 
    11     45
    12 
    13 >> atan2(-1, -1) * 180 / pi
    14 
    15 ans =
    16 
    17   -135
    18 
    19 >> 

           顺在在这里用Eigen验证下:(相关头文件去这个链接中查找: https://www.cnblogs.com/winslam/p/12765822.html )不去下载,下面C++代码你都跑不了

     1 #include"geometry.h"
     2 #include<iostream>
     3 using namespace std;
     4 
     5 int main()
     6 {
     7     Eigen::Matrix3d R1;
     8     R1 << 0.866, 0.433, 0.25, 0., 0.5, -0.866, -0.5, 0.75, 0.433;
     9 
    10     Pose pose1(R1);
    11     cout << "旋转矩阵 = " << endl; cout << pose1.rotation() << endl;
    12     cout << "欧拉角 = " << endl;   cout << pose1.euler_angle().transpose()*(180 / M_PI) << endl;
    13     cout << "四元数 = " << endl;   cout << pose1.quaternion().coeffs().transpose() << endl;
    14     cout << "角轴 = " << endl;
    15     cout << pose1.angle_axis().angle()* (180 / M_PI) << " " << pose1.angle_axis().axis().transpose() << endl;
    16     cout << "-----------------------------" << endl;
    17     return 1;
    18 }
    View Code

           打印结果:

    1 旋转矩阵 =  0.866  0.433   0.25
    2             0    0.5 -0.866
    3             -0.5   0.75  0.433 
    4 欧拉角 =   63.4349  14.4779 -26.5651                                                                                   
    5 四元数 =   0.482959  0.224145 -0.129407  0.836511  
    6 角轴 =     66.4519 0.881411 0.409071 -0.23617 

           可以看到Eigen的欧拉角结果和上述PPT中Matlab计算的结果不一样,但是他们旋转矩阵具体是一样的,这个是正常的,下面还会碰到。其实就是利用欧式旋转矩阵求解

    欧拉角的解并不唯一,这个问题在手眼标定中验证过。 

     

    二、欧拉旋转(Euler Angle)

            固定旋转与欧拉旋转的关系,例如:固定旋转次序为:XYZ,写成旋转矩阵则为:Rz*Ry*Rx;其等效的欧拉旋转次序为:ZYX,写成旋转矩阵则为:Rz*Ry*Rx,最后的映射矩阵是一样的,但是过程不一样,殊途同归。)例如下面例子:

          ZYZ的欧拉旋转次序,这个我是实际“体验过”,那是在自研机械臂上示教器是数据。

          欧拉旋转的方式如下图:

             形如固定旋转,我这里也给出:已经ZYZ类型欧拉旋转,求解欧拉角的一种方法:

          针对上面等式,这里用Eigen验证下:

           对于等式左边:

     1 #include"geometry.h"
     2 #include<iostream>
     3 using namespace std;
     4 
     5 int main()
     6 {
     7     // 低级错误:是60.0,不是60
     8     Eigen::Matrix3d R1;
     9     R1 = Eigen::AngleAxisd(60.0 / 180 * M_PI, Eigen::Vector3d::UnitX()) *
    10          Eigen::AngleAxisd(30.0 / 180 * M_PI, Eigen::Vector3d::UnitY()) *
    11           Eigen::AngleAxisd(              0.0, Eigen::Vector3d::UnitZ());
    12 
    13     Pose pose3(R1);
    14     cout << "旋转矩阵 = " << endl; cout << pose3.rotation() << endl;
    15     cout << "欧拉角 = " << endl;   cout << pose3.euler_angle().transpose()*(180 / M_PI) << endl;
    16     cout << "四元数 = " << endl;   cout << pose3.quaternion().coeffs().transpose() << endl;
    17     cout << "角轴 = " << endl;
    18     cout << pose3.angle_axis().angle()* (180 / M_PI) << " " << pose3.angle_axis().axis().transpose() << endl;
    19     cout << "-----------------------------" << endl;
    22     return 1;
    23 }

             针对等式右边,同理有:

    #include"geometry.h"
    #include<iostream>
    using namespace std;
    
    int main()
    {
        Eigen::Vector3d RPY;
        RPY << -56.3 / 180 * M_PI, 64.3 / 180 * M_PI, 73.9 / 180 * M_PI;
    
        cout << RPY(2, 0) << endl;
    
    
        Eigen::Matrix3d R2;
        // note: ZYZ
        R2 = Eigen::AngleAxisd(RPY(0, 0), Eigen::Vector3d::UnitZ()) *
             Eigen::AngleAxisd(RPY(1, 0), Eigen::Vector3d::UnitY()) *
             Eigen::AngleAxisd(RPY(2, 0), Eigen::Vector3d::UnitZ());
        Pose pose4(R2);
        cout << "旋转矩阵 = " << endl; cout << pose4.rotation() << endl;
        cout << "欧拉角 = " << endl;   cout << pose4.euler_angle().transpose()*(180 / M_PI) << endl;
        cout << "四元数 = " << endl;   cout << pose4.quaternion().coeffs().transpose() << endl;
        cout << "角轴 = " << endl;
        cout << pose4.angle_axis().angle()* (180 / M_PI) << " " << pose4.angle_axis().axis().transpose() << endl;
        cout << "-----------------------------" << endl;
    
        return 1;
    }

          对比两种旋转方式,可以看到Eigen计算的结果完全一致;但是比较有意思的是,对于下面,我用的欧拉角明明是( -56.3, 64.3, 73.9 )(ZYZ),结果打印输出的

    欧拉角居然是(59.9, 29.99, 0.031)。这是由于我写的Pose类底层,我只定义了ZYX的固定旋转方式。同时,也说明了,同一个旋转矩阵,可能对应不同的旋转方式(如:欧拉旋转、固定旋转),不同的旋转欧拉角、甚至不同的旋转次序

     三、旋转矩阵小结

           欧拉旋转和固定旋转的次序有效的排列组合为:12 = 3 * 2 * 2

           姿态的数学形式有旋转矩阵(约束:RTR=E)、欧拉角(万向锁问题)、旋转向量(角轴)、四元数(约束norm(x y z w) = 1),所以VSLAM在对位姿进行优化的时候,

    为了避免“带约束的优化”问题,一般都会采用旋转向量的形式作为姿态。

    参考:

    (台大机器人学之运动学——林沛群)

    https://www.bilibili.com/video/BV1v4411H7ez?p=3

    https://baike.baidu.com/item/%E6%97%8B%E8%BD%AC%E7%9F%A9%E9%98%B5/3265181?fr=aladdin#5

    《jlblanco2010geometry3D_techrep.pdf》

    https://blog.csdn.net/uranus1992/article/details/85788205

    查看全文
  • 相关阅读:
    多任务顺序执行解决方案
    数码摄影学习总结
    ASP.NET Core与RESTful API 开发实战(二)
    通过三点求圆心程序(二维和三维两种方式),代码为ABB机器人程序,其他语言也适用
    ABB机器人选项611-1 Path Recovery使用记录
    C#刷新chart控件方法及task的启停功能记录
    ABB机器人输送链跟踪问题记录
    有关C#跨线程操作控件的委托方法
    c#get、set属性及类的继承
    正则表达式学习记录
  • 原文地址:https://www.cnblogs.com/winslam/p/13625837.html
  • 最新文章
  • gulp Requiring external module babel-register
    docker + Kubernates install
    Mac java tool
    SetUp设置
    exe路径
    LabVIEW连接Access
    WPF使用程序集资源
    WPF跨程序集共享资源
    WPF文字颜色动画效果
    Path In WPF
  • 热门文章
  • 冒泡排序
    Typora上传图片
    JDK8 安装
    WPF MVVM 数据验证详解
    微服务
    Modbus功能码详解
    Modbus协议的相关知识
    Prism程序入口、View ViewModel关联、数据绑定、数据校验、cmd
    Prism框架模块化思想、Shell、Region、Moduel
    ASP.NET Core与RESTful API 开发实战(三)
Copyright © 2011-2022 走看看

资讯网贸易公司起名多少钱童第周简介周易预测学入门在线阅读abs发行部分南方城市供暖勇者别嚣张破解造梦西游4宣传片制作网站12333是什么电话电商网站设计欣赏恐龙为什么要死宝宝起名神器破解版柏树的种植方法和注意事项爱情公寓在哪里新出生婴儿起名电影天堂免女宝宝起名缺水木周易软件推荐11月个性签名嗯起个名字商标如何起名属虎男起名合适用什么字盗梦三国之名将无双破解版互联网站建设康斯坦丁 电影天堂周易气功建设个网站多少钱推八字算命看什么书seo快速排名培训起个快手名子少年生前被连续抽血16次?多部门介入两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”淀粉肠小王子日销售额涨超10倍高中生被打伤下体休学 邯郸通报单亲妈妈陷入热恋 14岁儿子报警何赛飞追着代拍打雅江山火三名扑火人员牺牲系谣言张家界的山上“长”满了韩国人?男孩8年未见母亲被告知被遗忘中国拥有亿元资产的家庭达13.3万户19岁小伙救下5人后溺亡 多方发声315晚会后胖东来又人满为患了张立群任西安交通大学校长“重生之我在北大当嫡校长”男子被猫抓伤后确诊“猫抓病”测试车高速逃费 小米:已补缴周杰伦一审败诉网易网友洛杉矶偶遇贾玲今日春分倪萍分享减重40斤方法七年后宇文玥被薅头发捞上岸许家印被限制高消费萧美琴窜访捷克 外交部回应联合利华开始重组专访95后高颜值猪保姆胖东来员工每周单休无小长假男子被流浪猫绊倒 投喂者赔24万小米汽车超级工厂正式揭幕黑马情侣提车了西双版纳热带植物园回应蜉蝣大爆发当地回应沈阳致3死车祸车主疑毒驾恒大被罚41.75亿到底怎么缴妈妈回应孩子在校撞护栏坠楼外国人感慨凌晨的中国很安全杨倩无缘巴黎奥运校方回应护栏损坏小学生课间坠楼房客欠租失踪 房东直发愁专家建议不必谈骨泥色变王树国卸任西安交大校长 师生送别手机成瘾是影响睡眠质量重要因素国产伟哥去年销售近13亿阿根廷将发行1万与2万面值的纸币兔狲“狲大娘”因病死亡遭遇山火的松茸之乡“开封王婆”爆火:促成四五十对奥巴马现身唐宁街 黑色着装引猜测考生莫言也上北大硕士复试名单了德国打算提及普京时仅用姓名天水麻辣烫把捣辣椒大爷累坏了

资讯网 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化