eigen 矩阵求逆_C++学习笔记——6. Eigen入门(矩阵运算及几何模块)

「本文介绍了C++中Eigen库的代数运算模块和几何模块,以程序实例演示了常见指令用法。」

Eigen是一个高层次开源C ++库,有效支持线性代数、矩阵和矢量运算、数值分析及其相关算法。

在SLAM或者VIO研究中,对Eigen库的使用可以说非常多,因此掌握该库是非常重要且基础的能力。下面的内容大量参考了

0. Linux系统安装Eigen库

在终端输入:

sudo apt-get install libeigen3-dev

默认安装路径是/usr/include/eigen3,在第一次使用头文件时,由于头文件路径问题,会提示无此头文件:error: Eigen/Core: No such file or directory,只需要在终端执行以下命令更改头文件路径即可:

sudo ln -s /usr/include/eigen3/Eigen /usr/include/Eigen

1. Eigen主要模块

(知乎中无法插入表格,所以讲表格做成截图插入)

2. 矩阵运算命令及实例

使用Eigen库的矩阵(包括向量)运算时,需要声明头文件,矩阵执行常见的运算指令:

matrix_33 = Matrix3d::Random(); //生成一个3*3的随机矩阵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() << endl; //求迹cout << "time 10:\n"<< 10 * matrix_33 << endl; //数乘cout << "inverse :\n"<< matrix_33.inverse() << endl; //求逆cout << "det :\n"<< matrix_33.determinant() << endl; //求行列式

同样,对于代码的认识,最好的方式还是通过阅读完整的程序实例,下面给出一个涵盖常见指令的实例,相信看完程序实例,就基本掌握和理解了矩阵运算的方式:

#include using namespace std;

#include //eigen核心部分#include //稠密矩阵的代数运算(逆、特征值等)#include using namespace Eigen;

#define MATRIX_SEZE 50

int main(int argc, char **argv)

{

//声明一个2*3的矩阵,eigen中所有的向量矩阵均为Eigen::Matrix,是一个模板类。 //三个参数分别为数据类型、行数、列数 Matrix matrix_23;

//声明一个三维向量,Vector_3d实际上是一个通过typedef定义的内置类型,本质上仍然是Eigen::Matrix模板类 Vector3d v_3d;

//Matrix vd_3d;

//声明一个3*3的矩阵,并初始化为0矩阵 Matrix3d matrix_33 = Matrix3d::Zero();

//不确定矩阵大小时,可以使用动态大小的矩阵 Matrix matrix_dynamic;

//或者更简单的方式 MatrixXd matrix_x;

//准备对Eigen矩阵初始化 //输入数据 matrix_23 << 1, 2, 3, 4, 5, 6;

//shuchu cout << "matrix 2*3 from 1 to 6 :\n"<< matrix_23 << endl;

//使用()访问矩阵中的元素 cout << "print matirx 2*3 : "<< endl;

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; //不能混乘两种类型的矩阵,因此需要显示转换类型:.cast Matrix result = matrix_23.cast() * v_3d;

cout << "[1,2,3;4,5,6]*[3,2,1] = "<< result.transpose() << endl;

//.transpose()是转置函数 cout << "not transpose [1,2,3;4,5,6]*[3,2,1] = "<< result << endl;

Matrix result2 = matrix_23 * v_3d.cast();

cout << "[1,2,3;4,5,6]*[3,2,1] = "<< result2.transpose() << endl;

//生成一个随机矩阵 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() << endl; //求迹 cout << "time 10:\n"<< 10 * matrix_33 << endl; //数乘 cout << "inverse :\n"<< matrix_33.inverse() << endl; //求逆 cout << "det :\n"<< matrix_33.determinant() << endl; //求行列式

//求特征值 //实对称矩阵可以保证对角化成功 SelfAdjointEigenSolver eigen_solver(matrix_33.transpose() * matrix_33); //SelfAdjointEigenSolvery用于求解特征值和特征向量 cout << "Eigen values =\n" << eigen_solver.eigenvalues() << endl;

cout << "Eigen vectors =\n" << eigen_solver.eigenvectors() << endl;

//练习求解方程 //求解Matrix_NN * x = v_NN方程 Matrix matrix_NN

= MatrixXd::Random(MATRIX_SEZE,MATRIX_SEZE); //MATRIX_SEZE在前面宏定义中 matrix_NN = matrix_NN *matrix_NN.transpose(); //此处理可以保证矩阵是半正定的 Matrix v_Nd = MatrixXd::Random(MATRIX_SEZE, 1);

clock_t time_stt = clock(); //用于计时

//直接求逆 Matrix 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 Qr decomposition 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 ldlt decomposition is "

<< 1000 * (clock() - time_stt) / (double) CLOCKS_PER_SEC << "ms" << endl;

cout << "x = " << x.transpose() << endl;

return 0;

}

3. 几何模块命令及实例

使用Eigen库的几何模块时,需要声明头文件,此模块支持进行四元数、欧拉角和旋转矩阵的运算。各种常见形式的表达方式如下所示:

Eigen::Matrix3d //旋转矩阵(3*3)Eigen::AngleAxisd //旋转向量(3*1)Eigen::Vector3d //欧拉角(3*1)Eigen::Quaterniond //四元数(4*1)Eigen::Isometry3d //欧式变换矩阵(4*4)Eigen::Affine3d //放射变换矩阵(4*4)Eigen::Projective3d //射影变换矩阵(4*4)

上述数据类型均为双精度(double)类型,若要改为单精度(float)类型,把最后的d改为f即可。

下面给出程序实例,看完实例应该能基本了解了几何变换的形式,若对相关数学知识不了解,可以相应去学习一下:

//本程序将演示Geometry几何模块的使用#include #include using namespace std;

#include #include //Geometry模块提供了各种旋转和平移的表示using namespace Eigen;

int main(int argc, char ** argv)

{

//3d旋转矩阵可以直接使用Matrix3d或者Matrix3f Matrix3d rotation_matrix = Matrix3d :: Identity();

//旋转向量使用AngleAxis,运算可以当做矩阵 AngleAxisd rotation_vector(M_PI / 4, Vector3d(0,0,1)); //眼Z轴旋转45° cout.precision(3); //输出精度为小数点后两位 cout << "rotation matrix =\n" << rotation_vector.matrix() << endl;

//用matrix转换成矩阵可以直接赋值 rotation_matrix = rotation_vector.toRotationMatrix();

//使用Amgleanxis可以进行坐标变换 Vector3d v(1, 0, 0);

Vector3d v_rotated = rotation_vector * v;

cout << "(1,0,0) after rotation (by angle axis) = " << v_rotated.transpose() << endl;

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

cout << "(1,0,0) after rotation (by matrix) = " << v_rotated.transpose() << endl;

//欧拉角:可以将矩阵直接转换成欧拉角 Vector3d euler_angles = rotation_matrix.eulerAngles(2, 1, 0); //按照ZYX顺序 cout << "yaw pitch row = "<< euler_angles.transpose() << endl;

//欧式变换矩阵使用Eigen::Isometry Isometry3d T = Isometry3d::Identity(); //实质为4*4的矩阵 T.rotate(rotation_vector); //按照rotation_vector进行转化 T.pretranslate(Vector3d(1, 3, 4)); //平移向量设为(1, 3, 4) cout << "Transform matrix =\n" << T.matrix() <

//变换矩阵进行坐标变换 Vector3d v_transformed = T *v;

cout << "v transormed =" << v_transformed.transpose() << endl;

//四元数 //直接把AngleAxis赋值给四元数,反之亦然 Quaterniond q = Quaterniond(rotation_vector);

cout << "quaternion from rotation vector = " << q.coeffs().transpose() << endl;

q = Quaterniond(rotation_matrix);

cout << "quaternion from rotation matrix = "<< q.coeffs().transpose() << endl;

//使用四元数旋转一个向量,使用重载的乘法即可 v_rotated = q * v;

cout << "(1,0,0) after rotation = " << v_rotated.transpose() << endl;

cout << "should be equal to " << (q * Quaterniond(0, 1, 0, 0) * q.inverse()).coeffs().transpose() << endl;

return 0;

}

你可能感兴趣的:(eigen,矩阵求逆)