4、IMU预积分理论(下):预积分残差构建,与视觉重投影误差的联合优化,预积分在因子图中的应用

好,咱们接着上回聊。上一章我们把预积分的“骨架”搭好了——怎么把IMU的测量值从世界坐标系里“解放”出来,变成两帧之间的相对运动。但光有骨架不行,得让它真正跑起来,跟视觉数据配合干活。

这一章,咱们就干三件事:第一,把预积分的结果拧成残差;第二,把这个残差和视觉重投影误差放到一个篮子里联合优化;第三,看看它在因子图里到底怎么摆。

我个人习惯把预积分残差叫做“IMU的委屈值”——它表达了“我觉得我应该这样运动,但视觉说你得那样运动,咱俩谁对?”

4.1 预积分残差:IMU的“委屈”到底怎么算?

先回忆一下,预积分给了我们什么?它给了我们两帧之间,基于IMU测量值的相对运动增量:旋转ΔR、速度Δv、位移Δp。还有对应的偏置ba和bg。

那残差怎么定义?说白了,就是“IMU预测的状态”减去“从状态变量里算出来的相对运动”。

假设我们有第i帧和第j帧的状态:位置p、速度v、旋转四元数q(或者旋转矩阵R),以及偏置ba、bg。那么,从i到j的相对运动,用状态变量算出来应该是:

ΔR_ij = R_i^T * R_j
Δv_ij = R_i^T * (v_j - v_i - g * Δt)
Δp_ij = R_i^T * (p_j - p_i - v_i * Δt - 0.5 * g * Δt^2)

而IMU预积分直接给了我们另一套ΔR_imu、Δv_imu、Δp_imu。这两套东西的差值,就是残差。

嗯,这里要注意:预积分值依赖于偏置。如果你在优化过程中更新了偏置,预积分值也得跟着变。我早期做项目时偷懒没做这一步,结果优化死活不收敛……后来才发现,偏置一变,预积分值就得重新算,或者至少做一阶线性近似更新。

核心公式:预积分残差

r_ΔR = Log( (ΔR_ij)^T * ΔR_imu(bg) )
r_Δv = Δv_ij - Δv_imu(ba, bg)
r_Δp = Δp_ij - Δp_imu(ba, bg)
再加上偏置的随机游走残差:r_ba = ba_j - ba_i, r_bg = bg_j - bg_i

旋转残差用了Log映射,把SO(3)上的误差映射到三维向量空间。这个细节很多初学者会懵——为什么不能用简单的减法?因为旋转是流形,不能直接减。你想想看,两个旋转矩阵的差,它还是旋转矩阵吗?不是。

4.2 联合优化:视觉和IMU怎么“吵架”又“和好”?

现在我们有两条线索:视觉重投影误差,和IMU预积分残差。联合优化,就是把它们放到一个大的代价函数里,一起最小化。

代价函数长这样:

min ∑ (视觉重投影误差)^T * Σ_vis^(-1) * (视觉重投影误差) 
    + ∑ (IMU预积分残差)^T * Σ_imu^(-1) * (IMU预积分残差)

Σ_vis和Σ_imu是信息矩阵,说白了就是权重。视觉不准的时候,Σ_vis就大(权重小);IMU噪声大的时候,Σ_imu就大。我建议你在实际调参时,先固定IMU的噪声模型(厂家一般会给),然后根据场景调整视觉的权重。

举个例子:在纹理丰富的室内,视觉权重可以大一些;在空旷的走廊,IMU权重得拉高,不然视觉会飘。

实战小技巧: 我曾经在跑一个地下车库的数据集时,视觉几乎全黑,全靠IMU撑着。那时候我把IMU的权重调高了10倍,才勉强没丢。事后复盘,其实应该在代码里加一个“视觉特征数量阈值”——特征少于20个时,自动降低视觉权重。

联合优化的求解,通常用高斯-牛顿法或者LM算法。你需要计算残差对状态变量的雅可比矩阵。IMU预积分残差的雅可比推导起来比较繁琐,但好在很多开源库(比如GTSAM、Ceres)已经帮你算好了。我个人建议:不要手推全部雅可比,但一定要理解它的结构——知道哪些变量耦合、哪些不耦合,这对调试bug至关重要。

4.3 预积分在因子图中的位置:一张图说清楚

因子图是表达SLAM问题的利器。每个节点代表一个状态变量(位姿、速度、偏置),每条边代表一个约束(因子)。

预积分在这里扮演的角色,就是连接两个关键帧之间的IMU因子

下面这张图是我手绘的因子图结构,你看一眼就明白了:

预积分在因子图中的位置 P1 P2 P3 P4 P5 V1 V2 V3 V4 V5 B1 B2 B3 B4 B5 IMU IMU IMU IMU 位姿节点 速度节点 偏置节点 IMU预积分因子 视觉因子

看到没?每个关键帧对应一组节点:位姿P、速度V、偏置B。IMU预积分因子(橙色虚线)连接相邻两帧的P、V、B节点。视觉因子(紫色实线)只连接位姿节点P。

这种结构的好处是:IMU因子提供了帧间运动的强约束,视觉因子提供了全局的几何约束。两者互补,缺一不可。

注意: 偏置节点B只通过IMU因子与相邻帧的B节点相连(随机游走模型),不直接受视觉影响。但视觉会通过影响位姿P,间接影响偏置的估计。这个耦合关系在优化中会自动体现。

4.4 实战中的几个坑

讲完了理论,我分享几个实际项目中踩过的坑:

  • 初始化偏置:预积分对偏置很敏感。我建议在系统启动时,先让IMU静止2-3秒,用这段时间的均值初始化偏置。别小看这一步,能省很多调试时间。
  • 信息矩阵的尺度:IMU预积分的信息矩阵和视觉重投影误差的信息矩阵,量纲不同。如果不做归一化,优化会偏向数值大的那个。我习惯在构建因子图时,把两个信息矩阵都除以它们对角线元素的均值。
  • 边缘化策略:当关键帧数量增长时,必须边缘化旧帧。预积分因子在边缘化时,会把约束“折叠”到先验中。这个操作如果处理不好,会导致信息丢失。我记得有一次,边缘化后定位精度直接掉了30%,查了两天才发现是边缘化时忘了更新预积分值的协方差。

4.5 小结

这一章我们聊了预积分残差的构建、联合优化的框架、以及因子图中的具体应用。说白了,预积分就是IMU和视觉之间的“翻译官”——它把IMU的高频测量值,翻译成视觉优化器能理解的“帧间约束”。

下一章我们会深入代码层面,看看这些理论怎么落地到C++实现中。到时候我会带着你一行一行地读代码,把今天讲的这些公式变成能跑的程序。


公众号:蓝海资料掘金营,微信deep3321