VIO-slam 系统构建

文章目录

  • 目录

    文章目录

    前言

    一、VIO系统数据的获取:图像传感器选型、IMU传感器选型

    二、建立linux系统+ROS环境

    三、如何读取图像数据

    四、如何读取IMU传感器数据

    五、标定图像和IMU数据的外参、相机的内参

    六、移植VINS-MONO或者VINS-FUSION:主要调试获取图像和imu的订阅数据

    七、实践VIO中遇到的问题

    总结


前言

分享一些自己学习+实践 VIO视觉融合惯导的定位算法系统工程化过程

一、VIO系统数据的获取:图像传感器选型、IMU传感器选型

二、建立linux系统+ROS环境

三、如何读取图像数据

四、如何读取IMU传感器数据

五、标定图像和IMU数据的外参、相机的内参

六、移植VINS-MONO或者VINS-FUSION:主要调试获取图像和imu的订阅数据

七、实践VIO中遇到的问题

1、在运行vins-mono中发现,Eigen报错,vins_estimator: /usr/include/eigen3/Eigen/src/Core/DenseStorage.h:109: Eigen::internal::plain_array<T, Size, MatrixOrArrayOptions, 16>::plain_array() [with T = double; int Size = 270; int MatrixOrArrayOptions = 0]: Assertion `(internal::UIntPtr(eigen_unaligned_array_assert_workaround_gcc47(array)) & (15)) == 0 && "this assertion is explained here: " "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" " **** READ THIS WEB PAGE !!! ****"' failed.

解决问题:

1)查阅Eigen官方文档找到问题所在。原因是Eigen库为了使用SSE加速,在内存上分配了128位的指针,涉及字节对齐问题,该问题在编译时不会报错,只在运行时报错。

原因1:类中有Eigen类型的成员变量
class Foo
{
  //...
  Eigen::Vector2d v;
  //...
};
//...
Foo *foo = new Foo;
 在生成定长的Matrix或Vector对象时,需要开辟内存,调用默认构造函数,通常x86下的指针是32位,内存位数没对齐就会导致程序运行出错。而对于动态变量(例如Eigen::VectorXd)会动态分配内存,因此会自动地进行内存对齐。

解决方法:在public下写一个宏EIGEN_MAKE_ALIGNED_OPERATOR_NEW

class Foo
{
  ...
  Eigen::Vector2d v;
  ...
public:
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};
...
Foo *foo = new Foo;
这个宏在new一个对象时会总是返回一个对齐的指针。

如果想要通过模板参数来定义一个定长变量,可以使用宏EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)。若NeedsToAlign是True,则进行对齐运算;若NeedsToAlign为False,则采用默认的对齐方式。

template<int n> class Foo
{
  typedef Eigen::Matrix<float,n,1> Vector;
  enum { NeedsToAlign = (sizeof(Vector)%16)==0 };
  ...
  Vector v;
  ...
public:
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)
};
...
Foo<4> *foo4 = new Foo<4>; // foo4 is guaranteed to be 128bit-aligned
Foo<3> *foo3 = new Foo<3>; // foo3 has only the system default alignment guarantee
如果觉得到处放EIGEN_MAKE_ALIGNED_OPERATOR_NEW太过繁琐,还可以采用以下的两种措施。

1)禁用对齐

class Foo
{
  ...
  Eigen::Matrix<double,2,1,Eigen::DontAlign> v;
  ...
};
这种方法在将变量赋值到一个临时的对齐向量时,仍然有可能重新启用矢量化。

void Foo::bar()
{
  Eigen::Vector2d av(v);
  // use av instead of v
  ...
  // if av changed, then do:
  v = av;
}
2)私有结构体

将定长的对象存储到私有结构体中,在构建主对象时固定分配内存。这里的明显优势是类Foo在对齐问题上保持不变。缺点是无论如何都需要堆分配。

struct Foo_d
{
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
  Vector2d v;
  ...
};
struct Foo {
  Foo() { init_d(); }
  ~Foo() { delete d; }
  void bar()
  {
    // use d->v instead of v
    ...
  }
private:
  void init_d() { d = new Foo_d; }
  Foo_d* d;
};
 原因2:STL容器中的元素是Eigen数据结构
使用Eigen::aligned_allocator告诉容器进行16字节对齐。

std::map<int, Eigen::Vector4f>
将其改成

std::map<int, Eigen::Vector4f, std::less<int>, 
         Eigen::aligned_allocator<std::pair<const int, Eigen::Vector4f> > >
另一种方法,使用宏EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION

#include<Eigen/StdVector>
/* ... */
EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Matrix2d)
std::vector<Eigen::Vector2d>
 原因3:通过值传递定长Eigen对象
void func(Eigen::Vector4d v);
在c++中使用值传递都是一个很糟糕的选项,意味着很多无用拷贝,这儿还会造成程序崩溃。通常采用引用传递:

void my_function(const Eigen::Vector2d& v);
 原因4:编译器对栈对齐做了错误假设(例如Windows上的GCC)
void foo()
{
  Eigen::Quaternionf q;
  //...
}
 GCC中编译器假设堆栈是16字节对齐,但在Windows中堆栈只能保证4字节对齐。当从另一个线程或另一个编译器编译的二进制文件调用函数时,可能会破坏堆栈对齐。

有三种方法可供参考:

1)局部

__attribute__((force_align_arg_pointer)) void foo()
{
  Eigen::Quaternionf q;
  //...
}
2)全局

-mincoming-stack-boundary=2
相当于告诉GCC堆栈需要2*2=4字节对齐

3) 全局

-mstackrealign
相当于向所有函数添加force_align_arg_pointer

如果不想要进行向量化,可以在编译时使用EIGEN_DONT_ALIGN_STATICALLY选项禁用所有16字节静态对齐,但保持16位堆对齐。或者同时使用EIGEN_DONT_VECTORIZE和EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT,这保持了16位的对齐代码,但不支持向量化。
 

2、ubuntu 16.4 的 ros kinetic 依赖的是boost158版本,使用167版本编译程序,就会报 or -rpath-link)
/usr/bin/ld: warning: libboost_thread.


总结

1、基础矩阵、单一性矩阵、本征矩阵为什么能计算出相机的旋转和平移;其原理是什么
2、相机旋转的时候为什么能用IMU进行测量其旋转的角度

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/256750.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL5.7多源复制的实验

MySQL5.7多源复制的实验 node1: 192.168.2.171 master1 node2: 192.168.2.172 slave node3: 192.168.2.170 master2 node2上执行&#xff1a; change master to master_host192.168.2.171, master_userrpl, master_passwordAbcd1234, master_port3306, master_log…

最优化课堂笔记04:非线性规划(考点4-5例题)

目录 4.1 多元函数的泰勒展开 4.2方向导数与梯度 4.2.1方向导数 n元函数在点沿特定方向的方向导数 4.2.2梯度 4.3二次函数及正定矩阵 4.4凸函数与凸规划 4.4.1凸函数 4.4.2凸规划 4.4无约束优化问题的极值条件 4.5约束优化问题的极值条件&#xff08;重点考点&#x…

k近邻算法C++二维情况下的实现

k近邻算法C二维实现 这是一个k近邻算法的二维实现&#xff08;即K2的情况&#xff09;。 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <cmath> u…

java——对象学习笔记

1.面向对象&#xff08;OOP&#xff09;的三大特性 对象的行为&#xff08;behavior&#xff09;&#xff1a;可以对对象施加哪些操作&#xff0c;或者可以对对象施加哪些方法。 对象的状态&#xff08;state&#xff09;&#xff1a;当施加那些方法后&#xff0c;对象如何响应…

C++获取一段算法程序耗时方法

1、添加头文件库#include <chrono> 2、代码编写 std::chrono::steady_clock::time_point t1 std::chrono::steady_clock::now(); std::chrono::steady_clock::time_point t2 std::chrono::steady_clock::now(); std::chrono::duration<double> time_used12 st…

cisco 动态路由协议RIP笔记

动态路由协议RIP router(config)#router rip 启动RIP进程 router(config-router)#network 1.0.0.0 宣告主网络号 router(config-router)#version 2 使用版本v2 router(config-router)#no auto-summary 关闭路由汇总功能 本文转自 meteor_hy 51CTO博客&#xff0c;原文链接&a…

EBS FORM开发问题总结

1&#xff0c;form是基于单表视图建立的&#xff0c;没有写on-insert此类的触发器。在视图上加了个rownum列结果导致form上的列不能更新 据说此种情形下的form会判断视图上的列是否属于基表&#xff0c;不属于的话会导致整个块不能更新。 2&#xff0c;在form界面上显示行号 在…

Django 学习资源

相关的分享&#xff1a; 开发者头条&#xff1a;http://toutiao.io/search?utf8%E2%9C%93&qdjango 极客头条及Django资讯&#xff1a;http://www.csdn.net/tag/django/news 一些优秀的文章&#xff1a; Django 常用测试方法&#xff1a;https://messense.me/django-common…

orb-slam2在PC和ARM上运行

ORBSLAM2的编译与运行 环境&#xff1a;Ubuntu16.04 ORBSLAM2 &#xff08;1&#xff09;安装工具 sudo apt-get install cmake sudo apt-get install git sudo apt-get install gcc g (2) 安装pangolin 安装依赖项&#xff1a; sudo apt-get install libglew-dev sudo ap…

烂泥:智能DNS使用与配置

公司的业务现在已经扩展到海外&#xff0c;对外提供的统一接口都是通过域名来解析的&#xff0c;但是海外用户访问国内接口的话&#xff0c;你懂的&#xff0c;很慢的。为了提高域名解析的速度&#xff0c;打算使用智能DNS功能&#xff0c;来解决海外用户域名解析慢的问题。 PS…

现代制造工程——考试复习01

第一部分 金属切削原理 1.切削过程中工件上的加工表面分类 2.不同工艺的工件和刀具的相对关系 3.不同工艺的主运动和进给运动的方向 4.思考&#xff1a;主运动一般只有一个&#xff0c;但是进给运动一个也可以是多个 5.切削三要素&#xff08;必考&#xff09; 6.思考&#x…

C++,C++编程,Windows编程,MFC

编程  我们日常生活中接触到的电子类产品中的应用都是由编程而来  为什么编程&#xff0c;偷懒  我们通过编程驱使&#xff08;指挥&#xff0c;命令&#xff09;的是电信号  为什么上面说编程是偷懒&#xff0c;电的发现&#xff0c;给人们带来了便利&#xff0c;人们…

orb-slam2 代码逻辑梳理

1、开发大型C系统&#xff0c;可以首先从头文件开始&#xff1b;先把头文件的各种接口定义好&#xff1b;含义定义好&#xff1b;实现的时候只管内部实现就行&#xff0c;不需要管理外部的逻辑交互 2、定义在类中的变量&#xff0c;可以在前面加个小标志&#xff0c;mcamerMati…

eclipse中java项目转换为web项目

123456789101112经常在eclipse中导入web项目时&#xff0c;出现转不了项目类型的问题&#xff0c;导入后就是一个java项目&#xff0c;有过很多次经历&#xff0c;今天也有同事遇到类似问题&#xff0c;就把这个解决方法记下来吧&#xff0c;免得以后再到处去搜索。解决步骤&am…

让执行程序引用特定目录下的Dll

当写一个软件&#xff0c;特别是大型的软件&#xff0c;经常会引用一些第三方的类库&#xff0c;再加上一些自己的项目&#xff0c;如果这些Dll全都放在主目录下的话&#xff0c;会显得比较杂乱。我们希望将项目的类库分类成文件夹存放&#xff0c;这样才显得比较整洁。 解决方…

Angularjs controller之间的通信

刚刚看了网上的一些关于控制器之间的通信&#xff1b;然后结合自己项目做了一些&#xff0c;这里主要做的是二个同级之间的controller通信。 Html&#xff1a; 1 <html>2 <script src"http://apps.bdimg.com/libs/angular.js/1.3.9/angular.min.js"><…

最优化课堂笔记05——一维最优化方法(含重点:黄金分割法)

5-1 一维搜索区间的确定 搜索区间只是适用于单峰区间 、 例子 5.2 黄金分割法&#xff08;重点&#xff09; 上面的a与b都会跟着计算的推进而变化的 例子重点 5.3二次插值法 总结&#xff1a; 5.4 切线法&#xff08;牛顿法&#xff09; 5.5 割线法&#xff08;不需要计算导数&…

C++中静态成员数据初始化问题

C中静态成员数据初始化问题 1、静态成员变量&#xff1a;定义为静态成员意味着它能被所有的实例化对象所共有&#xff0c;其修改值为该类的其它所有实例所见。 下面看一个例子 class people { public:people(int i):id(i){num;} private:static int num;int id; }; num为静…

moss2010 sharepoint 2010配置人员搜索

配置人员搜索 http://technet.microsoft.com/zh-cn/library/ee721049.aspx 相关补丁 http://support.microsoft.com/kb/2276339/zh-cn Search Configuration in SharePoint 2010 http://blog.concurrency.com/sharepoint/search-configuration-in-sharepoint-2010/ SharePoint …