3、IMU测量模型与运动学:加速度计与陀螺仪原理、IMU噪声模型、Allan方差分析
好,咱们进入第三章。这一章聊的是IMU——视觉惯性SLAM系统的“心脏”。说白了,没有IMU,纯视觉在快速运动或弱纹理场景下很容易“飘”。但IMU也不是完美的,它有自己的一套脾气。你得摸透它的测量模型和噪声特性,才能用好它。
核心观点:IMU的测量值 = 真实值 + 系统误差 + 随机噪声。我们的目标,就是把这堆“脏数据”洗干净,喂给后端优化器。
3.1 加速度计与陀螺仪原理
先说说加速度计。它测的是什么?不是速度,是比力(Specific Force)。你想想看,一个静止放在桌面上的加速度计,它读数是(0, 0, 9.81) m/s²。为什么?因为它感受到的是重力加速度的反作用力。这个力,就是比力。
陀螺仪呢?它测的是角速度。MEMS陀螺仪的原理其实挺巧妙的——利用科里奥利效应。一个振动的质量块,当它绕某个轴旋转时,会受到一个垂直于振动方向和旋转轴方向的力。测这个力的大小,就能反推出角速度。
我个人习惯把IMU的测量模型写成这样:
加速度计: a_m = R^T * (a_w - g) + b_a + n_a
陀螺仪: ω_m = ω_w + b_g + n_g
这里:
a_m、ω_m是测量值a_w、ω_w是世界坐标系下的真实值R是旋转矩阵,把世界系转到IMU系g是重力向量b_a、b_g是零偏(Bias)n_a、n_g是白噪声
嗯,这里要注意:加速度计测量的是“比力”,不是“加速度”。很多新手会搞混,以为加速度计直接输出加速度。其实不是的,它输出的是“非引力加速度”。所以我们在做预积分时,要先把重力项减掉。
我的经验:有一次在无人机上做VIO,发现高度一直在漂。查了半天,原来是加速度计的零偏没标定好。0.1 m/s²的零偏,积分10秒就能产生5米的误差。所以,零偏的初始标定非常重要。
3.2 IMU噪声模型
IMU的噪声,我把它分成两大类:
- 确定性误差:包括零偏、尺度因子、轴间耦合等。这些可以通过标定来补偿。
- 随机噪声:包括白噪声、随机游走、量化噪声等。这些需要用统计模型来描述。
在SLAM里,我们最关心的是两个噪声参数:
| 参数 | 符号 | 单位 | 物理意义 |
|---|---|---|---|
| 陀螺仪白噪声 | σ_g | rad/s/√Hz | 角速度测量的高频抖动 |
| 加速度计白噪声 | σ_a | m/s²/√Hz | 加速度测量的高频抖动 |
| 陀螺仪零偏随机游走 | σ_bg | rad/s²/√Hz | 零偏随时间缓慢漂移的速率 |
| 加速度计零偏随机游走 | σ_ba | m/s³/√Hz | 零偏随时间缓慢漂移的速率 |
为什么是这些参数?因为IMU的误差模型,本质上是一个“白噪声驱动”的系统。白噪声经过积分,会变成随机游走。你想想看,陀螺仪的角速度测量有白噪声,积分后得到角度,这个角度的误差就是随机游走。同理,加速度计的白噪声积分后得到速度误差,再积分得到位置误差——这就是为什么纯惯性导航的位置误差会随时间三次方增长。
避坑指南:我曾经在标定一个低成本IMU时,发现Allan方差曲线在短时间尺度上不是-1/2斜率。后来才发现,这个IMU的量化噪声特别大,把白噪声的频谱特征给掩盖了。所以,拿到一个新IMU,先别急着用,画个Allan方差图看看。
3.3 Allan方差分析
Allan方差,说白了就是用来“拆解”IMU噪声成分的工具。它通过分析不同时间尺度上的方差变化,把白噪声、随机游走、量化噪声、零偏不稳定性等一一分离出来。
计算步骤其实不复杂:
- 采集一段长时间的静态IMU数据(至少1小时,我建议2小时以上)
- 把数据分成若干段,每段时长τ
- 计算每段数据的平均值
- 计算相邻段平均值的差的方差
- 改变τ,重复步骤2-4
- 画出log(τ) vs log(Allan方差)的曲线
下面是我用Python写的一个简单实现:
def allan_variance(data, max_tau_ratio=0.1):
"""
计算Allan方差
data: 一维IMU数据
max_tau_ratio: 最大τ占数据长度的比例
"""
n = len(data)
max_tau = int(n * max_tau_ratio)
tau_list = []
avar_list = []
# 用对数间隔生成τ值
tau_values = np.unique(np.logspace(0, np.log10(max_tau), 50).astype(int))
for tau in tau_values:
# 计算每个时间段的平均值
m = n // tau
if m < 2:
break
# 分段平均
data_avg = data[:m*tau].reshape(m, tau).mean(axis=1)
# 计算相邻段差的方差
diff = data_avg[1:] - data_avg[:-1]
avar = 0.5 * np.mean(diff**2)
tau_list.append(tau)
avar_list.append(avar)
return np.array(tau_list), np.array(avar_list)
画出来的Allan方差曲线,不同斜率对应不同噪声类型:
| 斜率 | 噪声类型 | 读取位置 |
|---|---|---|
| -1/2 | 白噪声(角度随机游走) | τ=1处的值 |
| 0 | 零偏不稳定性 | 曲线最低点 |
| +1/2 | 零偏随机游走 | 大τ处的斜率 |
| -1 | 量化噪声 | 小τ处的斜率 |
| +1 | 速率斜坡 | 大τ处的斜率 |
我个人习惯,拿到一个新IMU,第一件事就是跑Allan方差。这就像医生给病人做体检,先看看各项指标是否正常。如果零偏不稳定性特别大,那这个IMU可能不太适合做高精度SLAM。
关键点:Allan方差曲线的最低点对应的τ值,就是IMU的“最佳积分时间”。在这个时间尺度上,IMU的噪声最小。如果你的SLAM系统里,IMU预积分的时间窗口接近这个值,那精度会比较好。
嗯,这里还要提一句。Allan方差分析需要静态数据,但实际应用中IMU是运动的。所以,我们通常用Allan方差来标定IMU的“本征噪声”,然后在SLAM系统里用这些参数来设置信息矩阵的权重。
这张图把整个IMU测量模型和噪声分析的脉络理清楚了。从原始测量出发,经过测量模型分解,再到确定性误差和随机噪声的分别处理,最后汇聚到SLAM系统的应用。你想想看,每一步都有对应的数学工具和工程方法。
实用建议:在实际项目中,我建议把Allan方差分析做成一个自动化脚本。每次标定完IMU,自动生成报告,包括噪声参数、曲线图、以及“IMU健康度”评分。这样团队里每个人都能快速判断IMU的状态。
好了,这一章的内容就到这里。IMU的测量模型和噪声分析,是视觉惯性SLAM的基石。把这块吃透了,后面的预积分、初始化、紧耦合优化,你才能理解为什么代码要那样写,参数要那样设。