Eigen库的介绍

Eigen库的介绍

Eigen是一个只包含头文件的库,由于在SLAM中经常需要使用Eigen,所以想要对Eigen的结构和使用方法记录总结,方便以后查询

一、Eigen的安装

Eigen的安装十分简单,只需要在终端输入
sudo apt-get install libeigen-dev
eigen的头文件默认在“/usr/include/eigen3”,如果不确定,可以输入以下命令查找

sudo uodatedb
locate eigen3

二、Eigen的头文件

模块头文件作用
code#include<Eigen/Core>核心模块,Matrix 矩阵和 Array 数组类,基本线性代数(包括三角形和自伴随乘积),数组操作。
geometry#include<Eigen/Geometry>几何模块,提供 Transform 变换、Translation 平移变换、缩放、Rotation2D 2D 旋转和3D rotations3D 旋转功能使用Quaternion四元数和AngleAxis三轴旋转的方式)
LU#include<Eigen/LU>Inverse逆、行列式和 LU 分解的求解方法(FullPivLU, PartialPivLU)
cholesky#inlcude<Eigen/Cholesky>提供 LLT 和 LDLT Cholesky 因式分解
Householder#include<Eigen/Householder>Householder 变换,这个模块被一些线性代数模块所使用
SVD#inlcude<Eigen/SVD>SVD分解与最小二乘求解方法(JacobiSVD, BDCSVD)
QR#include<Eigen/QR>QR 分解求解方法(HouseholderQR, ColPivHouseHolderQR, FullPivHouseholderQR)
Eigenvalues#include<Eigen/Eigenvalues>特征值、特征向量分解(EigenSolver, SelfAdjointEigenSolver, ComplexEigenSolver)
sparse#include<Eigen/sparse>稀疏矩阵存储及相关的基本线性代数 (SparseMatrix, SparseVector
dense#include<Eigen/dense>包含Core、Geometry、LU、SVD、QR和Eigenvalues头文件
Eigen#include<Eigen/Eigen>包括了Dense和Spare(整合库)

三、矩阵和向量

3.1矩阵和向量的定义

Eigen支持两类对象:用模板Eigen::Matrix表示的矩阵和向量,和用Eigen::Array表示的一维和二维数组,它们的定义如下:

typedef Matrix<Scalar,RowsAtCompileTime,ColsAtCompileTime,Options>MyMatrixType;
typedef Array<Scalar,RowsAtCompileTime,ColsAtCompileTime,Options>MyArrayType;
  1. Scalar 是标量的系数类型,如:float、double、int、bool等。
  2. RowsAtComileTImeColsAtCompileTime 表示矩阵的行列在编译时是否已知,或者是Dynamic 动态的
  3. Options 可以是 ColMajor 或 RowMajor 即列主序或行主序(存储时),默认是ColMajor
    一般情况下,即可拥有固定行列的矩阵,也可拥有动态列数的矩阵,比如
Matrix<double, 6, Dynamic>                  // 固定行数,动态列数(堆分配)
Matrix<double, Dynamic, 2>                  // 动态行数,固定列数
Matrix<double, Dynamic, Dynamic, RowMajor>  // 都是动态分配,行主序
Matrix<double, 13, 3>                       // 固定大小(一般在栈上分配)

因为类模板typedef,也可以简单的使用矩阵和数组的类型定义

// Matrix
Matrix<float,Dynamic,Dynamic>   <=>   MatrixXf
Matrix<double,Dynamic,1>        <=>   VectorXd
Matrix<int,1,Dynamic>           <=>   RowVectorXi
Matrix<float,3,3>               <=>   Matrix3f
Matrix<float,4,1>               <=>   Vector4f

// Arrays
Array<float,Dynamic,Dynamic>    <=>   ArrayXXf
Array<double,Dynamic,1>         <=>   ArrayXd
Array<int,1,Dynamic>            <=>   RowArrayXi
Array<float,3,3>                <=>   Array33f
Array<float,4,1>                <=>   Array4f

具体例子如:

//声明一个2*3de1矩阵
Eigen::Matrix<float,2,3> matrix_23;
//声明一个3*3的数组
Eigen::Array<int,3,3>array_33;
//同时,Eigen通过typedef提供了许多内置类型,不过底层依然是Eigen::Matrix
//例如Vector3d实质商就是Eigen::Matrix<double,3,1>,即三维向量
Vector3d v_3d;
//这是一样的
Matrix<float,3,1>vd_3d;

3.2矩阵的基础操作

初始化

//输入矩阵
Matrix_23<<1,2,3,4,5,6;

Vextor3d v_3d;
v1<<1,2,3;

Matrix3f m1;
m1<<1,2,3,4,5,6,7,8,9;

Arrayxf a1(4);
a1<<1,2,3,4

//输出
cout<<"matrix 2✖3 from 1 to 6"<<matrix_23<<endl;

改变矩阵,向量的大小

//vector
vector.resize(size);   //改变大小后丢失原始数据
vector.resize(other_vector);
vector.conservativeResize(size);  //改变大小后保留矩阵中的数据

//matrix
matrix.resize(ma_rows,ma_rols);
matrix.resize(Eigen::NoChange,ma_rols);
matrix.resize(ma_rows,Eigen::NoChange);
matrix.resize(other_matrix);
matrix.conservativeresize(ma_rows,ma_rols);

用()访问矩阵的元素

for(int i=0;i<2;i++)
	for(int j=0;j<3;j++)
	cout<<matrix_23(i,j)<<"\t";
cout<<endl;

矩阵和向量相乘

v_3d<<3,2,1;
vd_3d<<4,5,6;
//注意在Eigen里不能混合两种不同类型的矩阵,像这样就是错的
//Matrix<double,2,1>result=matrix_23*v_3d
Matrix<double,2,1>result=matrix_23.cast<double>()*v_3d
cout<<"[1,2,3;4,5,6]*[3,2,1]="result.transpose()<<endl;//输出结果的转置

Matrix<float,2,1>result2=matrix_23*v_3d;

四则运算

matrix_33=Matrix3d::random();//随机数矩阵
cout<<"random matrix:\n"<<matrix_33<<endl;
cout<<"transpose:\n"<<matrix_33.transpose()<<endl;
cout<<"sum:"<<matrix_33.sum()<<endl;   //各元素的和
cout<<"trace:"<<matrix_33.trace(0<<endl;   //迹
cout<<"inverse:\n"<<matrix_33.inverse()<<endl;  //逆
cout<<"times 10:\n"<<10*matrix_33<<endl;        //数乘
cout<<"det:\n"<<matrix_33.determinant()<<endl;    //行列式

四、geometry模块

Eigen::gemotry模块提供了各种旋转和平移的表示,和它们之间的变换方式。

4.1初始化

Eigen中四种旋转的双精度表示

Eigen::Matrix3d//旋转矩阵(3*3)
Eigen::AngleAxisd//旋转向量(3*1)
Eigen::Vector3d//欧拉角(3*1)
Eigen::quaterniond//四元数(4*1)
Eigen::Isometry  //欧式变换矩阵(4*4)
//3D旋转矩阵可以直接使用Matrix3d或matrix3f
matrix3d rotation_matrix=matrix3d::Identitf();//初始化为单位矩阵
//旋转向量使用AngleAxis
AngleAxisd ratation_vector(M_PI/4,vector3d(0,0,1));//沿z轴旋转45度
//将旋转向量转化为旋转矩阵
cout.precision(3)//控制输出的精度
cout<<"rotation matrix=\n"<<rotation_vector.matrix()<<endl;
//同理,矩阵可以直接赋值
rotation_matrix=rotation_vector.toRotationMatrix();

//使用AngleAxis实现矩阵旋转
Vector3d v(1,0,0);
Vector3d v_rotated=rotation_vector*v;

//使用旋转矩阵实现旋转
v_rotated=rotation_matrix*v;

4.2矩阵变换

欧拉角:将旋转矩阵变为欧拉角

vector3d euler_angles=rotation_matrix.eulerAngles(2,1,0);   //ZYX顺序
cout<<"yaw pitch roll="<<euler_angle.transpose()<<endl;

欧式变换矩阵的初始化

//欧式变换矩阵可以使用Eigen::Isometry
Isometry3d T=Isometry::Identity();//虽然是3D,但是实际上是4*4的矩阵
T.rotate(rotation_vector);           //旋转矩阵
T.pretranslate(Vector3d(1,3,4));     //平移向量
cout<<"Transform matrix=\n"<<T.matrix()<<endl;

用变换矩阵进行坐标变换

Vector3d v_transformed=T*v;     //相当于R*V+T
cout<<"v transform="<<v_transform.transpose()<<endl;

四元数的初始化

//法1:直接把AngleAxis复赋值给四元数。反之亦然
Quaterniond q=Quaterniond(rotation_vector);
//请注意coffes的顺序为(x,y,z,w),w为实部,前三者为虚部
cout<<"quaternion form rotation vector="<<q.coeffs().transpose()<<endl;
//法2:也可以把旋转矩阵赋给它
q=Quaterniond(rotation_matrix);

用四元数表示旋转

v_rotated=q*v  //注意数学上是qvq^(-1)

五、Ax=b的求解方法

	//解方程
    //求解matrix_NN*X=V_nd方程
    Matrix<double,Matrix_size,Matrix_size>matrix_NN=MatrixXd::Random(Matrix_size,Matrix_size);
    matrix_NN=matrix_NN*matrix_NN.transpose();
    Matrix<double,Matrix_size,1>v_Nd=MatrixXd::Random(Matrix_size,1);

    clock_t time_stt=clock();
    //直接求逆
    Matrix<double,Matrix_size,1> x=matrix_NN.inverse()*v_Nd;
    cout<<"time of normal inverse is"<<1000*(clock()-time_stt)/(double)CLOCKS_PER_SEC<<"ms"<<endl;
    cout<<"x="<<x.transpose()<<endl;

    //使用QR分解
    time_stt=clock();
    x=matrix_NN.colPivHouseholderQr().solve(v_Nd);
    cout<<"time of normal inverse is"<<1000*(clock()-time_stt)/(double)CLOCKS_PER_SEC<<"ms"<<endl;
    cout<<"x="<<x.transpose()<<endl;

    //使用cholesky分解
    time_stt=clock();
    x=matrix_NN.ldlt().solve(v_Nd);
    cout<<"time of normal inverse is"<<1000*(clock()-time_stt)/(double)CLOCKS_PER_SEC<<"ms"<<endl;
    cout<<"x="<<x.transpose()<<endl;
    return 0;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值