欧拉角与四元数

  • 要理解旋转欧拉角和四元数的关系。

旋转正向

绕轴旋转的正向,记住xyz这个顺序即可(提取以下每行的字符,不过是XYZ的滚筒排序):

  • 绕x轴旋转,由y到z是正向。
  • 绕y轴旋转,由z到x是正向。
  • 绕z轴旋转,由x到y是正向。

利用Eigen库进行旋转

采用Test的方式来理解Eigen库提供的绕轴旋转的功能,运行如下的代码可以观察到点绕着z轴旋转45度的效果:

#include <opencv2/opencv.hpp>
#include <Eigen/Dense>
#include <Eigen/Geometry>
#include <cmath>
 
// 绘制坐标轴
void DrawAxes(cv::Mat &img, const cv::Point2f &origin, float length, const cv::Scalar &color) {
    cv::Point2f x_end = origin + cv::Point2f(length, 0);
    cv::Point2f y_end = origin + cv::Point2f(0, length);
    cv::line(img, origin, x_end, color, 2);
    cv::putText(img, "x", x_end, cv::FONT_HERSHEY_SIMPLEX, 0.5, color, 2);
    cv::line(img, origin, y_end, color, 2);
    cv::putText(img, "y", y_end, cv::FONT_HERSHEY_SIMPLEX, 0.5, color, 2);
}
 
// 将四元数应用于点
cv::Point2f ApplyQuaternion(const Eigen::Quaterniond &q, const cv::Point2f &point) {
    Eigen::Vector3d v(point.x, point.y, 0);
    Eigen::Vector3d rotated = q * v;
    return cv::Point2f(rotated.x(), rotated.y());
}
 
int TestQuant() {
    // 创建一个空白图像
    cv::Mat img(500, 500, CV_8UC3, cv::Scalar(255, 255, 255));
 
    // 定义原点
    cv::Point2f origin(img.cols / 2, img.rows / 2);
 
    // 绘制初始坐标轴
    DrawAxes(img, origin, 230, cv::Scalar(0, 0, 255)); // 红色BGR
 
    // 创建一个绕 Z 轴旋转 45 度的四元数
    double angle = M_PI / 4; // 45 度
    Eigen::AngleAxisd rotation_z(angle, Eigen::Vector3d::UnitZ());
    Eigen::Quaterniond q(rotation_z);
 
    // 绘制旋转后的坐标轴
    cv::Point2f x_end_rotated = ApplyQuaternion(q, cv::Point2f(200, 0));
    cv::Point2f y_end_rotated = ApplyQuaternion(q, cv::Point2f(0, 200));
    std::cout << "x_end_rotated: " << x_end_rotated << std::endl;
    std::cout << "y_end_rotated: " << y_end_rotated << std::endl;
    cv::line(img, origin, x_end_rotated + origin, cv::Scalar(0, 255, 0), 2); // 绿色
    cv::putText(img, "x'", x_end_rotated + origin, cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 255, 0), 2);
    cv::line(img, origin, y_end_rotated + origin, cv::Scalar(0, 255, 0), 2); // 绿色
    cv::putText(img, "y'", y_end_rotated + origin, cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 255, 0), 2);
 
    // 显示图像
    cv::imshow("Quaternion Rotation", img);
    cv::waitKey(0);
 
    return 0;
}
 
int main() {
    TestQuant();
    return 0;
}

结果图:

image.png