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 3
| sudo 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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| #include <Eigen/Core> #include <Eigen/Dense> #include <Eigen/Eigen>
Eigen::Matrix<float, 2, 3> m23; m23.setZero(2,3); cout << "After m23 initilized!" << endl; cout<<m23<<endl; m23<<1,2,3,4,5,6; cout << "After m23 set value!" << endl; m23(1,2) = 54;
cout<<m23(1,2)<<endl;
Eigen::Matrix<double,2,2> information; information.fill(0.0);
Eigen::Matrix<float, 2, 3> m; m.setRandom(2,3); m = m23; m<<3,4,7,12,-2,10; cout<<m23+m<<endl; cout<<m23 * m.transpose()<<endl;
Eigen::Matrix3d m33 m33<<1,6,3,4,12,5,7,8,9; cout<<m33<<endl; cout<<m33.rows()<<endl; cout<<m33.cols()<<endl; cout << "Column major input:" << endl << m33 << "\n";
cout << "The first column is:" << endl << m33.col(0) << "\n"; cout << "The last column is: " << endl << m33.rightCols(1) << "\n"; cout << "The first row is: " << endl << m33.topRows<1>() << endl; cout << "The last row is: " << endl << m33.bottomRows<1>() << endl;
cout<<m33.transpose()<<endl; cout<<m33.sum()<<endl; cout<<m33.trace()<<endl; cout<<10*m33<<endl; cout<<m33.isUnitary()<<endl; cout<<m33.conjugate()<<endl; cout<<m33.adjoint()<<endl; cout<<m33.inverse()<<endl; cout<<m33.determinant()<<endl;
Eigen::Matrix<double, 2, 1> m21 = m23.cast<double>() * v3d;
|
由于元素级运算在矩阵中很常见,所以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 9
| Eigen::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); cout << endl << T.matrix() << endl;
|
rotate
函数比较强大,可接受的参数有四元数、旋转矩阵、旋转向量
必须要调用 Isometry3d::Identity()
对它进行初始化,后面的translate()
和rotate()
函数才有用。
稀疏矩阵
使用方式和普通矩阵不同
1 2 3 4
| Eigen::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 2 3 4 5 6 7 8 9
| Eigen::Matrix4d m; Eigen::Matrix3d rotation;
m.block(0,0,3,3) = rotation;
Eigen::Vector4d Vcol, Vrow;
m.col(3) = Vcol; m.row(3) = Vrow.transpose();
|
向量Eigen::Vector
1 2 3 4 5 6 7 8 9 10 11 12
| Eigen::VectorXd v(3); v<< 1,2,5; v(2) = 9;
Eigen::VectorXd vv(12); vv<< 1,2,3,4,5,6,7,8,9,10,11,12;
cout<< vv.block(0,0, 3,1).transpose() <<endl<<endl; cout<< vv.block(3,0, 3,1) <<endl<<endl; cout<< vv.block(6,0, 3,1) <<endl<<endl;
|
指定了3行,必须传入3个值,否则运行报错。
我们可以用Vector3f::UnitX()
, Vector3f::UnitY
和 Vector3f::UnitZ()
这三个函数表示三个方向的列向量,也就是输出结果为:
1 2 3 4 5
| X 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 2 3 4 5 6
| Eigen::Vector4d v(4); v<< 1,2,3,4;
cout << "head: "<<v.head(1) <<endl; cout << v.segment(1,2) <<endl; cout << "tail: "<<v.tail(1) <<endl;
|
Vector 转 Matrix
1 2 3 4
| Eigen::Vector3d v; v << 1,2,3;
Eigen::Matrix<double, 3, 1> m = v.template cast<double>();
|
从Eigen::Vector构建对角矩阵,其中Vector的元素占据矩阵的主对角线
1 2
| Eigen::Vector3d v(1,2,3); Eigen::Matrix3d m = v.asDiagonal();
|
从多个Eigen::Vector拼接成Eigen::Matrix
1 2 3 4 5 6 7 8
| Eigen::Vector3d v(3); v<< 2.1, 4.9, 0.4; std::vector<Eigen::Vector3d> vv; for(int i=0;i<4;i++) vv.push_back( v );
Eigen::Map<Eigen::Matrix3Xd> matrix(&vv[0].x(), 3, 4); cout << matrix <<endl;
|
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 14
| using 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;
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 4
| 1 4 7 2 5 8 3 6 9 The mapped vector v is: 1 2 3 4
|
参考:
Eigen矩阵库使用说明