第三节:传感器特性与误差模型
IMU、GPS、磁力计、气压计、里程计——这五个传感器,基本构成了我们做导航融合的“家底”。
说实话,我见过太多人一上来就调卡尔曼滤波参数,结果发现效果不好。为什么?因为根本没搞清楚每个传感器的脾气。你想想看,连传感器的误差特性都没摸透,融合出来的结果能靠谱吗?
3.1 IMU:加速度计与陀螺仪
IMU是导航融合的核心,但也是最“坑”的传感器。我习惯把IMU分成两类:消费级的(比如手机里的)和工业级的(比如用在无人机上的)。
加速度计的主要误差有:
- 零偏(Bias):静止时输出不为0。我遇到过最夸张的一次,某款国产IMU的零偏竟然有0.5g,相当于一直以为自己在加速。
- 比例因子误差:输入和输出不成正比。说白了就是“刻度不准”。
- 交叉轴耦合:X轴受力,Y轴也有输出。这在高精度应用里特别要命。
陀螺仪呢?除了零偏和比例因子,还有个头疼的东西——角度随机游走。这个后面用Allan方差能算出来。
重要提醒:IMU的零偏是随时间变化的。你开机时标定好的零偏,半小时后可能就变了。这就是为什么很多系统需要在线估计零偏。
3.2 GPS:位置与速度观测
GPS的误差模型相对成熟,但陷阱也不少。
GPS误差主要分两类:
- 公共误差:电离层延迟、对流层延迟、卫星钟差。这些可以通过差分GPS(RTK)消除。
- 非公共误差:多路径效应、接收机噪声。这些是随机的,很难建模。
我个人习惯把GPS的观测噪声设成高斯白噪声,但实际中你会发现——GPS的误差不是白噪声。尤其是在城市峡谷里,多路径效应会导致误差出现“拖尾”现象。嗯,这里要注意,如果你用标准卡尔曼滤波,遇到这种情况很容易发散。
小技巧:我建议在GPS信号好的时候,先跑一段Allan方差,看看实际噪声特性。别直接套手册上的参数。
3.3 磁力计:航向参考
磁力计这东西,说简单也简单,说复杂也复杂。简单是因为原理就是测地磁场,复杂是因为——地磁场太弱了,随便一个电机电流就能把它淹没。
磁力计的主要误差:
- 硬铁干扰:传感器附近的永磁体造成的固定偏置。比如扬声器、马达。
- 软铁干扰:铁磁性材料对磁力线的扭曲。这个比硬铁难处理,因为它会改变比例因子。
- 罗差:安装角度偏差导致的误差。
我曾经在一个机器人项目里,磁力计死活不准。折腾了两天,最后发现是底盘上的一个螺丝钉是铁的。你想想看,一颗螺丝钉就能让航向偏了十几度。
警告:磁力计标定不是一劳永逸的。换一个环境(比如从室内到室外),硬铁干扰就可能变化。我建议每次启动时都做一次快速标定。
3.4 气压计:高度参考
气压计用来测高度,原理很简单——气压随高度变化。但实际用起来,坑也不少。
主要问题:
- 温度漂移:气压计对温度敏感。我测过一款传感器,温度变化10度,高度读数能漂移2米。
- 风的影响:无人机在风中飞行时,气压计读数会剧烈抖动。
- 天气变化:同一个高度,晴天和阴天的气压能差几十帕,对应好几米的高度差。
我个人习惯的做法是:只用气压计的相对变化,不用绝对高度。比如,起飞时记录一个基准气压,然后只关心相对变化量。
3.5 里程计:速度与位移
里程计(轮式编码器)在机器人里很常见。它的误差模型相对简单:
- 刻度因子误差:轮子直径不准,或者打滑。
- 量化误差:编码器分辨率有限。
- 非系统误差:地面不平、轮胎磨损等。
我记得有一次做AGV小车,里程计积分出来的位置和实际差了10%。查了半天,发现是轮胎气压不足,导致轮子直径变小了。嗯,这种坑防不胜防。
3.6 Allan方差建模方法
好了,前面说了这么多传感器的误差特性,那怎么定量分析呢?Allan方差就是干这个的。
Allan方差的本质是:把传感器的输出数据,按不同的时间尺度做方差分析。通过观察方差随积分时间的变化曲线,可以识别出不同类型的噪声。
具体步骤:
- 采集一段长时间的静态数据(至少1小时,我建议2小时以上)。
- 把数据按不同的时间窗口长度τ进行分段。
- 计算每个窗口内的平均值,然后求相邻窗口平均值的差。
- 计算这些差值的方差,得到Allan方差σ²(τ)。
- 绘制log(σ) vs log(τ)曲线。
从Allan方差曲线上,你能读出:
- 斜率-1/2:角度随机游走(陀螺)或速度随机游走(加速度计)。
- 斜率0:零偏不稳定性。这是IMU最重要的指标之一。
- 斜率+1/2:速率斜坡(低频漂移)。
- 斜率+1:量化噪声。
下面是一个简单的Allan方差计算代码(Python):
import numpy as np
def allan_variance(data, max_tau):
"""
计算Allan方差
data: 传感器静态数据
max_tau: 最大积分时间
"""
n = len(data)
tau_values = []
avar_values = []
for tau in range(1, min(max_tau, n//2)):
# 计算每个窗口的平均值
m = n // tau
means = np.mean(data[:m*tau].reshape(-1, tau), axis=1)
# 计算相邻窗口的差值
diff = np.diff(means)
# 计算Allan方差
avar = 0.5 * np.mean(diff**2)
tau_values.append(tau)
avar_values.append(avar)
return np.array(tau_values), np.array(avar_values)
# 使用示例
# tau, avar = allan_variance(imu_data, 1000)
# 然后绘制log-log图
关键点:Allan方差曲线的最低点对应的τ值,就是传感器的最佳积分时间。在这个时间尺度上,传感器的噪声最小。这个参数对设计滤波器的时间常数很有参考价值。
3.7 实战建议
说了这么多,总结几条我踩过的坑:
- 别信手册上的参数。每个传感器都有个体差异,一定要自己测。
- Allan方差要跑够时间。我见过有人只采了10分钟数据就跑Allan方差,结果曲线全是噪声,啥也看不出来。
- 温度影响不能忽略。尤其是IMU和气压计,温度变化带来的漂移可能比随机噪声还大。
- 磁力计标定要勤快。每次换环境,最好都重新标定一次。
好了,这一节的内容就到这里。下一节我们会讲怎么把这些误差模型用到卡尔曼滤波里。到时候你会发现——误差模型建得好,滤波器调参少一半。