• 【Eigen】Chapter4 几何模块 Geometry


    Chapter4 Geometry

    (1)空间变换

    ​ 在本节中,将介绍几何模块提供的许多可能性,以处理2D和3D旋转以及射影或仿射变换

    Eigen的Geometry模块提供了两种不同的几何变换:

    ​ 1 抽象的变换,例如旋转(轴角或四元数表示),平移,缩放。这些转换未表示为矩阵,但是仍然可以将它们与表达式中的矩阵和向量混合,并根据需要将它们转换为矩阵。

    ​ 2 射影或仿射变换矩阵:请参见Transform类。这些确实是矩阵。注意, 如果要使用OpenGL 4x4矩阵,则需要Affine3f和Affine3d。

    ​ 可以从抽象转换构造一个Transform:Transform t(AngleAxis(angle,axis));

    ​ 或像这样:

    Transform t;
    t = AngleAxis(angle,axis);
    

    ​ 但是注意,不幸的是,由于C ++的工作方式,不能这样做:Transform t = AngleAxis(angle,axis);

    ​ 说明:在C ++语言中,这将要求Transform具有一个来自AngleAxis的非显式转换构造函数,但是我们真的不想在此允许隐式转换。

    ​ 1)变换的类型

    变换类型典型的初始化代码
    2D旋转Rotation2D rot2(angle_in_radian);
    3D旋转的轴角方法AngleAxis aa(angle_in_radian, Vector3f(ax,ay,az));
    3D旋转的四元数方法Quaternion q; q = AngleAxis(angle_in_radian, axis);
    N维缩放Scaling(sx, sy, sz)
    N维平移Translation(tx, ty, tz)
    N维仿射 Transform t = Translation3f(p) * [AngleAxisf](a,axis) * [Scaling]
    N维线性变换Matrix t = AngleAxisf(a,axis) * Scaling(s);

    ​ 关于旋转的注意事项

    ​ 要变换多个矢量,首选旋转矩阵,而对于其他用法,四元数是紧凑,快速和稳定的首选表示形式。最后,Rotation2D和AngleAxis主要是创建其他旋转对象的便捷类型。

    关于平移和缩放的注意事项
    

    ​ 像AngleAxis一样,这些类旨在简化线性(Matrix)和仿射(Transform)变换的创建/初始化。但是,与使用效率低下的AngleAxis不同,编写任何类型的转换作为输入的通用高效算法可能仍然很有趣。

    ​ 上述任何转换类型都可以转换为相同性质的任何其他类型,或者转换为更通用的类型。以下是一些其他示例:

    Rotation2Df r;  r  = Matrix2f(..);       // assumes a pure rotation matrix
    AngleAxisf aa;  aa = Quaternionf(..);
    AngleAxisf aa;  aa = Matrix3f(..);       // assumes a pure rotation matrix
    Matrix2f m;     m  = Rotation2Df(..);
    Matrix3f m;     m  = Quaternionf(..);       Matrix3f m;   m = Scaling(..);
    Affine3f m;     m  = AngleAxis3f(..);       Affine3f m;   m = Scaling(..);
    Affine3f m;     m  = Translation3f(..);     Affine3f m;   m = Matrix3f(..);
    

    ​ 2)仿射变换

    ​ 本部分介绍仿射变换,概念上,仿射变换是一个非奇异线性变换 linear()与一个平移变换t的复合,可能是因为x’ = linear()*x + t ;所以linear()是线性部分

    将变换应用于点VectorNf p1, p2; p2 = t * p1;
    将变换应用于向量VectorNf vec1, vec2;vec2 = t.linear() * vec1;
    应用一个更一般的变换作用在normal vectorVectorNf n1, n2;MatrixNf normalMatrix = t.linear().inverse().transpose();n2 = (normalMatrix * n1).normalized();
    将纯旋转变换作用在一个 normal vectorn2 = t.linear() * n1;
    OpenGL compatibility 3DglLoadMatrixf(t.data());
    OpenGL compatibility 2DAffine3f aux([Affine3f::Identity]());aux.linear().topLeftCorner<2,2>() = t.linear();aux.translation().start<2>() = t.translation();glLoadMatrixf(aux.data());

    ​ 3)欧拉角

    Matrix3f m;
    m = AngleAxisf(angle1, Vector3f::UnitZ())
        * AngleAxisf(angle2, Vector3f::UnitY())
        * AngleAxisf(angle3, Vector3f::UnitZ());
    
    (2)十四讲中的例子
    #include 
    #include 
    #include 
    #include 
    
    int main()
    {
        //------------1 声明旋转矩阵与向量并初始化-----------
        Eigen::Matrix3d rotation_matrix = Eigen::Matrix3d::Identity();
        std::cout << "rotation_matrix = \n" << rotation_matrix << std::endl;
        Eigen::AngleAxisd rotation_vector(M_PI / 4, Eigen::Vector3d(0, 0, 1));
        std::cout.precision(3);     //输出三位有效数字
        std::cout << "rotation_vector_matrix = \n" << rotation_vector.matrix() << std::endl;
        rotation_matrix = rotation_vector.toRotationMatrix();
    
        //-------------2 对v进行操作-------------
        Eigen::Vector3d v(1, 0, 0);
        Eigen::Vector3d v_rotated = rotation_vector * v;
        std::cout << "(1, 0, 0) after rotation (by matrix) = \n" << v_rotated.transpose() << std::endl;
        v_rotated = rotation_matrix * v;
        std::cout << "(1, 0, 0) after rotation (by matrix) = \n" << v_rotated.transpose() << std::endl;
    
        //-------------3 欧拉角------------------
        Eigen::Vector3d euler_angle = rotation_matrix.eulerAngles(2, 1, 0);
        std::cout << "yaw pitch roll = " << euler_angle.transpose() << std::endl;
    
        //-------------4 欧氏变换----------------
        Eigen::Isometry3d T = Eigen::Isometry3d::Identity();
        T.rotate(rotation_vector);
        T.pretranslate(Eigen::Vector3d(1, 3, 4));
        std::cout << "Transform matrix = \n" << T.matrix() << std::endl;
        //-------------5 坐标变换----------------
        Eigen::Vector3d v_transformed = T * v;
        std::cout << "v transformed = " << v_transformed.transpose() << std::endl;
        //-------------6 四元数------------------
        Eigen::Quaterniond q = Eigen::Quaterniond(rotation_vector);
        std::cout << "quaterniond from rotation vector = " << q.coeffs().transpose() << std::endl;
        q = Eigen::Quaterniond(rotation_matrix);
        std::cout << "quaterniond from rotation matrix = " << q.coeffs().transpose() << std::endl;
    
        v_rotated = q * v;
        std::cout << "(1, 0, 0) after rotation  = \n" << v_rotated.transpose() << std::endl;
        std::cout << "should be equal to " << (q * Eigen::Quaterniond(0, 1, 0, 0) * q.inverse()).coeffs().transpose() << std::endl;
    
    }
    
  • 相关阅读:
    PyQt5可视化编程-事件、信号和对话框
    Cross-validation: evaluating estimator performance
    MFC创建一个接收消息但不显示的窗口
    Android AMS——进程LRU列表更新(十七)
    应广单片机使用IHRC校准ILRC--附带产物随机数产生器
    【电源专题】案例:异常样机为什么只在40%以下电量时与其他样机显示电量差异10%,40%以上电量差异却都在5%以内。
    Unity实战之一个脚本实现雷达图
    PCL 滤波采样(二)——MLS平滑
    Ansible-roles学习
    树莓派Raspberrypi安装Kali Linux保姆教程(通过树莓派安装ARM Kali教程)
  • 原文地址:https://blog.csdn.net/ASUNAchan/article/details/127037990