一、简介
欧拉角:
Yaw :偏航 绕Y轴旋转
pitch :俯仰角 绕X轴旋转
Roll: 滚动 绕Z轴旋转
二、万向锁
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 |
三、矩阵和四元数、欧拉角之间的转换
-
四元数的定义
一个四元数可以表示为q = w + xi + yj + zk,为了方便,我们下面使用q = ((x, y, z),w) = (v, w),其中v是向量,w是实数,这样的式子来表示一个四元数。
q=((x,y,z)sin(θ/2), cos(θ/2))
-
欧拉角转四元数
// 定义一个四元素的机构
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;
}