Eigen —— 参考指南

本文介绍了Eigen库的基础知识,包括矩阵和向量类型、基本操作、预定义矩阵、映射外部数组、算法运算符、系数运算、简化函数、子矩阵和其他操作。Eigen库在机器人运动规划中的矩阵计算中扮演重要角色,提供了丰富接口和优化的运算功能。
摘要由CSDN通过智能技术生成

机器人的运动规划过程中会涉及大量的矩阵计算,而 EIGEN 库对于矩阵计算而言,其意义不言而喻。所以最近学习了一下 EIGEN 库的使用。并在此过程中记录自己的感悟和理解。本篇通过Eigen库的Quick reference guide来了解整个库。

新学的知识,总喜欢自己动手整理一下,不知道是不是强迫症。整理完才发现,太长了,头疼。

1. Eigen模块和头文件(Modules and Header files)

EIGEN库其由核心模块和若干附属模块构成,每一模块都有对应的头文件供编程引用。其文件组织结构列表如下:

模组 头文件 说明
Core #include <Eigen/Core> 矩阵(Matrix)和数据(Array)类,并涉及基本的线性代数和数组操作
Geometry #include <Eigen/Geometry> 涉及变换、平移、缩放、2D和3D旋转、四元数、角轴(AngleAxis)
LU #include <Eigen/LU> 逆运算、行列式、LU分解器 (FullPivLU, PartialPivLU)
Cholesky #include <Eigen/Cholesky> LLT and LDLT Cholesky 因式分解器
Householder #include <Eigen/Householder> Householder变换,也被其它线性代数模组所引用
SVD #include <Eigen/SVD> 基于最小二乘解算的SVD分解(JacobiSVD, BDCSVD)
QR #include <Eigen/QR> QR分解器 (HouseholderQR, ColPivHouseholderQR, FullPivHouseholderQR)
Eigenvalues #include <Eigen/Eigenvalues> 特征值特征向量分解(EigenSolver, SelfAdjointEigenSolver, ComplexEigenSolver)
Sparse #include <Eigen/Sparse> 稀疏矩阵存储和相关基础线性代数(SparseMatrix, SparseVector)
#include <Eigen/Dense> Includes Core, Geometry, LU, Cholesky, SVD, QR, and Eigenvalues header files
#include <Eigen/Eigen> Includes Dense and Sparse header files (整个EIGEN库)

对于不涉及稀疏矩阵运算的,头文件使用#include <Eigen/Dense>就可以满足要求,或者直接包含整个EIGEN库#include <Eigen/Eigen>,全面!任性!

2. 数组、矩阵和向量类型(Array, matrix and vector types)

Eigen库提供了矩阵和向量两种对象,都是由模版类进行表示的,矩阵用Matrix进行表示,而1维和2维数组则由模版类Array表示。Eigen库提供的模版类形式如下:

typedef Matrix< Scalar, RowsAtCompileTime, ColsAtCompileTime, Options > MyMatrixType;
typedef Array< Scalar, RowsAtCompileTime, ColsAtCompileTime, Options >  MyArrayType;
  • Scalar :是数据结构中标量元素的类型,例如 float, double, bool, int 等,即在模版类定义自定义数据类型时,其内部的元素只能是标量。
  • RowsAtCompileTime:指定编译时矩阵的行数,或用 Dynamic 参数,在运行时确定行数。
  • ColsAtCompileTime:指定矩阵的列数,或用 Dynamic 参数,在运行时确定行数。
  • Options:其值可以是 ColMajorRowMajor ,默认为 ColMajor

以下组合方式都是有效的:为了注释明显用%表示注释。

Matrix<double, 6, Dynamic>                  % Dynamic number of columns (heap allocation)
Matrix<double, Dynamic, 2>                  % Dynamic number of rows (heap allocation)
Matrix<double, Dynamic, Dynamic, RowMajor>  % Fully dynamic, row major (heap allocation)
Matrix<double, 13, 3>                       % Fully fixed (usually allocated on stack)

以上代码定义中,第一行定义的矩阵其行数是固定的,而列数是动态的,同理第二行定义。第三行则行列都是动态确定,最后一行则是指定了矩阵的固定行列数。这种方式,真是学到了。

而Eigen库为了使用上的方便,对常用的矩阵和数组类型进行了定义,如果不是个性化所需的数据类型,使用常用的已定义类型更加方便。矩阵类型中,已定义的有以下类型:

Matrix<float,Dynamic,Dynamic>   <=>   MatrixXf
Matrix<double,Dynamic,1>        <=>   VectorXd
Matrix<int,1,Dynamic>           <=>   RowVectorXi
Matrix<float,3,3>               <=>   Matrix3f
Matrix<float,4,1>               <=>   Vector4f

数组类型有以下已定义类型:

Array<float,Dynamic,Dynamic>    <=>   ArrayXXf
Array<double,Dynamic,1>         <=>   ArrayXd
Array<int,1,Dynamic>            <=>   RowArrayXi
Array<float,3,3>                <=>   Array33f
Array<float,4,1>                <=>   Array4f

<=> 后面表示定义的数据类型,就像double,float,int等一样,可以在包含头文件的代码中直接使用。例如:

using namespace Eigen;
MatrixXf variable_1;
VectorXd variable_2;
Matrix3f variable_3;
Vector4f variable_4;
ArrayXXf variable_5;

Eigen::Array33f variable_6;

在使用时要加命名空间,如果不想直接使用命名空间,则需要在数据类型之前加上作用域说明,如以上代码中的最后一行。同时矩阵和数组类型之间也有内在的转换机制。如下示例代码:

Array44f a1, a2;                  % 4 X 4 的二维数组
Matrix4f m1, m2;				  % 4 X 4 的矩阵
m1 = a1 * a2;                     % coeffwise product, 从数组到矩阵的隐式转换
a1 = m1 * m2;                     % matrix product, 从矩阵到数组的隐式转换
a2 = a1 + m1.array();             % 禁止混合数组和矩阵
m2 = a1.matrix() + m1;            % 如果需要混合运算,则需要显式转换
ArrayWrapper<Matrix4f> m1a(m1);   // m1a is an alias for m1.array(), they share the same coefficients
MatrixWrapper<Array44f> a1m(a1);

在以下的说明中,将使用*来强调特定对象的应用范围和领域:
* linear algebra matrix and vector only
* array objects only

2.1 基本矩阵运算(Basic matrix manipulation)

2.1.1 构造函数

对象定义可以用以下方式,类会自动调用构造函数,构造类对象。

Vector4d  v1;
Array3i   v2(x, y, z);        % 以x,y,z为元素构造类对象
Vector4d  v3(x, y, z, w);
Matrix4f  m1;
MatrixXf  m2;                 % 构造一个空对象

2.1.2 初始化

Eigen重载了<<运算符,可以直观的用数据为变量赋值,如下所示:

Vector3f  v1;     
v1 << x, y, z;                 % 将x,y,z按顺利赋值给对应的位置

ArrayXf   v2(4);  
v2 << 1, 2, 3, 4;

Matrix3f  m1;   
m1 << 1, 2, 3,                 % 按行赋值给矩阵
	  4, 5, 6,
	  7, 8, 9;
	  
int rows=5, cols=5;
MatrixXf m(rows,cols);
m << (Matrix3f() << 1, 2, 3, 4, 5, 6, 7, 8, 9).finished(),       % 以块的形式为矩阵赋值
     MatrixXf::Zero(3,cols-3),
     MatrixXf::Zero(rows-3,3),
     MatrixXf::Identity(rows-3,cols-3);
cout << m;

输出为:
		1 2 3 0 0
		4 5 6 0 0
		7 8 9 0 0
		0 0 0 1 0
		0 0 0 0 1

2.1.3 运行时可获取信息

使用类的优势之一就是提供了大量的成员函数,可以获取对象的信息,而Eigen中为矩阵类对象提供了丰富的接口:

vector.size();             % 获取向量的大小,即元素个数
vector.innerStride();      % 沿数据存储的方向移动一个位置,内存中需要移动的位置数
vector.data();             % 获取向量的数据

matrix.rows();             % 获取矩阵的行数
matrix.cols();		       % 获取矩阵的列数
matrix.innerSize();        % 按列存储的矩阵返回其行数,接行存储的矩阵返回其列数
matrix.outerSize();        % 按列存储的矩阵返回其列数,按行存储的矩阵返回其行数
matrix.innerStride();      % 返回内部实际存储时相邻元素之间的指针增量
matrix.outerStride();      % 返回按逻辑顺序存储时的指针增量
matrix.data();             % 获取矩阵的数据指针

2.1.4 编译时对象类型信息

ObjectType::Scalar              
ObjectType::RowsAtCompileTime
ObjectType::RealScalar          
ObjectType::ColsAtCompileTime
ObjectType::Index               
ObjectType::SizeAtCompileTime

2.1.5 调整大小

vector.resize(size);                         % 调整具有动态尺寸的向量大小
vector.resizeLike(other_vector);             % 按other_vector的尺寸调整具有动态尺寸的向量大小
vector.conservativeResize(size);
matrix.resize(nb_rows, nb_cols);             % 调整成具有指定行列数的矩阵
matrix.resize(Eigen::NoChange, nb_cols);	 % 只调整列
matrix.resize(nb_rows, Eigen::NoChange);	 % 只调整行
matrix.resizeLike(other_matrix);			 % 按other_matrix的大小调整矩阵
matrix.conservativeResize(nb_rows, nb_cols);

使用有风险,应用需要谨慎。

2.1.6 数据获取

带有范围检查的数据获取方式如下:

vector(i)     vector.x()
vector[i]     vector.y()
              vector.z()
              vector.w()
matrix(i,j)

不带有数据范围检查的获取方式:

vector.coeff(i)
vector.coeffRef(i)
matrix.coeff(i,j)
matrix.coeffRef(i,j)

2.1.7 赋值/Copy

object = expression;
object_of_float = expression_of_double.cast<float>();

如果可能,左侧为动态矩阵时,会被自动调整为与右侧相同的维数形式。

2.2 预定义矩阵(Predefined Matrices)

2.2.1 固定维数的矩阵和向量

typedef {
   Matrix3f|Array33f} FixedXD;
FixedXD x;

x = FixedXD::Identity();				   % 构造一个单位阵临时对象,并赋值给x
x = FixedXD::Zero();                       % 构造一个元素全是0的临时对象,并赋值给x
x = FixedXD::Ones();					   % 构造一个元素全是1的临时对象,并赋值给x
x = FixedXD::Constant(value);			   % 构造一个元素全是value的临时对象,并赋值给x
x = FixedXD::Random();					   % 构造一个元素是随机值的临时对象,并赋值给x
x = FixedXD::LinSpaced(size, low, high);   
  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值