当前位置:   article > 正文

自动驾驶中的欧拉角-四元数-坐标变换_欧拉角坐标系转换

欧拉角坐标系转换

前言

在对角度的描述中,有欧拉角,四元数两中描述方式,其中欧拉角最直观,但是不具备唯一性,即按照不同的旋转方式得到的欧拉角表示结果是不一样的。但四元数的表达方式是唯一的,所以针对不同的设备,如果用欧拉角表示角度,一定得确定是用的哪种旋转顺序,目前使用最多的是ZYX,即先旋转Z轴,再旋转Y轴,再旋转X轴。但是百度apollo用的是ZXY坐标系,这里要特别注意。

一、apollo 中的欧拉角转四元数

ZXY 旋转顺序

首先明确一点不同的旋转顺序,欧拉角和四元数之间转换的公式是不一样的,以下推导使用的旋转顺序为: Z,X,Y;

X :pitch;
Y: roll;
Z: yaw;
这里注意,绕X 轴旋转为pitch, 绕Y轴旋转为roll,与常用的坐标系有点不一样,这里要特别注意。

1.1.欧拉角转四元数

绕 [公式] 轴旋转角度为,绕 [公式] 轴旋转角度为,绕 [公式] 轴旋转角度为,把这三个角轴转换为四元数得到以下公式:
在这里插入图片描述四元数相乘得到:

在这里插入图片描述
其中
q(1):w,
q(2):x,
q(3):y,
q(4): z

1.2,四元数转欧拉角

四元数转欧拉角:
在这里插入图片描述其中x:滚转角roll,y:俯仰角pitch,z:偏航角yaw

二、 ZYX顺序情况

以下推导使用的旋转顺序为: Z,X,Y;

X :roll;
Y: pitch;
Z: yaw;

2.1 分别绕x,y,z旋转

在这里插入图片描述

2.2 欧拉角转化公式ZYX:旋转矩阵

在这里插入图片描述此时,该旋转矩阵表示全局坐标(大地)到局部坐标(车辆),
如roll ,pitch ,yaw :表示当前车辆在大地坐标下绕x,y,z旋转的角度;
vector[车辆坐标系的x,y,z] = cMw * vector[全局坐标系下的x,y,z];
例如:
世界坐标系下的坐标(Xw,Yw,Zw)转换到相机坐标系下(Xc,Yc,Zc)。
将旋转矩阵取逆即可得到 相机坐标系 到 世界坐标系下的坐标。
在这里插入图片描述

三、ZXY代码直接计算

ZXY全局到局部:
X:roll;
Y:pitch;
z: yaw


  double x1 = cos(yaw) * acc_x - sin(yaw) * acc_y;
  double y1 = sin(yaw) * acc_x + cos(yaw) * acc_y;
  double z1 = acc_z;

  double x2 = x1;
  double y2 = cos(roll) * y1 - sin(roll) * z1;
  double z2 = sin(roll) * y1 + cos(roll) * z1;

  acc_x = cos(pitch) * x2 + sin(pitch) * z2;
  acc_y = y2;
  acc_z = -sin(pitch) * x2 + cos(pitch) * z2;

  // AERROR << "out=" << acc_x << "," << acc_y << "," << acc_z;
  Eigen::Vector3d vec(acc_x, acc_y, acc_z);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

ZXY局部到全局:

  double x2 = cos(pitch) * acc_x + sin(pitch) * acc_z;
  double y2 = acc_y;
  double z2 = -sin(pitch) * acc_x + cos(pitch) * acc_z;
  double x1 = x2;
  double y1 = cos(roll) * y2 - sin(roll) * z2;
  double z1 = sin(roll) * y2 + cos(roll) * z2;
  acc_x = cos(yaw) * x1 - sin(yaw) * y1;
  acc_y = sin(yaw) * x1 + cos(yaw) * y1;
  acc_z = z1;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

四、ZXY 使用Eigen函数方法

X:roll;
Y:pitch;
z: yaw

//欧拉角转四元数
Eigen::Quaterniond tmp_q =
      Eigen::AngleAxisd(yaw_t, Eigen::Vector3d::UnitZ()) *
      Eigen::AngleAxisd(roll_t, Eigen::Vector3d::UnitX()) *
      Eigen::AngleAxisd(pitch_t, Eigen::Vector3d::UnitY());
  // AERROR << "Eigen: " << tmp_q.x() << "," << tmp_q.y() << "," << tmp_q.z()
  //        << "," << tmp_q.w();
  Eigen::Matrix3d rotation_mat = Eigen::Matrix3d::Identity();

  //四元数转旋转矩阵
  rotation_mat = tmp_q.toRotationMatrix();
  //局部到全局
  Vector3d vec0 = rotation_mat * orig;
  AERROR << "Eigen= " << vec0[0] << "," << vec0[1] << "," << vec0[2];
  //全局到局部
  Vector3d vec1 = rotation_mat.inverse() * orig;
  AERROR << "Eigen= " << vec1[0] << "," << vec1[1] << "," << vec1[2];
  //旋转矩阵按照ZXY方式得到欧拉角
  Vector3d vec_rpy = rotation_mat.eulerAngles(2, 0, 1); //ZXY
  // AERROR << "ypr=" << vec_rpy[0] << "," << vec_rpy[1] << "," << vec_rpy[2];
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

说明:原创文章,转载请注明出处

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/422768
推荐阅读
相关标签
  

闽ICP备14008679号