第一章总结:
1.关于使用fixed-size 和 dynamic-size MatrixXd相当于动态开辟一片内存,类似于 new Matrix3d 在编译时已经分配好内存 原则>4的矩阵用dynamic-size <= 4用fixed-size 2. transpose和adjoint会简单的返回一个代理对象并不对本省做转置。如果执行 b=a.transpose() ,a不变,转置结果被赋值给b。如果执行 a=a.transpose() Eigen在转置结束之前结果会开始写入a,所以a的最终结果不一定等于a的转置。这被称为“别名问题”。 3. 但是矩阵相乘不会有别名问题,m=mm是可以的,因为eigin内部做了特殊处理引入临时变量 tmp=mm m = tmp, 如果想要避免临时变量 c.noalias() += a*b 4. 当相同的矩阵或array在等式左右都出现时,很容易出现混淆。 compnent级别的操作不用考虑混淆。(组件级是指整体的操作,比如matrix加法、scalar乘、array乘等,这类操作是安全的,不会出现混淆。) 矩阵相乘,Eigen默认会解决混淆问题,如果你确定不会出现混淆,可以使用noalias()来提效。 混淆出现时,可以用eval()和xxxInPlace()函数解决。 混淆(别名问题),比如
MatrixXi mat(3,3);
mat << 1, 2, 3, 4, 5, 6, 7, 8, 9;
mat.bottomRightCorner(2,2) = mat.topLeftCorner(2,2);
cout << "After the assignment mat:\n" << mat << endl;
// The eval() solves the aliasing problem
mat.bottomRightCorner(2,2) = mat.topLeftCorner(2,2).eval(); //通过这个可以解决
cout << "After the assignment, mat = \n" << mat << endl;
\\结果
After the assignment, mat =
1 2 3
4 1 2
7 4 1
After the assignment, mat =
1 2 3
4 1 2
7 4 5
- Map类,实现用一片内存生成Matrix, Map mf(pf,rows,columns); pf是一个数组指针float * 定义一个MatrixXf 里面的数字是pf指向的内存里面的数据。类似于opencv 的 Mat 其中用内存指针生成Mat
- 存储是默认列优先存储。
- eigin在编译时会使用表达式变量,比如a = 3b + 4c 会提前给出a(0) = 3b(0) + 4c(0)表达式,计算时直接代入变量计算即可。类似于以前我们用matlab提前把公式用表达式表示。所以不用担心复杂公式的计算效率。
还有一个对齐问题。如果采用c++17 就不会有这个问题。
第二章总结 稠密线性矩阵
Ax = b 第二章就是讲解如何对A分解,求出x。有很多种分解方式,QR, SVD,LU等,不同的分解方式精度和效率不同。 具体参见官网。
- 最小二乘Ax-b可直接使用SVD分解得到
- 就地分解 从3.3开始, 可以直接在矩阵的内存里面对矩阵分解,这对于大型矩阵是非常友好的,可以节约内存
- 矩阵不同的分解的速度 官网提供。(我们还可以利用它提供例子自己针对自己的硬件测试)
第三章总结 稀疏线性矩阵
- SparseMatrix<>模板类是用于表示稀疏矩阵,注意稠密的用的是Matrix<>
SparseMatrix<>提供了高性能和低内存使用率 // 1. Values: 存储非零的系数值。注意,压缩列存储按照一列一列的顺序存储非零元素,同样,压缩行按照一行一行的顺序存储元素; // 2. InnerIndices: 存储非零的行(或列)下标。简单的说,我们可以先按照列或者行的顺序存储values,然后对于values中的每一个元素,确定其所在的行or列的下标; // 3. OuterStarts: 为每列(分别为行)存储前两个数组中第一个非零的索引。注意,这个数组存储的Values和InnerIndices中的位置; // 4. InnerNNZs:存储每列(分别为行)的非零元素个数。 // 注意:术语inner指的是内部向量,该向量是列主矩阵的列,或行主矩阵的行。 // 术语outer是指另一个方向,即行or列;
第四章总结 几何模块(主要是给空间转换使用)
Transform类 基本上我们用到的二维、三维旋转、平移 Eigen 都定义ok了。比如Affine3d Isometry3d 需要使用就查看geometry.
|