Eigen学习笔记(16)-空间变换
原文:Eigen官网-Space transformations
本篇将介绍基于geometry module的2D 、3D旋转和投影或仿射变换。
【Eigen学习笔记(16)-空间变换】Eigen中的Geometry module提供了两种不同的几何变换:
- 抽象变换,如旋转(rotation 由角和轴表示或由四元数表示)、平移(translation)、缩放(scaling)。这些转换不表示为矩阵,但您仍然可以将它们与表达式中的矩阵和向量混合,并根据需要将它们转换为矩阵。
- 投影或仿射变换矩阵:参见Transform类。这些以矩阵的形式进行表示。
Transform t(AngleAxis(angle,axis));
或者像这样:
Transform t;
t = AngleAxis(angle,axis);
但是根据C++的机制,不可以通过如下方式定义:
Transform t = AngleAxis(angle,axis);
解释:在C++语言中,这需要一个从AngleAxis到Transform的非显式转换构造函数,但是我们确实不希望允许在这里隐式转换。
1. Transformation的类型
Transformation type 转换类型 |
Typical initialization code 典型初始化代码 |
- |
---|---|---|
2D rotation from an angle 2D 旋转只需一个旋转角度 |
Rotation2D rot2(angle_in_radian); | |
3D rotation as an angle + axis 3D旋转需要旋转角度+旋转轴 |
AngleAxis aa(angle_in_radian, Vector3f(ax,ay,az));
The axis vector must be normalized. |
|
3D rotation as a quaternion 四元数形式的3D旋转 |
Quaternion q;
q = AngleAxis(angle_in_radian, axis); |
提供了两类方便的类型定义: Quaternionf for float Quaterniond for double 也可以直接给定参数: quater.x() = 0; quater.y() = 0; quater.z() = sin(M_PI/2.0 / 2.0); quater.w() = cos(M_PI/2.0 / 2.0); |
N-D Scaling 尺度缩放 |
Scaling(sx, sy) Scaling(sx, sy, sz) Scaling(s) Scaling(vecN) |
|
N-D Translation 平移 |
Translation Translation Translation Translation |
|
N-D Affine transformation 仿射变换 |
Transform Transform |
放射变换是一些变换的结合,按平移×旋转×缩放的顺序连乘 |
N-D Linear transformations (pure rotations, scaling, etc.) 线性变换 |
Matrix Matrix Matrix |
(1) AngleAxis示例:
结合
MatrixBase::Unit{X,Y,Z}
,可以用AngleAxis
方便的模仿Euler-angles。// Code:
Matrix3f m;
m = AngleAxisf(0.25*M_PI, Vector3f::UnitX())
* AngleAxisf(0.5*M_PI,Vector3f::UnitY())
* AngleAxisf(0.33*M_PI, Vector3f::UnitZ());
cout << m << endl << "is unitary: " << m.isUnitary() << endl;
// Output:
1.19e-0701
0.969-0.2490
0.2490.969 1.19e-07
is unitary: 1
(2) 对三维点进行变换
//变换前的点
Eigen::Vector3f v3f_a(x_m, y_m, 0.0);
//变换后的点:变换矩阵左乘点向量
Eigen::Vector3f v3f_b = affine3f*v3f_a;
(3) 要知道affine3f的四维矩阵Matrix4f,采用如下转换
Eigen::Matrix4f a;
Eigen::Affine3f b;
b.matrix() = a;
若要转换多个向量,首选的表示形式是旋转矩阵(rotation matrices),而对于其他用途,四元数(Quaternion)是可选择的表示形式,因为它们是紧凑、快速和稳定的。最后,Rotation2D和AngleAxis是创建其他旋转对象的最主要的便利类型。
关于Translation和Scaling的注释:
像AngleAxis一样,这些类被设计成简化linear(matrix)和affine(Transform)变换的创建和初始化。然而,与使用效率低的AngleAxis不同,这些类可能可应用于编写通用和高效的算法,这些算法可以任意类型的转换作为输入。
上述任何transformation types都可以转换为任何其他性质相同的类型,或转换为更通用的类型。以下是一些示例:
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. Transformation 类型之间的通用API 在某种程度上,Eigen的geometry module允许您编写处理任何类型转换表示的通用算法:
- | - |
---|---|
Concatenation of two transformations | gen1 * gen2; |
Apply the transformation to a vector | vec2 = gen1 * vec1; |
Get the inverse of the transformation | gen2 = gen1.inverse(); |
Spherical interpolation (Rotation2D and Quaternion only) |
rot3 = rot1.slerp(alpha,rot2); |
- | - |
---|---|
Apply the transformation to a point 对一个点应用变换 |
VectorNf p1, p2;
p2 = t * p1; |
Apply the transformation to a vector 对一个向量应用变换 |
VectorNf vec1, vec2;
vec2 = t.linear() * vec1; |
Apply a general transformation to a normal vector 对正则化向量应用一般变换 |
VectorNf n1, n2;
MatrixNf normalMatrix = t.linear().inverse().transpose(); n2 = (normalMatrix * n1).normalized(); |
Apply a transformation with pure rotation to a normal vector (no scaling, no shear) | n2 = t.linear() * n1; |
OpenGL compatibility 3D | glLoadMatrixf(t.data()); |
OpenGL compatibility 2D | Affine3f aux(Affine3f::Identity());
aux.linear().topLeftCorner<2,2>() = t.linear(); aux.translation().start<2>() = t.translation(); glLoadMatrixf(aux.data()); |
- | - |
---|---|
full read-write access to the internal matrix | t.matrix() = matN1xN1;
// N1 means N+1 matN1xN1 = t.matrix(); |
coefficient accessors | t(i,j) = scalar;
<=> t.matrix()(i,j) = scalar;
scalar = t(i,j); <=> scalar = t.matrix()(i,j); |
translation part | t.translation() = vecN;
vecN = t.translation(); |
linear part | t.linear() = matNxN;
matNxN = t.linear(); |
extract the rotation matrix | matNxN = t.rotation(); |
虽然可以通过连接基本转换来创建和更新转换对象,但Transform类还具有一个过程API:
- | procedural API | equivalent natural API |
---|---|---|
Translation | t.translate(Vector_(tx,ty,…));
t.pretranslate(Vector_(tx,ty,…)); |
t *= Translation_(tx,ty,…);
t = Translation_(tx,ty,…) * t; |
Rotation In 2D and for the procedural API, any_rotation can also be an angle in radian |
t.rotate(any_rotation);
t.prerotate(any_rotation); |
t *= any_rotation;
t = any_rotation * t; |
Scaling | t.scale(Vector_(sx,sy,…));
t.scale(s); t.prescale(Vector_(sx,sy,…)); t.prescale(s); |
t *= Scaling(sx,sy,…);
t *= Scaling(s); t = Scaling(sx,sy,…) * t; t = Scaling(s) * t; |
Shear transformation ( 2D only ! ) |
t.shear(sx,sy);
t.preshear(sx,sy); |
- |
注意,在这两个API中,任何多个转换都可以在一个表达式中连接,如下两个等效示例所示:
t.pretranslate(..).rotate(..).translate(..).scale(..);
t = Translation_(..) * t * RotationType(..) * Translation_(..) * Scaling(..);
4. Euler angles Euler角度可以方便地创建旋转对象。另一方面,由于存在24种不同的约定,它们使用起来非常混乱。此示例演示如何根据2-1-2约定创建旋转矩阵。
Matrix3f m;
m = AngleAxisf(angle1, Vector3f::UnitZ())
* AngleAxisf(angle2, Vector3f::UnitY())
* AngleAxisf(angle3, Vector3f::UnitZ());
参考:
使用eigen库进行空间变换
推荐阅读
- EffectiveObjective-C2.0|EffectiveObjective-C2.0 笔记 - 第二部分
- 由浅入深理解AOP
- 继续努力,自主学习家庭Day135(20181015)
- python学习之|python学习之 实现QQ自动发送消息
- Android中的AES加密-下
- 一起来学习C语言的字符串转换函数
- 定制一套英文学习方案
- 漫画初学者如何学习漫画背景的透视画法(这篇教程请收藏好了!)
- 《深度倾听》第5天──「RIA学习力」便签输出第16期
- 如何更好的去学习