【SLAM】VINS-MONO解析——后端优化(理论部分)

2023-05-16

7.后端非线性优化

7.1 理论基础

7.1.1 bayes模型,因子图和最小二乘
这一部分主要是对董靖博士在公开课《因子图的理论基础》上的回忆和总结。
(1)bayes模型
假设有黄色是机器人在不同时刻的位姿,蓝色是机器人观测到的路标点,红色是机器人对路标点的观测,绿色是机器人对自身运动的观测。
在这里插入图片描述
那么,这个过程可以用下面这个bayes-net来描述:
在这里插入图片描述
那么,可以有这样的定义:
黄色——机器人位姿——是状态量——X;
蓝色——路标点坐标——是状态量——X;
红色——机器人对路标点的观测——是观测量——Z;
绿色——机器人对自身运动的观测——是观测量——Z;

状态量X,对应着 待优化量,也就是g20里的vertex,ceres里的ParameterBlock;
观测量Z,对应着残差/因子,也就是g20里的edge,ceres里的ResidualBlock;

那么根据bayes法则,观测量Z和状态量X联合概率等于条件概率乘以边缘概率:
在这里插入图片描述
P(Z | X)是观测量Z对应的概率,也叫似然;
P(X, Z)是观测量Z和状态量X的联合概率;
P(X)是状态量的先验概率,比如说世界坐标系,这就是一个先验,假如说没有世界坐标系这个先验信息,那么系统整体性的漂移都能满足求解要求,那么就多了一个自由度的不可观。
而观测变量Z有一个特点,例如左一红圈,只跟状态变量x1和l1有关,而与路标点l2无关。其它的观测变量也有类似的特点,也就是稀疏性和不相关性这两个特点,所以整体的观测P(Z | X)又可以以每一个单独的观测叠乘来获得。
在这里插入图片描述

(2)因子图
首先要明确我们的求解目标是P(X | Z)最大时,也就是在观测Z的情况下,对应的X;
因为往往状态量X是不知道的,而在状态X下的观测Z,也就是P(Z | X)是知道的;
所以,需要找到待求量P(X | Z)和已知量P(Z | X)之间的关系:
在这里插入图片描述
P(X | Z)等于上式中中间的式子,正比于右边的式子。
P(Z)是观测的先验信息,对应的是测量传感器的数学模型,例如相机,IMU,轮速器。

我们想找到这么一组状态量X,使得在当前观测Z的情况下,出现状态P(X | Z)的概率最大!
可以转换为求解,在当前状态下对应的观测P(Z | X)乘以一个状态量的先验P(X)!
在这里插入图片描述
这就是传说中的,最大后验估计,转化为求似然乘以状态量的先验!

(3)因子的定义
在这里插入图片描述
那么,
在这里插入图片描述
就可以转换为,
在这里插入图片描述
因子的定义如下:
在这里插入图片描述
里面的f(xi)就是观测量的残差!也就是我们常说的IMU残差,重投影误差,先验误差等。
之所以用e的指数函数,因为传感器的测量噪声一般都满足gauss分布。

当因子连乘后,对应的最大似然估计就是最小二乘。
在这里插入图片描述

(3)残差,状态量,J,H的对应位置关系
因子图它最方便的地方就是能一眼确定这是什么类型的残差,还能知道当前残差对哪个状态量X的J块是有值的,哪块是0的!
在这里插入图片描述
就比如说左一红色方框因子,我们能一眼知道是套用重投影误差模型,对应的J是什么公式早就有了;它连着x1和l1,说明只有这两个位置的J是有值的。
不过需要注意的是,vins的因子图一般是下面这种形式的。同一个特征点是被2帧观测到的(重投影),而某一个IMU因子与相邻两帧的PVQ和bias相连的。
在这里插入图片描述

因此,往J大矩阵里面塞每一行非常方便!这也是g2o的逻辑,加状态量叫做加入vertex,加入一个残差,也就是J矩阵的一行,叫做加edge!
考虑到pose的数量远小于特征点的数量,在shur操作的时候一般会求pose部分的状态量,所以一般会把pose相关的edge放在J矩阵的上方。

7.1.2 后端模型
首先确定状态量X,
在这里插入图片描述
包括各帧的PVQ,bias,外参,特征点的逆深度。状态量的数量决定了H矩阵的维度和J矩阵的列数。PQ这两类状态是视觉和IMU都会优化的量。
目标函数为:
在这里插入图片描述
这三项分别为边缘化的先验信息、IMU的测量残差、视觉的重投影误差。这个目标函数就解释了vins系统为什么是紧耦合的系统,因为三个目标函数放在一起优化的!
对于这样的目标函数,可以构造一个下式所示的增量公式,迭代求解状态量X的最优解:
在这里插入图片描述
在这里插入图片描述

根据上一节内容,我们知道Jacobian和H是可以一行一行(若干行若干行)往里面加,接下来我们研究一下,怎么样往里面加。
在这里插入图片描述
上面这个因子图非常经典地讲解了IMU约束和视觉约束。

(1)IMU约束部分
在4.1.1.IMU预积分部分,我们已经知道:
在这里插入图片描述
等号左边减去右边,就是IMU残差:
在这里插入图片描述
优化变量是相邻两帧 (第bk、bk+1时刻)p、q、v、ba、bg:
在这里插入图片描述
这一部分,残差是15维的,状态量是7+9+7+9维的,所以说,每增加一个IMU约束,总的Jacobian矩阵增加了15行,增加了7+9+7+9列!(需要注意的是,四元数是4维的,但是Localdemension是3维的)。

接下来,我们需要弄清楚,残差对状态量的Jacobian是什么,对应位置补充上这个J的矩阵块就行了,其他位置还是0。崔神的推到结果如下。
残差对bk时刻的PVQ的Jacobian:15*7
在这里插入图片描述

残差对bk时刻的的速度/bias的Jacobian:15*9
在这里插入图片描述

残差对bk+1时刻的PVQ的Jacobian:15*7
在这里插入图片描述

残差对bk+1时刻的的速度/bias的Jacobian:15*9
在这里插入图片描述

然后就是在构造对应的H矩阵块的时候,需要乘上信息矩阵,JT (Pk+1) J + uI,也就是4.2对应部分。
在这里插入图片描述

(2)视觉约束部分
这部分的残差就是重投影误差,注意是在归一化平面上表示的:
在这里插入图片描述
但是和纯视觉不同的地方是,待优化的状态量X中的旋转平移,都是IMU系到w系到,而不是camera系到w系的:
在这里插入图片描述
这里的状态量有两个特点:
待优化量和IMU约束部分的待优化量有重叠,再次体现了紧耦合;
和IMU不同的是,IMU每次优化的状态量是相邻两帧的,但是视觉优化的2帧不一定是相邻的,因此用i,j表示。

特征点在归一化相机坐标系与在相机坐标系下的坐标关系为:
在这里插入图片描述
这块没有采用深度,而采用逆深度,因为逆深度满足高斯分布。

对于第 l 个路标点 P,将 P 从第一次观看到它的第 i 个相机坐标系,转换到当前的第 j 个相机坐标系下的像素坐标:
在这里插入图片描述
这个转换过程,经历了从ci坐标系-> bi坐标系->w坐标系-> bj坐标系-> cj坐标系这个过程。
上面这个等式,也就是:
在这里插入图片描述
那么,在归一化平面上的重投影坐标就是fcj = [xcj/zcj, ycj/zcj],重投影误差就是开头的公式。

这一部分,残差是2维的,状态量是7+7+m维的,所以说,每增加一个视觉约束,总的Jacobian矩阵增加了2行,增加了7+7+m列!(需要注意的是,四元数是4维的,但是Localdemension是3维的)。

因为根据链式法则,对Jacobian的计算可以分成:
1)视觉残差对重投影3D点fcj求导。
在这里插入图片描述

2) 再乘上fcj对各个优化变量求导。
在这里插入图片描述
然后就是在构造对应的H矩阵块的时候,需要乘上信息矩阵,JT (Pk+1) J + uI,视觉约束的协方差与标定相机内参时的重投影误差有关。VINS在代码中sqrt_info取1.5个像素,对应到归一化相机平面还需除以焦距f,最后得到的信息矩阵:(这里真正的信息矩阵其实是sqrt_info的平方)
在这里插入图片描述

(3)先验约束部分
放在8.1节介绍。

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

【SLAM】VINS-MONO解析——后端优化(理论部分) 的相关文章

  • echarts更换主题

    前言 本篇文章基于上一篇文章 xff1a vue工程整合echarts xff0c 因此这里主要讲的是主题是如何配置的 xff0c 其他代码在这里不再赘述 官网中已经说明了echarts除了有默认的主题外 xff0c 并且内置了dark主题
  • Java final修饰符详解

    final 在 Java 中的意思是最终 xff0c 也可以称为完结器 xff0c 表示对象是最终形态的 xff0c 不可改变的意思 final 应用于类 方法和变量时意义是不同的 xff0c 但本质是一样的 xff0c 都表示不可改变 x
  • Python Requests库安装和使用

    Python 提供了多个用来编写爬虫程序的库 xff0c 除了前面已经介绍的 urllib 库之外 xff0c 还有一个很重的 Requests 库 xff0c 这个库的宗旨是 让 HTTP 服务于人类 Requests 是 Python
  • C语言 十进制转十六进制

    问题描述 十六进制数是在程序设计时经常要使用到的一种整数的表示方式 它有0 1 2 3 4 5 6 7 8 9 A B C D E F共16个符号 xff0c 分别表示十进制数的0至15 十六进制的计数方法是满16进1 xff0c 所以十进
  • Pandas知识点超全总结

    Pandas知识点超全总结 一 数据结构1 Series1 创建2 切片 修改3 其他属性 2 DataFrame1 创建2 切片3 增加 修改4 删除5 查看 二 读写数据1 读数据1 excel文件2 csv文件3 sql文件 2 写数
  • socket通信小结

    1 网络中的进程之间如何进行通信 区别于本地的进程间通信 xff0c 我们首要解决的问题是如何唯一标识一个进程 xff0c 否则通信无从谈起 xff01 在本地可以通过进程PID来唯一标识一个进程 xff0c 但是在网络中这是行不通的 其实
  • eclipse alt+/代码智能提示总是报错:problems during content assist

    解决办法如下图 xff1a 依次点击红框标记的地方即可解决问题
  • linux C 遍历目录及其子目录 opendir -> readdir -> closedir

    在 linux 下遍历某一目录下内容 LINUX 下历遍目录的方法一般是这样的 xff1a 打开目录 gt 读取 gt 关闭目录 相关函数是 opendir gt readdir gt closedir xff0c 其原型如下 xff1a
  • 最全面的 linux 信号量解析

    一 xff0e 什么是信号量 信号量的使用主要是用来保护共享资源 xff0c 使得资源在一个时刻只有一个进程 xff08 线程 xff09 所拥有 信号量的值为正的时候 xff0c 说明它空闲 所测试的线程可以锁定而使用它 若为 0 xff
  • vue3学习一:let和const

    在函数的内部 xff0c 定义name变量 xff0c 当i等于false时 xff0c 按照Java语言 xff0c else里是拿不到name的 xff0c 并且会显示报错 xff0c 但是却不会报错 xff0c 这是因为javascr
  • PHP 中最全的设计模式(23种)

    PhpDesignPatterns PHP 中的设计模式 一 Introduction 介绍 设计模式 xff1a 提供了一种广泛的可重用的方式来解决我们日常编程中常常遇见的问题 设计模式并不一定就是一个类库或者第三方框架 xff0c 它们
  • 异常详细信息: System.NullReferenceException: 未将对象引用设置到对象的实例。

    我遇到的出现这种错误的原因一般是以下几种情况 xff1a 1 在绑定数据控件的时候 xff0c 建立数据库连接 OleDbConnection conn 61 new OleDbConnection 34 provider 61 micro
  • 连接不上Github,网络超时的检查和解决办法

    先附上图片吧 连接不上github但是其它网站都是正常上网 解决办法 win 43 r打开运行输入cmd 再命令行里输入 ping github com 看看返回值 我的全是请求超时 xff0c 发送的数据包全丢 xff08 我先ping了
  • 2018校招笔试真题汇总

    2018校招笔试真题汇总 最近看好多牛油贡献了很多考试的真题 xff0c 我把他们汇总在一起给到大家 xff0c 也感谢这些牛油的贡献 xff0c 只要进这个汇总贴的 xff0c 你们都将每人获得一份牛客送出的礼物一份 科大讯飞 xff1a
  • 【2】Docker的启动与停止

    1 xff09 启动 docker systemctl start docker 2 xff09 查看 docker 状态 systemctl status docker 3 xff09 查看 docker 概要信息 docker info
  • 【8】Docker中部署Redis

    1 xff09 拉取镜像 docker pull redis 这是我在 VMware 的 CentOS 中装过的 redis 版本 xff0c 拉取该指定版本使用 docker pull redis 5 0 12 命令 xff0c 不过下面
  • 操作系统学习之系统调用

    目录 一 操作系统学习之系统调用 1 什么是系统调用 2 系统调用有什么用 3 为什么需要系统调用 4 系统调用的具体流程 1 xff09 执行过程 2 如何实现用户态与内态之间的切换 3 系统调用常见名词 4 系统调用如何返回 传递返回值
  • 22-Docker-常用命令详解-docker pull

    常用命令详解 docker pull 前言docker pull语法格式options说明 使用示例未指定tag a 拉取所有 tagged 镜像 前言 本篇来学习docker pull命令 docker pull 作用 xff1a 从镜像
  • 720p,1080p对应像素解释

    720P是1280 720 61 921600 xff0c 即 分辨率为921600 xff0c 即大约92万像素 xff0c 921600接近100万像素 xff08 1280是按照16 9算出来的 xff0c 4 3的另算 xff0c
  • vue3学习二:模板字符串

    模板字符串是为了解决字符串拼接问题 xff0c 在es5中 xff0c 字符串拼接是这样的 xff1a let name 61 34 wjdsg 34 console log 34 您好 34 43 name 而在es6中可以使用模板字符串

随机推荐

  • Canal 读取 mysql bin_log

    场景 xff1a 在微服务开发的过程中多个项目协同完成一个功能 xff0c 工程与工程之间存在数据上的解耦 xff0c 底层服务为上层服务提供数据 而底层服务有需要对数据进行管理 解决方案 xff1a 基本底层服务 通过 canal 获取
  • PuTTY连接Linux服务器被拒绝问题

    PuTTY连接Linux服务器被拒绝问题 1 使用命令 xff1a ssh localhost 查看是否安装ssh1 2需要手动安装ssh1 2 1 输入命令 xff1a 1 2 2 若是出现下图所示 xff1a 1 2 3 查看进程 xf
  • 实时数据同步工具<Maxwell 操作案例>

    文章目录 案例一 xff1a 监控MySQL中的数据并输出到控制台案例二 xff1a Maxwell监控mysql的数据输出到kafka案例三 xff1a 监控MySQL指定表的数据并输出到kafka 案例一 xff1a 监控MySQL中的
  • Docker 镜像 Tag 管理

    Author xff1a rab 良好的镜像版本命名习惯能让我们更好的管理和使用镜像 xff08 如项目上线失败后可有效的进行版本回退等 xff09 xff0c 以下是 Docker 社区常用的 tag 方案 比如我现在已经构建了一个 co
  • APM与Pixhawk间的关系

    1 APM 本文APM指代 xff1a https github com ArduPilot ardupilot 2 Pixhawk 本文Pixhawk指代 xff1a https github com PX4 Firmware 3 关系
  • Pixhawk串口名称与硬件接口对应关系

    Pixhawk提供的串口较多 xff0c 通过ls dev 可以看到有如下7个tty设备 xff1a ttyACM0 ttyS0 ttyS1 ttyS2 ttyS3 ttyS4 ttyS5 ttyS6 但每个串口名称对应到Pixhawk硬件
  • Linux系统大小端判断

    大端模式 大端模式 xff0c 是指数据的低位保存在内存的高地址中 xff0c 而数据的高位保存在内存的低地址中 小端模式 小端模式 xff0c 是指数据的低位保存在内存的低地址中 xff0c 而数据的高位保存在内存的高地址中 判断程序 文
  • C preprocessor fails sanity check

    编译某一产品固件时 xff0c 遇到如下现象 xff1a checking how to run the C preprocessor opt mipsel 24kec linux uclibc bin mipsel 24kec linux
  • VLC同时开启播放多个视频流BAT脚本

    工作中 xff0c 难免会遇到要用同一个程序连续打开多个URL资源 路径的情况 xff0c 一个窗口一个窗口的启动效率太低 这里以VLC同时播放多个码流图像为例 xff0c 写个简单的BAT脚本 xff0c 供需要者参考 PS 1 使用方式
  • 【AI】Ubuntu14.04安装OpenCV3.2.0

    在ubuntu14 04系统上安装OpenCV3 2 0 环境要求 GCC 4 4 x or later CMake 2 8 7 or higher Git if failed you can replace it with git cor
  • 若依代码生成器(mybatis-plus)

    看这篇文章之前 xff0c 先去看一下我前面的文章 xff1a 若依前后端分离整合mybatis plus wjdsg的博客 CSDN博客 用过若依都知道 xff0c 若依自带的代码生成器 xff0c 是下载下来 xff0c 然后自己粘贴到
  • 【AI】基于OpenCV开发自定义程序编译方法

    基于OpenCV开发自定义程序编译方法 OpenCV自带的程序 xff0c 编译均采用cmake统一编译 若我们要基于OpenCV开发自己的程序 xff0c 如何快速编译 xff1f 本文以OpenCV库自带的facedetect cpp程
  • H3C SNMPv3 配置

    1 xff09 H3C SNMPv3 配置 snmp agent mib view included MIB 2 mib 2 noAuthNoPriv xff1a snmp agent group v3 mygroup read view
  • 【SLAM】VINS-MONO解析——综述

    目前网上有很多分析文章 xff0c 但是都只是一些比较基础的原理分析 xff0c 而且很多量 xff0c 虽然有推倒 xff0c 但是往往没有讲清楚这些量是什么 xff0c 为什么要有这些量 xff0c 这些量是从哪来的 xff0c 也没有
  • 【SLAM】VINS-MONO解析——前端

    各个部分的讲解如下链接 xff1a SLAM VINS MONO解析 综述 SLAM VINS MONO解析 feature tracker SLAM VINS MONO解析 IMU预积分 SLAM VINS MONO解析 vins est
  • 【SLAM】VINS-MONO解析——IMU预积分

    4 IMU预积分 IMU预积分主要干了2件事 xff0c 第一个是IMU预积分获得 值 xff0c 另一个是误差传递函数的获取 本部分的流程图如下图所示 各个部分的讲解如下链接 xff1a SLAM VINS MONO解析 综述 SLAM
  • 【SLAM】VINS-MONO解析——vins_estimator流程

    5 vins estimator 基本上VINS里面绝大部分功能都在这个package下面 xff0c 包括IMU数据的处理 前端 xff0c 初始化 我觉得可能属于是前端 xff0c 滑动窗口 后端 xff0c 非线性优化 后端 xff0
  • 【SLAM】VINS-MONO解析——初始化(理论部分)

    6 初始化 第一个问题 xff0c 为什么要初始化 xff1f 对于单目系统而言 xff0c 1 视觉系统只能获得二维信息 xff0c 损失了一维信息 深度 所以需要动一下 xff0c 也就是三角化才能重新获得损失的深度信息 xff1b 2
  • 【SLAM】VINS-MONO解析——初始化(代码部分)

    6 2 代码解析 这部分代码在estimator processImage 最后面 初始化部分的代码虽然生命周期比较短 xff0c 但是 xff0c 代码量巨大 xff01 主要分成2部分 xff0c 第一部分是纯视觉SfM优化滑窗内的位姿
  • 【SLAM】VINS-MONO解析——后端优化(理论部分)

    7 后端非线性优化 7 1 理论基础 7 1 1 bayes模型 xff0c 因子图和最小二乘 这一部分主要是对董靖博士在公开课 因子图的理论基础 上的回忆和总结 1 bayes模型 假设有黄色是机器人在不同时刻的位姿 xff0c 蓝色是机