这篇文章整理了常用Eigen函数(用途、参数的意义,必要时也会列出该函数所在的头文件)以及一些其它关于Eigen库的知识。

cuda

cuda support

Eigen 3.4.x officially supports CUDA (better than older versions). You should be using at least 3.3.90 (development of 3.4) or 3.4.0 release.

use cuda

When writing .cu files with Eigen, include the following before including any Eigen headers:

#define EIGEN_USE_GPU
#include <Eigen/Core>

Eigen’s GPU support is partial. For example: You can use basic matrix operations (+, *, etc.) on the device. You cannot use features like LLT, SVD, etc., inside a CUDA kernel.

一、基础知识

1. 参考资料
3. 模块组成
  • Core:Matrix和Array类,基础的线性代数运算和数组操作;
  • Geometry:旋转,平移,缩放,2维和3维的各种变换;
  • LU:求逆,行列式,LU分解;
  • Cholesky:LLTLDLT Cholesky分解;
  • Householder:Householder变换;
  • SVD:SVD分解;
  • QR:QR分解。
  • Eigenvalues:特征值,特征向量分解。
  • Sparse:稀疏矩阵的存储和运算。
  • Dense:包含了Core、Geometry、LU、Cholesky、SVD、QR、Eigenvalues等模块。
  • Eigen:包含了Dense和Sparse模块。
2.安装及CMake声明与使用

reference-1,2

3.使用
#include <Eigen>
Eigen::MatrixXd mat(line, row); // 矩阵
4. 类型

todo:

  • Matrix
  • Vector
  • Affine
  • Isometry
  • Array
  • Quaternion

二、创建及元素获取

本部分主要介绍Eigen中矩阵与向量的定义 index.

1
Matrix<Scalar, RowsAtCompileTime, ColsAtCompileTime, Options>
  • Scalar:指定元素类型,比如,float, double, bool, int 等。
  • RowsAtCompileTime:指定行数或者设置成动态(Dynamic);
  • ColsAtCompileTime:指定列数或者设置成动态(Dynamic);
  • Options:标志位,可以是ColMajor或RowMajor,默认是ColMajor;
Matrix<double, 3, Dynamic> m;
Eigen::MatrixXf matrix1(2,3);  // 定义了矩阵的大小,但是没有初始化;元素类型是float
Eigen::VectorXd vector1(4);    // 列向量;元素类型是double
Eigen::RowVectorXi vector1(4); // 行向量;元素类型是int
Eigen::Affine3f affine1;       // 3D 
2. 初始化
mat << 1, 2, 3,
       4, 5, 6;
mat.setIdentity(rows, cols); 
mat.setZero(rows, cols);
mat.setOnes(rows, cols);  
mat.setRandom(rows, cols);
3. 特殊矩阵
  • MatrixXd::Random(m,n):创建m×n维double类型的随机数矩阵
  • MatrixXd::Constant(m,n,p):创建m×n维double类型元素全为p的矩阵
  • MatrixXd::Zero(m,n):创建m×n维元素全为0的矩阵
  • MatrixXd::Ones(m,n):创建m×n维元素全为1的矩阵
  • MatrixXd::Identity(m,n):创建m×n维的单位阵
  • VectorXd::LinSpaced(size,low,high):创建一个size长度的从low到high的向量或一维矩阵
4. 元素获取

矩阵元素获取

  • mat.rows() : 获取矩阵的行数
  • mat.cols() : 获取矩阵的列数
  • mat.size() : 获取矩阵的元素个数
  • mat.data() : 返回一个指向矩阵或向量的首地址的指针, 以把这个返回值当做数组来使用。
  • mat.row(p) : 单独取出第p行
  • mat.col(p) : 单独取出第p列
  • mat.topLeftCorner(p,q) : 取出左上角p行q列的元素, 参考
  • mat(2,3) : 第3行第4列的元素, the indices for accessing elements should be of type int 向量元素获取
  • vec.segment(i,n) : 取向量第i到第i+n个元素,n is excluded
  • vec.segment(i) : 动态向量
  • vec.head(n) : 前 n 个元素
  • vec.tail(n) : 后 n 个元素
  • vec.x() : 获取向量 vec 的第一个元素
  • vec.w() : 获取向量 vec 的第4个元素
  • vec(3) : 获取向量 vec 的第4个元素
  • vec[3] : 获取向量 vec 的第4个元素
  • Eigen::VectorXd::head(n).array().log().sum(): the sum of natural logarithms of the first n elements of vector

三、 数据操作及本身运算

1. type conversion
  • Eigen::Affine3fEigen::Matrix4f的转换
Eigen::Affine3f A;
Eigen::Matrix4f M;
M = A.matrix();
A = M;
  • 矩阵 数组 <–> 普通数组 C++数组
Eigen::Array arr;
float *a; a = mat.data(); // share memory
mat = arr.matrix(); // share memory
arr = mat.array();
  • std::vector和Eigen::Matrix的转换
std::vector<double> ext;
Eigen::Matrix3d mat;
mat=Eigen::MatrixXd::Map(ext.data( ), 3, 3);
Eigen::VectorXd pf = Eigen::Map<Eigen::VectorXd, Eigen::Unaligned>(ext.data(), ext.size());
ext = std::vector<double>(&mat[0], mat.data()+mat.cols()*mat.rows());
2. 自身赋值

Eigen使用了lazy evaluation(懒惰评估),默认都是存在混淆混叠的,也就是在计算过程中会覆盖原来位置的值。

  • eval(): 自己对自己进行赋值的时候,先把结果存到临时变量,避免Eigen中的混叠(aliasing)问题.
mat = 0.5 * (mat + mat.transpose()).eval(); 
  • InPlace(): 强调改变矩阵自身
Matrix3d T;
T.col(0) = e1;
T.col(1) = e2;
T.col(2) = e3;
T.transposeInPlace();
  • noalias(): 为了避免混淆,Eigen会在计算中创建一个临时变量来存储计算的中间值。使用这个函数则明确表示不存在混淆,使eigen在计算时不再创建临时变量,可以提高计算效率。
3. 矩阵本身运算
  • transpose() :
  • inverse() : 逆矩阵
  • conjugate() : 共轭矩阵,实数的共轭还是其本身。
  • adjoint() : 伴随矩阵
  • trace(): 矩阵的迹
  • eigenvalues() : 特征值
  • determinant() : 行列式的值
  • diagonal() : 矩阵对角线元素 consist a new diagonal matrix
  • sum() : 所有元素求和
  • prod() : 所有元素求积
  • mean() : 所有元素求平均
  • minCoeff() : 所有元素最小值
  • minCoeff(&i,&j) : 元素最小值的位置,i、j为int类型或为Eigen的Index类型。
  • maxCoeff() : 所有元素最大值
  • maxCoeff(&i,&j) : 所有元素最大值的位置
  • nonZeros() : 非零元素个数
  • squaredNorm() : 矩阵(向量)的平方范数,对向量而言等价于其与自身做点积,数值上等于各分量的平方和。
  • norm() : 矩阵(向量)的平方范数开根号(对于向量即求模长)
  • lpNorm<p>() : p范数
  • lpNorm() : 无穷范数
  • normalize() : 矩阵(向量)的正则化(归一化),使所有元素的平方和等于1。
  • (mat>0).all() : 矩阵元素条件判断,mat中所有元素是否都大于0,是返回1,否则返回0。
  • (mat>0).any() : 矩阵元素条件判断,mat中所有元素是否有大于0的,有返回1,否则返回0。
  • (mat>0).count() : 矩阵符合条件的元素计数,返回mat中大于0元素的个数。
  • colwise() : 返回矩阵每列的值(把每列作为元素,todo)
  • rowwise() : 返回矩阵每行的值
  • fill() : 将所有元素均赋值为 n
  • mat1.transpose().colwise().reverse() : Rot90
  • reshape() : 不改变矩阵元素个数的情况下,改变矩阵中元素的大小,例如转置
  • conservativeResize(Eigen::NoChange, mat.cols() + 1): Resize the matrix to add one more column
  • cwiseAbs()
  • cwiseSqrt()
  • cwiseMin()
4. Array本身运算
  • abs() :
  • sqrt() :
  • pow() :
  • arr1.min(arr2) : 将两个Array中相应位置的最小值组成一个新Array
  • arr1.max(arr2) : 将两个Array中相应位置的最大值组成一个新Array
  • square() :
5. 向量本身运算
vec.setRandom(); // 设置随机数
vec.unitOrthogonal();
6. Eigen::Map

Eigen::Map 的作用是将一个已有的 C 数组映射为一个 Eigen 的向量或者矩阵。可以使用 Eigen 向量和矩阵的各种操作函数,依然使用已有数组的空间。

Map<MatrixXd> md1(data, 2, 4);
7. Eigen::Affine
// Define an Affine3f transformation
Eigen::Affine3f transform = Eigen::Affine3f::Identity();

// Set a translation component
transform.translation() << 1.0f, 2.0f, 3.0f;

// Extract the translation vector
Eigen::Vector3f translation = transform.translation();
9. Eigen与OpenCV的数据类型转换
Eigen::Matrix<float, 2, 3> matrix_23f;
matrix_23f << 1, 2, 3, 
              4, 5, 6;
cv::Mat mat_23f;
cv::eigen2cv(matrix_23f, mat_23f);

cv::Mat mat_23f(2, 3, CV_32F); // 也可以不加括号后面的,直接定义 cv::Mat mat_23f;
mat_23f = (cv::Mat_<float>(2, 3) << 
    1, 2, 3, 
    4, 5, 6);
Eigen::Matrix<float, 2, 3> matrix_23f;
cv::cv2eigen(mat_23f, matrix_23f);
example
  • 把extRotV中的数据按行优先的方式放入3×3矩阵中;extRot为该矩阵的映射;extRot可以使用Eigen矩阵的各种操作函数
extRot = Eigen::Map<const Eigen::Matrix<double, -1, -1, Eigen::RowMajor>>(extRotV.data(), 3, 3);
  • 从矩阵noise(0,0)处起,向右向下得到3×3的矩阵;取该矩阵的对角元构建对角矩阵;把对角矩阵的主元放入数组;把数组元素强制转换为 float
Eigen::Vector3f rpyN = noise.block<3, 3>(0, 0).diagonal().array().cast<float>();
  • <矩阵块的大小>(矩阵块的起始位置,必须是静态变量) = (数值初始化向量).转换为对角矩阵
noise.block<3, 3>(acc, acc) = Eigen::Vector3f(accSquare, accSquare, accSquare).asDiagonal();

四、 矩阵运算

1. 向量的叉乘和点乘
Eigen::Vector3d a,b;
a.dot(b);
a.cross(b);
kroneckerProduct(mat1,mat2); //???
2
  • 特征值,特征向量
Eigen::EigenSolver<Eigen::Matrix2d> eigen_solver(mat);
Eigen::MatrixXd eig_value = eigen_solver.pseudoEigenvalueMatrix();
Eigen::MatrixXd eig_vector = eigen_solver.pseudoEigenvectors();
3
MatrixXf m(2,2);
MatrixXf n(2,2);

result = m.array() * n.array(); // 相乘结果还是 Array
result = m.cwiseProduct(n); // 对应项相乘
6. rotation
  • 角轴 <–> 四元数
Eigen::AngleAxisd rollAngle(Eigen::AngleAxisd(rpy[0],Eigen::Vector3d::UnitX()));
Eigen::AngleAxisd pitchAngle(Eigen::AngleAxisd(rpy[1],Eigen::Vector3d::UnitY()));
Eigen::AngleAxisd yawAngle(Eigen::AngleAxisd(rpy[2],Eigen::Vector3d::UnitZ()));
Eigen::Quaterniond q3 = yawAngle*pitchAngle*rollAngle;

Eigen::Quaternionf q1;
q1 = Eigen::AngleAxisf(roll, Vector3f::UnitX()) * Eigen::AngleAxisf(pitch, Vector3f::UnitY()) * Eigen::AngleAxisf(yaw, Vector3f::UnitZ());

Eigen::AngleAxisf aa1;
aa1 = q; // 赋值是可以的,不过必须要像这样分两行写,而不能写成一行 `AngleAxisf aa = q`。
Eigen::AngleAxisf aa2(q);
  • 旋转阵 –> 四元数
Matrix3f rot = Matrix3f::Identity();
Quaternion q3;
q3 = rot; // 赋值可以,不过必须要像这样分两行写,而不能写成一行 `Quaternion q2 = rot`
Quaternion q4(rot);

Matrix3f rot1 = q.toRotationMatrix();
  • 旋转阵 –> 欧拉角
Vector3f angles = rot1.eulerAngles(0, 1, 2); 
7. Euclidean Transformation Matrix
Eigen::Isometry3d T = Eigen::Isometry3d::Identity(); // 虽然称为 3d ,实质上是 4*4 的矩阵
T.rotate ( rotationAxis ); // 按照 angle-axis 记录的旋转阵进行旋转
T.pretranslate ( Eigen::Vector3d ( 1,3,4 ) ); // 在变换阵的”左边“添加一个平移
T.translate( Eigen::Vector3d ( 1,3,4 ) ); // 在变换阵的”右边“增加一个平移???

五、求解

// Solve Ax = b. Result stored in x. Matlab: x = A \ b.
x = A.ldlt().solve(b);  // A sym. p.s.d.    #include <Eigen/Cholesky>
x = A.llt().solve(b);  // A sym. p.d.      #include <Eigen/Cholesky>
x = A.lu().solve(b);  // Stable and fast. #include <Eigen/LU>
x = A.qr().solve(b);  // No pivoting.     #include <Eigen/QR>
x = A.svd().solve(b);  // Stable, slowest. #include <Eigen/SVD>
// .ldlt() -> .matrixL() and .matrixD()
// .llt()  -> .matrixL()
// .lu()   -> .matrixL() and .matrixU()
// .qr()   -> .matrixQ() and .matrixR()
// .svd()  -> .matrixU(), .singularValues(), and .matrixV()

六、 calculate

1 wise

cwiseProduct()
2 Isometry

欧氏变换矩阵使用 Eigen::Isometry