VINS 外参在线标定

2023-05-16

在VINS中相机的外参 R i c R_{ic} Ric是可以在线动态标定的,实现函数为:

/**
 * @brief 外参在线标定
 * 
 * @param corres 两帧图像之间的共视特征点
 * @param delta_q_imu 两帧图像之间的IMU预积分量
 * @param calib_ric_result 标定结果存放
 * @return true 
 * @return false 
 */
bool InitialEXRotation::CalibrationExRotation(vector<pair<Vector3d, Vector3d>> corres, Quaterniond delta_q_imu, Matrix3d &calib_ric_result)

基本原理

R c b R b k b k + 1 R c b T = R c k c k + 1 ⇒ R c b R b k b k + 1 = R c k c k + 1 R c b ⇒ q c b ⊗ q b k b k + 1 = q c k c k + 1 ⊗ q c b ⇒ [ q b k b k + 1 ] R q c b = [ q c k c k + 1 ] L q c b ⇒ { [ q c k c k + 1 ] L − [ q b k b k + 1 ] R } q c b = 0 \begin{aligned} &R_{c b} R_{b_{k} b_{k+1}} R_{c b}^{T}=R_{c_{k} c_{k+1}} \\ &\Rightarrow R_{c b} R_{b_{k} b_{k+1}}=R_{c_{k} c_{k+1}} R_{c b} \\ &\Rightarrow q_{c b} \otimes q_{b_{k} b_{k+1}}=q_{c_{k} c_{k+1}} \otimes q_{c b} \\ &\Rightarrow\left[q_{b_{k} b_{k+1}}\right]_{R} q_{c b}=\left[q_{c_{k} c_{k+1}}\right]_{L} q_{c b} \\ &\Rightarrow\left\{\left[q_{c_{k} c_{k+1}}\right]_{L}-\left[q_{b_{k} b_{k+1}}\right]_{R}\right\} q_{c b}=0 \end{aligned} RcbRbkbk+1RcbT=Rckck+1RcbRbkbk+1=Rckck+1Rcbqcbqbkbk+1=qckck+1qcb[qbkbk+1]Rqcb=[qckck+1]Lqcb{[qckck+1]L[qbkbk+1]R}qcb=0

其中涉及到四元数的左乘和右乘矩阵:
q = [ x y z w ] T = [ q v q w ] , [ q ] L = q w I + [ [ q v ] × q v − q v T 0 ] , [ q ] R = q w I + [ − [ q v ] × q v − q v T 0 ] q=[x y z w]^{T}=\left[\begin{array}{c} q_{v} \\ q_{w} \end{array}\right], \quad[q]_{L}=q_{w} I+\left[\begin{array}{cc} {\left[q_{v}\right]_{\times}} & q_{v} \\ -q_{v}^{T} & 0 \end{array}\right], \quad[q]_{R}=q_{w} I+\left[\begin{array}{cc} -\left[q_{v}\right]_{\times} & q_{v} \\ -q_{v}^{T} & 0 \end{array}\right] q=[xyzw]T=[qvqw],[q]L=qwI+[[qv]×qvTqv0],[q]R=qwI+[[qv]×qvTqv0]

当有多对这样的组合后就可以构建超定方程即公式
A = { [ q c k c k + 1 1 ] L − [ q b k b k + 1 1 ] R [ q c k c k + 1 2 ] L − [ q b k b k + 1 2 ] R ⋯ [ q c k c k + 1 n ] L − [ q b k b k + 1 n ] R } , A ⋅ q c b = 0 A=\left\{\begin{array}{c} {\left[q_{c_{k} c_{k+1}}^{1}\right]_{L}-\left[q_{b_{k} b_{k+1}}^{1}\right]_{R}} \\ {\left[q_{c_{k} c_{k+1}}^{2}\right]_{L}-\left[q_{b_{k} b_{k+1}}^{2}\right]_{R}} \\ \cdots \\ {\left[q_{c_{k} c_{k+1}}^{n}\right]_{L}-\left[q_{b_{k} b_{k+1}}^{n}\right]_{R}} \end{array}\right\}, \quad A \cdot q_{c b}=0 A=[qckck+11]L[qbkbk+11]R[qckck+12]L[qbkbk+12]R[qckck+1n]L[qbkbk+1n]R,Aqcb=0

通过SVD分解就可以得到 q c b q_{cb} qcb,然后再取逆即可得到外参 q b c = i n v ( q c b ) q_{b c}=i n v\left(q_{c b}\right) qbc=inv(qcb)

代码实现

bool InitialEXRotation::CalibrationExRotation(vector<pair<Vector3d, Vector3d>> corres, Quaterniond delta_q_imu, Matrix3d &calib_ric_result)
{
    this->frame_count++; // 记录进入该函数的次数,用于定义A矩阵的规模的

    Rc.push_back(solveRelativeR(corres));// 求取帧间变换阵R,(第k+1帧变换到第k帧的)R_c(k+1)^ck

    Rimu.push_back(delta_q_imu.toRotationMatrix()); // 两帧之间的陀螺仪预积分值中的旋转变化量 R

    Rc_g.push_back(ric.inverse() * delta_q_imu * ric);  // 图像k帧到k+1帧的旋转

    Eigen::MatrixXd A(frame_count * 4, 4);
    A.setZero();
    int sum_ok = 0;
    for (int i = 1; i <= frame_count; i++)
    {
        Quaterniond r1(Rc[i]);
        Quaterniond r2(Rc_g[i]);
        // 两个线性变换转过的角度
        double angular_distance = 180 / M_PI * r1.angularDistance(r2);
        //ROS_DEBUG("%d %f", i, angular_distance);
        // 加权的方式控制误匹配的点
        double huber = angular_distance > 5.0 ? 5.0 / angular_distance : 1.0;
        ++sum_ok;
        Matrix4d L, R;

        // 构建四元数左乘矩阵
        double w = Quaterniond(Rc[i]).w();
        Vector3d q = Quaterniond(Rc[i]).vec();
        L.block<3, 3>(0, 0) = w * Matrix3d::Identity() + Utility::skewSymmetric(q);
        L.block<3, 1>(0, 3) = q;
        L.block<1, 3>(3, 0) = -q.transpose();
        L(3, 3) = w;

        // 构建四元数右乘矩阵
        Quaterniond R_ij(Rimu[i]);
        w = R_ij.w();
        q = R_ij.vec();
        R.block<3, 3>(0, 0) = w * Matrix3d::Identity() - Utility::skewSymmetric(q);
        R.block<3, 1>(0, 3) = q;
        R.block<1, 3>(3, 0) = -q.transpose();
        R(3, 3) = w;

        // 超定方程系数矩阵
        A.block<4, 4>((i - 1) * 4, 0) = huber * (L - R);
    }
	// SVD分解求解超定方程
    JacobiSVD<MatrixXd> svd(A, ComputeFullU | ComputeFullV);
    Matrix<double, 4, 1> x = svd.matrixV().col(3);
    Quaterniond estimated_R(x);
    // 这里得到的是R_ci,取逆可得 R_ic
    ric = estimated_R.toRotationMatrix().inverse();
    Vector3d ric_cov;
    ric_cov = svd.singularValues().tail<3>();

    // 用0.25来限定倒数第二小的奇异值,如果全部奇异值都非常小接近0,则说明相机没有进行充分的旋转,无法进行初始化
    // 至少会迭代windowSize次
    if (frame_count >= windowSize && ric_cov(1) > 0.25)
    {
        calib_ric_result = ric;
        return true;
    }
    else
        return false;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

VINS 外参在线标定 的相关文章

  • Qt实现线程安全的单例模式

    实现方式 1 实现单例 把类的构造函数 拷贝构造函数 赋值操作符定义为private的 xff1b 把获取单例的接口和唯一的实例指针定义为static的 xff0c 不需要实例化 xff0c 直接通过类名即可访问 2 支持多线程 采用双重校
  • 文本文件和二进制文件的差异和区别

    广义上的二进制文件包括文本文件 xff0c 这里讨论的是狭义上的二进制文件与文本文件的比较 xff1a 能存储的数据类型不同 文本文件只能存储char型字符变量 二进制文件可以存储char int short long float 各种变量
  • Qt实现记录日志文件log

    概述 Qt有两种实现记录日志的方式 xff0c 第一种是安装自定义的Qt消息处理程序 xff0c 自动输出程序产生的调试消息 警告 关键和致命错误消息的函数 xff1b 第二种是自定义一个类 xff0c 可以在程序指定位置打印输出指定的内容
  • Qt在linux环境下调用动态库,pro工程文件加载库和QLibrary加载库两种方式

    QT调用动态库 xff0c 在编译时和运行时的方式不同 xff0c 编译时可在pro文件加载或使用QLibrary类加载 xff1b 运行时依赖环境变量 xff0c windows下直接把动态库拷贝到可执行文件目录即可 xff0c linu
  • linux下QT发布程序双击打不开解决方法

    现象 Qt开发的程序 xff0c 使用 终端可以打开 xff0c 双击却打不开 阶段一 右键可执行程序 xff0c 选择属性 xff0c 可执行程序类型如果是 application x sharedlib xff0c 在QT的pro文件添
  • Qt发起http请求,get和post方式,并接收响应数据

    目录 Qt发起http请求get xff0c 异步接收Qt发起http请求post xff0c 异步接收Qt发起http请求get和post xff0c 收发同步http下载网络图片 Qt发起http请求get xff0c 异步接收 get
  • QT实现浏览器访问网页,使用QWebEngineView

    支持访问网页 xff0c 前进 后退 刷新 xff0c 点击超链接自动跳转 xff0c 获取网页鼠标事件 xff0c 重新编译QWebEngineView库后还可以支持播放mp4等视频 xff1b Qt在debug模式运行有时访问网页很卡
  • Qt程序打包成安装包exe

    本章介绍把Qt开发的程序打包成安装包的方法 xff0c 程序打包成install exe xff0c 可双击安装 xff0c 有默认安装路径 xff0c 也可以选择安装目录 xff0c 自动生成桌面快捷方式和开始菜单选项 xff0c 可以在
  • C/C++socket网络编程

    目录 tcp和udp通信流程图socket函数bind函数listen函数accept函数connect函数recv recvfrom read函数send write sendto sendmsg函数close shutdown函数hto
  • OSPF路由协议解释

    目录 OSPF路由协议OSPF数据包类型OSPF邻区状态OSPF的邻接关系建立过程 路由名词解释OSPF开源项目 OSPF路由协议 OSPF简介 1 xff08 Open Shortest Path First xff09 xff0c 开放
  • redis服务搭建,C++实现redis客户端,redis远程可视化工具

    目录 redis简介redis服务搭建redis常用命令C 43 43 实现redis客户端redis远程可视化工具 Another Redis DeskTop Manager redis简介 官方网址 xff1a https redis
  • Dijkstra算法图解,C++实现Dijkstra算法

    目录 Dijkstra算法简介数据结构抽象初始化开始计算第一轮计算第二轮计算第三轮计算第四轮计算算法总结 C 43 43 实现Dijkstra算法 Dijkstra算法简介 Dijkstra算法计算是从一个顶点到其余各顶点的最短路径算法 x
  • python实现ID3决策树分类算法

    所有的分类与回归算法中心思想大致是一样的 xff0c 那就是根据现有带标签的数据集训练一个分类器模型 xff0c 然后对待未知的样本 xff0c 根据训练好的分类模型来判定它属于哪个类 分类与回归的区别在我看来就是标签连续与否的区别 xff
  • Multiclass SVM(多类别SVM分类)关于其 loss function 的求导

    这两天学习cs231n的课程 xff0c 顺便做一做该课程配套的作业 在assignment1中有遇到用multiclass SVM来对cifar10进行分类的问题 其中 xff0c 为了进行训练 xff0c 需要计算loss 和相关梯度
  • 解决Ubuntu14.04 下不显示wifi的情况

    本人电脑安装完Ubuntu14 04后 xff0c 发现只能连接有线网 xff0c 而在右上角的网络下拉菜单中找不到wifi 网上的大多数教程大概为以下两类 xff1a 一类是 sudo apt get update sudo apt ge
  • Ubuntu系统下连接SJTU的校园wifi

    本人目前系统是Ubuntu 16 04 xff0c 但是14 04下按照这个方法也能成功连接上 xff08 亲测有效 xff09 如下方法应该能解决linux系统无法连接SJTU校园网的问题 首先 xff0c 点击连接SJTU wifi x
  • VS 代码对齐、折叠以及其他常用快捷键整理

    VS 代码对齐 折叠以及其他常用快捷键整理 Ctrl 43 M 43 O 折叠所有方法 Ctrl 43 M 43 M 折叠或者展开当前方法 Ctrl 43 M 43 L 展开所有方法 Ctrl 43 K xff0c Ctrl 43 D 61
  • Postman使用详解

    一 Postman背景介绍 用户在开发或者调试网络程序或者是网页B S模式的程序的时候是需要一些方法来跟踪网页请求的 xff0c 用户可以使用一些网络的监视工具比如著名的Firebug等网页调试工具 今天给大家介绍的这款网页调试工具不仅可以
  • 玩转51单片机 (一):Keil4中多文件项目中全局变量、头文件和源文件

    首先 xff0c 工程文件夹下有src inc 和 project三个文件夹 xff0c 分别存放源文件 头文件和工程文件 然后 xff0c 将所有源文件 头文件都添加到项目里面 xff0c 并将头文件目录添加到魔术棒下C51选项 的 In
  • Vins-Fusion工控机运行Debug

    一 问题记录 在自己的笔记本上运行Vins Fusion效果OK xff0c 但在工控机上运行出现静止状态轨迹飘飞 xff0c 笔记本上和工控机上都是ubantu 18 04系统 xff0c 摄像头硬件均为ZED2i xff0c 配置文件相

随机推荐

  • xavier安装torch-gpu

    1 查看xavier安装的jetpack版本 xff1a sudo apt show nvidia jetpack 一般情况下都是462的 2 查看cuda版本 xff1a cat usr local cuda version txt 3
  • 保存图像(cv::imwrite)

    保存图像文件道指定目录路径 只有8位 xff0c 16位的PNG xff0c JPG xff0c Tiffy文件格式而且时单通道或者三通道的BGR的图像才通过这种方式保存 保存PNG格式的时候可以保存透明通道的图片 可以指定压缩参数 inc
  • 解决 ssh: Could not resolve hostname \342\200\223t: Name or service not known

    问题 xff1a 在配置github时输入以下内容时报错 xff1a ssh T git 64 github span class token punctuation span com 方法 xff1a 将上述内容换为以下内容 ssh sp
  • python实现随机森林

    定义 xff1a 随机森林指的是利用多棵决策树对样本进行训练并预测的一种分类器 可回归可分类 所以随机森林是基于多颗决策树的一种集成学习算法 xff0c 常见的决策树算法主要有以下几种 xff1a 1 ID3 xff1a 使用信息增益g D
  • 从Github上下载文件的方法汇总

    前言 对于程序猿来说 xff0c Github简直就是个宝藏 xff0c 里面有世界各地大神的代码 xff0c 可以放心安全高效的食用 xff0c 本文整理了Github文件的一些下载方法 xff0c 仅供参考 1 通过git命令行 特点
  • fatal error: Python.h: No such file or directory #include “Python.h“

    在TX2上安装h5py时 xff0c pypi org没有对应的轮子 xff0c 需要自己用源码安装 xff0c 源码中涉及到C语言 xff0c 所以需要编译 xff0c 然而在编译的过程中报错 fatal error span class
  • 基于Python的ZED2教程 0.ZED2介绍

    本文主要介绍了ZED2的基本简介和硬件配置 基本简介 ZED2双目深度传感立体相机是位于美国旧金山Stereo labs公司制作的一款产品 xff0c 其与Kinect相机等流行的深度图像原理不同 xff0c 该深度相机的深度计算是通过双目
  • 基于Python的ZED2教程 1.打开ZED2

    本教程简单的对ZED相机进行了配置和打开 xff0c 然后打印出ZED 相机的串口号 xff0c 接着关闭相机 准备工作 由于ZED SDK在GPU上运算 xff0c 因此需要先在 nvidia com下载最新版的Cuda 然后 xff0c
  • 2.Open3D教程——文件读取和保存

    文件读取和保存 本教程演示了Open3D如何读写基本数据结构 1 点云 下面的代码读取和写入点云 span class token keyword print span span class token punctuation span s
  • 7.Open3D教程——表面重建

    在许多情况下 xff0c 我们希望生成密集的三维几何体 xff0c 即三角形网格 然而 xff0c 从多视点立体方法 xff0c 或深度传感器 xff0c 我们只能获得一个非结构化的点云 为了从非结构化输入中得到三角形网格 xff0c 我们
  • PASCAL VOC数据集

    一 简介 PASCAL pattern analysis statistical modelling and computational learning VOC visual object classes 该挑战赛的竞赛项目主要包括 图像
  • ubuntu python 通过奥比中光摄像头获取深度图片和彩色图片

    1 依赖 安装Openni Openni下载Openni添加至环境 xff08 要通过全局变量找到Openni头文件和库 xff09 安装primesense和openni pip install primesense pip instal
  • ROS tf使用报错:ImportError: dynamic module does not define module export function (PyInit__tf2)

    1 报错内容 Traceback span class token punctuation span most recent call last span class token punctuation span File span cla
  • ubuntu cuda cudnn tensorRT的卸载和安装

    1 安装显卡驱动 显卡安装教程 查看N卡驱动支持的最高cuda版本 nvidia smi 2 卸载 span class token function sudo span span class token function apt get
  • 初识VSCode

    Visual Studio Code xff08 以下简称vscode xff09 是一个轻量且强大的代码编辑器 xff0c 跨平台支持Windows xff0c Mac OS X和Linux 内置JavaScript TypeScript
  • Modbus通信及数据存储读取

    1 存储区代号 代码号功能1区输入线圈0区输出线圈3区输入寄存器4区输出寄存器 2 功能码 代码功能0x01读取输出线圈0x02读取输入线圈0x03读取输出寄存器0x04读取输入寄存器0x05写入单个线圈0x06写入单个寄存器0x0F写入多
  • 着色器语言 GLSL (opengl-shader-language)入门大全

    GLSL 中文手册 基本类型 类型说明void空类型 即不返回任何值bool布尔类型 true falseint带符号的整数 signed integerfloat带符号的浮点数 floating scalarvec2 vec3 vec4n
  • Data structure alignment (数据结构对齐 / 内存对齐)

    开篇的话 在比较老的编译器里 xff0c 如果没有对变量取地址的操作 xff0c 那么有些局部变量是通过寄存器保存的 xff0c 不占栈上内存 xff0c 根本不存在内存中如何排列的问题 xff0c 比如TurboC 2 0这种 在一些较新
  • C++primer plus和C++ primer的读书心得

    C 43 43 两本巨著primer plus和primer太过于经典 xff0c 以至于读过多次 xff0c 每次阅读仍然有新的收获 xff0c 所以将一些零碎的知识点整理在这里 xff0c 与大家共同进步 1 i 43 43 与 43
  • VINS 外参在线标定

    在VINS中相机的外参 R i c R ic R i c 是可以在线动态标定的 xff0c 实现函数为 xff1a 6