Eigen库的学习使用


前言

记录下Eigen的学习,参考SLAM十四讲。Eigen库是一个线性运算的C++模板库,支持线性代数、矩阵、矢量运算。
常用的头文件:

#include <Eigen/Dense>
#include <Eigen/Geometry>
#include <Eigen/Core>
using namespace Eigen;
using namespace std;

一、基本使用

定义:Eigen::Matrix<float,rows,cols> 第一个参数类型:float(单精度)、double(双精度);后两个参数类型:矩阵的行列。

1.矩阵输入输出:

直接使用重载运算符<<输入输出;for遍历输入输出

Eigen::Matrix<float,2,3> matrix_23; //定义2X3矩阵,float型
matrix_23<<1,2,3,4,5,6;  //输入
for(int i=0;i<matrix_23.rows();i++)             //遍历输出
{
    for(int j=0;j<matrix_23.cols();j++)
    {
        cout<<matrix_23(i,j)<<"\t";
    }
    cout<<endl;
}
Eigen::Matrix3d matrix_33;      //3X3方阵,double
for(int i=0;i<3;i++)            //矩阵输入
{
    for(int j=0;j<3;j++)
    {
        matrix_33(i,j) = 1;
    }
}
cout<<matrix_33<<endl;

Eigen::vector3d vec_3d;    //向量  3行1列
vec_3d<<1,2,3;
cout<<vec_3d<<endl;

Eigen::Matrix<double,3,1> vec_3d_2;   //同样表示3行1列---矩阵
vec_3d_2 = vec_3d;
cout<<vec_3d_2<<endl;

2.一些特殊的矩阵

Eigen::Matrix<double,Dynamic,Dynamic> matrix_dynamic  //动态矩阵
Eigen::MatrixXd::Zero(3,3);   //3x3零矩阵
Eigen::MatrixXd::Ones(5,5);   //5x5全1矩阵
Eigen::MatrixXd::Identity(2,2);  //2x2单位矩阵
Eigen::MatrixXd::Random(3,3);   //3x3随机矩阵

3.矩阵的基本运算

Matrix3d matrix_33;
matrix_33 << 1,2,3,4,5,6,7,8,9;
cout<<matrix_33.sum()<<endl;         //矩阵元素之和
cout<<matrix_33.prod()<<endl;        //矩阵元素之积
cout<<matrix_33.mean()<<endl;       //平均值
cout<<matrix_33.norm()<<endl;        //2范数--元素平方和的1/2次方
cout<<matrix_33.minCoeff()<<endl;    //返回矩阵最小元素
cout<<matrix_33.maxCoeff()<<endl;    //返回矩阵最大元素
//matrix_33.minCoeff(&i,&j)     //返回最小元素的位置
cout<<matrix_33.trace()<<endl;          //矩阵的迹---对角线元素和
cout<<matrix_33.transpose()<<endl;       //矩阵转置,原矩阵不变
//cout<<matrix_33.transposeInplace();    //转置并改变赋值给原矩阵
cout<<matrix_33.determinant()<<endl;       //行列式
cout<<matrix_33.conjugate()<<endl;            //共轭矩阵---实部不变,虚部取反
cout<<matrix_33.inverse()<<endl;               //矩阵的逆---行列式0,没有逆
cout<<matrix_33.adjoint();           //共轭转置

Matrix<float,2,3> matrix_23;
cout<<"矩阵的行数"<<matrix_23.rows()<<endl;
cout<<"矩阵的列数"<<matrix_23.cols()<<endl;
matrix_23 << 1,2,3,4,5,6;
cout<<"矩阵第二行的元素:"<<matrix_23.row(1)<<endl;   //按行输出
cout<<"矩阵第二列的元素:"<<endl;
cout<<matrix_23.col(1)<<endl;      //按列输出
cout<<matrix_23.block<2,2>(0,1)<<endl;  //从矩阵0行1列位置处取2X2矩阵

4.向量计算

Vector3d vec_3d;
Matrix<float,3,1> vf_3d;
Matrix<float,2,3> matrix_23;
vec_3d<<3,2,1;
vf_3d<<4,5,6;
matrix_23<<1,2,3,4,5,6;
Matrix<double,2,1> matrix_21 = matrix_23.cast<double>()* vec_3d;
cout<<matrix_21<<endl;

Vector3d v(1,2,3);
Vector3d w(4,5,6);
cout<<"向量点积:";
cout<<v.dot(w)<<endl;
cout<<"向量叉积:";
cout<<v.cross(w)<<endl;
cout<<"向量的模:";
cout<<v.norm()<<endl;

5.特征值和特征向量

Matrix3d matrix_33;
matrix_33 = Matrix3d::Random();
cout<<matrix_33<<endl;

//自伴随特征求解
SelfAdjointEigenSolver<Matrix3d> eigen_solver(matrix_33.transpose() * matrix_33);
//特征求解
EigenSolver<Matrix3d> eigen_solver(matrix_33.transpose() * matrix_33);

cout<<"特征值:"<<endl;
cout<<eigen_solver.eigenvalues()<<endl;
cout<<"特征向量:"<<endl;
cout<<eigen_solver.eigenvectors()<<endl;

6.方程求解

/*
       matrix_NN * x = v_Nd
*/
#define MATRIX_SIZE 50
Matrix<double,MATRIX_SIZE ,MATRIX_SIZE > matrix_NN = MatrixXd::Random(MATRIX_SIZE ,MATRIX_SIZE );
//设置半正定矩阵
matrix_NN = matrix_NN * matrix_NN.transpose();
//v_Nd矩阵
Matrix<double,MATRIX_SIZE ,1> v_Nd = MatrixXd::Random(MATRIX_SIZE ,1);

//可逆矩阵求解方程
Matrix<double,MATRIX_SIZE ,1> x1 = matrix_NN.inverse() * v_Nd;
cout<<x1<<endl;
cout<<"------------------------分割线1------------------------"<<endl;
//QR分解求解,可以求解非方阵
Matrix<double,MATRIX_SIZE ,1> x2 = matrix_NN.colPivHouseholderQr().solve(v_Nd);
cout<<x2<<endl;
cout<<"------------------------分割线2------------------------"<<endl;
//cholesky分解求解
Matrix<double,MATRIX_SIZE ,1> x3 = matrix_NN.ldlt().solve(v_Nd);
cout<<x3<<endl;

7.旋转矩阵、旋转向量、四元数

Eigen::AngleAxisd t_v(M_PI/4,Vector3d(0,0.1));    //旋转向量,绕(0,0,1)z轴旋转M_PI/4
Matrix3d t_r = t_v.matrix();                //旋转矩阵,将旋转向量转为旋转矩阵
Quaterniond t_q(t_v);                            //四元数

//对旋转向量赋值
AngleAxisd V1(M_PI/4,Vector3d(0,0,1));        //使用旋转角度和旋转轴(单位向量)来初始化
cout<<"Rotation vector 1:";
cout<<V1.matrix()<<endl;

AngleAxisd V2;
V2.fromRotationMatrix(t_r);  //使用fromRotationMatrix()函数对旋转向量赋值(四元数没有该方法)
cout<<"Rotation vector 2:";
cout<<V2.matrix()<<endl;

AngleAxisd V3;
V3 = t_r;         //直接用旋转矩阵对旋转向量赋值
cout<<"Rotation vector 3:"; 
cout<<V3.matrix()<<endl;

AngleAxisd V4(t_r);     // 使用旋转矩阵对旋转向量初始化
cout<<"Rotation vector 4:";
cout<<V4.matrix()<<endl;

AngleAxisd V5;
V5 = t_q;           //使用四元数对旋转向量赋值
cout<<"Rotation vector 5:";
cout<<V5.matrix()<<endl;

AngleAxisd V6(t_q);           //使用四元数对旋转向量初始化
cout<<"Rotation vector 6:";
cout<<V6.matrix()<<endl;
cout<<"-----------------------------------------------------------------"<<endl;
//对旋转矩阵赋值
Matrix3d R1 = Matrix3d::Identity();        //旋转矩阵函数初始化旋转矩阵  

Matrix3d R2;
R2 = t_v.matrix();        //使用旋转向量的成员函数matrix()对旋转矩阵赋值

Matrix3d R3;
R3 = t_v.toRotationMatrix();          //使用旋转向量的成员函数toRotationMatrix()对旋转矩阵赋值

Matrix3d R4;
R4 = t_q.matrix();               //使用四元数的成员函数matrix()对旋转矩阵赋值

Matrix3d R5;
R5 = t_q.toRotationMatrix();   //使用四元数的成员函数toRotationMatrix()对旋转矩阵赋值
cout<<"-----------------------------------------------------------------"<<endl;
//对四元数赋值  Eigen中的四元数前三维是虚部,最后一维是实部
 //使用旋转角度和旋转轴向量初始化四元数 q=[cos(A/2),n_x*sin(A/2),n_y*sin(A/2),n_z*sin(A/2)]
Quaterniond Q1(cos((M_PI/4)/2), 0*sin((M_PI/4)/2),0*sin((M_PI/4)/2),1*sin((M_PI/4)/2));
cout<<"Quaterniond Q1:"<<endl;
cout<<Q1.coeffs()<<endl;

Quaterniond Q2;
Q2 = t_r;       //旋转矩阵对四元数直接赋值
cout<<"Quaterniond Q2:"<<endl;
cout<<Q2.coeffs()<<endl;

Quaterniond Q3(t_r);   //旋转矩阵对四元数赋值
cout<<"Quaterniond Q3:"<<endl;
cout<<Q3.coeffs()<<endl;

Quaterniond Q4;
Q4  = t_v;    //旋转向量对四元数初始化
cout<<"Quaterniond Q4:"<<endl;
cout<<Q4.coeffs()<<endl;

Quaterniond Q5(t_v);    //旋转向量对四元数初始化
cout<<"Quaterniond Q5:"<<endl;
cout<<Q5.coeffs()<<endl;

8.欧拉角、平移向量、变换矩阵

//旋转矩阵转欧拉角
Matrix3d rotation_matrix = Matrix3d::Identity();
Vector3d enler_angles = rotation_matrix.enlerAngles(2,1,0); //0:x轴,1:y轴,2:z轴(2,1,0)代表输出角度顺序
cout<<"yaw,pitch,roll:"<<enler_angles.transpose()<<endl;

//旋转矩阵和平移向量定义变换矩阵Isometry3d
Matrix3d rotation_m = Matrix3d::Identity();
Vector3d t1;
t1<<3.214096e-14,-1.998401e-15,-4.041212e-14;
Eigen::Isometry3d T1 = Eigen::Isometry3d::Identity();    //初始化
T1.rotate(rotation_m );    //导入旋转矩阵
T1.pretranslate(t1);       //导入平移向量
cout<<T1.matrix()<<endl;

//四元数和平移向量定义变换矩阵
Quaterniond q1(0.35,0.2,0.3,0.1);
q1.normalize();          //归一化
Vector3d t2(0.3, 0.3, 0.3);
Eigen::Isometry3d T2(q1);
T2.pretranslate(t2);
cout<<T2.matrix()<<endl;

//通过Eigen::Matrix4d构造变换矩阵
Matrix3d rotation_m2 = Matrix3d::identity();  //初始化
Eigen::Matrix4d T3;
T3.setIdentity();
T3.block<3,3>(0,0) = rotation_m2;
T3.topRightCorner(3,1) = t2;
cout<<T3.matrix()<<endl;

总结

本文简要的介绍了Eigen的学习使用,对于常见的函数给出了使用方法,其它的函数用到去查官方文档即可。

  • 8
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Eigen是一个C++模板,用于线性代数计算。通过学习Eigen的源码,可以深入了解其内部实现原理,从而更好地利用该进行编程。 首先,学习Eigen的源码可以帮助我们理解它是如何实现矩阵和向量的表示和运算的。Eigen采用模板编程的方式,可以适应不同的矩阵和向量类型,包括动态大小和静态大小,以及不同的数据类型,如浮点数、整数等。通过查看源码,我们可以了解Eigen是如何使用模板来实现通用的矩阵和向量类型,并提供相应的运算功能。 其次,学习Eigen的源码还可以帮助我们了解其高效的实现方式。Eigen在设计和实现时,考虑了性能和内存使用效率。它采用矩阵和向量的表达形式,可以有效地进行运算,并尽量减少内存的分配和拷贝。通过分析源码,我们可以学习Eigen是如何通过优化算法和数据结构来提高计算性能的。 此外,学习Eigen的源码还有助于我们了解其丰富的功能和用法。Eigen提供了大量的线性代数计算功能,包括矩阵乘法、矩阵分解、特征值分解、线性方程求解等。通过深入学习Eigen的源码,我们可以理解每个功能的实现细节,进而更好地应用于实际问题中。 综上所述,通过学习Eigen的源码,我们可以深入了解其内部实现原理,掌握其高效的计算方式,同时了解其丰富的功能和用法。这将有助于我们更好地利用Eigen进行线性代数计算。 ### 回答2: Eigen是一个用于线性代数的C++模板,包含了各种矩阵运算、向量运算和线性方程求解等功能。通过学习Eigen的源码,可以深入理解矩阵运算的原理和实现细节,提高代码效率和准确性。 首先,Eigen源码使用模板实现了矩阵和向量的各种运算操作,这意味着可以使用不同的数据类型和维度来进行运算,使得代码更加灵活和通用。学习源码可以了解到模板元编程的技巧和实现方式,提高代码设计的灵活性。 其次,Eigen的源码包含了矩阵和向量的基本运算方法,如加减乘除、转置、求逆等,可以通过源码学习到这些运算方法的具体实现原理和优化技巧。了解这些细节可以帮助我们更好地理解算法的本质和性能优化的方法,提高代码的效率。 此外,Eigen的源码还包含了线性方程求解的方法,如LU分解、QR分解和特征值分解等。学习源码可以了解到这些求解方法的具体实现过程和数学原理,加深对数学建模和求解问题的理解。 最后,学习Eigen源码还可以帮助我们理解矩阵和向量的内存布局和访问方式。Eigen使用列优先的内存布局方式,了解源码可以了解到这种布局方式的原理和优势,避免内存访问的冗余和低效。 总之,通过学习Eigen的源码,可以深入理解线性代数的各种运算方法和数学原理,提高代码效率和准确性。同时,还可以学习到模板元编程的技巧和实现方式,提高代码设计的灵活性。 ### 回答3: Eigen是一个用于线性代数运算的C++模板,由于其高性能和易用性,被广泛应用于科学计算、机器学习等领域。学习Eigen的源码可以帮助我们深入理解其内部实现原理,进而更好地使用进行开发。 在学习Eigen源码时,首先我们可以从它的模板结构和设计思想入手。Eigen使用了大量模板元编程的技术,利用C++的模板特性实现了高度的灵活性和通用性。通过阅读Eigen的模板实现,我们可以学习到如何利用模板编程来实现复杂的数学运算和算法,以及如何提高程序性能和可维护性。 其次,我们可以关注Eigen的矩阵和向量运算部分的源码。Eigen提供了丰富的矩阵和向量运算接口,包括基本的加减乘除运算、转置、求逆、特征值分解等等。通过深入研究其源码,我们可以了解到这些运算是如何实现的,了解它们的算法和优化方法,从而更好地掌握Eigen使用技巧。 此外,学习Eigen源码还可以让我们了解到一些底层的计算优化技术。Eigen使用了一些特殊的技巧和优化策略,如内存对齐、向量化指令、并行计算等等,以提高运算性能。通过学习这些优化技术,我们可以将其应用到自己的程序中,提高程序的执行效率。 总之,学习Eigen的源码可以帮助我们更好地理解其内部实现原理,并且提高我们对线性代数的理解和运用能力。通过深入研究Eigen的源码,我们可以获得更多关于高性能计算和模板编程的经验,为我们日后的程序开发和科学计算提供有益的借鉴。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值