当前位置: 首页 > java >正文

Eigen中Eigen::Affine3d和Eigen::Isometry3d详解

1. 背景:仿射变换 vs 等距变换

在三维空间中,一个 齐次变换矩阵(4×4)一般写作:

T=[At01],A∈R3×3,t∈R3 T = \begin{bmatrix} A & \mathbf{t} \\ 0 & 1 \end{bmatrix}, \quad A \in \mathbb{R}^{3\times 3}, \mathbf{t} \in \mathbb{R}^3 T=[A0t1],AR3×3,tR3

这里的 A 决定了旋转/缩放/剪切,t 是平移。

  • Affine Transform (仿射变换)

    T(x)=Ax+t T(\mathbf{x}) = A\mathbf{x} + \mathbf{t} T(x)=Ax+t

    A 可以是任意非奇异矩阵,允许旋转、缩放、剪切。

  • Isometry (等距变换)

    T(x)=Rx+t,R∈SO(3) T(\mathbf{x}) = R\mathbf{x} + \mathbf{t}, \quad R \in SO(3) T(x)=Rx+t,RSO(3)

    这里 R 必须是正交矩阵,且 det⁡(R)=+1\det(R)=+1det(R)=+1,即纯旋转,不允许缩放/畸变。
    这是 SE(3) 里标准的位姿表示。

所以:

  • Affine3d = 一般的仿射变换(包含旋转+平移+缩放+剪切)。
  • Isometry3d = Affine3d 的子集(只允许旋转+平移)。

2. Eigen 里的实现关系

在 Eigen 里:

  • Affine3d 继承自 Transform<double, 3, Affine>
  • Isometry3d 继承自 Transform<double, 3, Isometry>

它们本质上都是 Eigen::Transform 的模板特化,只是内部对 矩阵 A 的约束不同

类型模板参数允许的变换典型用途
Eigen::Affine3dTransform<double,3,Affine>旋转、平移、缩放、剪切图形学/通用几何变换
Eigen::Isometry3dTransform<double,3,Isometry>旋转 + 平移(R ∈ SO(3))机器人学/SLAM 位姿

3. 转换关系

3.1 Isometry3d → Affine3d

总是安全的,因为等距变换一定是仿射变换的特例:

Eigen::Isometry3d iso = Eigen::Isometry3d::Identity();
Eigen::Affine3d affine = iso;  // OK

3.2 Affine3d → Isometry3d

可能丢失信息:
如果 Affine3d 中包含缩放/剪切,转成 Isometry3d 时会 直接假设线性部分是旋转矩阵,数值不符合 SE(3) 要求的话,结果不可预测。

Eigen::Affine3d affine = Eigen::Affine3d::Identity();
affine.linear() *= 2.0; // 缩放
Eigen::Isometry3d iso = affine; //  结果不是严格的旋转+平移

3.3 构造与赋值

// 直接从旋转+平移构造
Eigen::Isometry3d iso = Eigen::Translation3d(1,2,3) * Eigen::AngleAxisd(M_PI/4, Eigen::Vector3d::UnitZ());
Eigen::Affine3d affine = iso; // 安全

4. 常见接口差异

两者常用接口大部分相同,比如:

  • .translation() → 获取/设置平移
  • .linear() → 获取/设置旋转部分(注意:Affine3d 不一定是正交矩阵!)
  • * 运算符 → 变换向量或点
  • .matrix() → 获取 4×4 齐次矩阵

唯一区别:

  • Isometry3d 在数值上 保证旋转矩阵正交,适合表示位姿。
  • Affine3d 不做约束,可能引入畸变。

5. 实际应用建议

  • 机器人学 / SLAM / 计算机视觉
    Isometry3d,保证运算结果在 SE(3),不会意外引入缩放。

    Eigen::Isometry3d Tcw;  // 相机位姿
    Eigen::Vector3d Pc = Tcw * Pw;
    
  • 计算机图形学 / CAD / 建模
    Affine3d,因为可能需要缩放、剪切等操作。


6. 小示例

#include <Eigen/Dense>
#include <iostream>int main() {// 构造 Isometry3d (旋转+平移)Eigen::Isometry3d iso = Eigen::Isometry3d::Identity();iso.translate(Eigen::Vector3d(1,2,3));iso.rotate(Eigen::AngleAxisd(M_PI/4, Eigen::Vector3d::UnitZ()));// 构造 Affine3dEigen::Affine3d affine = Eigen::Affine3d::Identity();affine.linear() *= 2.0;  // 加缩放affine.translation() << 1, 2, 3;// 转换Eigen::Affine3d affine_from_iso = iso; // 安全Eigen::Isometry3d iso_from_affine = affine; //  不一定合法std::cout << "Isometry3d matrix:\n" << iso.matrix() << "\n\n";std::cout << "Affine3d matrix:\n" << affine.matrix() << "\n";
}

总结:

  • Affine3d = 仿射变换(更通用,允许缩放/剪切)
  • Isometry3d = 仿射变换的子集(严格 SE(3),只允许旋转+平移)
  • 实际上 Isometry3d 更适合 位姿 (pose)Affine3d 更适合 通用几何变换
  • Isometry3d 可以安全转 Affine3d,反之不保证合法

7.综合示例

下面是一个 综合示例,完整演示 Eigen::Affine3dEigen::Isometry3d 的构造、转换、使用、对比,适合 SLAM / 机器人学场景。


综合示例:位姿运算与差异对比

#include <Eigen/Dense>
#include <iostream>int main() {// -------------------------------// 1. 构造 Isometry3d(严格的位姿:旋转+平移)// -------------------------------Eigen::Isometry3d T1 = Eigen::Isometry3d::Identity();T1.translate(Eigen::Vector3d(1, 0, 0));  // 平移T1.rotate(Eigen::AngleAxisd(M_PI/4, Eigen::Vector3d::UnitZ()));  // 绕Z轴旋转45度std::cout << "Isometry3d T1:\n" << T1.matrix() << "\n\n";// -------------------------------// 2. 构造 Affine3d(包含缩放的仿射变换)// -------------------------------Eigen::Affine3d T2 = Eigen::Affine3d::Identity();T2.translate(Eigen::Vector3d(0, 2, 0));  // 平移T2.linear() *= 2.0;  // ⚠️ 加缩放,破坏正交性std::cout << "Affine3d T2 (with scaling):\n" << T2.matrix() << "\n\n";// -------------------------------// 3. 类型转换// -------------------------------Eigen::Affine3d affine_from_iso = T1;  // ✅ 永远安全Eigen::Isometry3d iso_from_affine = T2;  // ⚠️ 丢失缩放信息,不一定合法std::cout << "Affine from Isometry (safe):\n" << affine_from_iso.matrix() << "\n\n";std::cout << "Isometry from Affine (unsafe if scaled):\n" << iso_from_affine.matrix() << "\n\n";// -------------------------------// 4. 应用:变换点// -------------------------------Eigen::Vector3d p(1, 1, 1);Eigen::Vector3d p_T1 = T1 * p;   // 严格位姿变换Eigen::Vector3d p_T2 = T2 * p;   // 包含缩放的仿射变换std::cout << "Original point: " << p.transpose() << "\n";std::cout << "Transformed by Isometry3d T1: " << p_T1.transpose() << "\n";std::cout << "Transformed by Affine3d T2 (scaled): " << p_T2.transpose() << "\n\n";// -------------------------------// 5. 提取旋转和平移// -------------------------------std::cout << "T1 translation: " << T1.translation().transpose() << "\n";std::cout << "T1 rotation matrix:\n" << T1.rotation() << "\n\n";std::cout << "T2 translation: " << T2.translation().transpose() << "\n";std::cout << "T2 linear part (not guaranteed orthogonal):\n" << T2.linear() << "\n\n";return 0;
}

输出要点(示例)

Isometry3d T1:
0.707 -0.707 0 1
0.707  0.707 0 0
0      0     1 0
0      0     0 1Affine3d T2 (with scaling):
2 0 0 0
0 2 0 2
0 0 2 0
0 0 0 1Affine from Isometry (safe):   // 完全一致
Isometry from Affine (unsafe): // 旋转矩阵不是严格正交Original point: 1 1 1
Transformed by Isometry3d T1:  1 1.41421 1
Transformed by Affine3d T2 (scaled): 2 4 2T1 translation: 1 0 0
T1 rotation matrix: 正交矩阵
T2 translation: 0 2 0
T2 linear part: 非正交矩阵(带缩放)

综合结论

  • Isometry3d 保证 SE(3) 位姿,适合 SLAM/机器人学。
  • Affine3d 更通用,可以引入缩放/剪切(但在位姿优化中通常不合理)。
  • Isometry3d → Affine3d 永远安全。
  • Affine3d → Isometry3d 可能非法。
  • 处理点云/位姿变换时,建议 优先用 Isometry3d

http://www.xdnf.cn/news/20376.html

相关文章:

  • 得物前端二面面经总结
  • LeetCode_数学
  • 解析、创建Excel文件的开源库OpenXLSX介绍
  • ES06-SpringData集成
  • Valgrind检测内存泄漏入门指南
  • ClickHouse 中的物化列与物化视图
  • SpringBoot01-配置文件
  • 未来教育行业的 Go 服务开发解决方案与实践
  • 【PyTorch实战:Tensor】4、NumPy与PyTorch Tensor指南:深度学习中的数据操作与转换
  • Python基础(①⑧Queue)
  • 机床夹具设计 +选型
  • 持续集成和持续交付 (CI/CD) 工具——Jenkins
  • `objdump`与`addr2line`工具详解
  • 新服务器初始化:Git全局配置与SSH密钥生成
  • 【Canvas与图标】古铜色“HTML”图标
  • eclipse 安装 lombok
  • 【基础-单选】下列哪一项不属于ArkUI组件的公共事件?
  • JVM调优总结
  • ECharts Gallery:Apache官方数据可视化模板库,助你快速制作交互图表并实现深度定制
  • 微服务的编程测评系统22-项目部署结束
  • 基于Echarts+HTML5可视化数据大屏展示-图书馆大屏看板
  • 软考 系统架构设计师系列知识点之杂项集萃(142)
  • JVM中如何调优新生代和老生代?
  • 基于LSTM深度学习的网络流量测量算法matlab仿真
  • C++ 内存模型:用生活中的例子理解并发编程
  • linux C 语言开发 (三) 建立云服务器
  • C++ 小游戏:拍桌子
  • Nmap网络扫描工具详细使用教程
  • 算法学习路径
  • 基于 Gemini 的 CI/CD 自动化测评 API 集成实战教程