原文:Eigen官网-Space transformations
本篇将介绍基于geometry module的2D 、3D旋转和投影或仿射变换。
Eigen中的Geometry module提供了两种不同的几何变换:
- 抽象变换,如旋转(rotation 由角和轴表示或由四元数表示)、平移(translation)、缩放(scaling)。这些转换不表示为矩阵,但您仍然可以将它们与表达式中的矩阵和向量混合,并根据需要将它们转换为矩阵。
- 投影或仿射变换矩阵:参见Transform类。这些以矩阵的形式进行表示。
可以从抽象转换构造一个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<float,2>(tx, ty) Translation<float,3>(tx, ty, tz) Translation<float,N>(s) Translation<float,N>(vecN) |
|
N-D Affine transformation 仿射变换 |
Transform<float,N,Affine> t = concatenation_of_any_transformations; Transform<float,3,Affine> t = Translation3f§ * AngleAxisf(a,axis) * Scaling(s); |
放射变换是一些变换的结合,按平移×旋转×缩放的顺序连乘 |
N-D Linear transformations (pure rotations, scaling, etc.) 线性变换 |
Matrix<float,N> t = concatenation_of_rotations_and_scalings; Matrix<float,2> t = Rotation2Df(a) * Scaling(s); Matrix<float,3> t = AngleAxisf(a,axis) * Scaling(s); |
(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-07 0 1
0.969 -0.249 0
0.249 0.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); |
3. 仿射变换(Affine transformations)
泛型仿射变换用Transform类表示,其实质是(Dim+1)^2的矩阵。在Eigen中,我们选择不区分点和向量,这样所有点实际上都由原点的位移向量表示。考虑到这一点,在应用转换时,实数点和向量会进行区分。
– | – |
---|---|
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()); |
Component accessors
– | – |
---|---|
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(); |
Transformation creation
虽然可以通过连接基本转换来创建和更新转换对象,但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());
暂无评论内容