2021-01-09利用eigen矩阵基本操作

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021-01-09利用eigen矩阵基本操作相关的知识,希望对你有一定的参考价值。

参考技术A 头文件

#include <eigen3/Eigen/core>

#include <eigen3/Eigen/dense>

#include <eigen3/Eigen/Geometry>

//如果想要省略eigen3,需要在CMakeLists.txt文件当中添加:

include_directories("/usr/include/eigen3")

矩阵定义

Eigen::Matrix matrix_name = Eigen::Matrix <double, 3, 4> //知道矩阵的大小3*4大小的矩阵

Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> matrix_notknow_size;//不知道矩阵的大小 ,这样定义

Eigen::MatrixXd matrix_nSize; //更简单地定义矩阵,不知道矩阵的大小。

矩阵数据格式的变换

matrix_nSize.cast<double>()  //把矩阵数据格式转换成double格式,因为矩阵只能相同格式地相乘。

基本的矩阵操作:转置、求逆、求迹、求和、数乘、行列式

matrix_nSize.transpose() //转置

matrix_nSize.sum() //矩阵各元素求和

matrix_nSize.trace() //求迹

matrix_nSize.inverse() //求逆

10 * matrix_nSize //矩阵数乘,数乘是可以不同类型来做的.

matrix_nSize.determinant() //求行列式

矩阵特征值求解

matrix_real = Eigen::Matrix3d::Random();

matrix_realSymentry = matrix_real.transpose() * matrix_real;//这是一个实对称矩阵

Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eigen_solver (matrix_realSymentry) //特征求解器

cout << "Eigen values = " << eigen_solver.eigenvalues() <<endl; //输出特征值

cout << "Eigen vectors = " << eigen_solver.eigenvectors() << endl; //输出特征向量

矩阵QR分解求方程的解

x = matrix_NN.colPivHouseholderQr().solve(v_Nd);

/********************************************************

旋转矩阵、旋转向量、四元数的使用

********************************************************/

旋转向量的定义

Eigen::AngleaAxisd rotation_vector (M_PI/4, Eigen::Matrix3d::Identity())

rotation_matrix = rotation_vector.toRoationMatrix();//把旋转向量转换成旋转矩阵

rotation_matrix = rotation_vector.Matrix();// 另外一种旋转矩阵的表达形式

欧拉角

Eigen::vector3d euler_angles = rotation_matrix.eulerAngles(2, 1, 0);// z y x 顺序, yaw, pitch, row;

变换矩阵

Eigen::Isometry3d T = Eigen::Isometry3d::Identity();

T.rotate(rotation_vector);

T.pretranslate(Eigen::Vector3d(1, 3, 4));

cout <<"Transform matrix is \n" << T.matrix() << endl;

cout <<"Rotation vector is \n" << rotation_vector.axis() << endl;

四元数

Eigen::Quaterniond q = Eigen::quaterniond (rotation _vector);

cout << " quaterniond = \n" << q.coeffs() << endl;

v_rotated = q *  v;

参考书目《视觉SLAM十四讲:从理论到实践》

如何使用 C++ 将 Eigen 稀疏矩阵转换为数组?

【中文标题】如何使用 C++ 将 Eigen 稀疏矩阵转换为数组?【英文标题】:How to convert an Eigen sparse matrix into an array in C++ using the? 【发布时间】:2015-07-02 11:37:57 【问题描述】:

我使用 Eigen 包在 C++ 中创建了一个稀疏矩阵 mat。矩阵工作正常,但我试图将其转换为数组以用作位图。 mat的大小为N+1。

天真地,我尝试了以下操作:

  double zmat[N+1][N+1];

  for(int i=0; i<=N; i++)
      for(int j=0; j<=N; j++)
          zmat[i][j]=mat.coeffRef(i,j);
          
  

但这在我调试时给了我一个例外:

Unhandled exception at 0x0116B2C7 in Open_GL_test.exe: 0xC00000FD: Stack overflow (parameters: 0x00000000, 0x001D2000).

有什么想法吗?

【问题讨论】:

N 的值是多少?它一定很大,你遇到了堆栈溢出。 你为什么使用这个N+1符号?恕我直言,zmat[N][N]i&lt;N/j&lt;N 更干净 @CoryKramer N = 600 在这个例子中。 @tobi303 该矩阵用于建立一维有限元问题。我让 N 表示段数,所以有 N+1 个点。 【参考方案1】:
double zmat[N+1][N+1];

这就是给您带来麻烦的原因。在函数中将大矩阵声明为局部变量并不是一个好主意。局部变量在堆栈上分配。许多机器将堆栈的大小限制为少量数据。在我的机器上,堆栈限制约为 8 兆字节。这意味着N 的值大于大约一千将立即导致堆栈溢出。 N 的值大于几百(但小于一千)将导致在调用树的下方某处难以跟踪堆栈溢出。

不要在堆栈上分配大量数据。一些替代方案是

在命名空间范围内声明变量, 使用newdelete 分配(随后释放)矩阵, 使用普通的 Eigen 矩阵,它会为您执行 newdelete

【讨论】:

【参考方案2】:

David Hammen's 答案是正确的(double zmat[N+1][N+1]; 对于堆栈来说太大了)。但是,我觉得有必要为您的使用付出两分钱。

双循环不必要地冗长且缓慢。更糟糕的是,在矩阵的每个元素上使用coeffref 实际上会使矩阵有效地密集。在documentation for coeffRef 中它说:

如果元素不存在,则通过 insert(Index,Index) 函数将其插入,如果不存在,该函数本身会将矩阵转换为非压缩形式。 如果元素不存在,这是一个 O(log(nnz_j)) 操作(二分查找)加上 insert(Index,Index) 函数的成本。

这意味着它不仅冗长,而且会增加您的内存需求并可能成为瓶颈。您可以改为使用

MatrixXd::Map(&zmat[0], (N+1), (N+1)) = mat.toDense();

MatrixXd::Map(zmat, (N+1), (N+1)) = mat.toDense();  // double zmat = new ...

这不仅更具可读性,而且效率也更高。

【讨论】:

这行不通。需要双循环,因为mat.coeffRef(i,j) 是一个稀疏矩阵。 糟糕,错过了。固定。

以上是关于2021-01-09利用eigen矩阵基本操作的主要内容,如果未能解决你的问题,请参考以下文章

EIgen基本运算学习

利用Eigen进行矩阵计算

Eigen学习之简单线性方程与矩阵分解

使用 Eigen3 的稀疏矩阵的特征值

Eigen库矩阵和向量的运算

使用 Eigen 3.3.3 进行矩阵运算