深入理解Eigen几何模块:从旋转矩阵到四元数
概述
在计算机视觉和机器人学领域,几何变换是最基础也是最重要的概念之一。本文将通过分析gaoxiang12/slambook项目中的eigenGeometry.cpp示例代码,深入讲解如何使用Eigen库进行各种几何变换操作。
Eigen是一个强大的C++模板库,专门用于线性代数运算,其几何模块提供了丰富的功能来处理2D和3D空间中的旋转、平移等变换。
基本旋转表示
旋转矩阵
旋转矩阵是表示旋转最直接的方式。在3D空间中,旋转矩阵是一个3×3的正交矩阵:
Eigen::Matrix3d rotation_matrix = Eigen::Matrix3d::Identity();
这里创建了一个3×3的单位矩阵,表示不进行任何旋转。
旋转向量(轴角表示)
旋转向量是一种紧凑的旋转表示方式,它用一个旋转轴和一个旋转角度来表示旋转:
Eigen::AngleAxisd rotation_vector(M_PI/4, Eigen::Vector3d(0,0,1));
这行代码表示绕Z轴旋转45度(π/4弧度)。旋转向量可以方便地转换为旋转矩阵:
rotation_matrix = rotation_vector.toRotationMatrix();
坐标变换
有了旋转表示后,我们可以用它来变换向量:
Eigen::Vector3d v(1,0,0);
Eigen::Vector3d v_rotated = rotation_vector * v;
// 或者使用旋转矩阵
v_rotated = rotation_matrix * v;
这两种方式都会得到相同的结果,因为它们在数学上是等价的。
欧拉角
欧拉角是一种直观的旋转表示方式,它将旋转分解为绕三个坐标轴的连续旋转:
Eigen::Vector3d euler_angles = rotation_matrix.eulerAngles(2,1,0);
这里的参数(2,1,0)表示ZYX顺序,也就是常见的yaw-pitch-roll顺序。欧拉角虽然直观,但存在万向节死锁问题,不适合用于插值或连续旋转。
刚体变换
刚体变换(欧氏变换)包括旋转和平移,可以用4×4的齐次坐标矩阵表示:
Eigen::Isometry3d T = Eigen::Isometry3d::Identity();
T.rotate(rotation_vector);
T.pretranslate(Eigen::Vector3d(1,3,4));
这里创建了一个变换矩阵,先旋转再平移。使用这个变换矩阵可以同时进行旋转和平移操作:
Eigen::Vector3d v_transformed = T*v; // 等价于 R*v + t
四元数
四元数是表示旋转的另一种方式,它避免了欧拉角的万向节死锁问题,且计算效率高:
Eigen::Quaterniond q = Eigen::Quaterniond(rotation_vector);
四元数有四个分量,顺序为(x,y,z,w),其中w是实部,(x,y,z)是虚部。四元数也可以从旋转矩阵构造:
q = Eigen::Quaterniond(rotation_matrix);
使用四元数旋转向量时需要注意数学上的定义:
v_rotated = q*v; // 数学上是 qvq^{-1}
实际应用建议
-
选择旋转表示:根据具体需求选择合适的旋转表示方式。旋转矩阵通用但冗余;欧拉角直观但有万向节死锁;四元数紧凑且适合插值。
-
性能考虑:在需要大量旋转运算时,四元数通常是最佳选择,因为它只需要存储4个数字且运算效率高。
-
变换组合:当需要组合多个变换时,使用变换矩阵(Isometry3d)最为方便,可以清晰地表示旋转和平移的组合。
-
精度问题:在长时间运行或多次变换组合后,旋转矩阵可能会失去正交性,需要定期重新正交化。
通过掌握Eigen几何模块的这些基本操作,我们可以在SLAM、机器人运动学、计算机视觉等领域有效地处理各种几何变换问题。这些基础知识对于理解更复杂的算法和系统至关重要。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考