Eigen常用操作
Eigen3安装: ubuntu如何安装Eigen
include_directories (/usr/include/Eigen/)
这篇博客主要内容有:
- Eigen常用头文件
- Eigen矩阵和向量的基本定义与初始化
- 高级初始化
- 行向量RowVectorXd
- 块赋值 - 基本运算函数
- 常用块操作
- 计算特征值和特征向量
- Array类, ArrayXf , ArrayXXf
- 解线性最小二乘
- 齐次 min||Mx||,分不带约束和带约束条件
- 非齐次 min||Mx + b||,分不带约束和带约束添加
1. 常用头文件
#include <Eigen/Dense>
#include <Eigen/Core>
#include <Eigen/LU>
#include <Eigen/Geometry>
#include <Eigen/Cholesky>
#include <Eigen/SVD>
#include <Eigen/QR>
#include <Eigen/Eigenvalues>
#include <Eigen/Sparse>
#include <Eigen/Eigen>
2. 基本定义及初始化
Eigen::Matrix<double,2,2> m;
m << 1,2,3,4;
Eigen::MatrixXf m1(2,3);
m1 << 1,2,3,
4,5,6;
Eigen::Matrix3d m2 = Eigen::Matrix3d::Identity();
Eigen::Matrix3d m3 = Eigen::Matrix3d::Random();
Eigen::Vector3f v1 = Eigen::Vector3f::Zero();
Eigen::Vector3d v2(1.0, 2.0, 3.0);
Eigen::VectorXf v3(20);
v3 << 1.0 , 2.0 , 3.0;
cout << m1(1,1) << endl;
cout << v1(1) << endl;
3. 高级初始化
using namespace Eigen;
RowVectorXd rv1(1,2,3);
RowVectorXd rv2(4);
rv2 << 1,2,3,4;
RowVectorXd joined_rv12(7);
joined_rv12 << rv1 , rv2;
1 2 3 1 2 3 4;
MatrixXf m4(2,2);
m4 << 1,2,3,4;
MatrixXf m5(4,4);
m5 << m4, m4 / 10, m4 * 10, m4;
1 2 0.1 0.2
3 4 0.3 0.4
10 20 1 2
30 40 3 4
Matrix3f m6;
m6.row(0) << 1,2,3;
m6.block(1,0,2,2) << 4,5,6,7;
m6.col(2).tail(2) << 6,9;
1 2 3
4 5 6
6 7 9
3. 基本运算函数
MatrixXf m7 = MatrixXf::Random(3,3);
m7.row(i);
m7.col(j);
m7.transpose();
m7.conjugate();
m7.adjoint();
m7.minCoeff();
m7.maxCoeff();
m7.trace();
m7.sum();
m7.prod();
m7.mean();
Vector3f v4(4,5,6);
Vector3f v5(7,8,9);
v4.dot(v5);
v4.cross(v5);
Vector3f v6 = m7 * v5;
Matrix3f m_sum = m6 + m7;
Matrix3f m_dec = m6 - m7;
Matrix3f m_prod = 2.5 * m7;
Matrix3f m_prod2 = m6 * m7;
Matrix3d m_dev = m7 / 2.0;
4. 常用块操作
MatrixXd m8 = MatrixXd::Random(3,3);
m8.row(i);
m8.col(j);
Matrix<double,p,q> m9 = m8.block(i,j,p,q);
m8.block<p,q>(i,j);
③ Matrix其他块操作
④ Vector块操作
注: ③ ④中的图,引用了大佬的博客:Eigen库使用指南
5.计算特征值和特征向量
Eigen::MatrixXd m9 = Eigen::MatrixXd::Random(3,3);
Eigen::MatrixXd mTm = m9.transpose() * m9;
Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> eigen_solver(mTm);
Eigen::VectorXd eigenvalues = eigen_solver.eigenvalues();
Eigen::MatrixXd eigenvectors = eigen_solver.eigenvectors();
Eigen::VectorXd v0 = eigenvectors.col(0);
6. Array类
Eigen中的Array类,定义了许多Matrix和Vector类没有的运算,比如矩阵和标量的加减运算,Array和Matrix之间也容易相互转换.
6.1 Array的初始化和访问
typedef Array<float ,Dynamic,1> ArrayXf;
typedef Array<float,3,1> Array3f;
typedef Array<double,Dynamic ,Dynamic > ArrayXXd;
typedef Array<double ,3,3 > Array33d;
Eigen::Array33f a1 = Eigen::Array33f::Zero();
Eigen::ArrayXf a2 = Eigen::ArrayXf::Zero(3);
Eigen::ArrayXXf a3 = Eigen::ArrayXXf::Zero(3,4);
Eigen::Array33f a3 = Eigen::ArrayXXf::Zero();
Eigen::ArrayXXf a4(2,2);
a4 << 1,2,3,4;
cout << a4(0,0) << endl;
6.2 Array高级初始化
ArrayXXf a5(10, 4);
a5.col(0) = ArrayXf::LinSpaced(10, 0, 90);
a5.col(1) = M_PI / 180 * a5.col(0);
a5.col(2) = a5.col(1).sin();
a5.col(3) = a5.col(1).cos();
std::cout << " Degrees Radians Sine Cosine\n";
std::cout << a5 << std::endl;
输出为:
//output
Degrees Radians Sine Cosine
0 0 0 1
10 0.174533 0.173648 0.984808
20 0.349066 0.34202 0.939693
30 0.523599 0.5 0.866025
40 0.698132 0.642788 0.766044
50 0.872665 0.766044 0.642788
60 1.0472 0.866025 0.5
70 1.22173 0.939693 0.34202
80 1.39626 0.984808 0.173648
90 1.5708 1 -4.37114e-08
参考博客地址: eigen中高级初始化
7. 解线性最小二乘方程
7.1 齐次线性最小二乘 min||Mx||,M是4 * 4矩阵
(1) 无约束条件:
m
i
n
∣
∣
M
x
∣
∣
min||Mx||
min∣∣Mx∣∣
- 理论上:取MTM的最小特征值对应的特征向量作为x的解;
- 工程上:对M做svd分解,
M
=
U
Σ
V
T
M = U{\Sigma}V^T
M=UΣVT,取最小奇异值对应的V的列向量作为x的解(实际上,奇异值一般按由大到小排列,V的最后一列就是解),证明:证明AX=0的最小二乘解是ATA最小特征值对应的特征向量
- 求解方法有两种:特征向量分解 和 svd分解
- 注意,对于MX = 0的问题,做分解的时候,一般会变成
M
T
M
X
=
0
M^TMX = 0
MTMX=0.
- 注意,要先判别矩阵的病态性,如果条件数太大,表示病态严重,则结果精度很低
Eigen::JacobiSVD<Eigen::MatrixXd> svd(MTM);
double cond = svd.singularValues()(0) / svd.singularValues()(svd.singularValues().size() - 1);
if (cond > max_cond_number)
{
std::cout << colouredString("Matrix A is almost singular.", RED, BOLD) << std::endl;
return 0;
}
Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> eigen_solver(MTM);
Eigen::VectorXd eigenvalues = eigen_solver.eigenvalues();
Eigen::MatrixXd eigenvectors = eigen_solver.eigenvectors();
Eigen::VectorXd X = eigenvectors.col(0);
Eigen::JacobiSVD<Eigen::MatrixXd> svd(MTM, Eigen::ComputeFullU |Eigen::ComputeFullV);
Eigen::Vector3d X = svd.matrixV().block<4,1>(0,3);
(2) 带约束条件:
m
i
n
∣
∣
M
X
∣
∣
,
X
[
0
]
∗
X
[
3
]
=
X
[
1
]
∗
X
[
2
]
,
∣
∣
X
∣
∣
=
1
min||MX|| , X[0]*X[3] = X[1]*X[2], ||X|| = 1
min∣∣MX∣∣,X[0]∗X[3]=X[1]∗X[2],∣∣X∣∣=1;
- 有n约束,就取最小的n个列向量,乘以n个系数,然后用n个约束去求解n个系数,就是方程的最小二乘解.
X
=
a
∗
V
1
+
b
∗
V
2
X = a*V_1 + b*V_2
X=a∗V1+b∗V2
Eigen::JacobiSVD<Eigen::MatrixXd> svd(MTM, Eigen::ComputeFullU |Eigen::ComputeFullV);
Eigen::Vector3d V1 = svd.matrixV().block<4,1>(0,3);
Eigen::Vector3d V2 = svd.matrixV().block<4,1>(0,2);
7.2 非齐次线性最小二乘 min||Mx - b||
(1) 不带约束条件
- 采用奇异值分解;
- 注意,要先判别矩阵的病态性,如果条件数太大,表示病态严重,则结果精度很低
Eigen::JacobiSVD<Eigen::MatrixXd> svd(M);
double cond = svd.singularValues()(0) / svd.singularValues()(svd.singularValues().size() - 1);
if (cond > max_cond_number)
{
std::cout << colouredString("Matrix A is almost singular.", RED, BOLD) << std::endl;
return 0;
}
Eigen::VectorXd X = Eigen::Vector2d::Zero();
X = M.colPivHouseholderQr().solve(b);
- 除了colPivHouseholderQr()分解,还有:
(2) 带约束条件
- 拉格朗日数乘法,请参考论文中的部分求解:Simultaneous Calibration of Odometry and Parameters for Mobile Robots
- 采用非线性优化的方法(需要较好的初始值,需要合理的权重)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)