Eigen简化版使用手册

简介

Eigen是C++语言里的一个开源模版库,支持线性代数运算,矩阵和矢量运算,数值分析及其相关的算法。在Eigen中,所有的矩阵和向量都是Matrix模板类的对象,向量只是特殊的矩阵而已,无论是行向量还是列向量。

Matrix类

Matrix类共有6个模板参数,主要使用的是前三个参数,剩余的都有默认值,参数分别是

 Matrix<typename Scalar,        // 变量类型, i.e. float
        int RowsAtCompileTime,  // 行
        int ColsAtCompileTime,  // 列
        int Options = 0,        // 矩阵的存储方式,RowMajor表示按行存储。默认是按列存储的。
        int MaxRowsAtCompileTime = RowsAtCompileTime, // 行上限
        int MaxColsAtCompileTime = ColsAtCompileTime> // 列上限

其中Scalar是变量类型,如float,int等。

Matrix除了添加固定的行列之外,还可以用参数Dynamic设置动态尺寸,就是先声明变量后面再固定尺寸。

typedef Matrix<double, Dynamic, Dynamic> MatrixXd;
typedef Matrix<int, Dynamic, 1> VectorXi;
typedef Matrix<float, 3, Dynamic> VectorXi

Matrix初始化

Matrix3f a; // a是3x3的矩阵,分配了float[9]的空间但是没有进行初始化
MatrixXf b; // b是个0x0的矩阵
MatrixXf a(10,15); // 这里a是10x15的矩阵,分配了空间没有进行初始化;

VectorXf b(30); //b是个尺寸为30的向量没有初始化。
Vector2d a(5.0, 6.0); // 尺寸小于4的向量可以直接在定义时初始化
Vector3d b(5.0, 6.0, 7.0);
Vector4d c(5.0, 6.0, 7.0, 8.0);

逗号初始化

#include <iostream>
#include <Eigen/Dense>
 
using namespace Eigen;
using namespace std;
int main() {
    Eigen::MatrixXd m(2, 2);
    m(0, 0) = 1;
    m(0, 1) = 2;
    m(1, 0) = 3;
    m(1, 1) = 4;
    cout << m << endl;
    m << 1, 2, 3, 4;
    cout << m << endl;
    m.row(0) << 1, 2;
    m.row(1) << 3, 4;
    cout << m << endl;
    m.block<2, 2>(0, 0) << 1, 2, 3, 4;
    cout << m << endl;
    // 以上得到的m都是一样的
    
    // Random(Index rows, Index cols);
    Eigen::MatrixXd m1 = Eigen::MatrixXd::Random(3, 3);
    // Constant(Index rows, Index cols, const Scalar& value);
    Eigen::MatrixXd m2 = Eigen::MatrixXd::Constant(3, 3, 1.2);
    // (-1,1)+1.2 = (0.2,2.2)
    // (0.2,2.2)*50 = (10,110)
    m1 = (m1 + m2) * 50;
    cout << "m1 = " << endl << m1 << endl;
    Eigen::VectorXd v(3);
    v << 1, 2, 3; // or Eigen::Vector3d v(1, 2, 3);
    cout << "m1*v = " << endl << m1 * v << endl;
    float num = m1(0, 1);
    num = v(2); // num = v[2]也是可以的
    return 0;
}

组合多个向量/矩阵

组合后的向量/矩阵的尺寸要预先设定好

#include <iostream>
#include <Eigen/Dense>
 
using namespace Eigen;
using namespace std;
int main() {
    Eigen::MatrixXd m2(3, 3);
    m2 << 1,2,3,4,5,6,7,8,9;
    Eigen::MatrixXd m3 = m2.transpose();
    cout << "m2 = " << m2 << endl;
    cout << "m3 = " << m3 << endl;
    Eigen::MatrixXd m4(3, 6);
    m4 << m2, m3;
    cout << "m4 = " << m4 << endl;
    Eigen::MatrixXd m5(5, 3);
    m5 << m2, m3.block<2, 3>(0, 0);
    cout << "m5 = " << m5 << endl;
}
/*
m2 = 1 2 3
4 5 6
7 8 9
m3 = 1 4 7
2 5 8
3 6 9
m4 = 1 2 3 1 4 7
4 5 6 2 5 8
7 8 9 3 6 9
m5 = 1 2 3
4 5 6
7 8 9
1 4 7
2 5 8
*/

特殊矩阵和数组

zero():

std::cout << "A fixed-size array:\n";
Array33f a1 = Array33f::Zero();
std::cout << a1 << "\n\n";
std::cout << "A one-dimensional dynamic-size array:\n";
ArrayXf a2 = ArrayXf::Zero(3);
std::cout << a2 << "\n\n";
std::cout << "A two-dimensional dynamic-size array:\n";
ArrayXXf a3 = ArrayXXf::Zero(3, 4);
std::cout << a3 << "\n";

Constant():

// Constant(Index rows, Index cols, const Scalar& value);
Eigen::MatrixXd m2 = Eigen::MatrixXd::Constant(3, 3, 1.2);
Eigen::Vector3d v(3); 

Random():

// Random(Index rows, Index cols);
Eigen::MatrixXd m1 = Eigen::MatrixXd::Random(3, 3);

Identity():获得单位矩阵,这个方法只能用于矩阵,不能用于数组。

// Identity(Index rows, Index cols);
Eigen::MatrixXd m1 = Eigen::MatrixXd::Indentity(3, 3);

LinSpaced():只能用于向量和一维的数组.

ArrayXXf table(10, 4);
table.col(0) = ArrayXf::LinSpaced(10, 0, 90);
table.col(1) = M_PI / 180 * table.col(0);
table.col(2) = table.col(1).sin();
table.col(3) = table.col(1).cos();
std::cout << "  Degrees   Radians      Sine    Cosine\n";
std::cout << table << std::endl;
/*
Degrees   Radians      Sine    Cosine
        0         0         0         1
       10     0.175     0.174     0.985
       20     0.349     0.342      0.94
       30     0.524       0.5     0.866
       40     0.698     0.643     0.766
       50     0.873     0.766     0.643
       60      1.05     0.866       0.5
       70      1.22      0.94     0.342
       80       1.4     0.985     0.174
       90      1.57         1 -4.37e-08
*/

上述特殊矩阵均可以用setZero(), setIdentity(), setLinSpaced()实现,举例:

const int size = 6;
MatrixXd mat1(size, size);
mat1.topLeftCorner(size/2, size/2)     = MatrixXd::Zero(size/2, size/2);
mat1.topRightCorner(size/2, size/2)    = MatrixXd::Identity(size/2, size/2);
mat1.bottomLeftCorner(size/2, size/2)  = MatrixXd::Identity(size/2, size/2);
mat1.bottomRightCorner(size/2, size/2) = MatrixXd::Zero(size/2, size/2);
std::cout << mat1 << std::endl << std::endl;
MatrixXd mat2(size, size);
mat2.topLeftCorner(size/2, size/2).setZero();
mat2.topRightCorner(size/2, size/2).setIdentity();
mat2.bottomLeftCorner(size/2, size/2).setIdentity();
mat2.bottomRightCorner(size/2, size/2).setZero();
std::cout << mat2 << std::endl << std::endl;
MatrixXd mat3(size, size);
mat3 << MatrixXd::Zero(size/2, size/2), MatrixXd::Identity(size/2, size/2),
        MatrixXd::Identity(size/2, size/2), MatrixXd::Zero(size/2, size/2);
std::cout << mat3 << std::endl;
/*
0 0 0 1 0 0
0 0 0 0 1 0
0 0 0 0 0 1
1 0 0 0 0 0
0 1 0 0 0 0
0 0 1 0 0 0
*/

临时对象

Eigen在赋值给一个变量之前,返回的是表达式对象,当需要时被确定为矩阵或数组,即为临时对象。可以这样使用:

MatrixXf mat = MatrixXf::Random(2, 3);
std::cout << mat << std::endl << std::endl;
mat = (MatrixXf(2,2) << 0, 1, 1, 0).finished() * mat;
std::cout << mat << std::endl;

Matrix尺寸调整

m1.rows(), m1.cols()获取行数/列数;

m1.resize(r, c); resize之后若矩阵大小不变,则存储内存不变,否则内存改变

#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
  MatrixXd m(2,5);
  m.resize(4,3);
  std::cout << "The matrix m is of size "
            << m.rows() << "x" << m.cols() << std::endl;
  std::cout << "It has " << m.size() << " coefficients" << std::endl;
  VectorXd v(2);
  v.resize(5);
  std::cout << "The vector v is of size " << v.size() << std::endl;
  std::cout << "As a matrix, v is of size "
            << v.rows() << "x" << v.cols() << std::endl;
            
/*The matrix m is of size 4x3
It has 12 coefficients
The vector v is of size 5
As a matrix, v is of size 5x1*/

矩阵和向量的运算

加减

运算符两侧必须有相同的行和列,而且还要有相同的数据类型。因为Eigen并不做自动类型转换,可用的操作符有:

a+b;
a-b;
-a;
a += b;
a -= b;

标量乘除

没有太多限制,正常使用

M*x
M/x

矩阵乘法/向量乘法

矩阵相乘使用运算符*实现,由于向量也是一种特殊的矩阵,因此矩阵乘以向量和向量间的外积是一样的方法。但是矩阵与向量相乘时需要注意,Vector2d u(-1,1)相当于u是一个2*1的向量,因此下面代码中mat*u可行,但是mat*u.transpose()会出错。

#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
  Matrix2d mat;
  mat << 1, 2,
         3, 4;
  Vector2d u(-1,1), v(2,0);
  std::cout << "Here is mat*mat:\n" << mat*mat << std::endl;
  std::cout << "Here is mat*u:\n" << mat*u << std::endl;
  std::cout << "Here is u^T*mat:\n" << u.transpose()*mat << std::endl;
  std::cout << "Here is u^T*v:\n" << u.transpose()*v << std::endl;
  std::cout << "Here is u*v^T:\n" << u*v.transpose() << std::endl;
  std::cout << "Let's multiply mat by itself" << std::endl;
  mat = mat*mat;
  std::cout << "Now mat is mat:\n" << mat << std::endl;
}

转置和共轭

对矩阵的转置、共轭和共轭转置由成员函数transpose(),conjugate(),adjoint()实现

MatrixXcf a = MatrixXcf::Random(2,2);
cout << "Here is the matrix a\n" << a << endl;
cout << "Here is the matrix a^T\n" << a.transpose() << endl;
cout << "Here is the conjugate of a\n" << a.conjugate() << endl;
cout << "Here is the matrix a^*\n" << a.adjoint() << endl;

至于基本的数值运算符、transpose()和adjoint()会简单的返回一个中间对象而不是对原对象做处理。比如你做b=a.transpose(),那么a会保存不变。然而当你做a=a.transpose()时Eigen会在转置执行结束前就往a中写入数据,导致结果出错。同样如果只执行a.transpose(),a不会发生改变。

点积(数量积)和叉积

点积:v1.dot(v2),保证v1,v2纬度一致即可,转置不转置无所谓

叉积:v1.cross(v2), 叉积仅仅用于尺寸为3的向量,点积可以用于任意尺寸的向量。

矩阵按元素相乘

res = m1.cwiseProduct(m2)

矩阵基础运算

Eigen提供了一些对于矩阵或向量的规约操作,如sum(),prod(),maxCoeff()和minCoeff()

#include <iostream>
#include <Eigen/Dense>
using namespace std;
int main()
{
  Eigen::Matrix2d mat;
  mat << 1, 2,
         3, 4;
  cout << "Here is mat.sum():       " << mat.sum()       << endl; // 求和
  cout << "Here is mat.prod():      " << mat.prod()      << endl; // 求积
  cout << "Here is mat.mean():      " << mat.mean()      << endl; // 平均
  cout << "Here is mat.minCoeff():  " << mat.minCoeff()  << endl; // 最小值
  cout << "Here is mat.maxCoeff():  " << mat.maxCoeff()  << endl; // 最大值
  cout << "Here is mat.trace():     " << mat.trace()     << endl; // 矩阵的迹,对角线元素和
  cout << "Here is mat.trace():     " << mat.diagonal().sum() << endl; // 同上
  
  std::ptrdiff_t i, j;
  double mixVal = mat.minCoeff(&i, &j); // 获取最小值的位置
 }
 /*
 Here is mat.sum():       10
Here is mat.prod():      24
Here is mat.mean():      2.5
Here is mat.minCoeff():  1
Here is mat.maxCoeff():  4
Here is mat.trace():     5
*/

部分规约,指的是对矩阵或数组按行或列进行的操作。例如mat.colwise().maxCoeff()就是按列求最大值。

#include <iostream>
#include <Eigen/Dense>
using namespace std;
using namespace Eigen;
int main()
{
  MatrixXf mat(2,4);
  mat << 1, 2, 6, 9,
         3, 1, 7, 2;
  
  MatrixXf::Index   maxIndex;
  float maxNorm = mat.colwise().sum().maxCoeff(&maxIndex);
  
  std::cout << "Maximum sum at position " << maxIndex << std::endl;
  std::cout << "The corresponding vector is: " << std::endl;
  std::cout << mat.col( maxIndex ) << std::endl;
  std::cout << "And its sum is is: " << maxNorm << std::endl;
}
/*
Maximum sum at position 2
The corresponding vector is: 
6
7
And its sum is is: 13
*/

广播,概念类似于部分规约,不同之处在于广播通过对向量在一个方向上的复制,将向量解释成矩阵。注意需要用matrix+vector,如下例子将一个列向量加到矩阵的每一列中

#include <iostream>
#include <Eigen/Dense>
using namespace std;
int main()
{
  Eigen::MatrixXf mat(2,4);
  Eigen::VectorXf v(2);
  
  mat << 1, 2, 6, 9,
         3, 1, 7, 2;
         
  v << 0,
       1;
       
  //add v to each column of m
  mat.colwise() += v;
  
  std::cout << "Broadcasting result: " << std::endl;
  std::cout << mat << std::endl;
}
/*
Broadcasting result: 
1 2 6 9
4 2 8 3
*/

Array

Array类提供了和Matrix不同的操作,Matrix主要为了线性代数而设计,而Array类是通常用的数组。Array类提供了更方便的元素级的操作,但是没有线性代数方面的意义,比如给每个元素的值加上一个常数或按照元素相乘两个array对象。

Array模板类的参数同Matrix类相同,前三个参数同样是

Array<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime>

Array初始化

Eigen为Array对象同样提供了常用的类型的定义,由于array通常指的是一维或二维的数组,因此这些常用的定义和Matrix的稍有不同。ArrayNt表示一维的数组,N和t分别代表尺寸和数据类型,对于二维数组使用ArrayNNt定义。以下是一些例子:

Array23f a1; // 2*3 array
Array3f a1; // 3*1 array
ArrayXf a1; // dynamic array

赋值方式与Matrix基本一致,不赘述。

#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
using namespace std;
int main()
{
  ArrayXXf  m(2,2);
  
  // assign some values coefficient by coefficient
  m(0,0) = 1.0; m(0,1) = 2.0;
  m(1,0) = 3.0; m(1,1) = m(0,1) + m(1,0);
  
  // print values to standard output
  cout << m << endl << endl;
 
  // using the comma-initializer is also allowed
  m << 1.0,2.0,
       3.0,4.0;
     
  // print values to standard output
  cout << m << endl;
}

数组运算

数组加减运算

Array可以和同样大小的Array加减,也可以和标量进行加减。

#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
using namespace std;
int main()
{
  ArrayXXf a(3,3);
  ArrayXXf b(3,3);
  a << 1,2,3,
       4,5,6,
       7,8,9;
  b << 1,2,3,
       1,2,3,
       1,2,3;
       
  // Adding two arrays
  cout << "a + b = " << endl << a + b << endl << endl;
  // Subtracting a scalar from an array
  cout << "a - 2 = " << endl << a - 2 << endl;
}
/*
a + b = 
 2  4  6
 5  7  9
 8 10 12

a - 2 = 
-1  0  1
 2  3  4
 5  6  7
*/

数组乘法运算

和标量乘没啥,两个数组相乘时是对应元素相乘,要求数组大小相同

#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
using namespace std;
int main()
{
  ArrayXXf a(2,2);
  ArrayXXf b(2,2);
  a << 1,2,
       3,4;
  b << 5,6,
       7,8;
  cout << "a * b = " << endl << a * b << endl;
}
/*
a * b = 
 5 12
21 32
*/

数组元素级别操作

Array对象还有其他的一些操作:

abs()返回数组每个元素的绝对值

sqrt()计算每个元素的根。

min()两个尺寸相同的数组,可以使用方法构建一个新的数组,新的数组的元素是原来的两个数组的对应位置的最小值

#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
using namespace std;
int main()
{
  ArrayXf a = ArrayXf::Random(5);
  a *= 2;
  cout << "a =" << endl 
       << a << endl;
  cout << "a.abs() =" << endl 
       << a.abs() << endl;
  cout << "a.abs().sqrt() =" << endl 
       << a.abs().sqrt() << endl;
  cout << "a.min(a.abs().sqrt()) =" << endl 
       << a.min(a.abs().sqrt()) << endl;
}

此外对数组还能进行布尔运算:

#include <Eigen/Dense>
#include <iostream>
using namespace std;
using namespace Eigen;
int main()
{
  ArrayXXf a(2,2);
  
  a << 1,2,
       3,4;
  cout << "(a > 0).all()   = " << (a > 0).all() << endl; // 若0换成和a相同大小的Matrix,则a可以为matrix
  cout << "(a > 0).any()   = " << (a > 0).any() << endl;
  cout << "(a > 0).count() = " << (a > 0).count() << endl;
  cout << endl;
  cout << "(a > 2).all()   = " << (a > 2).all() << endl;
  cout << "(a > 2).any()   = " << (a > 2).any() << endl;
  cout << "(a > 2).count() = " << (a > 2).count() << endl;
}

Array和Matrix相互转换

元素级别操作可以用Array,线代运算可以用Matrix。

a1 = m1.array();
m1 = a1.matrix();

块操作(Array&Matrix)

块指的是矩阵或数组中的一个矩形区域,块表达式可以用于左值或者右值,同样不会耗费运行时间,由编译器优化。

块基本操作

Eigen中最常用的块操作是block()方法,共有两个版本。

/*
matrix.block(c, r, h, w);
matrix.block<h, w>(c, r);
*/
#include <Eigen/Dense>
#include <iostream>
using namespace std;
int main()
{
  Eigen::MatrixXf m(4,4);
  m <<  1, 2, 3, 4,
        5, 6, 7, 8,
        9,10,11,12,
       13,14,15,16;
  cout << "Block in the middle" << endl;
  cout << m.block<3,2>(0,1) << endl << endl;
  for (int i = 2; i <= 3; ++i)
  {
    cout << "Block of size " << i-1 << "x" << i << endl;
    cout << m.block(0,1,i-1,i) << endl << endl;
  }
}
/*
Block in the middle
 2  3
 6  7
10 11

Block of size 1x2
2 3

Block of size 2x3
2 3 4
6 7 8
*/

上述例子中的块操作方法作为表达式的右值,意味着是只读形式的,然而,块操作也可以作为左值使用,意味着你可以给他赋值。下面的例子说明了这一点,当然对于矩阵的操作是一样的。

#include <Eigen/Dense>
#include <iostream>
using namespace std;
using namespace Eigen;
int main()
{
  Array22f m;
  m << 1,2,
       3,4;
  Array44f a = Array44f::Constant(0.6);
  cout << "Here is the array a:" << endl << a << endl << endl;
  a.block<2,2>(1,1) = m;
  cout << "Here is now a with m copied into its central 2x2 block:" << endl << a << endl << endl;
  a.block(0,0,2,3) = a.block(2,1,2,3);
  cout << "Here is now a with bottom-right 2x3 block copied into top-left 2x2 block:" << endl << a << endl << endl;
}
/*
Here is the array a:
0.6 0.6 0.6 0.6
0.6 0.6 0.6 0.6
0.6 0.6 0.6 0.6
0.6 0.6 0.6 0.6

Here is now a with m copied into its central 2x2 block:
0.6 0.6 0.6 0.6
0.6   1   2 0.6
0.6   3   4 0.6
0.6 0.6 0.6 0.6

Here is now a with bottom-right 2x3 block copied into top-left 2x2 block:
  3   4 0.6 0.6
0.6 0.6 0.6 0.6
0.6   3   4 0.6
0.6 0.6 0.6 0.6
*/

行和列操作

按行和按列分布的特殊块

/*
matrix.row(i);
matrix.col(i);
*/
#include <Eigen/Dense>
#include <iostream>
using namespace std;
int main()
{
  Eigen::MatrixXf m(3,3);
  m << 1,2,3,
       4,5,6,
       7,8,9;
  cout << "Here is the matrix m:" << endl << m << endl;
  cout << "2nd Row: " << m.row(1) << endl;
  m.col(2) += 3 * m.col(0);
  cout << "After adding 3 times the first column into the third column, the matrix m is:\n";
  cout << m << endl;
}
/*
Here is the matrix m:
1 2 3
4 5 6
7 8 9
2nd Row: 4 5 6
After adding 3 times the first column into the third column, the matrix m is:
 1  2  6
 4  5 18
 7  8 30
*/

边角相关的操作

Eigen同样提供了对于挨着矩阵或数组的边、角的特殊操作方法,比如topLeftCorner()方法可用于操作矩阵左上角的区域。具体例子比较多,不一一介绍,知道了自己查链接

#include <Eigen/Dense>
#include <iostream>
using namespace std;
int main()
{
  Eigen::Matrix4f m;
  m << 1, 2, 3, 4,
       5, 6, 7, 8,
       9, 10,11,12,
       13,14,15,16;
  cout << "m.leftCols(2) =" << endl << m.leftCols(2) << endl << endl;
  cout << "m.bottomRows<2>() =" << endl << m.bottomRows<2>() << endl << endl;
  m.topLeftCorner(1,3) = m.bottomRightCorner(3,1).transpose();
  cout << "After assignment, m = " << endl << m << endl;
}
/*
m.leftCols(2) =
 1  2
 5  6
 9 10
13 14

m.bottomRows<2>() =
 9 10 11 12
13 14 15 16

After assignment, m = 
 8 12 16  4
 5  6  7  8
 9 10 11 12
13 14 15 16
*/

对于向量和一维数组的操作

主要关注一下segment(i, n)的用法

#include <Eigen/Dense>
#include <iostream>
using namespace std;
int main()
{
  Eigen::ArrayXf v(6);
  v << 1, 2, 3, 4, 5, 6;
  cout << "v.head(3) =" << endl << v.head(3) << endl << endl;
  cout << "v.tail<3>() = " << endl << v.tail<3>() << endl << endl;
  v.segment(1,4) *= 2;
  cout << "after 'v.segment(1,4) *= 2', v =" << endl << v << endl;
}
/*
v.head(3) =
1
2
3

v.tail<3>() = 
4
5
6

after 'v.segment(1,4) *= 2', v =
 1
 4
 6
 8
10
 6
*/

几何模块

<Eigen/Geometry>主要用于空间旋转变换的响应运算,有部分特殊的矩阵需要单独学习,例如

  • 旋转向量AngleAxisd;
  • 四元数Quaterniond;
  • 欧式变换矩阵Isometry3d;
  • 仿射变换矩阵Affine3d;
  • 射影变换矩阵Projective3d;

对于旋转矩阵和欧拉角就直接用Matrix和Vector就行。

  • 旋转矩阵Matrix3d
  • 欧拉角Vector3d

旋转矩阵转欧拉角

Vector3d euler_angles = rotation_matrix.eulerAngles(2, 1, 0);
cout << "yaw pitch roll = " << euler_angles.transpose() * (180 / M_PI) << endl;

旋转向量

旋转向量在Eigen中等同于旋转矩阵,一个向量v由rotation_vector * v旋转就等同于rotation_vector.matrix() * v

#include <Eigen/Geometry>
// AngleAxisd(angle_radian, vector3d)
AngleAxisd rotation_vector(M_PI, vector3d(0,0,1);
rotation_vector.angle(); // 获取弧度
rotation_vector.axis(); // 获取旋转轴
rotation_vector.toRotationMatrix(); // 获取旋转矩阵
rotation_vector.matrix(); // 同上

变换矩阵

变换矩阵就是旋转矩阵和平移向量的齐次形式,初始化以及赋值方式和matrix不太一样,例子如下

// Isometry3d() 初始化
Isometry3d T = Isometry3d::Identity(); // 初始化,必要
T.rotate(rotation_vector); // 设置旋转矩阵,rotation_matrix也行
T.pretranslate(Vector3f(0, 0, 3)); // 设置平移向量
cout << "Transform matrix = \n" << T.matrix() << endl; // T.matrix()才是变换矩阵

// 利用变换矩阵进行坐标变换,变换时的T就相当于R*v+t
Vector3d v_transformed = T * v;
cout << "v transformed = " << v_transformed.transpose() << endl;

四元数

四元数可以有旋转向量或者旋转矩阵获得

// Quaterniond(const Scalar &w, const Scalar &x, const Scalar &y, const Scalar &z)
Quaterniond q(rotation_vector);
Quaterniond q(1, 2, 3, 4); // 初始化时(w, x, y,  z)
cout << q.coeffs() << endl; // 输出 (x, y, z, w)
cout << q.x() << endl;
v_roteted = q * v; // 用四元数表示旋转

线性代数

主要了解LU,QR,SVD这几种分解方式。

基本的线性求解

假定有方程$Ax=b$,用Eigen求解方式如下:

#include <iostream>
#include <Eigen/Dense>
using namespace std;
using namespace Eigen;
int main()
{
   Matrix3f A;
   Vector3f b;
   A << 1,2,3,  4,5,6,  7,8,10;
   b << 3, 3, 4;
   cout << "Here is the matrix A:\n" << A << endl;
   cout << "Here is the vector b:\n" << b << endl;
   Vector3f x = A.colPivHouseholderQr().solve(b);
   cout << "The solution is:\n" << x << endl;
   FullPivHouseholderQR<Matrix3f> det(A);
   x = det.solve(b);
   cout << "The solution is:\n" << x << endl;
}
/*
Here is the matrix A:
 1  2  3
 4  5  6
 7  8 10
Here is the vector b:
3
3
4
The solution is:
-2
 1
 1
*/

例子中colPivHouseholderQr()方法即为QR分解,返回一个类ColPivHouseholderQR的对象,因此那句话也可以写成

ColPivHouseholderQR<Matrix3f> dec(A);
Vector3f x = dec.solve(b);

常见的分解方式还有:

DecompositionMethodRequirements
PartialPivLUpartialPivLu()Invertible
FullPivLUfullPivLu()None
HouseholderQRhouseholderQr()None
ColPivHouseholderQRcolPivHouseholderQr()None
LLTllt()Positive definite
LDLTldlt()Positive or negative semidefinite
JacobiSVDjacobiSvd()None

特征值和特征向量

先放着,晚点看链接

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值