PCL 欧拉角

本文详细介绍了三维空间中欧拉角(Yaw,Pitch,Roll)的概念,以及它们与旋转矩阵和四元数之间的转换方法。包括Z-X-Y顺规下的旋转矩阵计算,欧拉角转四元数和四元数转欧拉角的算法实现,并给出了C++代码示例。同时,提到了在不同坐标系(左手系和右手系)中的差异以及PCL库中的转换操作。
摘要由CSDN通过智能技术生成

一、简介

欧拉角:

Yaw :偏航 绕Y轴旋转

pitch :俯仰角 绕X轴旋转

Roll: 滚动 绕Z轴旋转

3D Rotation Converter

Quaternions - Visualisation

二、万向锁

Roll: 滚动 绕X轴旋转 的自由度消失的问题,倒是原来的三个自由度变成了两个自由度,YZ两个自由度重合了。

欧拉角的顺规

Z-X-Y, X-Y-Z, X-Y-X, Z-X-Y ···

欧拉角与旋转矩阵之间的转化公式及原理_欧拉角转旋转矩阵-CSDN博客

右手坐标系下基础旋转矩阵

//在右手系中绕X轴旋转p° 对应的矩阵Rx
        | 1    0        0 |
  Rx=   | 0   cosp   -sinp|
        | 0   sinp    cosp|
//在右手系中绕Y轴旋转h° 对应的矩阵Ry
        | cosh   0   sinh|
  Ry=   |  0     1     0 |
        |-sinh   0   cosh|
//在右手系中绕Z轴旋转b° 对应的矩阵Rz
        |cosb  -sinb   0 |
  Rz=   |sinb   cosb   0 |
        |  0     0     1 |
//欧拉角(p,h,b)在右手系中对应的旋转矩阵(Z-X-Y顺规)
               |cosbcosh-sinbsinpsinh  -sinbcosp  cosbsinh+sinbsinpcosh|
R = Rz*Rx*Ry = |sinbcosh+cosbsinpsinh   cosbcosp  sinbsinh-cosbsinpcosh|
               |     -cospsinh            sinp           cospcosh      |

左手系下的基础旋转矩阵

//在左手系中绕X轴旋转p° 对应的矩阵Rx
        | 1     0        0 |
  Rx=   | 0    cosp    sinp|
        | 0   -sinp    cosp|
//在左手系中绕Y轴旋转h° 对应的矩阵Ry
        | cosh   0   -sinh|
  Ry=   |  0     1      0 |
        | sinh   0    cosh|
//在左手系中绕Z轴旋转b° 对应的矩阵Rz
        |cosb    sinb   0 |
  Rz=   |-sinb   cosb   0 |
        |  0      0     1 |
//欧拉角(p,h,b)在右手系中对应的旋转矩阵(Z-X-Y顺规)
                |cosbcosh+sinbsinpsinh   sinbcosp  -cosbsinh+sinbsinpcosh|
R1 = Rz*Rx*Ry = |-sinbcosh+cosbsinpsinh  cosbcosp   sinbsinh+cosbsinpcosh|
                |      cospsinh            -sinp           cospcosh      |

三、矩阵和四元数、欧拉角之间的转换

  1. 四元数的定义

一个四元数可以表示为q = w + xi + yj + zk,为了方便,我们下面使用q = ((x, y, z),w) = (v, w),其中v是向量,w是实数,这样的式子来表示一个四元数。

q=((x,y,z)sin(θ/2), cos(θ/2))

  1. 欧拉角转四元数

//  定义一个四元素的机构
struct  Quaternion
{
    double  w, x, y, z;
};

 //  欧拉角度转四元素
Quaternion    EulerAngles2Quaternion (double  yaw, double pitch, double roll)  // 按照zyx 的内旋的方式进行选择   这里写入的是弧度
{
    double cosy = cos(yaw * 0.5);
    double siny = sin(yaw * 0.5);
    double cosp = cos(pitch * 0.5);
    double sinp = sin(pitch * 0.5);
    double cosr = cos(roll * 0.5);
    double sinr = sin(roll * 0.5);



    // 开始计算 四元数
    Quaternion q;
    q.w = cosy * cosp * cosr + siny * sinp * sinr;
    q.x = cosy * cosp * sinr - siny * sinp * cosr;
    q.y = siny * cosp * sinr + cosy * sinp * cosr;
    q.z = siny * cosp * cosr - cosy * sinp * sinr;
   return q;
}
int main()
{
    Quaternion  q;
    q=EulerAngles2Quaternion(0.349, 0.524, 0.698);  // z y x 
    cout << q.w << endl;
    cout << q.x << endl;
    cout << q.y << endl;
    cout << q.z << endl;
}

matlab 用欧拉角转四元数
>>        yaw = 0.349; 
       pitch = 0.524; 
       roll = 0.698;
       q = angle2quat( yaw, pitch, roll )% z y x 的顺序

q =

    0.9092    0.2830    0.2970    0.0704

四元数转欧拉角



//  定义一个四元素的机构
struct  Quaternion
{
    double  w, x, y, z;
};

struct EulerAngles
{
        double roll, pitch, yaw;  // 对应的是弧度制   x  y z 
};



// 四元数转欧拉角 
EulerAngles    Quaternion2EulerAngles(Quaternion  q)
{
    EulerAngles  e;
    double sinr_cosp = 2 * (q.w * q.x + q.y * q.z);
    double cosr_cosp = 1 - 2 * (q.x * q.x + q.y * q.y);
    e.roll = std::atan2(sinr_cosp, cosr_cosp);


    
    double sinp = 2 * (q.w * q.y - q.z * q.x);
    if (std::abs(sinp) >= 1)  
    e.pitch = std::copysign(M_PI / 2, sinp); // use 90 degrees if out of range
    else
        e.pitch = std::asin(sinp);

    // 同理   
    double siny_cosp = 2 * (q.w * q.z + q.x * q.y);
    double cosy_cosp = 1 - 2 * (q.y * q.y + q.z * q.z);
    e.yaw = std::atan2(siny_cosp, cosy_cosp);
    return  e;
}



int main()
{
    Quaternion  q;
    q=EulerAngles2Quaternion(0.349, 0.524, 0.698);  // z y x 
    cout << q.w << endl;
    cout << q.x << endl;
    cout << q.y << endl;
    cout << q.z << endl;


    EulerAngles e;
    e=Quaternion2EulerAngles(q);
    cout <<"roll:    "<< e.roll << endl;
    cout <<"pitch:  "<< e.pitch<< endl;
    cout << "yaw:   "<<e.yaw << endl;
}

matlab


>> q = [0.909, 0.283, 0.297,0.070];
       [pitch, roll, yaw] = quat2angle( q, 'zyx' )

pitch =

    0.3484


roll =

    0.5243


yaw =

    0.6980

欧拉角转矩阵


// 欧拉角 转旋转矩阵  zyx 的格式旋转的
// 传入弧度  

Eigen::Matrix3d EulerAnglesZYX2RotationMatrix(const double yaw, const double pitch, const double roll)
{

    // 第二部  分别计算Rx  Ry  Rz 的矩阵
    Eigen::Matrix<double, 3, 3> Rz;
    Rz << cos(yaw),    -sin(yaw),    0,
               sin(yaw),     cos(yaw),     0,
                 0, 0, 1;
    cout << "Rz:  " << endl;
    cout << Rz << endl;

    //Ry  
    Eigen::Matrix<double, 3, 3> Ry;
    Ry << cos(pitch), 0., sin(pitch),
        0., 1., 0.,
        -sin(pitch), 0., cos(pitch);
    cout << "Ry:  " << endl;
    cout << Ry << endl;


    // Rx
    Eigen::Matrix<double, 3, 3> Rx;
    Rx << 1., 0., 0.,
        0., cos(roll), -sin(roll),
        0., sin(roll), cos(roll);

    cout << "Rx:  " << endl;
    cout << Rx << endl;

    return  Rz*Ry*Rx;
}


int main()
{

    Eigen::Matrix3d matrix =EulerAnglesZYX2RotationMatrix(0.349, 0.524, 0.698);

    cout << "matrix:  " << endl;
    cout << matrix << endl;

}


>> R=angle2dcm(0.349,0.524,0.698,'ZYX')

R =

    0.8136    0.2961   -0.5003
    0.0402    0.8299    0.5565
    0.5800   -0.4729    0.6633

>> R1=R'

R1 =

    0.8136    0.0402    0.5800
    0.2961    0.8299   -0.4729
   -0.5003    0.5565    0.6633

>> 

旋转矩阵转欧拉角



 Eigen::Vector3d   RotationMatrix2EulerAnglesZYX(const Eigen::Matrix3d &R)
{
    Eigen::Vector3d n = R.col(0);
    Eigen::Vector3d o = R.col(1);
    Eigen::Vector3d a = R.col(2);

    Eigen::Vector3d e(3);
    double y = atan2(n(1), n(0));
    double p = atan2(-n(2), n(0) * cos(y) + n(1) * sin(y));
    double r = atan2(a(0) * sin(y) - a(1) * cos(y), -o(0) * sin(y) + o(1) * cos(y));
    e(0) = y;
    e(1) = p;
    e(2) = r;

    return e;

}


int main()
{

    Eigen::Matrix3d matrix =EulerAnglesZYX2RotationMatrix(0.349, 0.524, 0.698);

    cout << "matrix:  " << endl;
    cout << matrix << endl;

    Eigen::Vector3d  euler = RotationMatrix2EulerAnglesZYX(matrix);
    cout << "欧拉角度是    :  " << endl;
    cout << euler << endl;
}

旋转矩阵转四元数


 Quaternion RotationMatrix2Quaternion(const Eigen::Matrix3d &R)
 {
     Quaternion q;
     q.w = sqrt(1 + R(1, 1) + R(2, 2) + R(3, 3)) / 2;
     q.x = (R(3, 2) - R(2, 3)) / 4 * q.w;
     q.y=(R(1,3)-R(3,1))/ 4 * q.w;
     q.z = (R(2, 1) - R(1, 2)) / 4 * q.w;
     return  q;
 }


 //  这个和旋转角度有关系
 Quaternion RotationMatrix2Quaternion(const Eigen::Matrix3d &R)
 {
     Quaternion q;
     q.w = sqrt(1 + R(1, 1) + R(2, 2) + R(3, 3)) / 2;
     q.x = (R(3, 2) - R(2, 3)) / 4 * q.w;
     q.y=(R(1,3)-R(3,1))/ 4 * q.w;
     q.z = (R(2, 1) - R(1, 2)) / 4 * q.w;
     return  q;
 }

所有代码:



# if  1 

//  定义一个四元素的机构
struct  Quaternion
{
    double  w, x, y, z;
};

 //  欧拉角度转四元素
Quaternion    EulerAngles2Quaternion (double  yaw, double pitch, double roll)  // 按照zyx 的内旋的方式进行选择   这里写入的是弧度
{
    double cosy = cos(yaw * 0.5);
    double siny = sin(yaw * 0.5);
    double cosp = cos(pitch * 0.5);
    double sinp = sin(pitch * 0.5);
    double cosr = cos(roll * 0.5);
    double sinr = sin(roll * 0.5);



    // 开始计算 四元数
    Quaternion q;
    q.w = cosy * cosp * cosr + siny * sinp * sinr;
    q.x = cosy * cosp * sinr - siny * sinp * cosr;
    q.y = siny * cosp * sinr + cosy * sinp * cosr;
    q.z = siny * cosp * cosr - cosy * sinp * sinr;
   return q;
}

struct EulerAngles
{
        double roll, pitch, yaw;  // 对应的是弧度制   x  y z 
};
EulerAngles    Quaternion2EulerAngles(Quaternion  q)
{
    EulerAngles  e;
    double sinr_cosp = 2 * (q.w * q.x + q.y * q.z);
    double cosr_cosp = 1 - 2 * (q.x * q.x + q.y * q.y);
    e.roll = std::atan2(sinr_cosp, cosr_cosp);


    
    double sinp = 2 * (q.w * q.y - q.z * q.x);
    if (std::abs(sinp) >= 1)  
    e.pitch = std::copysign(M_PI / 2, sinp); // use 90 degrees if out of range
    else
        e.pitch = std::asin(sinp);

    // 同理   
    double siny_cosp = 2 * (q.w * q.z + q.x * q.y);
    double cosy_cosp = 1 - 2 * (q.y * q.y + q.z * q.z);
    e.yaw = std::atan2(siny_cosp, cosy_cosp);
    return  e;
}


// 欧拉角 转旋转矩阵  zyx 的格式旋转的
// 传入弧度  

Eigen::Matrix3d EulerAnglesZYX2RotationMatrix(const double yaw, const double pitch, const double roll)
{

    // 第二部  分别计算Rx  Ry  Rz 的矩阵
    Eigen::Matrix<double, 3, 3> Rz;
    Rz << cos(yaw),    -sin(yaw),    0,
               sin(yaw),     cos(yaw),     0,
                 0, 0, 1;
    cout << "Rz:  " << endl;
    cout << Rz << endl;

    //Ry  
    Eigen::Matrix<double, 3, 3> Ry;
    Ry << cos(pitch), 0., sin(pitch),
        0., 1., 0.,
        -sin(pitch), 0., cos(pitch);
    cout << "Ry:  " << endl;
    cout << Ry << endl;


    // Rx
    Eigen::Matrix<double, 3, 3> Rx;
    Rx << 1., 0., 0.,
        0., cos(roll), -sin(roll),
        0., sin(roll), cos(roll);

    cout << "Rx:  " << endl;
    cout << Rx << endl;

    return  Rz*Ry*Rx;
}


 Eigen::Vector3d   RotationMatrix2EulerAnglesZYX(const Eigen::Matrix3d &R)
{
    Eigen::Vector3d n = R.col(0);
    Eigen::Vector3d o = R.col(1);
    Eigen::Vector3d a = R.col(2);

    Eigen::Vector3d e(3);
    double y = atan2(n(1), n(0));
    double p = atan2(-n(2), n(0) * cos(y) + n(1) * sin(y));
    double r = atan2(a(0) * sin(y) - a(1) * cos(y), -o(0) * sin(y) + o(1) * cos(y));
    e(0) = y;
    e(1) = p;
    e(2) = r;

    return e;

}

 //  这个和旋转角度有关系
 Quaternion RotationMatrix2Quaternion(const Eigen::Matrix3d &R)
 {
     Quaternion q;
     q.w = sqrt(1 + R(1, 1) + R(2, 2) + R(3, 3)) / 2;
     q.x = (R(3, 2) - R(2, 3)) / 4 * q.w;
     q.y=(R(1,3)-R(3,1))/ 4 * q.w;
     q.z = (R(2, 1) - R(1, 2)) / 4 * q.w;
     return  q;
 }

int main()
{

    Eigen::Matrix3d matrix =EulerAnglesZYX2RotationMatrix(0.349, 0.524, 0.698);

    cout << "matrix:  " << endl;
    cout << matrix << endl;

    Eigen::Vector3d  euler = RotationMatrix2EulerAnglesZYX(matrix);
    cout << "欧拉角度是    :  " << endl;
    cout << euler << endl;

    Quaternion  q;
    q = RotationMatrix2Quaternion(matrix);
    cout << "四元素    :  " << endl;
    //q=EulerAngles2Quaternion(0.349, 0.524, 0.698);  // z y x 
    cout << q.w << endl;
    cout << q.x << endl;
    cout << q.y << endl;
    cout << q.z << endl;

}

PCL 相互转换

pcl 欧拉角转四元数


    //[ x: 0.6977819, y: 0.5243475, z: 0.3479638 ]
    float yaw = 0.3479638; // 弧度角

    float pitch = 0.5243475; // 弧度角
    float roll = 0.6977819; // 弧度角


    //  Z   Y   X  的顺序
    quaternion = Eigen::AngleAxisd(yaw, Eigen::Vector3d::UnitZ()) *
                         Eigen::AngleAxisd(pitch, Eigen::Vector3d::UnitY()) *
                         Eigen::AngleAxisd(roll, Eigen::Vector3d::UnitX());

    cout << "4元数x:"<< quaternion.x() << endl;
    cout << "4元数y:"<< quaternion.y() << endl;
    cout << "4元数z:"  << quaternion.z() << endl;
    cout << "4元数w:" << quaternion.w() << endl;
    cout << "====================================================================" << endl;
    cout << endl;
    cout << endl;
    cout << endl;
    cout << endl;

    Eigen::Isometry3d iso = Eigen::Translation3d(1, 2, 3) * quaternion;
    Eigen::Matrix4d res = iso.matrix();
    cout << "等距映射:" << endl << res << endl;
    cout << "====================================================================" << endl;

PCL 四元数转旋转矩阵


    // 四元数转旋转矩阵
    // [ 0.2830271, 0.2970436, 0.0698527, 0.9092752 ]
    //===============================================================
    Eigen::Matrix<double, 3, 3> rotationmatrix = quaternion.toRotationMatrix();
    cout << " 四元数转旋转矩阵" << endl;
    cout << rotationmatrix << endl;
    cout << "--------------------------------------------------------------------------------------------------------------------" << endl;

PCL 旋转矩阵转四元数


// 旋转矩阵构造四元数

    // 3,从旋转矩阵构造四元数
    Eigen::Quaterniond qua(rotationmatrix);

    cout << "qua4元数x:" << qua.x() << endl;
    cout << "qua4元数y:"  << qua.y() << endl;
    cout << "qua4元数z:" << qua.z() << endl;
    cout << "qua4元数w:" << qua.w() << endl;

PCL 四元数转欧拉角


    // 4,从四元数转换为欧拉角
    Eigen::Vector3d eulerzyx = qua.toRotationMatrix().eulerAngles(2,1,0);  //2 1 0 表示的是 旋转顺序 ZYX
    cout << "四元数转换为欧拉角:" << endl << eulerzyx << endl;  //弧度单位

PCL 欧拉角转旋转矩阵


      // 5,从欧拉角转换为旋转矩阵(先转四元数, 再转旋转矩阵)
    Eigen::Quaterniond quaternion_1 = Eigen::AngleAxisd(eulerzyx(0), Eigen::Vector3d::UnitZ()) *Eigen::AngleAxisd(eulerzyx(1), Eigen::Vector3d::UnitY()) *Eigen::AngleAxisd(eulerzyx(2), Eigen::Vector3d::UnitX());
    Eigen::Matrix3d RTM= quaternion_1.toRotationMatrix();
    cout << "从欧拉角转换为旋转矩阵(先转四元数, 再转旋转矩阵):" << endl << RTM << endl;

PCL所有代码


int main()
{
    Eigen::Matrix<float, 4, 4> transformation = Eigen::Matrix<float, 4, 4>::Identity();
    Eigen::Quaterniond quaternion;

    //1,从弧度(欧拉角)转四元数
    cout << "===================================================================="<< endl;

    //[ x: 0.6977819, y: 0.5243475, z: 0.3479638 ]
    float yaw = 0.3479638; // 弧度角

    float pitch = 0.5243475; // 弧度角
    float roll = 0.6977819; // 弧度角


    //  Z   Y   X  的顺序
    quaternion = Eigen::AngleAxisd(yaw, Eigen::Vector3d::UnitZ()) *
                         Eigen::AngleAxisd(pitch, Eigen::Vector3d::UnitY()) *
                         Eigen::AngleAxisd(roll, Eigen::Vector3d::UnitX());

    cout << "4元数x:"<< quaternion.x() << endl;
    cout << "4元数y:"<< quaternion.y() << endl;
    cout << "4元数z:"  << quaternion.z() << endl;
    cout << "4元数w:" << quaternion.w() << endl;
    cout << "====================================================================" << endl;
    cout << endl;
    cout << endl;
    cout << endl;
    cout << endl;

    Eigen::Isometry3d iso = Eigen::Translation3d(1, 2, 3) * quaternion;
    Eigen::Matrix4d res = iso.matrix();
    cout << "等距映射:" << endl << res << endl;
    cout << "====================================================================" << endl;
      

    // 2 四元数转旋转矩阵
    // [ 0.2830271, 0.2970436, 0.0698527, 0.9092752 ]
    //===============================================================
    Eigen::Matrix<double, 3, 3> rotationmatrix = quaternion.toRotationMatrix();
    cout << " 四元数转旋转矩阵" << endl;
    cout << rotationmatrix << endl;
    cout << "--------------------------------------------------------------------------------------------------------------------" << endl;


    // 3,从旋转矩阵构造四元数
    Eigen::Quaterniond qua(rotationmatrix);

    cout << "qua4元数x:" << qua.x() << endl;
    cout << "qua4元数y:"  << qua.y() << endl;
    cout << "qua4元数z:" << qua.z() << endl;
    cout << "qua4元数w:" << qua.w() << endl;


    cout << "--------------------------------------------------------------------------------------------------------------------" << endl;



    // 4,从四元数转换为欧拉角
    Eigen::Vector3d eulerzyx = qua.toRotationMatrix().eulerAngles(2,1,0);  //2 1 0 表示的是 旋转顺序 ZYX
    cout << "四元数转换为欧拉角:" << endl << eulerzyx << endl;  //弧度单位
    cout << "--------------------------------------------------------------------------------------------------------------------" << endl;




      // 5,从欧拉角转换为旋转矩阵(先转四元数, 再转旋转矩阵)
    Eigen::Quaterniond quaternion_1 = Eigen::AngleAxisd(eulerzyx(0), Eigen::Vector3d::UnitZ()) *Eigen::AngleAxisd(eulerzyx(1), Eigen::Vector3d::UnitY()) *Eigen::AngleAxisd(eulerzyx(2), Eigen::Vector3d::UnitX());
    Eigen::Matrix3d RTM= quaternion_1.toRotationMatrix();
    cout << "从欧拉角转换为旋转矩阵(先转四元数, 再转旋转矩阵):" << endl << RTM << endl;

    system("pause");

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值