如何用Realsense D435i运行VINS-Mono等VIO算法 获取IMU同步数据

2023-05-16

前言

Intel Realsense D435i在D435的基础上硬件融合了IMU,然而目前网上关于这款摄像头的资料非常少,本文主要介绍自己拿着d435i历经曲折最后成功运行VINS-Mono的过程。。。


重要

最近官方更新了GitHub上的Realsense ROS Wrapper和librealsense,据反映在d435i的IMU数据获取上存在一些问题,如时间戳混乱、运行VINS的时候没有数据等。这些问题造成的现象包括但不限于:
1、roslaunch VINS后只能看到特征跟踪图像,没有world坐标系,终端也不报任何错误
2、终端一直提示imu message ins disorder!
由于其源码与本博客的差异较大,且在本博客的方法下这些问题并无法解决,我上传了自己当时版本的Realsense ROS Wrapper,供大家参考。(我的librealsense是2.17.1的,可能需要配套使用)
https://download.csdn.net/download/qq_41839222/11122224

如果一直报imu message ins disorder!且roslaunch /camera/imu后并看不出明显的时间戳混乱的,可以把源码上这行注释掉再试试效果~


准备工作

1、Intel Realsense D435i、Ubuntu 16.04
2、已经安装好Realsense驱动,如果没有的话可以参考:https://blog.csdn.net/qq_41839222/article/details/86503113
3、已经安装好VINS-Mono并且在数据集上正常工作
https://github.com/HKUST-Aerial-Robotics/VINS-Mono

一开始很神奇地发现VINS-Mono上居然有realsense的配置文件,以为事情非常简单,但运行以后发现并没有工作(因为不存在imu_topic: "/camera/imu/data_raw"啊)。

存在问题

运行realsense2_camera时,如

roslaunch realsense2_camera rs_camera.launch 

realsense d435i在ROS中发布的IMU数据分成了两个:
“/camera/gyro/sample” 发布角速度
“/camera/accel/sample” 发布线加速度

同时这两个的时间戳也不太一样,在launch文件中的频率也不一样:

  <arg name="gyro_fps"            default="400"/>
  <arg name="accel_fps"           default="250"/>

在这里插入图片描述
但是显然VINS-Mono是需要订阅一个同时具有角速度和线加速度信息的topic。

因此问题变成了如何让realsense2_camera发布这么一个topic。

解决方法:看源码

realsense2_camera\src\base_realsense_node.cpp就是写了如何发布所有topic,代码很长,一开始绕了不少弯路。

其中void BaseRealSenseNode::setupStreams():

if (gyro_profile != _enabled_profiles.end() &&
            accel_profile != _enabled_profiles.end())
        {
            ROS_INFO("starting imu...");
            std::vector<rs2::stream_profile> profiles;
            profiles.insert(profiles.begin(), gyro_profile->second.begin(), gyro_profile->second.end());
            profiles.insert(profiles.begin(), accel_profile->second.begin(), accel_profile->second.end());
            auto& sens = _sensors[GYRO];
            sens.open(profiles);

            auto imu_callback_inner = [this](rs2::frame frame){
                imu_callback(frame);
            };

            auto imu_callback_sync_inner = [this](rs2::frame frame){
                imu_callback_sync(frame, _imu_sync_method);
            };

            if (_imu_sync_method > imu_sync_method::NONE)
            {
                std::string unite_method_str;
                int expected_fps(_fps[GYRO] + _fps[ACCEL]);
                unite_method_str = "COPY";
                if (_imu_sync_method == imu_sync_method::LINEAR_INTERPOLATION)
                {
                    unite_method_str = "LINEAR_INTERPOLATION";
                    expected_fps = 2 * std::min(_fps[GYRO], _fps[ACCEL]);
                }
                ROS_INFO_STREAM("Gyro and accelometer are enabled and combined to IMU message at " 
                                 << expected_fps << " fps by method:" << unite_method_str);
                sens.start(imu_callback_sync_inner);
            }
            else
            {
                sens.start(imu_callback_inner);

                if (_enable[GYRO])
                {
                    ROS_INFO_STREAM(_stream_name[GYRO] << " stream is enabled - " << "fps: " << _fps[GYRO]);
                    auto gyroInfo = getImuInfo(GYRO);
                    _info_publisher[GYRO].publish(gyroInfo);
		    
                }

                if (_enable[ACCEL])
                {
                    ROS_INFO_STREAM(_stream_name[ACCEL] << " stream is enabled - " << "fps: " << _fps[ACCEL]);
                    auto accelInfo = getImuInfo(ACCEL);
                    _info_publisher[ACCEL].publish(accelInfo);
                }
            }
        }

可以看到这里的条件判断:if (_imu_sync_method > imu_sync_method::NONE),最后讲执行回调函数sens.start(imu_callback_sync_inner);不然就执行_info_publisher[GYRO].publish(gyroInfo)和_info_publisher[ACCEL].publish(accelInfo)。

而我们一开始的launch文件就是采用了后面一种,最后直接发布了GYRO和ACCEL。
那么如何让_imu_sync_method不是NONE呢,在文件中搜索_imu_sync_method,直到看到:

std::string unite_imu_method_str("");
_pnh.param("unite_imu_method", unite_imu_method_str, DEFAULT_UNITE_IMU_METHOD);
if (unite_imu_method_str == "linear_interpolation")
	_imu_sync_method = imu_sync_method::LINEAR_INTERPOLATION;
else if (unite_imu_method_str == "copy")
	_imu_sync_method = imu_sync_method::COPY;
else
	_imu_sync_method = imu_sync_method::NONE;

当unite_imu_method_str 是 "copy"或者“linear_interpolation”就行了!
而这又是读取了launch文件中的unite_imu_method,所以在rs_camera.launch中直接修改:

  <arg name="unite_imu_method"      default="copy"/>

重新运行realsense2_camera

roslaunch realsense2_camera rs_camera.launch 

此时可以看到发布的topic变成了"/camera/imu"

rostopic list
rostopic echo /camera/imu

在这里插入图片描述
大功告成!

p.s. 除此以外我还修改了enable_sync参数,是对相机和IMU进行同步的。

  <arg name="enable_sync"           default="true"/>

运行VINS

这里还需要修改一下配置文件:(在realsense_color_config.yaml基础上)
1、订阅的topic

#common parameters
imu_topic: "/camera/imu"
image_topic: "/camera/color/image_raw"

2、相机的内参,通过读取camera_info得到或者自己标定,采用以下命令可以读取厂家的camera_info,但与实际可能存在差距。

rostopic echo /camera/color/camera_info

3、IMU到相机的变换矩阵

# Extrinsic parameter between IMU and Camera.
estimate_extrinsic: 0   # 0  Have an accurate extrinsic parameters. We will trust the following imu^R_cam, imu^T_cam, don't change it.
                        # 1  Have an initial guess about extrinsic parameters. We will optimize around your initial guess.
                        # 2  Don't know anything about extrinsic parameters. You don't need to give R,T. We will try to calibrate it. Do some rotation movement at beginning.                        
#If you choose 0 or 1, you should write down the following matrix.

这里IMU和camera之间的外参矩阵建议使用Kalibr工具进行离线标定,也可以改成1或者2让估计器自己标定和优化。

4、IMU参数,这个需要对IMU的噪声和Bias进行标定,同时重力加速度对结果有影响。

#imu parameters       The more accurate parameters you provide, the better performance
acc_n: 0.2          # accelerometer measurement noise standard deviation. #0.2
gyr_n: 0.05         # gyroscope measurement noise standard deviation.     #0.05
acc_w: 0.02         # accelerometer bias random work noise standard deviation.  #0.02
gyr_w: 4.0e-5       # gyroscope bias random work noise standard deviation.     #4.0e-5
g_norm: 9.81       # gravity magnitude

5、realsense d435i说是已经做好了硬件同步所以不需要在线估计同步时差(但是用kalibr标定出来和在线估计出来都存在大概-0.06的时间差)

#unsynchronization parameters
estimate_td: 0                      # online estimate time offset between camera and imu
td: 0.000                           # initial value of time offset. unit: s. readed image clock + td = real image clock (IMU clock)

6、相机曝光方式应为全局曝光

#rolling shutter parameters
rolling_shutter: 0                      # 0: global shutter camera, 1: rolling shutter camera
rolling_shutter_tr: 0               # unit: s. rolling shutter read out time per frame (from data sheet). 

然后就可以运行了

roslaunch realsense2_camera rs_camera.launch 
roslaunch vins_estimator realsense_color.launch 
roslaunch vins_estimator vins_rviz.launch

实际效果

在这里插入图片描述
在这里插入图片描述
能够正常工作,但是绕房间一圈以后发现离起点有距离,还需要再调试一下!
还有就是如果突然图像跟踪失败并且没有重定位,轨迹会一直往前方走,这是因为只用到IMU数据时,IMU积分得到的位移、速度和角度值一定会发生漂移。对IMU进行参数标定和适当修改重力加速度的值会减少偏移的程度但不能去除。

最后欢迎各位一起交流!


在找到这个解决方法前本人还进行了很多其他尝试,各位也可以作为参考:

1、有人成功地实现了使用RealSense ZR300运行VINS,采用的驱动是eth-asl的maplab_realsense,这个程序还对IMU的陀螺仪、加速度计、图像的时间戳做了对齐处理。
但是我尝试了并没有读取到d435i的设备,应该是是有地方需要修改下。
Ubuntu 16.04 上用RealSense ZR300跑Vins Mono

2、在一开始看源码还没有发现它可以执行imu_callback_sync_inner回调函数的时候,以为就是在imu_callback获取传感器数据并发布的。它这里是不同时读取的,通过stream_index判断读取的内容是GYRO和ACCEL。

于是我用了一个很蠢的办法:可以看到被我注释的地方,我定义了一个静态数组imu_acc,在需要读取ACCEL数据的时候把数据存下来,在读取GYRO的时候取出来。最后的确可以让“/camera/gyro/sample”中具有加速度信息,最后可以运行VINS。

auto stream_index = (stream == GYRO.first)?GYRO:ACCEL;
    if (0 != _info_publisher[stream_index].getNumSubscribers() ||
        0 != _imu_publishers[stream_index].getNumSubscribers())
    {
        double elapsed_camera_ms = (/*ms*/ frame.get_timestamp() - /*ms*/ _camera_time_base) / 1000.0;
        ros::Time t(_ros_time_base.toSec() + elapsed_camera_ms);

        auto imu_msg = sensor_msgs::Imu();
        imu_msg.header.frame_id = _optical_frame_id[stream_index];
        imu_msg.orientation.x = 0.0;
        imu_msg.orientation.y = 0.0;
        imu_msg.orientation.z = 0.0;
        imu_msg.orientation.w = 0.0;
        imu_msg.orientation_covariance = { -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};

        auto crnt_reading = *(reinterpret_cast<const float3*>(frame.get_data()));
        ConvertFromOpticalFrameToFrame(crnt_reading);
	//static float imu_acc[3] = {0,0,0};
        if (GYRO == stream_index)
        {
            imu_msg.angular_velocity.x = crnt_reading.x;
            imu_msg.angular_velocity.y = crnt_reading.y;
            imu_msg.angular_velocity.z = crnt_reading.z;
//imu_msg.linear_acceleration.x = imu_acc[0];
//imu_msg.linear_acceleration.y = imu_acc[1];
//imu_msg.linear_acceleration.z = imu_acc[2];
        }
        else if (ACCEL == stream_index)
        {
            imu_msg.linear_acceleration.x = crnt_reading.x;
            imu_msg.linear_acceleration.y = crnt_reading.y;
            imu_msg.linear_acceleration.z = crnt_reading.z;
//imu_acc[0]=imu_msg.linear_acceleration.x;
//imu_acc[1]=imu_msg.linear_acceleration.y;
//imu_acc[2]=imu_msg.linear_acceleration.z;	
        }

同时修改VINS的yaml文件

#common parameters
imu_topic: "/camera/gyro/sample"
image_topic: "/camera/color/image_raw"

需要注意的是这个方法在运行VINS前还需要有先订阅加速度的topic,比如:

rostopic echo /camera/accel/sample

然后再订阅gyro的topic,或是运行VINS,不然"/camera/gyro/sample"中还是只有角速度信息。

当然因为现在已经找到了imu_callback_sync_inner回调函数可以直接发布IMU所有信息,就不需要这样做了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何用Realsense D435i运行VINS-Mono等VIO算法 获取IMU同步数据 的相关文章

随机推荐

  • ubuntu18.04安装ORB_SLAM3以及遇到的问题

    目录 1 安装c 43 43 11 2 安装Pangolin a xff09 安装依赖 b xff09 编译pangolin 切换到pangolin下载包里面 3 安装opencv 4 eigen3安装 5 boost安装 6 编译ORB
  • 【论文写作】Word中公式快捷输入方式

    环境 Win10 64位 用到软件 Mirsoft Word MathType Mathpix snipping tool Quicker 说明 xff1a 点击链接可以直达官网 一 前言 针对Word中公式输入效率低的问题 xff0c 本
  • 练习7-10 查找指定字符 (15分)

    本题要求编写程序 xff0c 从给定字符串中查找某指定的字符 输入格式 xff1a 输入的第一行是一个待查找的字符 第二行是一个以回车结束的非空字符串 xff08 不超过80个字符 xff09 输出格式 xff1a 如果找到 xff0c 在
  • 用cropper.js裁剪图片并上传到服务器,解析base64转存图片到本地

    今天要写上传图片功能 xff0c 研究了一下cropper 将图片上传服务器并保存到本地 html lt html gt lt head gt lt title gt 基于cropper js的图片裁剪 lt title gt lt met
  • 通讯协议详解

    1 xff0c 概念 网络协议指的是计算机网络中互相通信的对等实体之间交换信息时所必须遵守的规则的集合 网络上的计算机之间是如何交换信息的呢 xff1f 就像我们说话用某种语言一样 xff0c 在网络上的各台计算机之间也有一种语言 xff0
  • 自动识别击打控制系统

    目录 摘 要 关键词 一 系统方案 1 1 系统基本方案 1 2 程序算法的具体流程 二 视觉程序识别框架 2 1多线程 2 2 opencv配置文件 2 3 主函数 三 装甲板识别算法 3 1 装甲板识别 3 2 识别函数介绍 四 目标位
  • 基于stm32风力摆控制系统(电赛获得省一)

    目录 需要源文档及程序进入主页 一 系统方案 完整文档以及代码可主页私 1 1 系统基本方案 1 1 1 控制方案设计 1 1 2 机械结构方案设计
  • 基于stm32的所有嵌入式项目代码

    nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp 本人本科和硕士阶段的专业都是嵌入式方向 做了许许多多的项目 包括51 stm32 freeRTOS linux操作系统 多进程线程实现功能 包括裸机开发 驱动开
  • 基于图像处理的水果自助售卖系统(自助水果售卖机)

    目录 第一章 nbsp 概述 1 1 发展概要 1 2 国内外研究现状 1 3 研究目的和意义 1 4 方案介绍
  • 基于stm32的无人机控制系统设计

    基于stm32的无人机控制系统设计 整篇文章有两万字左右 字数太多了 实在是懒得全部放在这上面来 太废时间了 需要完整论文可主页联系 第一章 前言 1 1项目背景和意义 1 2国内外发展现状 1 3本文研究的主要内容 第二章 设计方案论证与
  • 基于Robot Studio的工业机器人汽车喷涂仿真设计

    基于Robot Studio的工业机器人汽车喷涂仿真设计 整篇文章字数有一万四左右 图片太多了 实在是懒得全部放在这上面来 太废时间了 获得完整论文关注可查看主页私信我 摘要 关键词 1 绪论 1 1研究背景与意义 1 2国内外研究现状 2
  • 基于单片机的压力流量报警器(附代码+仿真+论文)

    基于单片机的压力流量报警器 附代码 仿真 论文 完整论文 代码 仿真可关注我在主页私我 摘要 关键字 第一章绪论 1 1课题背景及其意义 1 2 国内外的研究状况 1 3本文的主要研究内容及论文结构安排 第二章 方案的设计与论证 2 1控制
  • 基于STM32的微型电子琴设计

    基于STM32的微型电子琴设计 第一章 总体设计 1 1 系统功能 1 2 主要技术性能指标 第二章硬件设计 2 1 整体硬件图 2 2 按键模块 2 3 扬声器模块 2 4 显示模块 2 5 主控模块 第三章 软件设计 3 1 主要工作原
  • 百度2015校园招聘软件开发笔试题及答案

    简单题 xff08 本题共30分 xff09 请简述Tcp ip的3次握手以及4次挥手过程 xff1f 并解释为何关闭连接需要4次挥手 10分 详细答案参见TCP IP协议三次握手与四次握手流程解析 TCP三次握手 四次挥手过程如下 通常情
  • 智能算法实现PID智能车控制系统

    智能算法实现PID智能车控制系统 TOC 智能算法实现PID智能车控制系统 摘要 关键词 第一章绪论 1 1智能车概述 1 2智能PID研究现状 1 3本文工作 第二章 PID控制简介 第三章 内模PID简介 3 1 内模PID控制 第四章
  • esp8266WiFi模块通过MQTT连接华为云

    esp8266WiFi模块通过MQTT连接华为云 总结 xff1a 一 MQTT透传AT固件烧录二 串口调试2 1 设置模块为STA模式2 2 连接WiFi2 3 设置MQTT的登陆用户名与密码2 4 设置MQTT的ClientID2 5
  • tx2性能不够怎么办

    关闭pycharm xff0c 使用终端直接Python3 5 加路径脚本名运行
  • 瑞泰烧录捞取

    关于将pc主机上的镜像文件拷贝到tx2上的方法 一 给Linux主机搭建环境 2 2 解压 Linux Driver Package tar vxjf Tegra lt t arch ver gt Linux R aarch64 tbz2
  • Realsense D435i 在ubuntu上安装SDK与ROS Wrapper 运行ORB-SLAM2、RTAB和VINS-Mono

    前言 等了一个月的realsense d435i终于发货了 xff01 这款D435i xff08 见下图 xff09 在D435的基础上 xff0c 另外搭载了博世的惯性测量单元 xff08 IMU xff09 xff0c 可以作为研究V
  • 如何用Realsense D435i运行VINS-Mono等VIO算法 获取IMU同步数据

    前言 Intel Realsense D435i在D435的基础上硬件融合了IMU xff0c 然而目前网上关于这款摄像头的资料非常少 xff0c 本文主要介绍自己拿着d435i历经曲折最后成功运行VINS Mono的过程 重要 最近官方更