电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
【7天搞定视觉SLAM】番外2——Eigen的使用
分 享
扫描二维码分享
【7天搞定视觉SLAM】番外2——Eigen的使用
slam
hero_chao
关注
发布时间: 2020-04-20
丨
阅读: 582
# Eigen ## 1.介绍 > Eigen目前最新的版本是3.4,除了C++标准库以外,不需要任何其他的依赖包。Eigen使用的CMake建立配置文件和单元测试,并自动安装。如果使用Eigen库,只需包特定模块的的头文件即可。 - 矩阵的定义:Eigen中关于矩阵类的模板函数中,共有六个模板参数,常用的只有前三个。其前三个参数分别表示矩阵元素的类型、行数和列数。 - 矩阵类型:Eigen中的矩阵类型一般都是用类似MatrixXXX来表示,可以根据该名字来判断其数据类型,比如”d”表示double类型,”f”表示float类型,”i”表示整数,”c”表示复数;Matrix2f,表示的是一个2*2维的,其每个元素都是float类型。 - 数据存储:Matrix创建的矩阵默认是按列存储,Eigen在处理按列存储的矩阵时会更加高效。如果想修改可以在创建矩阵的时候加入参数。 - 矩阵和向量的算术运算:在Eigen中算术运算重载了C++的+、-、* 从http://eigen.tuxfamily.org/index.php?title=Main_Page 下载稳定版本,解压缩; ## 2.实践 打开ubuntu系统,打开终端,首先我们新建一个项目 ```cpp sudo gedit useGeometry.cpp ``` 复制如下内容 ```cpp #include <iostream> #include <cmath> using namespace std; #include <eigen core=""> #include <eigen geometry=""> using namespace Eigen; // 本程序演示了 Eigen 几何模块的使用方法 int main(int argc, char **argv) { // Eigen/Geometry 模块提供了各种旋转和平移的表示 // 3D 旋转矩阵直接使用 Matrix3d 或 Matrix3f Matrix3d rotation_matrix = Matrix3d::Identity(); // 旋转向量使用 AngleAxis, 它底层不直接是Matrix,但运算可以当作矩阵(因为重载了运算符) AngleAxisd rotation_vector(M_PI / 4, Vector3d(0, 0, 1)); //沿 Z 轴旋转 45 度 cout.precision(3); cout << "rotation matrix =\n" << rotation_vector.matrix() << endl; //用matrix()转换成矩阵 // 也可以直接赋值 rotation_matrix = rotation_vector.toRotationMatrix(); // 用 AngleAxis 可以进行坐标变换 Vector3d v(1, 0, 0); Vector3d v_rotated = rotation_vector * v; cout << "(1,0,0) after rotation (by angle axis) = " << v_rotated.transpose() << endl; // 或者用旋转矩阵 v_rotated = rotation_matrix * v; cout << "(1,0,0) after rotation (by matrix) = " << v_rotated.transpose() << endl; // 欧拉角: 可以将旋转矩阵直接转换成欧拉角 Vector3d euler_angles = rotation_matrix.eulerAngles(2, 1, 0); // ZYX顺序,即yaw-pitch-roll顺序 cout << "yaw pitch roll = " << euler_angles.transpose() << endl; // 欧氏变换矩阵使用 Eigen::Isometry Isometry3d T = Isometry3d::Identity(); // 虽然称为3d,实质上是4*4的矩阵 T.rotate(rotation_vector); // 按照rotation_vector进行旋转 T.pretranslate(Vector3d(1, 3, 4)); // 把平移向量设成(1,3,4) cout << "Transform matrix = \n" << T.matrix() << endl; // 用变换矩阵进行坐标变换 Vector3d v_transformed = T * v; // 相当于R*v+t cout << "v tranformed = " << v_transformed.transpose() << endl; // 对于仿射和射影变换,使用 Eigen::Affine3d 和 Eigen::Projective3d 即可,略 // 四元数 // 可以直接把AngleAxis赋值给四元数,反之亦然 Quaterniond q = Quaterniond(rotation_vector); cout << "quaternion from rotation vector = " << q.coeffs().transpose() << endl; // 请注意coeffs的顺序是(x,y,z,w),w为实部,前三者为虚部 // 也可以把旋转矩阵赋给它 q = Quaterniond(rotation_matrix); cout << "quaternion from rotation matrix = " << q.coeffs().transpose() << endl; // 使用四元数旋转一个向量,使用重载的乘法即可 v_rotated = q * v; // 注意数学上是qvq^{-1} cout << "(1,0,0) after rotation = " << v_rotated.transpose() << endl; // 用常规向量乘法表示,则应该如下计算 cout << "should be equal to " << (q * Quaterniond(0, 1, 0, 0) * q.inverse()).coeffs().transpose() << endl; return 0; } ``` 大家一定要仔细分析一下。 ```cpp sudo gedit CMakeLists.txt ``` 复制如下 ```cpp cmake_minimum_required( VERSION 2.8 ) project( geometry ) # 添加Eigen头文件 include_directories( "/usr/include/eigen3" ) add_executable(useGeometry useGeometry.cpp) ``` 以下程序也可帮助理解。 ```cpp #include "stdafx.h" #include <iostream> #include <eigen dense=""> template <typename t=""> static void matrix_mul_matrix(T* p1, int iRow1, int iCol1, T* p2, int iRow2, int iCol2, T* p3) { if (iRow1 != iRow2) return; //列优先 //Eigen::Map< Eigen::Matrix<t, eigen::dynamic,="" eigen::dynamic=""> > map1(p1, iRow1, iCol1); //Eigen::Map< Eigen::Matrix<t, eigen::dynamic,="" eigen::dynamic=""> > map2(p2, iRow2, iCol2); //Eigen::Map< Eigen::Matrix<t, eigen::dynamic,="" eigen::dynamic=""> > map3(p3, iCol1, iCol2); //行优先 Eigen::Map< Eigen::Matrix<t, eigen::dynamic,="" eigen::rowmajor=""> > map1(p1, iRow1, iCol1); Eigen::Map< Eigen::Matrix<t, eigen::dynamic,="" eigen::rowmajor=""> > map2(p2, iRow2, iCol2); Eigen::Map< Eigen::Matrix<t, eigen::dynamic,="" eigen::rowmajor=""> > map3(p3, iCol1, iCol2); map3 = map1 * map2; } int main(int argc, char* argv[]) { //1. 矩阵的定义 Eigen::MatrixXd m(2, 2); Eigen::Vector3d vec3d; Eigen::Vector4d vec4d(1.0, 2.0, 3.0, 4.0); //2. 动态矩阵、静态矩阵 Eigen::MatrixXd matrixXd; Eigen::Matrix3d matrix3d; //3. 矩阵元素的访问 m(0, 0) = 1; m(0, 1) = 2; m(1, 0) = m(0, 0) + 3; m(1, 1) = m(0, 0) * m(0, 1); std::cout << m << std::endl << std::endl; //4. 设置矩阵的元素 m << -1.5, 2.4, 6.7, 2.0; std::cout << m << std::endl << std::endl; int row = 4; int col = 5; Eigen::MatrixXf matrixXf(row, col); matrixXf << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20; std::cout << matrixXf << std::endl << std::endl; matrixXf << Eigen::MatrixXf::Identity(row, col); std::cout << matrixXf << std::endl << std::endl; //5. 重置矩阵大小 Eigen::MatrixXd matrixXd1(3, 3); m = matrixXd1; std::cout << m.rows() << " " << m.cols() << std::endl << std::endl; //6. 矩阵运算 m << 1, 2, 7, 3, 4, 8, 5, 6, 9; std::cout << m << std::endl; matrixXd1 = Eigen::Matrix3d::Random(); m += matrixXd1; std::cout << m << std::endl << std::endl; m *= 2; std::cout << m << std::endl << std::endl; std::cout << -m << std::endl << std::endl; std::cout << m << std::endl << std::endl; //7. 求矩阵的转置、共轭矩阵、伴随矩阵 std::cout << m.transpose() << std::endl << std::endl; std::cout << m.conjugate() << std::endl << std::endl; std::cout << m.adjoint() << std::endl << std::endl; std::cout << m << std::endl << std::endl; m.transposeInPlace(); std::cout << m << std::endl << std::endl; //8. 矩阵相乘、矩阵向量相乘 std::cout << m*m << std::endl << std::endl; vec3d = Eigen::Vector3d(1, 2, 3); std::cout << m * vec3d << std::endl << std::endl; std::cout << vec3d.transpose()*m << std::endl << std::endl; //9. 矩阵的块操作 std::cout << m << std::endl << std::endl; std::cout << m.block(1, 1, 2, 2) << std::endl << std::endl; std::cout << m.block<1, 2>(0, 0) << std::endl << std::endl; std::cout << m.col(1) << std::endl << std::endl; std::cout << m.row(0) << std::endl << std::endl; //10. 向量的块操作 Eigen::ArrayXf arrayXf(10); arrayXf << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10; std::cout << vec3d << std::endl << std::endl; std::cout << arrayXf << std::endl << std::endl; std::cout << arrayXf.head(5) << std::endl << std::endl; std::cout << arrayXf.tail(4) * 2 << std::endl << std::endl; //11. 求解矩阵的特征值和特征向量 Eigen::Matrix2f matrix2f; matrix2f << 1, 2, 3, 4; Eigen::SelfAdjointEigenSolver<eigen::matrix2f> eigenSolver(matrix2f); if (eigenSolver.info() == Eigen::Success) { std::cout << eigenSolver.eigenvalues() << std::endl << std::endl; std::cout << eigenSolver.eigenvectors() << std::endl << std::endl; } //12. 类Map及动态矩阵的使用 int array1[4] = { 1, 2, 3, 4 }; int array2[4] = { 5, 6, 7, 8 }; int array3[4] = { 0, 0, 0, 0}; matrix_mul_matrix(array1, 2, 2, array2, 2, 2, array3); for (int i = 0; i < 4; i++) std::cout << array3[i] << std::endl; return 0; } ``` 然后按照cmake编译流程编译即可。 这里就实现了我们的实践实例,希望可以帮助大家理解概念。</eigen::matrix2f></t,></t,></t,></t,></t,></t,></typename></eigen></iostream></eigen></eigen></cmath></iostream>
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
0
)
hero_chao
关注
评论
(0)
登录后可评论,请
登录
或
注册
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交