jjzjj

SLAM知识点——Eigen旋转量间变换求解、变换矩阵求解

Jerry_Sea 2024-05-12 原文

文章目录

0 前言

下面内容包含头文件如下:

#include<iostream>
#include<Eigen/Core>              //核心矩阵运算库(Vector3d,Matrix3d)
#include<Eigen/Dense>          // 稠密矩阵的代数运算(逆和特征值)
#include<Eigen/Geometry>  // 引入旋转平移(旋转矩阵、旋转向量、欧拉角、四元数、平移向量)
#include<opencv2/opencv.hpp>

using namespace cv;
using namespace std;

#define DEG2RAD(x) ((x)*0.017453293)

1 旋转向量间变换求解

旋转量包括:欧拉角、旋转矩阵、旋转向量、四元数

1.1 欧拉角

1.1.1 欧拉角 -> 旋转矩阵

1)Eigen库将欧拉角转换为旋转矩阵

  float init_roll = 1.4162955503546129e+00,init_pitch=1.9927596853157299e+00,init_yaw = -5.5358076219140663e+01;

  Eigen::AngleAxisf init_rotation_x(DEG2RAD(init_roll), Eigen::Vector3f::UnitX());
  Eigen::AngleAxisf init_rotation_y(DEG2RAD(init_pitch), Eigen::Vector3f::UnitY());
  Eigen::AngleAxisf init_rotation_z(DEG2RAD(init_yaw), Eigen::Vector3f::UnitZ());

  Eigen::Matrix3f R_M;
  R_M=init_rotation_z*init_rotation_y*init_rotation_x;
  std::cout<<"R_M: "<<std::endl<<R_M<<std::endl;

  /*
      R_M: 
          0.568102     0.822958 -0.000574131
        -0.822223     0.567565   -0.0426499
        -0.0347732    0.0247016      0.99909
  */

欧拉角转换成旋转矩阵(相对于世界坐标系的旋转矩阵)通常是按外旋方式(绕固定轴),X-Y-Z顺序。 外旋是左乘,旋转顺序x-y-z(rpy),所以是先R(x),再R(y)*R(x),最后R(z)*R(y)*R(x);

2)自定义函数将欧拉角转为旋转矩阵

//这里theta也是弧度制
Eigen::Matrix3d eulerAnglesToRotationMatrix(Eigen::Vector3d &theta)
{
    Eigen::Matrix3d R_x;    // 计算旋转矩阵的X分量
    R_x <<
            1,              0,               0,
            0,  cos(theta[0]),  -sin(theta[0]),
            0,  sin(theta[0]),   cos(theta[0]);

    Eigen::Matrix3d R_y;    // 计算旋转矩阵的Y分量
    R_y <<
            cos(theta[1]),   0, sin(theta[1]),
            0,   1,             0,
            -sin(theta[1]),  0, cos(theta[1]);

    Eigen::Matrix3d R_z;    // 计算旋转矩阵的Z分量
    R_z <<
            cos(theta[2]), -sin(theta[2]), 0,
            sin(theta[2]),  cos(theta[2]), 0,
            0,              0,             1;
    Eigen::Matrix3d R = R_z * R_y * R_x;
    return R;
}

注意:

  Eigen::Vector3d point3d(p_x,p_y,p_z);
  Eigen::Vector3d theta(fixroll,fixpitch,fixyaw);
  Eigen::Matrix3d R_2 = eulerAnglesToRotationMatrix(theta);
  std::cout<<"R_2_P: "<<std::endl<<R_2*point3d<<std::endl;
  
  //上述矩阵乘以点坐标进行变换,等价于下述变换
  
  float x =p_x * cos(fixyaw) - p_y * sin(fixyaw);
  float y = p_y * cos(fixyaw) + p_x * sin(fixyaw);
  p_x = x;
  p_y = y;
  //再绕y轴
  float temp_x = p_x;
  p_x =  p_x * cos(fixpitch) + p_z * sin(fixpitch);
  p_z = -temp_x * sin(fixpitch) + p_z * cos(fixpitch);
  //最后绕x轴
  float temp_y = p_y;
  float temp_z = p_z;
  p_y = temp_y * cos(fixroll) - temp_z * sin(fixroll);
  p_z = temp_y * sin(fixroll) + temp_z * cos(fixroll);
  cout<<"pxpypz: "<<p_x<<" "<<p_y<<" "<<p_z<<endl;

参考:欧拉角和旋转矩阵之间的转换

1.2 旋转矩阵

1.2.1 旋转矩阵 -> 欧拉角

1)tf库

  tf::Matrix3x3 M;
  M.setValue(5.6810212543969762e-01, 8.2295789186479229e-01,  -5.7413088648496612e-04, -8.2222312468457914e-01,  5.6756515720693990e-01, -4.2649893058088473e-02,  -3.4773207542891066e-02, 2.4701553819839669e-02,  9.9908995263011369e-01);
  double roll, pitch, yaw;
  M.getRPY(roll, pitch, yaw);
  std::cout<<"eulerAngle:  "<<roll* 180 / M_PI<<" "<<pitch* 180 / M_PI<<" "<<yaw* 180 / M_PI<<std::endl;
    /*
      eulerAngle:  1.4163 1.99276 -55.3581
  */
  • 使用tf最有效!#include<tf/tf.h>
  • 使用eigen库,该方法行不通!!eigen将matrix转欧拉角会出错。
    ypr = R_AB.eulerAngles(2, 1, 0);
  • 使用公式法计算,但是准确性不够:

2)公式法

Eigen::Vector3d rotationMatrixToEulerAngles(Eigen::Matrix3d &R)
{
    assert(isRotationMatirx(R));
    double sy = sqrt(R(0,0) * R(0,0) + R(1,0) * R(1,0));
    bool singular = sy < 1e-6;
    double x, y, z;
    if (!singular)
    {
        x = atan2( R(2,1), R(2,2));
        y = atan2(-R(2,0), sy);
        z = atan2( R(1,0), R(0,0));
    }
    else
    {
        x = atan2(-R(1,2), R(1,1));
        y = atan2(-R(2,0), sy);
        z = 0;
    }
    return {x, y, z};
}

2 变换矩阵求解

2.1 欧拉角+平移向量 -> 变换矩阵

  float init_x=-1.0393021697572675e+00, init_y=2.5139219579635164e-03, init_z = -0.177126;
  float init_roll = 1.4162955503546129e+00,init_pitch=1.9927596853157299e+00,init_yaw = -5.5358076219140663e+01;
  
  Eigen::Translation3f init_translation(init_x, init_y, init_z);

  Eigen::AngleAxisf init_rotation_x(DEG2RAD(init_roll), Eigen::Vector3f::UnitX());
  Eigen::AngleAxisf init_rotation_y(DEG2RAD(init_pitch), Eigen::Vector3f::UnitY());
  Eigen::AngleAxisf init_rotation_z(DEG2RAD(init_yaw), Eigen::Vector3f::UnitZ());

  Eigen::Matrix4f  T_M =  Eigen::Matrix4f::Identity();
  T_M = (init_translation * init_rotation_z * init_rotation_y * init_rotation_x).matrix();  //current_guess_为ndt计算的初始换变换估计位置,4*4矩阵
  std::cout<<"T_M:  "<<std::endl<<T_M<<std::endl;

  /*
      T_M:  
          0.568102     0.822958 -0.000574132      -1.0393
        -0.822223     0.567565   -0.0426499   0.00251392
        -0.0347732    0.0247016      0.99909    -0.177126
                0            0            0            1
  */

对比1.1.1部分,可以看到R_M是T_M的左上角3x3矩阵。

2.2 旋转矩阵+平移向量 -> 变换矩阵

包含头文件:#include<tf/tf.h>

  Eigen::Matrix3d R_M;
  R_M<<2.7137982845306396e-01, -9.6243983507156372e-01,   7.9119475558400154e-03, 9.6094810962677002e-01,   2.7047842741012573e-01, -5.8482807129621506e-02,   5.4146166890859604e-02, 2.3474026471376419e-02,    9.9825710058212280e-01;
  Eigen::Vector3d t(-6.2644982337951660e-01, 9.2981266975402832e-01,   5.9500701725482941e-02);
  Eigen::Isometry3d  T_M3=Eigen::Isometry3d::Identity();   // T_M3是一个4x4的矩阵
  T_M3.rotate (R_M);
  T_M3.pretranslate (t);
  std::cout<<"T_M3: "<<std::endl<<T_M3.matrix()<<std::endl;
  Eigen::Matrix4d T_M4 =  Eigen::Matrix4d::Identity();
  T_M4 = T_M3.matrix(); 
  std::cout<<"T_M4: "<<std::endl<<T_M4<<std::endl;
  /*
    T_M3:
        0.27138   -0.96244 0.00791195   -0.62645
        0.960948   0.270478 -0.0584828   0.929813
        0.0541462   0.023474   0.998257  0.0595007
        0          0          0          1
  T_M4: 
        0.27138   -0.96244 0.00791195   -0.62645
        0.960948   0.270478 -0.0584828   0.929813
        0.0541462   0.023474   0.998257  0.0595007
        0          0          0          1
  */

更多变换参考:
[1] https://blog.csdn.net/hero_cjn/article/details/105229484

有关SLAM知识点——Eigen旋转量间变换求解、变换矩阵求解的更多相关文章

  1. 旋转矩阵的几何意义 - 2

    点向量坐标矩阵的几何意义介绍旋转矩阵的几何含义之前,先介绍一下点向量坐标矩阵的几何含义点:在一维空间下就是一个标量,如同一条直线上,以任意某一个位置为0点,以一定的尺度间隔为1,2,3...,相反方向为-1,-2,-3...;如此就形成了一维坐标系,这时候任何一个点都可以用一个数值表示,如点p1=5,即即从原点出发沿着x轴正方向移动5个尺度;点p2=-3,负方向移动3个尺度;     在一维坐标系上过原点做垂直于一维坐标系的直线,则形成了二维坐标系,此时描述一个点需要两个数值来表示点p3=(3,2),即从原点出发沿着x轴正方向移动3个尺度,在此基础上沿着y轴正方向移动两个尺度的位置就是点p3。

  2. Unity 3D 制作开关门动画,旋转门制作,推拉门制作,门把手动画制作 - 2

    Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u

  3. ruby - 我怎样才能更好地了解/了解更多关于 Ruby 的知识? - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我最近开始学习Ruby,这是我的第一门编程语言。我对语法感到满意,并且我已经完成了许多只教授相同基础知识的教程。我已经写了一些小程序(包括我自己的数组排序方法,在有人告诉我谷歌“冒泡排序”之前我认为它非常聪明),但我觉得我需要尝试更大更难的东西来理解更多关于Ruby.关于如何执行此操作的任何想法?

  4. 华为OD机试真题 C++ 实现【带传送阵的矩阵游离】【2023 Q2 | 200分】 - 2

            所有题目均有五种语言实现。C实现目录、C++实现目录、Python实现目录、Java实现目录、JavaScript实现目录题目n行m列的矩阵,每个位置上有一个元素你可以上下左右行走,代价是前后两个位置元素值差的绝对值.另外,你最多可以使用一次传送阵(只能从一个数跳到另外一个相同的数)求从走上角走到右下角最少需要多少时间。输入描述:第一行两个整数n,m,分别代表矩阵的行和列。后面n行,每行m个整数,分别代表矩阵中的元素。输出描述:一个整数,表示最少需要多少时间。

  5. 欧拉角表示的姿态矩阵(313和312转序) - 2

    一、习惯约定图片来自PSINS(高精度捷联惯导算法)PSINS工具箱入门与详解.pptx二、基本旋转矩阵绕x轴逆时钟旋转α\alphaα角度Rx(α)=[ 1000cos⁡αsin⁡α0−sin⁡αcos⁡α]R_x(\alpha)=\begin{bmatrix}\1&0&0\\0&\cos\alpha&\sin\alpha\\0&-\sin\alpha&\cos\alpha\end{bmatrix}Rx​(α)=​ 100​0cosα−sinα​0sinαcosα​​绕y轴逆时钟旋转α\alphaα角度Ry(α)=[ cos⁡α0−sin⁡α010sin⁡α0cos⁡α]R_y(\alpha

  6. 欧拉角、旋转矩阵及四元数 - 2

    欧拉角、旋转矩阵及四元数1.简介2.欧拉角2.1欧拉角定义2.2右手系和左手系2.3转换流程3.旋转矩阵4.四元数4.1四元数与欧拉角和旋转矩阵之间等效变换4.2测试Matlab代码5.总结1.简介常用姿态参数表达方式包括方向余弦矩阵、欧拉轴/角参数、欧拉角、四元数以及罗德里格参数等。高分辨率光学遥感卫星主要采用欧拉角与四元数对姿态参数进行描述。这里着重讲解欧拉角、旋转矩阵和四元数。2.欧拉角2.1欧拉角定义欧拉角是表征刚体旋转的一种方法之一,由莱昂哈德·欧拉引入的三个角度,用于描述刚体相对于固定坐标系的方向。在摄影测量、空间科学或其它技术领域,一般用一组(三个)欧拉角描述两个空间坐标之间的旋

  7. 交叉编译eigen 到hi3559 - 2

    3559操作自记录0502ubuntu操作日志sudoapt-getinstallcmake-qt-guiwhereisaarch64-himix100-linux-gccaarch64-himix100-linux-gcc:/opt/hisi-linux/x86-arm/aarch64-himix100-linux/bin/aarch64-himix100-linux-gcc然后把同级的gnu放进来了,然后confige,然后generate然后make(没有输出安全通过),然后makeinstallhaitu@ubuntu:~/eigen-3.4.0/aarch_eigen$cdbuild

  8. ruby - 如何修改矩阵(Ruby std-lib Matrix 类)? - 2

    我理解RubystdlibMatrix是不可修改的,也就是说,例如。m=Matrix.zero(3,4)不会写m[0,1]=7但我非常想做...我可以用笨拙的编程来做,比如defmodify_value_in_a_matrix(matrix,row,col,newval)ary=(0...m.row_size).map{|i|m.rowi}.map(&:to_a)ary[row][col]=newvalMatrix[*ary]end...或者作弊,比如Matrix.send:[]=,0,1,7但我想知道,这一定是人们一直遇到的问题。有没有一些标准的、习惯的方法可以做到这一点,而不必使用

  9. 线性代数让我想想:快速求三阶矩阵的逆矩阵 - 2

    快速求三阶矩阵的逆矩阵前言一般情况下,我们求解伴随矩阵是要注意符号问题和位置问题的(如下所示)A−1=1[  ][−[  ]−[  ]−[  ]  −[  ]]=A−1=1[  ][   M11−[M12]   M13−[M21]   M22−[M23]     M31−[M32]   M33]⊤\begin{aligned}&A^{-1}=\frac{1}{[\\]}\left[\begin{array}{cccccc}&-[\\]&\\-[\\]&&-[\\]\\\\&-[\\]&\\\end{array}\right]=\\\\&A^{-1}=\frac{1}{[\\]}\left[\b

  10. 相机校准—外参矩阵 - 2

    在本文中,我们将探讨摄影机的外参,并通过Python中的一个实践示例来加强我们的理解。相机外参摄像头可以位于世界任何地方,并且可以指向任何方向。我们想从摄像机的角度来观察世界上的物体,这种从世界坐标系到摄像机坐标系的转换被称为摄像机外参。那么,我们怎样才能找到相机外参呢?一旦我们弄清楚相机是如何变换的,我们就可以找到从世界坐标系到相机坐标系的基变换的变化。我们将详细探讨这个想法。具体来说,我们需要知道相机是如何定位的,以及它在世界空间中的位置,有两种转换可以帮助我们:有助于确定摄影机方向的旋转变换。有助于移动相机的平移变换。让我们详细看看每一个。旋转通过旋转改变坐标让我们看一下将点旋转一个角度

随机推荐