从零学习SLAM(位姿图)

本文探讨了视觉SLAM中PoseGraph的概念及其优化过程,分析了PoseGraph如何通过简化特征点优化,专注于相机位姿之间的关系,以提高大规模场景下的计算效率。
部署运行你感兴趣的模型镜像

视觉SLAM笔记

 

1. Pose Graph 的意义

带有相机位姿和空间点的图优化称为 BA,能够有效地求解大规模的定位与建图问题
但是,随着时间的流逝,机器人的运动轨迹将越来越长,地图规模也将不断增长
像 BA 这样的方法,计算效率就会(令人担忧地)不断下降

根据前面的讨论,发现特征点在优化问题中占据了绝大多数部分
而实际上,经过若干次观测之后,那些收敛的特征点,空间位置估计就会收敛至一个值保持不动
而发散的外点则通常看不到了
对收敛点再进行优化,似乎是有些费力不讨好的

因此,更倾向于在优化几次之后就把特征点固定住,只把它们看作位姿估计的约束
而不再实际地优化它们的位置估计

沿着这个思路往下走,会发现:是否能够完全不管路标,而只管轨迹呢?
完全可以构建一个只有轨迹的图优化
而位姿节点之间的边,可以由两个关键帧之间通过特征匹配之后得到的运动估计来给定初始值
不同的是,一旦初始估计完成,就不再优化那些路标点的位置,而只关心所有的相机位姿之间的联系了
通过这种方式,省去了大量的特征点优化的计算,只保留了关键帧的轨迹
从而构建了所谓的位姿(Pose Graph)


在这里插入图片描述

在 BA 中,特征点数量远大于位姿节点的数量,一个关键帧往往关联了数百个关键点
而实时 BA 的最大计算规模,即使利用稀疏性,在当前的主流 CPU 上一般也就是几万个点左右
这就限制了 SLAM 应用场景
所以,当机器人在更长的时间和空间中运动时,必须考虑一些解决方式:

  1. 要么像滑动窗口法那样,丢弃一些历史数据
  2. 要么像 Pose Graph 的做法那样,舍弃对路标点的优化,只保留 Pose 之间的边

2. Pose Graph 的优化

关于 Pose Graph 图优化中的节点和边
这里的节点表示相机位姿,以 ξ1,……,ξn 来表达
而边,则是两个位姿节点之间相对运动的估计,该估计可能来自于特征点法或直接法
但不管如何,估计了,比如说 ξi 和 ξj 之间的一个运动 ∆ξij
该运动可以有若干种表达方式,取比较自然的一种:
在这里插入图片描述
或按李群的写法:
在这里插入图片描述
按照图优化的思路来看,实际当中该等式不会精确地成立
因此设立最小二乘误差,然后和以往一样,讨论误差关于优化变量的导数

这里,把上式的 ∆Tij 移至等式右侧,构建误差 eij:
在这里插入图片描述
注意优化变量有两个: ξi 和 ξj
因此求 eij 关于这两个变量的导数
按照李代数的求导方式,给 ξi 和 ξj 各一个左扰动: δξi 和 δξj
于是误差变为:
在这里插入图片描述
该式中,两个扰动项被夹在了中间
为了利用 BCH 近似,希望把扰动项移至式子左侧或右侧
暂时把它当作想当然的东西:
在这里插入图片描述
稍加改变,有:
在这里插入图片描述
该式表明,通过引入一个伴随项,能够“交换”扰动项左右侧的 T
利用它,可以将扰动挪到最右(当然最左亦可),导出右乘形式的雅可比矩阵(挪到左边时形成左乘):

在这里插入图片描述

因此,按照李代数上的求导法则,求出了误差关于两个位姿的雅可比矩阵
关于Ti 的:
在这里插入图片描述
以及关于 Tj 的:

在这里插入图片描述
由于 se(3) 上的左右雅可比 Jr 形式过于复杂,通常取它们的近似
如果误差接近于零,就可以设它们近似为 I 或:

在这里插入图片描述
理论上来说,即使在优化之后,由于每条边给定的观测数据并不一致,误差通常也不见得近似于零
所以简单地把这里的 Jr 设置为 I 会有一定的损失

了解雅可比求导后,剩下的部分就和普通的图优化一样了
简而言之,所有的位姿顶点和位姿——位姿边构成了一个图优化
本质上是一个最小二乘问题,优化变量为各个顶点的位姿,边来自于位姿观测约束

记 E 为所有边的集合,那么总体目标函数为:
在这里插入图片描述
依然可以用 Gauss-Newton、 Levenberg-Marquardt 等方法求解此问题
除了用李代数表示优化位姿以外,别的都是相似的
根据先前的经验,这自然可以用 Ceres 或 g2o进行求解

这里写图片描述

 


 

 

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

开始完成SLAM实战可按以下步骤和方法进行: 1. **了解SLAM后端处理方法**:SLAM的后端一般有两种处理方法,一种是以扩展卡尔曼滤波(EKF)为代表的滤波方法,另一种是以图优化为代表的非线性优化方法,目前SLAM研究的主流热点几乎都是基于图优化的 [^1]。 2. **学习ROS相关知识**:ROS(机器人操作系统)在SLAM中应用广泛,可学习如【ROS tf2】发布静态坐标系、【Point Cloud ROS】用一张彩色图像和深度图像生成点云图像、两张点云图像之间的位姿变换、对点云进行位姿态变换等内容,为后续实战打下基础 [^2]。 3. **掌握算法原理**:学习ros navigation AMCL move_base配置文件以及A - Star、Dijkstra等算法原理,同时了解图的创建方法,例如用已提供的矩阵创建图的具体实现 [^3]。 4. **深入研究Vins - Fusion**:这是较为常用的SLAM系统,可研究其主题框架和数据流分析。前端基于LK光流法跟踪特征法,要掌握其原理、源码细节处理及与特征点法对比的优劣;后端基于BA优化进行位姿估计,包括构建IMU残差、左右目残差、单目前后两帧残差、前帧左目当前帧右目残差等;回环检测基于词袋模型DBoW进行分析;还要了解外参矩阵实时估计、3d - 2d PNP求解、三角化、初始化如何实现位姿对齐等内容 [^4]。 ### 代码示例 以下是创建图(用已提供的矩阵)的代码示例: ```cpp /* * 创建图(用已提供的矩阵) * * 参数说明: * vexs -- 顶点数组 * vlen -- 顶点数组的长度 * edges -- 边数组 * elen -- 边数组的长度 */ MatrixUDG::MatrixUDG(char vexs[], int vlen, char edges[][2], int elen) { int i, p1, p2; // 初始化"顶点数"和"边数" mVexNum = vlen; mEdgNum = elen; // 初始化"顶点" for (i = 0; i < mVexNum; i++) mVexs[i] = vexs[i]; // 初始化"边" for (i = 0; i < mEdgNum; i++) { // 读取边的起始顶点和结束顶点 p1 = getPosition(edges[i][0]); p2 = getPosition(edges[i][1]); mMatrix[p1][p2] = 1; mMatrix[p2][p1] = 1; } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值