因子图及GTSAM库介绍

因子图优化及 GTSAM 库介绍

因子图

在 slam 的后端优化问题中,我们通常会通过一些传感器的观测,比如视觉特征点, IMU 预积分量, Lidar面点和边缘点的约束去构建一个优化问题,求解状态量(如位姿、速度等),这个时候我们考虑一个问题,当给这个系统新增一个约束时,我们就会重新所有的约束的状态的优化问题进行求解,当图优化模型增大时,显然进行一次优化的时间也会增加很多,一方面实时性遭遇了挑战,另一方面,很久之前的状态似乎也没有继续更新的必要。为了解决这个问题,一种方式是使用滑动窗口来控制优化问题的规模,通常来讲滑动窗口需要好处理边缘化的问题,另一方面,我们可以使用因子图的模型来解决这个问题

Kaess 等科研人员提出 iSAM ,即增量平滑和建图,使其可以自动增量处理大规模优化问题,具体来说,其内部使用一种基于概率的贝叶斯树,使得每次给因子图增加一个约束时,其会根据贝叶斯树的连接关系,调整和当前结点 “ 关系比较密切 ” 的结点,比如,t=10时刻的结点加进来,他会优先处理t=9和t=8的节点。如此,既保障了优化问题的求解精度,也使得耗时不会随着优化问题的增大而增大。

滑动窗口一般需要自己去调整滑动,但是iSAM就会自动选择关系密切的节点。

关于因子图优化理论可以参考 iSAM , iSAM2 相关论文等文献。

因子图中一些概念

变量结点:类似 g2O 中的顶点或者 ceres 中的参数块,代表需要被优化的变量,可能就代表着一个位姿,一个零偏等

因子结点:类似 g2O 中的边或者 ceres 中的 cost function ,代表约束,如预积分约束、位姿先验约束、帧间位姿约束等

GTSAM库的介绍

GTSAM全称是 Georgia Tech Smoothing and Mapping library ,是佐治亚理工学院的科研人员基于因子图和贝叶斯网络推出的一个 C++ 库文件,如果你想在你的工程里使用因子图优化的相关算法,那么最常用的方式就是借助 GTSAM 这个库来实现,因为其内部已经封装了关于因子图优化以及 iSAM 相关的算法实现,因此,我们只需要像调用其他第三方库的方式(如 openCV , PCL 等)调用 GTSAM 库即可

关于 GTSAM 库的详细介绍可以参考其官方文档 GTSAM | GTSAM is a BSD-licensed C++ library that implements sensor fusion for robotics and computer vision using factor graphs.

GTSAM 关于 IMU 预积分相关接口介绍

通过第八章相关介绍可知,我们对两个关键帧之间的若干帧 IMU 进行预积分,以形成预积分约束,对两帧之间的位置、速度、姿态以及零偏进行约束。 GTSAM 从 4.0 版本开始就在内部增加了 IMU 预积分相关的接口,因此,为了实现把预积分因子加入到图优化框架中,我们有必要熟悉一下 GTSAM 中跟 IMU 预积分相关的接口定义。

gtsam::PreintegrationParams

预积分相关参数,我们对 IMU 数据进行预积分之前通常需要事先知道 IMU 的噪声,重力方向等参数

gtsam::PreintegratedImuMeasurements

跟预积分相关的计算就在这个类中实现

这个类有一些重要的接口

(1) resetIntegrationAndSetBias

将预积分量复位,也就是说清空刚刚的预积分量,重新开始一个新的预积分量,

比如刚刚计算了一个第一帧到第二帧的预积分,然后不想重新创建一个预积分类,复用之前的对象,就需要reset

注意:预积分的计算依赖一个初始的 IMU 零偏,因此,在复位之后需要输入零偏值,所以这里复位和重设零偏在一个接口里。

(2) integrateMeasurement

输入 IMU 的测量值,其内部会自动实现预积分量的更新以及协方差矩阵的更新

(3) deltaTij

预积分量跨越的时间长度

(4) predict

使用之前的状态和零偏,预测现在的状态。

预积分量可以计算出两帧之间的相对位置、速度、姿态的变化量,那结合上一帧的状态量就可以计算出下一关键帧根据预积分结果的推算值

预积分前端代码讲解

该模块涉及到的变量结点

gtsam::Pose3 // 表示六自由度位姿
gtsam::Vector3 // 表示三自由度速度
gtsam::imuBias::ConstantBias //表示 IMU 零偏

以上也是预积分模型中涉及到的三种状态变量

涉及到的因子结点

gtsam::PriorFactor<T>

先验因子,表示对某个状态量 T 的一个先验估计,约束某个状态变量的状态不会离该先验值过远

gtsam::ImuFactor

imu 因子,通过 IMU 预积分量构造出 IMU 因子,即 IMU 约束,相当于一个帧间约束

gtsam::BetweenFactor

状态量间的约束,约束相邻两状态量之间的差值不会距离该约束过远

 

### 滑动窗口因子图优化中边缘化的实现与原理 #### 1. 边缘化的定义与作用 在滑动窗口优化中,随着新的观测数据不断加入,因子图的规模会持续增大。为了保持系统的实时性和计算效率,通常采用滑动窗口策略限制因子图的大小。当超出窗口范围的老节点需要移除时,通过边缘化操作将其影响转化为一个新的先验因子并保留在当前图中[^3]。 边缘化的核心在于,在删除旧变量的同时尽可能保留其对后续变量的影响关系。具体来说,边缘化是在子图范围内进行的操作,该子图包含了待边缘化变量 \(x_m\) 和与其相连的所有因子集合 \(Z_m\),以及那些与 \(x_m\) 具有相关性的其他变量 \(x_r\)。 --- #### 2. 数学推导与高斯噪声假设下的简化 由于实际应用中往往假定误差服从高斯分布,因此可以将因子表示为二次型的形式: \[ f(x) = \frac{1}{2} (h(x) - z)^T R^{-1} (h(x) - z), \] 其中 \(h(x)\) 是测量模型,\(z\) 是观测值,\(R\) 是协方差矩阵。基于此假设,整个因子图可视为一个最小二乘问题,而边缘化则对应于条件概率密度函数的积分运算。对于多维高斯分布而言,这一过程可以通过代数方法高效完成。 --- #### 3. C++ 实现中的关键技术点 以 VINS-Fusion 的 `MarginalizationManager` 类为例,其实现主要包括以下几个方面[^2]: - **收集被边缘化帧及其关联信息**: 将要被边缘化的帧标记出来,并记录这些帧所涉及的所有 IMU 预积分因子和特征重投影因子。 - **构建局部子图**: 提取上述提到的子图部分 (\(x_m, Z_m, x_r\)) 并对其进行处理。 - **执行边缘化操作**: 利用 Schur 补等技术消去 \(x_m\) 对应的部分,得到更新后的增广信息矩阵和右侧常量项。 以下是伪代码示例: ```cpp void MarginalizationManager::marginalize() { // Step 1: Collect frames and factors to be marginalized. std::vector<Frame> oldFrames; collectOldFrames(oldFrames); // Step 2: Build the local subgraph involving these frames. SparseMatrix H; // Information matrix Vector b; // Right-hand side vector buildSubGraph(H, b, oldFrames); // Step 3: Perform marginalization using Schur complement or similar techniques. SparseMatrix augmentedH; Vector updatedB; applySchurComplement(H, b, augmentedH, updatedB); } ``` --- #### 4. 边缘化带来的优势 通过对老节点实施边缘化,不仅能够有效控制因子图的增长速度,还能显著减少内存消耗和计算负担。与此同时,借助生成的新先验因子,系统得以保存必要的历史约束信息,从而维持较高的定位精度[^1]。 --- #### 5. 应用场景举例 在 GNSS/INS/Camera 融合框架下,每当新增一帧图像或者一组传感器读数时,都会触发一次增量式的图优化流程。如果未采取任何措施任由图无限扩展,则可能导致性能瓶颈甚至崩溃;反之,合理运用滑动窗口机制配合边缘化手段即可缓解此类风险。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不忘初心t

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值