Eigen是一个基于C++模板的线性代数库,安装后只需要包含头文件即可,它没有库文件,所以不需要链接,一般是INCLUDE_DIRECTORIES(/usr/include/eigen3)
安装:sudo apt-get install libeigen3-dev
,这是最新版本
查看Eigen的版本:不能用命令查看,版本在Macros.h,在/usr/local/include/eigen3/Eigen/src/Core/util
,可以执行命令: grep 'define EIGEN_....._VERSION\>' $(locate Macros.h | grep Core/util)
,结果是三个版本部分的宏定义。目前我所用为3.2.92
卸载Eigen:删除所有Eigen的文件即可1
2
3sudo rm -rf /usr/include/eigen3 /usr/lib/cmake/eigen3 /usr/share/doc/libeigen3-dev /usr/share/pkgconfig/eigen3.pc /var/lib/dpkg/info/libeigen3-dev.list /var/lib/dpkg/info/libeigen3-dev.md5sums
sudo updatedb
locate eigen
如果locate之后没有结果,那就是卸载成功了
要安装其他版本,就需要下载对应得deb安装,比如libeigen3-dev_3.2.0-8_all.deb
,我使用gdebi安装时失败,报警 A later version is already installed ,最终发现还是要用dpkg安装,这一点以前没有发现,其他软件包应该也会有这样问题
矩阵Eigen::Matrix基本使用方法
1 |
|
由于元素级运算在矩阵中很常见,所以Eigen对于Matrix其实内置了一些函数,均以cwise开头。mat.cwiseAbs()元素取绝对值、mat.cwiseSqrt()逐元素开根号、mat.cwiseMin()将两个矩阵中相应位置的最小值组成一个新矩阵
Eigen提供了一些基础的算法,如sum(),求所有元素和;prod(),求所有元素之积;mean(),求元素平均值;minCoeff(),最小元素;maxCoeff(),最大元素;trace(),求迹
Eigen::Isometry3d
Eigen::Isometry3d
相当于一个四维矩阵1
2
3
4
5
6
7
8
9Eigen::AngleAxisd v(M_PI / 3, Eigen::Vector3d(1,0,0).normalized() );
Eigen::Quaterniond q(1,0,0,0);
Eigen::Vector3d translate(1,2,3);
// 初始化为单位矩阵
Eigen::Isometry3d T = Eigen::Isometry3d::Identity();
T.translate(translate);
// T.rotate(q.matrix() ) 或者 T.rotate(v)
T.rotate(q);
cout << endl << T.matrix() << endl;rotate
函数比较强大,可接受的参数有四元数、旋转矩阵、旋转向量
必须要调用 Isometry3d::Identity()
对它进行初始化,后面的translate()
和rotate()
函数才有用。
稀疏矩阵
使用方式和普通矩阵不同1
2
3
4Eigen::SparseMatrix<double> hessian(2, 2);
// 注意稀疏矩阵的初始化方式,无法使用<<初始化
hessian.insert(0, 0) = 2.0;
hessian.insert(1, 1) = 2.0;
从子矩阵和向量拼接成新矩阵
比如现在有一个3X3的矩阵,一个行向量和一个列向量,二者的最后一个元素相同,要拼接成4X4的矩阵
mat = mat1.block(i, j, p, q);
// 从矩阵 mat1 的 i 行 j 列开始获取一个 p 行 q 列的子矩阵mat = mat1.block<p, q>(i, j);
// 从矩阵 mat1 的 i 行 j 列开始获取一个 p 行 q 列的子矩阵(动态矩阵)
1 | Eigen::Matrix4d m; |
向量Eigen::Vector
1 | // 常用这种方式,Xd 代表double型的任意行数向量,但后面的参数必须指定行数 |
指定了3行,必须传入3个值,否则运行报错。
我们可以用Vector3f::UnitX()
, Vector3f::UnitY
和 Vector3f::UnitZ()
这三个函数表示三个方向的列向量,也就是输出结果为:1
2
3
4
5X Y Z
1 0 0
0 1 0
0 0 1
其实向量只是一个特殊的矩阵,但是Eigen也为它单独提供了一些简化的块操作,如下三种形式:
head tail segment
获取向量的前n个元素:vector.head(n);
获取向量尾部的n个元素:vector.tail(n);
获取从向量的第i个元素开始的n个元素:vector.segment(i,n);
1 | Eigen::Vector4d v(4); |
Vector 转 Matrix
1 | Eigen::Vector3d v; |
从Eigen::Vector构建对角矩阵,其中Vector的元素占据矩阵的主对角线
1 | Eigen::Vector3d v(1,2,3); |
从多个Eigen::Vector拼接成Eigen::Matrix
1 | Eigen::Vector3d v(3); |
Map类用于通过C++中普通的连续指针或者数组 (指针地址连续)来构造Eigen里的Matrix类,这就好比Eigen里的Matrix类的数据和raw C++array 共享了一片地址,也就是引用。
有个庞大的Matrix类,在一个大循环中要不断读取Matrix中的一段连续数据,如果每次都用block operation 去引用数据会太繁琐。于是就事先将这些数据构造成若干Map,那么以后循环中直接操作Map就行了。
Eigen::Map
Map类用于通过C++中普通的连续指针或者数组来构造Eigen里的Matrix类,这就好比Eigen里的Matrix类的数据和raw C++array 共享了一片地址,也就是引用。 比如有个API只接受普通的C++数组,但又要对普通数组进行线性代数操作,那么用它构造为Map类。 实际上Map类并没有自己申请一片空内存,只是一个引用1
2
3
4
5
6
7
8
9
10
11
12
13
14using DynamicArray = Eigen::Array<int, Eigen::Dynamic, Eigen::Dynamic>;
std::vector<int> cells{1,2,3,4,5,6,7,8,9};
for(auto& v: cells)
cout << v << " ";
cout << endl << endl;
// 维度不要超过 3x3,否则出现invalid数据
Eigen::Map<const DynamicArray> full_correspondence_costs(cells.data(), 3, 3);
cout << full_correspondence_costs <<endl;
int data[] = {1,2,3,4,5,6,7,8,9};
Eigen::Map<Eigen::RowVectorXi> m(data, 4);
cout << "The mapped vector v is: " << m << "\n";
运行结果:1
2
3
41 4 7
2 5 8
3 6 9
The mapped vector v is: 1 2 3 4
参考:
Eigen矩阵库使用说明