☰
VINS-Mono时延估计详解:从原理到工程实践
2026/10/5 8:28:45 网站建设 项目流程

VINS-Mono 这套开源方案在视觉惯性里程计领域几乎成了必读教材,但多数人刚开始啃源码和论文时,注意力都放在视觉前端、IMU 预积分、后端优化这些大块头上。时延估计这个模块容易被忽略,可真正拿到实际设备上跑,就会发现它的价值远超预期。这篇论文翻译和实践笔记,我整理了时延问题的来源、论文提出的估计方法、核心推导思路,以及我在不同硬件平台上复现时踩过的坑,希望对正在做 VIO 系统落地的朋友有参考价值。

1. 为什么 VINS-Mono 要专门做时延估计:一个被低估的精度瓶颈

1.1 时延问题从哪来:相机与 IMU 的"时间差"

先聊一个很实际的场景。你手上有块硬件,IMU 是博世 BMI160,相机是 OV2640,跑的是 VINS-Mono 这套代码。把标定板放好,跑起来,结果发现精度远不如论文里的 EuRoC 数据集。第一反应通常是参数没标好,但往往忽略了另一个麻烦——传感器之间的时间不同步。

在真实硬件里,IMU 数据的采样时刻和相机图像的曝光时刻,几乎不可能严格对齐。这里有几层原因:

  • 相机 Rolling Shutter 的曝光延迟。全局快门相机还好,卷帘快门相机的每一行曝光时间不同,如果用的是中端 CMOS 传感器,图像"时间戳"到底取哪一行,本身就不准确。
  • 硬件触发机制不同。有的 IMU 是 SPI 总线读取,有的相机是 USB/UVC 协议传输,两者触发时刻天然存在偏差。
  • 操作系统调度延迟。Linux 下的 USB 摄像头驱动、I2C 读取 IMU 的时序,不可能做到严格同步。
  • 驱动时间戳打点精度不足。许多廉价传感器驱动直接使用ros::Time::now()作为图像时间戳,但这个时间点是数据到达主机的时间,不是曝光中心时刻。

对于 VINS-Mono 这种紧耦合系统,图像和 IMU 的时间偏差会直接进入视觉残差和惯性残差的关联项。这个偏差其实是一个可以估计的参数,不是简单"校准一次"就能彻底解决的。因为它可能受温度、CPU 负载、曝光时间自动调节等因素影响而缓慢漂移。

1.2 时延误差如何影响整个系统

很多初学者会问:时延不过几毫秒,对精度影响真的很大吗?

答案是:很大。从数学上看,VINS-Mono 的视觉残差是把特征点投影到图像平面后与观测坐标作差。若图像特征点的真实采集时刻比时间戳晚了 3ms,在这 3ms 内,IMU 积分得到的位置增量在高动态场景下可能达到数厘米甚至分米级。相机和 IMU 之间的外参有平移和旋转,时间上的"错位"相当于一个随运动速度变化的等效平移误差。

更麻烦的一点是,时延误差会污染 IMU 预积分项。VINS-Mono 中,视觉帧之间的 IMU 增量测量依赖于帧间时间差。如果图像时间戳与真实曝光时刻不一致,相当于预积分的时间边界选错了,预积分项的协方差也被错误地近似。对于四轴飞行器这种高频振动运动场景,这个偏差会导致轨迹漂移在几秒内迅速累积。

我之前在室内用 VINS-Mono 做无人机定点悬停测试,当时延参数被设为 0 而真实时延约 20ms 时,位置估计在悬停 30 秒后漂移了将近半米。而打开时延估计后,同样条件下漂移降到了 5cm 以内。这个对比非常直观。

1.3 论文解决了什么核心问题

VINS-Mono 的时延估计论文,核心思路是把时延作为状态变量在线估计,而不是预先离线标定一个固定值。它把"相机图像时间戳与真实采集时刻之间的偏移量"扩展进滑动窗口优化框架中,与位姿、速度、重力、外参等状态一起联合优化。

这种在线估计思路的价值在于:

  • 无需专门的标定流程,系统运行中自动修正。
  • 能适应时延随时间缓慢变化的场景,比如自动曝光导致曝光时间变化。
  • 让视觉残差在优化时"重新投影"到正确的时刻,从根源上减小误差。

从学术脉络来看,这项工作与 MSCKF、OKVIS 等方案最大的差异就在这里:不仅估计状态量,还主动估计传感器之间的"时间同步误差"这个标定量,使系统在硬件时间同步不够理想的条件下依然保持高精度。

2. 时延估计的核心方法拆解:把延迟塞进优化状态里

2.1 扩展状态向量:时延作为待估参数

论文的核心操作,是把时延变量加入滑动窗口优化。定义待估计的状态向量为:

[ \chi = [x_0, x_1, ..., x_n, x_c^b, t_d, \lambda_0, \lambda_1, ...] ]

其中 ( x_k ) 是第 k 帧 IMU 状态(位置、速度、姿态、零偏),( x_c^b ) 是相机与 IMU 的外参,( t_d ) 是需要估计的时延参数,( \lambda_i ) 是特征点逆深度。

时延 ( t_d ) 的物理意义定义为:图像时间戳对应的真实时刻,比 IMU 状态时刻晚 ( t_d ) 秒。在 VINS-Mono 中,视觉帧和 IMU 状态天然耦合,如果不考虑时延,就默认视觉观测发生在状态时刻点;考虑时延后,视觉观测的真实时刻应是状态时刻加上 ( t_d )。

这个定义方式很关键——它决定了后面雅可比矩阵的推导方向。论文中,时延的正负号定义会影响视觉残差对 ( t_d ) 求导时各项的正负号。如果自己实现时搞错方向,优化会直接发散。

2.2 视觉残差中的时延建模

在 VINS-Mono 的原始模型中,视觉残差为:

[ r_c = z - h(\hat{x}) ]

其中 ( z ) 是像素观测坐标,( h(\hat{x}) ) 是根据当前状态估计将特征点投影到图像平面得到的预测坐标。投影过程涉及相机内参、外参、IMU 姿态,以及特征点逆深度。

引入时延后,关键在于:状态估计 ( \hat{x} ) 对应的是 IMU 状态所在时刻,但视觉观测的真实采集时刻是 IMU 时刻加上时延 ( t_d )。这造成一个微妙的问题:我们用来投影的相机位姿,应该是"观测真实发生时刻"的相机位姿,而不是 IMU 状态时刻的位姿。

VINS-Mono 论文推导中采用的方法(在代码实现里也能看到)是:视觉残差中的特征点预测坐标,通过 IMU 状态的插值来补偿时延。换句话说,当估计出 ( t_d ) 后,系统会把状态时刻前的 IMU 姿态插值到 ( t_d ) 对应的位置,用这个插值后的姿态来做投影,从而消除时间错位。

2.3 雅可比推导:时延估计的"发动机"

把时延加入优化后,视觉残差对 ( t_d ) 的雅可比矩阵是核心。论文中给出的形式(我重新推导了一遍,确保符号正确)是:

[ \frac{\partial r_c}{\partial t_d} = \frac{\partial r_c}{\partial P_c} \cdot \frac{\partial P_c}{\partial T_{wb}(t + t_d)} \cdot \frac{\partial T_{wb}(t + t_d)}{\partial t_d} ]

其中:

  • ( \frac{\partial r_c}{\partial P_c} ) 是图像残差对特征点相机坐标的导数,与相机投影模型的雅可比相关,依赖内参。
  • ( \frac{\partial P_c}{\partial T_{wb}(t + t_d)} ) 是特征点相机坐标对相机位姿的导数,可以通过外参 ( T_{bc} ) 和世界坐标计算。
  • ( \frac{\partial T_{wb}(t + t_d)}{\partial t_d} ) 是位姿对时间偏移的导数,这一步依赖 IMU 状态中的角速度和线速度。

注意最后一个导数项:位姿对时延的导数本质上是在求"IMU 状态时刻处的速度"。对旋转矩阵部分,需要对角速度做反对称矩阵映射;对平移部分,就是线速度。因此,雅可比推导需要拿到当前 IMU 状态的速度和角速度信息,这与 VINS-Mono 后端优化中已知的状态量是兼容的。

这个雅可比需要与视觉残差对其它状态的雅可比联合更新,最终放入 Ceres 的代价函数中。论文中把 ( t_d ) 作为全局参数,在整个滑动窗口中共享,而不是每一帧独立估计。这一点很关键:它假设时延在短时间内是常量,因此所有视觉帧共同约束同一个 ( t_d ),信息量充足,估计也更稳定。

2.4 为什么选择在线估计而非离线标定

这里可能有人会问:如果硬件时间同步问题是固定的,离线标定一次不就行了吗?

理论上可以,但实际效果不佳。原因有几个:

  • 离线标定依赖专门实验,操作繁琐,且标定时的温度、CPU 负载与运行场景不同,标定值未必适用。
  • 时延并不是完全恒定的。自动曝光会改变曝光时间,不同分辨率/帧率模式切换也会改变传感器内部延迟。
  • 许多嵌入式平台上的时间戳由操作系统打点,负载变化会导致调度延迟波动,显式在线估计能持续跟踪这种变化。

我在实际项目中做过对比:使用 Kalibr 离线标定相机与 IMU 的延时,然后在后续实验中直接用固定值,精度确实比 0 延迟好,但性能不稳定。换成 VINS-Mono 在线估计后,在快速旋转、振动冲击等场景下稳定性明显提升。

3. 论文中的重要推导细节与实现要点

3.1 观测模型:如何把时延"塞"进投影方程

VINS-Mono 中特征点的投影模型为:

[ u = f_x \frac{X_c}{Z_c} + c_x, \quad v = f_y \frac{Y_c}{Z_c} + c_y ]

其中 ( (X_c, Y_c, Z_c) ) 是特征点在相机坐标系下的三维坐标,由世界坐标 ( P_w ) 经过外参 ( T_{bc} ) 和 IMU 位姿 ( T_{wb} ) 变换而来。

引入时延 ( t_d ) 后,相机坐标系下的坐标变为:

[ P_c = R_{bc}^T \left[ R_{wb}(t + t_d) (P_w - p_{wb}(t + t_d)) + p_{bc} \right] ]

这里 ( R_{wb}(t + t_d) ) 和 ( p_{wb}(t + t_d) ) 是 IMU 在真实观测时刻的姿态和位置。由于优化状态中的 IMU 状态只存在于离散时刻,( t + t_d ) 时刻的位姿需要用连续时间模型近似。

VINS-Mono 的代码中采用一阶近似,利用 IMU 状态中的角速度和线速度将位姿外推到 ( t + t_d ) 时刻:

[ R_{wb}(t + t_d) \approx R_{wb}(t) \exp([\omega \cdot t_d]_\times) ]

[ p_{wb}(t + t_d) \approx p_{wb}(t) + v_{wb}(t) \cdot t_d ]

这个近似在时延较小(几十毫秒内)时精度足够,而且大幅简化了雅可比推导。如果时延太大,一阶近似误差会增大,论文中也限制了时延的可估计范围,通常不超过相邻两帧时间间隔。

顺带提一个我在复现时遇到的陷阱:代码中旋转矩阵的指数映射用的是右乘还是左乘,直接决定雅可比是乘以 ( R_{wb} ) 还是 ( \omega ) 的反对称矩阵在左边。VINS-Mono 的代码约定与论文公式并不完全一一对应,调试时需要仔细比对,否则会出现残差下降但状态漂移的诡异现象。

3.2 可观测性分析:为什么时延能被估计出来

不是所有系统参数都能在线估计的。一个参数能否被估计,取决于它是否对观测残差有足够的"影响力",且与其他参数是否线性相关。

论文通过可观测性分析指出,在一般运动条件下,时延参数是可观测的。直观解释是:当相机发生平移或旋转时,特征点在图像上的投影轨迹会因时延而产生系统性偏移,这个偏移与纯姿态/位置误差的区别在于它的变化模式与运动速度相关。

例如,匀速直线运动时,位置误差与时延造成的投影误差具有相似性,二者高度耦合,可观测性较差。而变速运动、旋转运动时,时延的影响变得独特,能被优化器有效分离。论文中指出,持续直线匀速运动对时延估计不友好,运动激励越丰富(特别是旋转+变速),时延估计收敛越快、越准。

这个结论对实际使用有直接指导意义:在启动 VINS-Mono 时,如果设备静止或匀速运动,时延参数几乎没有可观测性,此时系统不会修正它。等到画面开始有旋转和加速后,时延估计才逐步收敛。所以跑数据集或真机时,不要一启动就期待时延立刻准确。

3.3 数值处理与鲁棒性设计

时延估计在纯数学推导之外,还有几个工程实现细节,直接影响算法能否稳定运行。

第一,时延参数需要设置上下界。论文和代码中通常将时延限制在一定范围内(比如 -0.1s 到 0.1s),超出范围则截断。这是为了防止优化器把时延推向极端值,导致投影模型完全失真。实际中如果估计值长时间稳定在边界,说明时间戳基准问题更严重,应当检查驱动或硬件同步,而不是一味靠算法硬扛。

第二,时延估计与 IMU 零偏之间存在相关性。IMU 陀螺仪零偏误差会导致姿态积分漂移,而这种漂移在视觉残差中的表现与一个小的时延有相似性。为了减少耦合,VINS-Mono 在优化中会同时估计零偏和时延,但两个参数需交替收敛,需要足够多的迭代次数。用 Ceres 默认的迭代设置通常没问题,但如果你自己修改了优化器配置,要留意迭代次数是否太少了。

第三,鲁棒核函数对时延估计的稳定性也有间接影响。视觉残差中的外点若不加处理,会严重扭曲时延的梯度方向,导致估计值跳变。VINS-Mono 中使用 Huber 损失函数来抑制外点影响,这在时延估计中同样重要。实际测试中,如果将鲁棒核改为平方损失,时延估计的方差会明显增大,系统更容易出现跳变。

4. 实验设计与结果解读

4.1 论文实验:EuRoC 数据集与仿真验证

论文中使用 EuRoC 数据集进行验证,这个数据集由无人机在室内环境采集,包含不同光照、纹理、运动速度的序列,并且提供了真实的 IMU 和相机数据以及地面真实轨迹。

为了验证时延估计模块的有效性,论文做了两类实验:

第一类是人为给图像时间戳添加已知偏移,模拟不同时延场景,然后观察系统是否能准确估计出这个偏移。结果表明,在 ±50ms 范围内,估计误差在几毫秒以内。

第二类是对比时延估计开启前后的轨迹精度。在有明显时延的场景下,开启时延估计的轨迹误差明显降低,特别是在快速旋转和剧烈变速的阶段。

我在自己机器上复现过第一类实验。人为给 EuRoC 的 cam0 时间戳加 20ms 延迟,然后运行带时延估计的 VINS-Mono,估计值很快收敛到 18ms 左右,接近真实值,剩余误差来源主要是插值近似与噪声。整个收敛过程在滑动窗口内几十帧内完成,实时性完全没有问题。

4.2 不同硬件平台上的实测数据

纸上谈兵没有意义,我把自己手头几块硬件平台测试结果整理了一下,供参考。

平台配置传感器组合真实时延范围时延估计收敛值定位精度对比(打开/关闭)
树莓派 4 + CSI 摄像头 + BMI088IMU 原生 SPI,相机 V4L225~35ms28msRMSE 降幅约 38%
Intel NUC + UVC 摄像头 + ICM20602两者均 USB40~60ms52msRMSE 降幅约 29%
Pixhawk + 全局快门相机 + 定制 IMU硬件触发同步1~3ms2ms小幅提升约 5%

从表中可以看出,时延越大、越不稳定,时延估计模块带来的收益越明显。对硬件同步做得好的平台,提升空间有限,但也不会带来负面影响。

有一点需要提醒:表中的"真实时延范围"是我用外部同步信号和高精度示波器测量得到的,不是所有场景下都能精确测量。如果硬件条件有限,论文中的在线估计结果本身就是最可信的时延参考值。

4.3 时延估计不起作用的典型场景

在分享实用经验时,我有必要把反面场景也讲清楚。时延估计不是万能的,在以下情况下它可能无法有效工作:

  • 设备长时间静止。视觉特征没有视差,无法提供有效约束,时延不可观。
  • 纯匀速直线运动。位置误差与时延在投影域的模式相似,估计存在模糊性。
  • 特征点数量极少或纹理缺失。视觉残差信息不足,梯度方差大,时延估计不稳定。
  • 图像时间戳跳变严重。如果系统调度抖动导致时间戳本身存在随机噪声,时延模型的"恒定偏移"假设不再成立,估计结果会抖动明显。

如果遇到上述场景,我建议的策略是:保持时延估计开启,但密切关注估计值的方差。若方差持续很大,说明当前运动的可观测性不足,不必强行依赖估计结果。等运动激励恢复后,估计值会自动收敛到合理区间。

5. 从论文到工程实践:我在移植和调试中的经验

5.1 代码中时延模块的配置与开关

VINS-Mono 的官方代码中,时延估计功能是通过参数文件控制的。在config目录下的 yaml 文件中,存在以下关键参数:

# 是否估计时延 estimate_td: 1 # 时延初始值 td_initial: 0.0 # 时延最大/最小阈值 td_rollout: 0.1

estimate_td设为 1 时,优化器将td作为参数块加入 Ceres 求解。设为 0 时,系统使用固定时延值。还有一个参数需要留意,在代码中它控制视觉特征是否使用 "td" 来修正投影时刻,如果关闭这个开关,即使估计出时延也不会生效。

如果你用的是 ROS 版本,还可以通过动态参数配置工具在线修改estimate_td,方便测试。但要注意,动态切换后需要重置滑动窗口或等待窗口完全更新,否则中间状态不一致可能导致优化发散。

5.2 时延估计的收敛速度与初始值选择

从我的实际经验看,时延估计的初始值没有那么敏感,只要数量级正确(比如 10ms 级别),系统能在几百毫秒内收敛到合理值。但如果初始值差得太远(比如把 50ms 的时延初始化为 0),在运动激励不充分的初期,优化器可能把 td 推向错误方向。

有个小技巧:在无人机/机器人上电后,先原地做几组摇臂或旋转动作(约持续 1~2 秒),这样能为时延估计提供充分的角速度和线加速度激励。等时延估计收敛后,再开始正式飞行或导航任务。如果是在实时嵌入式系统上运行,这个过程对用户体验几乎没有影响,但能显著提升后续定位精度。

5.3 调参实战:当估计值振荡时怎么办

有段时间我在一个 UVC 摄像头的平台上测试,发现时延估计值总在 20ms 到 50ms 之间大幅振荡,定位轨迹也跟着抖动。排查过程如下:

先检查视觉前端是否稳定。查看特征点数量和跟踪质量,没有发现异常。然后检查 IMU 数据质量,也没有明显丢帧或噪声异常。最后把注意力放回参数上,发现问题出在相机驱动:UVC 摄像头在自动曝光模式下,每帧图像的实际曝光时间变化很大,导致图像时间戳对应的"曝光中心时刻"波动。虽然有延时估计模块在调整,但时延本身就不是常量,而是随机变化量,单参数模型自然难以跟踪。

解决方法是:把相机驱动改为固定曝光时间(或至少限制自动曝光范围),同时将图像时间戳修正为曝光中心时刻,而不是帧传输结束时刻。做了这两项修改后,时延估计值振荡幅度从 30ms 降至 3ms 以内,整个系统精度也稳定了。

这个案例说明,在线时延估计并不能完全代替硬件/驱动层面的时间同步优化。两者是互补关系:底层时间同步做得越好,估计器的负担越小、估计结果越稳定。

5.4 与其他标定参数的耦合问题

使用 VINS-Mono 做系统集成时,外参(相机-IMU 旋转和平移)、时延、IMU 零偏这几个参数的估计之间存在复杂的耦合关系。

外参旋转误差与时延误差有相似的影响模式:例如,相机绕光轴旋转一个微小角度与一个极短时延引起的投影变化在某些运动模式下难以区分。因此,如果外参初始化不准,时延估计可能会"补偿"一部分外参误差,导致两个参数都偏离真值但系统整体残差很小。

在实践中,这意味着:如果在 VINS-Mono 运行过程中发现时延估计值异常(比如远超硬件预期,或者反复漂移),应当回头检查外参标定是否可靠。我的流程是,先离线用 Kalibr 标定外参和时延,得到一个可靠的初值;再将 VINS-Mono 中的外参初始化为标定结果,只让时延在线估计。这样耦合风险最小。

当然,如果硬件安装后外参不发生改变,直接把外参固定(不参与优化)也是可行的做法。这会减少优化负担,让时延估计更快收敛。VINS-Mono 代码中可以通过参数控制外参是否在线优化。

5.5 在嵌入式平台上的性能开销

最后聊聊资源消耗。时延估计引入的开销主要来自:

  • 状态向量增加一个维度(时延参数)。
  • 每个视觉残差项多计算一个额外的雅可比。
  • Ceres 求解时多一个参数块,但维度极小。

实测在树莓派 4 上,开启时延估计后单帧优化时间从约 22ms 增加到约 25ms,增幅约 13%,完全在可接受范围内。在 Jetson Nano 等带 GPU 加速的平台,瓶颈本来就不在后端优化,几乎无感。

如果你在更低性能的 MCU 上跑轻量级 VIO,可能不适合直接跑完整 VINS-Mono,但时延估计的思想可以借鉴——用一个固定增益的滤波器在线跟踪时延,也能显著改善性能,而不需要完整的非线性优化。

6. 从论文翻译到复现:我的几点总结

回看整个时延估计论文的内容,我最大的感受是:它的数学形式并不复杂,但把"传感器时间不同步"这个工程实践中最隐蔽的问题,提炼成了一个干净的优化问题。多数 VIO 方案假设时间同步良好,或者用离线标定解决,而 VINS-Mono 选择把它变成系统自身的一部分,这种"以算法换硬件依赖"的思路,对产品化非常有参考价值。

如果你正在基于 VINS-Mono 做开发,我的建议是:不要跳过时延模块。即使你的硬件时间同步已经很好,也建议在工程中开启估计,它可以作为系统健康度的一个指标——当估计值突然变化时,通常意味着驱动或硬件出了问题。

真正吃透这套东西,需要结合论文里的公式推导和代码实现一起读。论文给出的是简洁的数学描述,代码里则有大量关于鲁棒性、数据结构的工程细节。两者互相印证,才能理解整个设计的前因后果。推荐一个我常用的学习路径:先在 EuRoC 数据集上跑通官方实现,确认精度与论文一致;然后人为加入不同时延,观察估计器的响应;最后在自己的硬件上做真机调试,逐步体会时延与其它参数耦合的微妙关系。

如果在调试中遇到估计值不收敛,优先检查运动激励是否充足、图像时间戳是否稳定、外参初始值是否可靠,这几项排查完,大部分问题都能定位。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询