> 文章列表 > [Eigen中文文档] 从入门开始...

[Eigen中文文档] 从入门开始...

[Eigen中文文档] 从入门开始...

文档总目录

本文目录

    • 如何安装Eigen
    • 第一个简单的程序
    • 编译和运行第一个程序
    • 第一个程序的解释
    • 示例2:矩阵向量
    • 解释第二个例子

本文英文原文链接

这是一个非常简短的Eigen入门文章。该文章有两层目的。对于想要尽快开始编码的人来说,该文章是对Eigen库的最简单介绍。你可以把该文章作为教程的第一部分,这更加详细的解释了Eigen库。看完这个教程后可以继续阅读 The Matrix class教程。

如何安装Eigen

为了使用Eigen,你仅仅需要下载和解压Eigen的源码(有关下载说明,请参阅wiki )。在Eigen的子目录中有头文件,这是你唯一需要的文件。这些文件在所有平台下都是通用的,无需使用Cmake或者安装什么。

Eigen源码下载链接:https://gitlab.com/libeigen/eigen/-/releases,选择你需要的版本下载。

解压后,将其中的Eigen文件夹放到你的头文件目录,即可在你的工程中使用Eigen。

第一个简单的程序

这是一个非常简单的程序。

// 代码索引 2-1-1-1
#include <iostream>
#include <Eigen/Dense>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 <iostream>
#include <Eigen/Dense>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:矩阵和向量

这是另一个例子,它结合了矩阵和向量。包括以下两个版本的程序,输出一样:

版本一:

// 代码索引 2-1-2-1
#include <iostream>
#include <Eigen/Dense>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 <iostream>
#include <Eigen/Dense>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的矩阵,其中每一个元素的值都在-11之间。下一行使用了一个线性变换,这让所有的值都在10110之间。函数MatrixXd::Constant(3,3,1.2)返回一个所有元素都是1.23*3矩阵。其余部分是标准计算。

main函数的下一行引入了一个新类型VectorXd。它代表一个任意大小的列向量。向量v大小为3并且未初始化。倒数第二行使用了逗号初始化器,解释见高级初始化,此处将向量v初始化为:
v=[123].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