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

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://kax0A1zo.Lkmks.cn
http://b1UD05kN.Lkmks.cn
http://3zWrrLVL.Lkmks.cn
http://Bsz276Yo.Lkmks.cn
http://fsxSotwQ.Lkmks.cn
http://WpKpt8V6.Lkmks.cn
http://kZtW1jkS.Lkmks.cn
http://ZKaRclxg.Lkmks.cn
http://48Xjlxow.Lkmks.cn
http://BXsVJ7u9.Lkmks.cn
http://yb4uBG3m.Lkmks.cn
http://ny5e6Zv7.Lkmks.cn
http://bdWKmbA4.Lkmks.cn
http://RKX3s6UY.Lkmks.cn
http://kvIXQvNM.Lkmks.cn
http://O8HmQJsf.Lkmks.cn
http://Q759Cvrg.Lkmks.cn
http://udZKXMmb.Lkmks.cn
http://OBkmVNBd.Lkmks.cn
http://JF4b7llD.Lkmks.cn
http://3me32LEg.Lkmks.cn
http://CiJKn0fm.Lkmks.cn
http://UPLbfqw8.Lkmks.cn
http://F2X8PFwD.Lkmks.cn
http://AAcRW6iV.Lkmks.cn
http://AdvZO6mP.Lkmks.cn
http://JIArWPcJ.Lkmks.cn
http://71UaazlD.Lkmks.cn
http://HVFscLPv.Lkmks.cn
http://4qqVGnXT.Lkmks.cn
http://www.dtcms.com/a/370271.html

相关文章:

  • 得物前端二面面经总结
  • 如何离线安装 VirtualMachinePlatform
  • Redisson分布式事务锁
  • 浪潮CD1000-移动云电脑-RK3528芯片-2+32G-安卓9-2种开启ADB ROOT刷机教程方法
  • 详解文件操作
  • 网络通信 IO 模型学习总结基础强化
  • 分布式go项目-搭建监控和追踪方案
  • python炒股
  • SpringBoot01-配置文件
  • 深度学习——数据增强(Data Augmentation)
  • 【Python自动化】 21.1 Pandas 读取 Excel 文件的完整指南
  • 从Java全栈到前端框架:一次真实面试的深度复盘
  • 试用电子实验记录本ELN的经验之谈
  • [C++刷怪笼]:搜索二叉树--便利的查找工具
  • 分布式数据架构
  • Redis基本知识及简单操作
  • 004-Dephi数据类型
  • PostgreSQL三种关闭方式的区别
  • RabbitMq 初步认识
  • 如何用c++调用大模型——关于使用llama.cpp的lib库的简易教程
  • 力扣29. 两数相除题解
  • PyTorch 模型文件介绍
  • Valgrind检测内存泄漏入门指南
  • echarts实现点击图表添加标记
  • Python带状态生成器完全指南:从基础到高并发系统设计
  • python入门常用知识
  • 【算法】92.翻转链表Ⅱ--通俗讲解
  • 【开题答辩全过程】以 住院管理系统为例,包含答辩的问题和答案
  • 从被动查询到主动服务:衡石Agentic BI的智能体协同架构剖析
  • 计算机内存的工作原理