文档总目录
本文英文原文链接
这是一个非常简短的Eigen入门文章。该文章有两层目的。对于想要尽快开始编码的人来说,该文章是对Eigen库的最简单介绍。你可以把该文章作为教程的第一部分,这更加详细的解释了Eigen库。看完这个教程后可以继续阅读 The Matrix class教程。
为了使用Eigen,你仅仅需要下载和解压Eigen的源码(有关下载说明,请参阅wiki )。在Eigen的子目录中有头文件,这是你唯一需要的文件。这些文件在所有平台下都是通用的,无需使用Cmake或者安装什么。
Eigen源码下载链接:https://gitlab.com/libeigen/eigen/-/releases,选择你需要的版本下载。
解压后,将其中的Eigen文件夹放到你的头文件目录,即可在你的工程中使用Eigen。
这是一个非常简单的程序。
// 代码索引 2-1-1-1
#include
#include
using Eigen::MatrixXd;
int main()
{
MatrixXd m(2,2);
m(0,0) = 3;
m(1,0) = 2.5;
m(0,1) = -1;
m(1,1) = m(1,0) + m(0,1);
std::cout << m << std::endl;
}
在告诉您如何编译之后,我们将解释该程序。
不需要链接任何库。编译上述程序时唯一需要记住的是编译器必须能够找到Eigen头文件。放置Eigen源代码的路径必须在 include
路径中。使用GCC编译器时,需要用-I
选项达到这一目的,因此可以使用如下命令编译程序:
g++ -I /path/to/eigen/ my_program.cpp -o my_program
在linux或者Mac OS X中,你也可以使用符号链接或者复制Eigen文件夹到/usr/local/include/
。这样,你就可以使用下列命令来编译程序:
g++ my_program.cpp -o my_program
当你运行该程序时,将产生以下输出:
3 -1
2.5 1.5
// 代码索引 2-1-1-1
#include
#include
using Eigen::MatrixXd;
int main()
{
MatrixXd m(2,2);
m(0,0) = 3;
m(1,0) = 2.5;
m(0,1) = -1;
m(1,1) = m(1,0) + m(0,1);
std::cout << m << std::endl;
}
Eigen头文件定义了很多类型,但对于简单的应用程序,仅使用类型MatrixXd
可能就足够了。它代表任意大小的矩阵,其中X
代表任意大小,d
代表元素的类型是double
。有关可用于表示矩阵的不同类型的概述,请参阅快速参考指南。
头文件Eigen/Dense
定义了关于MatrixXd
类型及相关类型的成员函数(另请参阅头文件表)。头文件中定义的所有的类和函数都在Eigen
命名空间中。
上述main
函数的第一行声明了一个MatrixXd
类型的矩阵m
,然后指定了该矩阵的大小为2*2
,但没有初始化该矩阵。语句m(0,0) = 3
代表将该2*2
矩阵的左上角元素设置为3
。你可以使用圆括号去访问矩阵中对应的元素,如m(0,0)
。按照计算机科学中的惯例,第一个元素的索引为 0。
下面的三行代码设置其它三个元素。最后一行代码把矩阵m
输送给标准的输出流。
这是另一个例子,它结合了矩阵和向量。包括以下两个版本的程序,输出一样:
版本一:
// 代码索引 2-1-2-1
#include
#include
using Eigen::MatrixXd;
using Eigen::VectorXd;
int main()
{
MatrixXd m = MatrixXd::Random(3,3);
m = (m + MatrixXd::Constant(3,3,1.2)) * 50;
std::cout << "m =" << std::endl << m << std::endl;
VectorXd v(3);
v << 1, 2, 3;
std::cout << "m * v =" << std::endl << m * v << std::endl;
}
版本二:
// 代码索引 2-1-3-1
#include
#include
using Eigen::Matrix3d;
using Eigen::Vector3d;
int main()
{
Matrix3d m = Matrix3d::Random();
m = (m + Matrix3d::Constant(1.2)) * 50;
std::cout << "m =" << std::endl << m << std::endl;
Vector3d v(1,2,3);
std::cout << "m * v =" << std::endl << m * v << std::endl;
}
输出:
m =
94 89.8 43.5
49.4 101 86.8
88.3 29.8 37.8
m * v =
404
512
261
注意,这里的浮点型数字,官网只截取了前面几位,而且做了四舍五入。
版本一首先使用Random()
函数初始化了一个3*3
的矩阵,其中每一个元素的值都在-1
和1
之间。下一行使用了一个线性变换,这让所有的值都在10
到110
之间。函数MatrixXd::Constant(3,3,1.2)
返回一个所有元素都是1.2
的3*3
矩阵。其余部分是标准计算。
main
函数的下一行引入了一个新类型VectorXd
。它代表一个任意大小的列向量。向量v
大小为3
并且未初始化。倒数第二行使用了逗号初始化器,解释见高级初始化,此处将向量v
初始化为:
v = [ 1 2 3 ] . v=\begin{bmatrix} 1 \\ 2 \\ 3 \end{bmatrix}. v= 123 .
最后一行让矩阵m
和向量v
相乘然后输出结果。
现在来解释版本二。
版本一中的MatrixXd
表示任意大小的矩阵,版本二中的Matrix3d
表示固定大小的矩阵(此处为 3*3)。因为类型已经固定了矩阵的大小,所以没有必要在构造函数中指定大小,只需要对其初始化即可。
同理,VectorXd
代表任意大小的列向量,Vector3d
代表固定大小的列向量(此处为 3)。同样因为类型已经固定了向量的大小,所以没有必要在构造函数中指定大小,只需要对其初始化即可。
使用固定大小的矩阵和向量有两个优点。编译器会编译出更好(更快)的代码,因为它知道矩阵和向量的大小。在类型中指定大小还允许在编译时进行更严格的检查。例如,如果你尝试将一个 Matrix4d
(4*4 矩阵)与 一个 Vector3d
(大小为 3 的向量)相乘,编译器会报错。然而,使用太多类型会增加编译时间和可执行文件的大小。矩阵的大小在编译时也可能是未知的。经验法则是对大小为 4*4
或更小的矩阵使用固定大小的类型,其他使用任意大小的类型MatrixXd
。