我如何使用Eigen库创建包含pitch、yaw、roll的旋转矩阵?
因为我找不到一个现成的函数来实现这个功能,所以我自己写了一个,如果将来有人遇到同样的问题,这里就是它。
Eigen::AngleAxisd rollAngle(roll, Eigen::Vector3d::UnitZ());
Eigen::AngleAxisd yawAngle(yaw, Eigen::Vector3d::UnitY());
Eigen::AngleAxisd pitchAngle(pitch, Eigen::Vector3d::UnitX());
Eigen::Quaternion<double> q = rollAngle * yawAngle * pitchAngle;
Eigen::Matrix3d rotationMatrix = q.matrix();
凯撒的回答没问题,但正如David Hammen所说,这取决于您的应用。对我来说(水下或空中车辆领域),获胜组合是:
Eigen::Quaterniond
euler2Quaternion( const double roll,
const double pitch,
const double yaw )
{
Eigen::AngleAxisd rollAngle(roll, Eigen::Vector3d::UnitX());
Eigen::AngleAxisd pitchAngle(pitch, Eigen::Vector3d::UnitY());
Eigen::AngleAxisd yawAngle(yaw, Eigen::Vector3d::UnitZ());
Eigen::Quaterniond q = yawAngle * pitchAngle * rollAngle;
return q;
}
创建旋转矩阵所需的只有俯仰角、偏航角、翻滚角以及执行矩阵乘法的能力。
首先,为每个旋转轴(即俯仰、偏航、翻滚)创建一个旋转矩阵。这些矩阵将具有以下值:
俯仰矩阵:
1, 0, 0, 0,
0, cos(pitch), sin(pitch), 0,
0, -sin(pitch), cos(pitch), 0,
0, 0, 0, 1
cos(yaw), 0, -sin(yaw), 0,
0, 1, 0, 0,
sin(yaw), 0, cos(yaw), 0,
0, 0, 0, 1
滚动矩阵:
cos(roll), sin(roll), 0, 0,
-sin(roll), cos(roll), 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
接下来,将它们全部相乘。顺序很重要。对于普通的旋转,您需要先将Roll矩阵乘以Yaw矩阵,然后将乘积乘以Pitch矩阵。但是,如果您想通过倒退来“撤消”旋转,则需要按相反的顺序执行乘法(除了角度具有相反的值之外)。
我从Euler Angle Visualization Tool这个网站上将他们的Java实现翻译成了C++。
#include <iostream>
#include <math.h>
#include <Eigen/Dense>
Eigen::Matrix3d rotation_from_euler(double roll, double pitch, double yaw){
// roll and pitch and yaw in radians
double su = sin(roll);
double cu = cos(roll);
double sv = sin(pitch);
double cv = cos(pitch);
double sw = sin(yaw);
double cw = cos(yaw);
Eigen::Matrix3d Rot_matrix(3, 3);
Rot_matrix(0, 0) = cv*cw;
Rot_matrix(0, 1) = su*sv*cw - cu*sw;
Rot_matrix(0, 2) = su*sw + cu*sv*cw;
Rot_matrix(1, 0) = cv*sw;
Rot_matrix(1, 1) = cu*cw + su*sv*sw;
Rot_matrix(1, 2) = cu*sv*sw - su*cw;
Rot_matrix(2, 0) = -sv;
Rot_matrix(2, 1) = su*cv;
Rot_matrix(2, 2) = cu*cv;
return Rot_matrix;
}
int main() {
Eigen::Matrix3d rot_mat = rotation_from_euler(0, 0, 0.5*M_PI);
std::cout << rot_mat << std::endl;
return 0;
}
这里是一个使用标准的ZYX顺序实现的例子,就像在wikipedia中找到的那样。
template <typename T>
Eigen::Matrix3<T> eulerZYX_2_rot(T roll_rad, T pitch_rad, T yaw_rad) {
// ZYX order, same as rot_z(yaw_rad) * rot_y(pitch_rad) * rot_x(roll_rad)
static_assert(std::is_floating_point_v<T>, "Floating point required.");
T sx = sin(roll_rad);
T cx = cos(roll_rad);
T sy = sin(pitch_rad);
T cy = cos(pitch_rad);
T sz = sin(yaw_rad);
T cz = cos(yaw_rad);
Eigen::Matrix3<T> rot(3, 3);
rot(0, 0) = cz * cy;
rot(0, 1) = cz * sy * sx - sz * cx;
rot(0, 2) = cz * sy * cx + sz * sx;
rot(1, 0) = sz * cy;
rot(1, 1) = sz * sy * sx + cz * cx;
rot(1, 2) = sz * sy * cx - cz * sx;
rot(2, 0) = -sy;
rot(2, 1) = cy * sx;
rot(2, 2) = cy * cx;
return rot;
}