1. 第一步初始化imu外参(可以从参数文档中读取,也可以计算出),VINS中处理如下:

# Extrinsic parameter between IMU and Camera.
estimate_extrinsic: # Have an accurate extrinsic parameters. We will trust the following imu^R_cam, imu^T_cam, don't change it.
# Have an initial guess about extrinsic parameters. We will optimize around your initial guess.
# 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 or , you should write down the following matrix.
#Rotation from camera frame to imu frame, imu^R_cam
extrinsicRotation: !!opencv-matrix
rows:
cols:
dt: d
data: [0.0148655429818, -0.999880929698, 0.00414029679422,
0.999557249008, 0.0149672133247, 0.025715529948,
-0.0257744366974, 0.00375618835797, 0.999660727178]
#Translation from camera frame to imu frame, imu^T_cam
extrinsicTranslation: !!opencv-matrix
rows:
cols:
dt: d
data: [-0.0216401454975,-0.064676986768, 0.00981073058949]

2. 在优化中,每来一帧则对外参更新一次

Matrix3d ric[NUM_OF_CAM];
Vector3d tic[NUM_OF_CAM];
//添加参数块
ceres::LocalParameterization *local_parameterization = new PoseLocalParameterization();
problem.AddParameterBlock(para_Ex_Pose[i], SIZE_POSE, local_parameterization);
if (!ESTIMATE_EXTRINSIC)
{
ROS_DEBUG("fix extinsic param");
problem.SetParameterBlockConstant(para_Ex_Pose[i]);
}
else
ROS_DEBUG("estimate extinsic param");
//添加残差块
if (ESTIMATE_TD)
{
ProjectionTdFactor *f_td = new ProjectionTdFactor(pts_i, pts_j, it_per_id.feature_per_frame[].velocity, it_per_frame
it_per_id.feature_per_frame[].cur_td, it_per_frame.cur_td,
it_per_id.feature_per_frame[].uv.y(), it_per_frame.uv.y());
problem.AddResidualBlock(f_td, loss_function, para_Pose[imu_i], para_Pose[imu_j], para_Ex_Pose[], para_Feature[feature_index], para_Td[]); }
else
{
ProjectionFactor *f = new ProjectionFactor(pts_i, pts_j);
problem.AddResidualBlock(f, loss_function, para_Pose[imu_i], para_Pose[imu_j], para_Ex_Pose[], para_Feature[feature_inde
}

该残差块为视觉模型计算重投影误差 Vision Model

空间上的一个3D特征点会被camera多次观测到,jth 图像帧的camera的残差值被定义为,考虑lth 特征点第一次在ith 图像帧中被观察到恢复的深度信息,投影到第j 帧图像帧的重投影误差

3. 相机imu外参的重要性

  • 外参是相机和imu之间的桥梁,后端优化是以imu的坐标系为优化基准,所以在进行重投影误差时需要使用外参将空间点转换到相机坐标系。
  • 初始化的三角化时也会用到外参来求出两个相机之间的旋转平移。
f_manager.triangulate(Ps, &(TIC_TMP[]), &(RIC[]));
Eigen::Vector3d pts_camera_i = pts_i / inv_dep_i;
Eigen::Vector3d pts_imu_i = qic * pts_camera_i + tic;
Eigen::Vector3d pts_w = Qi * pts_imu_i + Pi;
Eigen::Vector3d pts_imu_j = Qj.inverse() * (pts_w - Pj);
Eigen::Vector3d pts_camera_j = qic.inverse() * (pts_imu_j - tic);
Eigen::Map<Eigen::Vector2d> residual(residuals);

qcb(qbjw(qwbi(qbcqcb(qbjw(qwbi(qbcqcb(qbjw(qwbi(qbcqcb(qbjw(qwbi(qbccjlcjl

相机imu外参标定的更多相关文章

  1. VINS(四)初始化与相机IMU外参标定

    和单目纯视觉的初始化只需要获取R,t和feature的深度不同,VIO的初始化话通常需要标定出所有的关键参数,包括速度,重力方向,feature深度,以及相机IMU外参$R_{c}^{b}$和$p_{ ...

  2. 相机-imu外参校准总结

    1. 研究背景及相关工作 1)研究背景 单目视觉惯性slam是一种旨在跟踪移动平台的增量运动并使用来自单个车载摄像头和imu传感器的测量结果同时构建周围环境地图的技术.视觉相机和惯性测量单元(imu) ...

  3. 解放双手——相机与IMU外参的在线标定

    本文作者 沈玥伶,公众号:计算机视觉life,编辑部成员 一.相机与IMU的融合 在SLAM的众多传感器解决方案中,相机与IMU的融合被认为具有很大的潜力实现低成本且高精度的定位与建图.这是因为这两个 ...

  4. 相机IMU融合四部曲(三):MSF详细解读与使用

    相机IMU融合四部曲(三):MSF详细解读与使用 极品巧克力 前言 通过前两篇文章,<D-LG-EKF详细解读>和<误差状态四元数详细解读>,已经把相机和IMU融合的理论全部都 ...

  5. 相机IMU融合四部曲(一):D-LG-EKF详细解读

    相机IMU融合四部曲(一):D-LG-EKF详细解读 极品巧克力 前言 前两篇文章<Google Cardbord的九轴融合算法>,<Madgwick算法详细解读>,讨论的都是 ...

  6. 【项目实战】自备相机+IMU跑通Vins-Mono记录

    前言 初次接触SLAM,公司要求用自己的设备来跑通vinsmono这个程序,虽然已经跑通了别人的数据包,但是真正自己上手来运行这个程序,发现真的是困难重重,特意在此记载下来整个过程,以供大家参考. 我 ...

  7. 相机IMU融合四部曲(二):误差状态四元数详细解读

    相机IMU融合四部曲(二):误差状态四元数详细解读 极品巧克力 前言 上一篇文章,<D-LG-EKF详细解读>中,讲了理论上的SE3上相机和IMU融合的思想.但是,还没有涉及到实际的操作, ...

  8. 机械手相机9点坐标标定-基于C#+EmguCV

    很多初学者,都对标定概念模糊不清,分不清坐标系之间的关系,搞不清相机标定和机械手相机标定有什么关系,想当初自己也是一个人摸索了很久,本文将尽量给大家解释. 我们通常所说的相机标定分为两种,一种是相机参 ...

  9. kalibr论文阅读笔记

    单目相机IMU标定 该论文将相机IMU标定分为两个大方面: 一. 使用基函数来估计时间偏差 二. 相机和IMU的空间位置转换 校准变量:重力.外参旋转和平移.时钟偏移.IMU位姿.加速度计偏置.陀螺仪 ...

随机推荐

  1. linux一切皆文件之文件描述符

    一.知识准备 1.在linux中,一切皆为文件,所有不同种类的类型都被抽象成文件.如:普通文件.目录.字符设备.块设备.套接字等2.当一个文件被进程打开,就会创建一个文件描述符.这时候,文件的路径就成 ...

  2. Yii 集成 PHPExcel读取Excel文件

    PHPexcel官方下载以后,放入Yii的protected\extensions\phpexcel下面 try { spl_autoload_unregister(array('YiiBase', ...

  3. 关于SQL注入中编码问题的疑问

    提到SQL注入的绕过,编码是其中最普通的一种方法,最常用的URL编码.之前一直有个疑问,编码与未编码到底有哪些地方存在区别? 以下是本人自己对URL编码的一些见解,可能有错误的地方欢迎大佬们指正. 什 ...

  4. 理解基本包装类型Number,String,Boolean

    在前面我们知道了引用类型是什么了,也就能理解包装类型了.包装对象其实也是一种引用类型,之所以要单独提出来只不过是因为它们可以把原始类型的值变成(包装成)对象,这样它们也就获得了各自类型相应的特殊行为了 ...

  5. Web打印连续的表格,自动根据行高分页

    拿到这个需求,我已经蛋碎了一地,经过N天的攻克,终于是把它搞定了,只是不知道会不会在某种情况下出现BUG.表示我心虚没有敢做太多的测试.... ---------------------------- ...

  6. WPF引用ActiveX提示没有注册类或不是有效的Win32程序

    VS2017开发WPF时,需要引用UKey组件读取插入的Ukey编号和密钥 该组件在网页端调用时使用ObjectId进行ActiveX注册即可,后来做成WPF客户端进行读取遇到该问题. 解决: 右键项 ...

  7. golang刷Leetcode系列 --- 加1

    加一 给定一个非负整数组成的非空数组,在该数的基础上加一,返回一个新的数组. 最高位数字存放在数组的首位, 数组中每个元素只存储一个数字. 你可以假设除了整数 0 之外,这个整数不会以零开头. 示例 ...

  8. chromium之dynamic_annotations

    看看介绍 // This file defines dynamic annotations for use with dynamic analysis // tool such as valgrind ...

  9. Oracle登录失败:监听程序当前无法识别连接描述符中请求的服务

    Oracle11g下载地址:https://pan.baidu.com/s/1p3RwLUTAl1Ys4yXmXJ3OVQ 安装步骤视频链接:https://pan.baidu.com/s/1c0FC ...

  10. foreach传值