windSnowLi 2025-07-27 22:18 采纳率: 100%
浏览 19
已结题

C++ Eigen坐标系旋转矩阵乘顺序问题

已知A坐标系通过平移x y z并先绕自身X轴旋转rx再绕新的Y轴旋转ry再绕新的Z轴旋转rz;我想构建旋转矩阵,并且旋转矩阵能转回rx ry rz,经过实测

 Eigen::Matrix3d R;
 R = Eigen::AngleAxisd(r.x(), Eigen::Vector3d::UnitX()) * 
Eigen::AngleAxisd(r.y(), Eigen::Vector3d::UnitY()) * 
Eigen::AngleAxisd(r.z(), Eigen::Vector3d::UnitZ());

经过


   R.eulerAngles(0, 1, 2);

可以得到原始的rx,ry,rz,
可查到说旋转矩阵是从右往左应用,理解为了


Eigen::AngleAxisd(r.z(), Eigen::Vector3d::UnitZ()) * Eigen::AngleAxisd(r.y(), Eigen::Vector3d::UnitY()) * Eigen::AngleAxisd(r.x(), Eigen::Vector3d::UnitX());

式中的r与再通过

   R.eulerAngles(0, 1, 2);

得到的值不一样
麻烦请问一下,是我Eigen中的旋转矩阵乘顺序理解错误还是(0,1,2)的顺序也是从右往左来理解的问题?

是不是数学层面从右往左,但C++执行顺序是从左往右这方面的原因吗?
以下代码输出1 2 3

    auto&& fun = [](int a) {
        std::cout << a << "\n";
        return a;
    };
    int b = fun(1) * fun(2) * fun(3);

  • 写回答

4条回答 默认 最新

  • 宝码香车 优质创作者: JavaScript技术领域 2025-07-27 23:05
    关注

    让【宝码香车】来帮你解答,本回答参考DeepSeek编写,并整理提供。

    如果还有疑问可以点击头像关注私信或评论。如果答案让您满意,请采纳、点赞、关注,非常感谢!
     
    若您愿意支持,欢迎直接打赏,将不胜感激!
     

    在Eigen库中,旋转矩阵的乘法顺序确实容易引起混淆。根据你的问题描述,我将从数学原理和Eigen实现两个层面进行解释:

    1. 数学原理层面:
      旋转矩阵的乘法顺序遵循从右向左应用的规则。当你需要先绕X轴旋转,再绕Y轴,最后绕Z轴时,数学表达式应为:
    R = Rz * Ry * Rx
    

    这是因为旋转是相对于当前坐标系的连续变换。

    1. Eigen实现层面:
      你观察到的现象是正确的。在Eigen中,以下两种写法是等价的:
    // 写法1(推荐)
    Eigen::Matrix3d R = 
        Eigen::AngleAxisd(rz, Eigen::Vector3d::UnitZ()) * 
        Eigen::AngleAxisd(ry, Eigen::Vector3d::UnitY()) * 
        Eigen::AngleAxisd(rx, Eigen::Vector3d::UnitX());
    
    
    // 写法2(与写法1等效)
    Eigen::Matrix3d R = 
        (Eigen::AngleAxisd(rz, Eigen::Vector3d::UnitZ()) * 
        (Eigen::AngleAxisd(ry, Eigen::Vector3d::UnitY()) * 
        Eigen::AngleAxisd(rx, Eigen::Vector3d::UnitX()));
    
    1. 关于eulerAngles提取:
    Vector3d euler = R.eulerAngles(0, 1, 2);  // 0:X轴, 1:Y轴, 2:Z轴
    

    这里的参数顺序(0,1,2)表示提取欧拉角的顺序是X-Y-Z,对应的是旋转矩阵R = Rz * Ry * Rx的逆过程。

    1. 你的测试代码说明:
    auto&& fun = [](int a) {
        std::cout << a << "\n";
        return a;
    };
    int b = fun(1) * fun(2) * fun(3);  // 输出1 2 3
    

    这说明C++中乘法操作数的求值顺序是从左到右,但这与矩阵乘法本身的结合性无关。矩阵乘法始终是右结合的。

    1. 正确理解顺序:

    "初始坐标系"

    总结:

    • 数学上旋转矩阵乘法是右结合的:R = Rz * Ry * Rx
    • Eigen的实现与数学一致,乘法顺序也是从右向左
    • eulerAngles(0,1,2)提取的是X-Y-Z顺序的欧拉角
    • C++表达式求值顺序不影响矩阵乘法本身的结合性

    建议始终使用最直观的写法(写法1),这样代码既符合数学表达,又能正确反映旋转顺序。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

问题事件

  • 系统已结题 8月5日
  • 已采纳回答 7月28日
  • 修改了问题 7月27日
  • 创建了问题 7月27日