一.Eigen库模块和头文件
Eigen库被分为一个Core模块和其他一些模块,每个模块有一些相应的头文件。 为了便于引用,Dense模块整合了一系列模块;Eigen模块整合了所有模块。一般情况下,include<Eigen/Dense>
就够了。
二、矩阵和向量定义与初始化
1.模板
在Eigen,所有的矩阵和向量都是Matrix模板类的对象,Vector只是一种特殊的矩阵(一行或者一列)。Matrix有6个模板参数,主要使用前三个参数,剩下的有默认值。
Matrix<typename Scalar,
int RowsAtCompileTime,
int ColsAtCompileTime,
int Options = 0,
int MaxRowsAtCompileTime = RowsAtCompileTime,
int MaxColsAtCompileTime = ColsAtCompileTime>
Scalar是表示元素的类型,RowsAtCompileTime为矩阵的行,ColsAtCompileTime为矩阵的列。
Options是一个比特标志位,这里,我们只介绍一种RowMajor,它表明matrix使用按行存储,默认是按列存储。
MaxRowsAtCompileTime和MaxColsAtCompileTime表示在编译阶段矩阵的上限。主要是避免动态内存分配,使用数组。
2.矩阵创建与初始化
Ⅰ.创建:Eigen定义了一些通用类型
- MatrixNt = Matrix<type, N, N> 特殊地有 MatrxXi = Matrix<int, Dynamic, Dynamic>
- VectorNt = Matrix<type, N, 1> 比如 Vector2f = Matrix<float, 2, 1>
- RowVectorNt = Matrix<type, 1, N> 比如 RowVector3d = Matrix<double, 1, 3>
N可以是2,3,4或X(Dynamic),t可以是i(int)、f(float)、d(double)、cf(complex)、cd(complex)等。
常用如下:
typedef Matrix<float, 4, 4> Matrix4f; //矩阵
typedef Matrix<float, 3, 1> Vector3f; //向量
typedef Matrix<int, 1, 2> RowVector2i;
typedef Matrix<double, Dynamic, Dynamic> MatrixXd; //动态矩阵
typedef Matrix<int, Dynamic, 1> VectorXi;
Ⅱ.初始化:
默认构造函数不执行任何空间分配,也不初始化矩阵的元素。
Matrix3f a; //a是一个3*3的矩阵,分配了float[9]的空间,但未初始化内部元素
MatrixXf b; //b是一个动态大小的矩阵,定义是未分配空间(0*0)
Matrix3f a(3,3); //对指定大小的Matrix传递sizes也是合法的(传递被忽略)
使用构造函数提供4以内尺寸的vector的初始化:
Vector2d a(5.0, 6.0);
Vector3d b(5.0, 6.0, 7.0);
逗号初始化:
Matrix3f m;
m << 1, 2, 3,
4, 5, 6,
7, 8, 9;
std::cout << m;
使用块结构初始化(块操作在下面矩阵操作详细介绍):
MatrixXf matA(2, 2);
matA << 1, 2, 3, 4;
MatrixXf matB(4, 4);
matB << matA, matA/10, matA/10, matA;
std::cout << matB << std::endl;
使用功能函数:setZero(), MatrixBase::setIdentity()和 DenseBase::setLinSpaced()
const size = 6;
MatrixXd mat2(size, size);
mat2.topLeftCorner(size/2, size/2).setZero();
mat2.topRightCorner(size/2, size/2).setIdentity();
mat2.bottomLeftCorner(size/2, size/2).setIdentity();
mat2.bottomRightCorner(size/2, size/2).setZero();
std::cout << mat2 << std::endl << std::endl;
Ⅲ 特殊的矩阵和向量的创建
零阵:类的静态成员函数Zero(),有三种定义形式
类似的有常量矩阵:Constant([rows],[cols],value),Random()随机矩阵
单位阵Identity()方法只能使用与Matrix不使用Array
std::cout << "A fixed-size array:\n";
Array33f a1 = Array33f::Zero();
std::cout << a1 << "\n\n";
std::cout << "A one-dimensional dynamic-size array:\n";
ArrayXf a2 = ArrayXf::Zero(3);
std::cout << a2 << "\n\n";
std::cout << "A two-dimensional dynamic-size array:\n";
ArrayXXf a3 = ArrayXXf::Zero(3, 4);
std::cout << a3 << "\n";
输出:
A fixed-size array:
0 0 0
0 0 0
0 0 0
A one-dimensional dynamic-size array:
0
0
0
A two-dimensional dynamic-size array:
0 0 0 0
0 0 0 0
0 0 0 0
LinSpaced(size, low, high),生成一个从low到high等间距取值的矩阵,间距为size
ArrayXXf table(10, 4);
table.col(0) = ArrayXf::LinSpaced(10, 0, 90);
std::cout << table.col(0) << std::endl;
3.矩阵基础操作与元素访问
Ⅰ 元素访问:通过中括号获取元素,对于矩阵是:(行,列);对于向量,只是传递它的索引,以0为起始。
MatrixXd m(2,2);
m(0,0) = 3;
m(1,0) = 2.5;
m(index)也可以用于获取矩阵元素,但取决于matrix的存储顺序,默认是按列存储的,当然也可以改为按行。[ ]操作符可以用于向量元素的获取,但是不能用于matrix,因为C++中[]不能传递超过一个参数。
Ⅱ 矩阵操作
resize:重新调整动态matrix的大小
MatrixXd m(2,5);
m.resize(4,3); //m大小变为4x3
块操作:函数.block(),有两种形式
operation | 构建一个动态尺寸的block | 构建一个固定尺寸的block |
起点(i,j)块大小(p,q) | .block(i,j,p,q) | .block< p,q >(i,j) |
Eigen::MatrixXf m(4,4);
m << 1, 2, 3, 4,
5, 6, 7, 8,
9,10,11,12,
13,14,15,16;
cout << "Block in the middle" << endl;
cout << m.block<2,2>(1,1) << endl << endl;
角相关操作 :
operation | dynamic-size block | fixed-size block |
左上角p\*q | matrix.topLeftCorner(p,q); | matrix.topLeftCorner< p,q >(); |
左下角p\*q | matrix.bottomLeftCorner(p,q); | matrix.bottomLeftCorner< p,q >(); |
右上角p\*q | matrix.topRightCorner(p,q); | matrix.topRightCorner< p,q >(); |
右下角p\*q | matrix.bottomRightCorner(p,q); | matrix.bottomRightCorner< p,q >(); |
前q行 | matrix.topRows(q); | matrix.topRows< q >(); |
后q行 | matrix.bottomRows(q); | matrix.bottomRows< q >(); |
左p列 | matrix.leftCols(p); | matrix.leftCols< p >(); |
右p列 | matrix.rightCols(p); | matrix.rightCols< p >(); |
Eigen::Matrix4f m;
m << 1, 2, 3, 4,
5, 6, 7, 8,
9, 10,11,12,
13,14,15,16;
cout << "m.leftCols(2) =" << endl << m.leftCols(2) << endl << endl;
vectors的块操作:
operation | dynamic-size block | fixed-size block |
前n个 | vector.head(n); | vector.head< n >(); |
后n个 | vector.tail(n); | vector.tail< n >(); |
i起始的n个元素 | vector.segment(i,n); | vector.segment< n >(i); |
assignment:复制一个矩阵到另外一个,操作符=。Eigen会自动resize左变量大小等于右变量大小,当左边矩阵大小固定时不允许这样操作。
MatrixXf a(2,2);
MatrixXf b(3,3);
a = b; //a变成了3x3
+,- 运算:左右两侧变量具有相同的尺寸(行和列),并且元素类型相同(Eigen不自动转化类型),包括a+b、a-b、-a、a+=b、a-=b
Matrix2d a;
a << 1, 2,
3, 4;
MatrixXd b(2,2);
b << 2, 3,
1, 4;
a + b;
a += b;
x、÷(标量): matrix*scalar、scalar*matrix、matrix/scalar、matrix*=scalar、matrix/=scalar
Matrix2d a;
a << 1, 2,
3, 4;
Vector3d v(1,2,3);
v *= 2;
×(矩阵): a*b、a*=b
Matrix2d mat;
mat << 1, 2,
3, 4;
mat = mat*mat;
向量点积和叉运算:dot()执行点积,cross()执行叉积
Vector3d v(1,2,3);
Vector3d w(0,1,2);
cout << "Dot product: " << v.dot(w) << endl;
double dp = v.adjoint()*w; // automatic conversion of the inner product to a scalar
cout << "Dot product via a matrix product: " << dp << endl;
cout << "Cross product:\n" << v.cross(w) << endl;
转置和共轭:transpose转置、conjugate共轭、adjoint(共轭转置) 伴随矩阵
MatrixXcf a = MatrixXcf::Random(2,2);
cout << "Here is the matrix a\n" << a << endl;
cout << "Here is the matrix a^T\n" << a.transpose() << endl;
cout << "Here is the conjugate of a\n" << a.conjugate() << endl;
cout << "Here is the matrix a^*\n" << a.adjoint() << endl;
归约:sum()、prod()、maxCoeff()和minCoeff(),他们对所有元素进行操作
Eigen::Matrix2d mat;
mat << 1, 2,
3, 4;
cout << "Here is mat.sum(): " << mat.sum() << endl; //加
cout << "Here is mat.prod(): " << mat.prod() << endl; //乘
cout << "Here is mat.mean(): " << mat.mean() << endl; //平均
cout << "Here is mat.minCoeff(): " << mat.minCoeff() << endl; //最小值
cout << "Here is mat.maxCoeff(): " << mat.maxCoeff() << endl; //最大值
cout << "Here is mat.trace(): " << mat.trace() << endl; //迹(对角线元素和)
4.Array类和元素级操作
相对于Matrix提供的线性代数运算,Array类提供了更为一般的数组功能。Array类为元素级的操作提供了有效途径,比如点加(每个元素加值)或两个数据相应元素的点乘。
Array是个类模板(类似于Matrx),前三个参数是必须指定的,后三个是可选的
Array<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime>
Type | Tyoedef |
Array<float,Dynamic,1> | ArrayXf |
Array<float,3,1> | Array3f |
Array<double,Dynamic,Dynamic> | ArrayXXd |
Array<double,3,3> | Array33d |
2.初始化和获取元素都类似于矩阵
3.加减乘也类似于矩阵,但要求大小相同,而且乘法执行的是相应元素相乘
4.其他元素级操作
Function | function |
abs | 绝对值 |
sqrt | 平方根 |
min(.) | 两个array相应元素的最小值 |
5.array和matrix之间的转换
当需要线性代数类操作时,请使用Matrix;但需要元素级操作时,需要使用Array。这样就需要提供两者的转化方法。
Matrix提供了.array()函数将它们转化为Array对象。
Array提供了.matrix()函数将它们转化为Matrix对象。
另外,Matrix提供了cwiseProduct函数也实现了点乘。
MatrixXf m(2,2);
MatrixXf n(2,2);
MatrixXf result(2,2);
m << 1,2,
3,4;
n << 5,6,
7,8;
result = m * n;
cout << "-- Matrix m*n: --" << endl << result << endl << endl;
result = m.array() * n.array();
cout << "-- Array m*n: --" << endl << result << endl << endl;
result = m.cwiseProduct(n);
cout << "-- With cwiseProduct: --" << endl << result << endl << endl;
result = m.array() + 4;
cout << "-- Array m + 4: --" << endl << result << endl << endl;