3. 时域预处理:数据清洗、异常值剔除、缺失值插补、时间戳对齐

各位好,咱们接着聊IMU数据预处理。上一章讲了频域滤波,但说实话,很多噪声问题在时域就能解决大半。我做了这么多年惯导,发现一个规律:时域预处理做得好,后面滤波能省一半力气。今天咱们就聊聊数据清洗、异常值剔除、缺失值插补和时间戳对齐这四个核心环节。

3.1 数据清洗——先把脏数据筛出去

什么叫脏数据?说白了就是那些明显不对劲的采样值。比如加速度计突然跳了个100g,或者陀螺仪在静止时输出漂到了100°/s——这明显是传感器抽风了。

我个人习惯,拿到原始数据第一件事不是滤波,而是先做一次粗筛。怎么筛?很简单:

  • 物理范围检查:加速度计输出不能超过±16g(看量程),陀螺仪不能超过±2000°/s。超出直接标记为无效。
  • 变化率检查:相邻采样点变化不能太离谱。比如1ms内加速度变化超过10g,这基本是跳变噪声。
  • 零值检查:连续出现多个0值?大概率是传感器掉线了。

重要经验:我在项目中遇到过,某次无人机试飞数据里,加速度计Z轴连续出现了3个0值。当时没在意,结果积分后速度直接飞了。后来加了零值检测,这类问题再没出现过。

3.2 异常值剔除——别让一个坏点毁了整段数据

异常值和脏数据不太一样。脏数据是明显超出物理范围的,异常值则是在合理范围内但统计上离群的点。比如静止状态下,加速度计输出应该在1g附近,突然冒出来个1.5g——这就是异常值。

我常用的方法有三种:

方法 原理 适用场景
3σ准则 超出均值±3倍标准差的值视为异常 数据近似正态分布时
中位数绝对偏差 基于中位数的稳健统计量 数据有较多离群点时
滑动窗口法 局部窗口内检测离群点 非平稳信号(如运动数据)

嗯,这里要注意:千万别用全局统计量去检测运动数据中的异常值。你想想看,无人机在做剧烈机动时,加速度变化本来就大,用全局3σ会把正常机动信号当异常剔除掉。

我的建议:对于运动数据,用滑动窗口法。窗口大小取50-100个采样点,窗口内用中位数绝对偏差检测。这样既能剔除真正的异常点,又不会误伤正常信号。

代码实现其实很简单:

def detect_outliers_mad(data, window=50, threshold=3.0):
    """基于滑动窗口的中位数绝对偏差异常检测"""
    outliers = np.zeros_like(data, dtype=bool)
    for i in range(window, len(data) - window):
        segment = data[i - window:i + window]
        median = np.median(segment)
        mad = np.median(np.abs(segment - median))
        if mad == 0:
            continue
        if np.abs(data[i] - median) / mad > threshold:
            outliers[i] = True
    return outliers

3.3 缺失值插补——数据断了怎么办?

IMU数据缺失的原因很多:通信丢包、缓存溢出、传感器掉电。我见过最夸张的一次,某款低成本IMU在高温下会间歇性丢数据,丢得还挺规律——每100个点丢2个。

缺失值处理,我按优先级排序:

  1. 线性插值:最简单,适合短时间缺失(1-5个点)。精度够用。
  2. 样条插值:适合缺失段较长(5-20个点),能保持平滑性。
  3. 前向填充:用上一个有效值填充。适合静止或匀速运动场景。
  4. 模型预测:用ARIMA或卡尔曼预测。适合长段缺失,但计算量大。

避坑指南:我曾经在某个项目中,对缺失的陀螺仪数据用了线性插值。结果插值后的角速度在缺失段出现了明显的"平顶"现象,导致后续姿态解算出现了漂移。后来改用样条插值,问题解决了。

记住:陀螺仪数据对平滑性要求高,尽量用高阶插值

3.4 时间戳对齐——多传感器融合的命门

这个坑我踩过不止一次。IMU、GPS、视觉传感器各自有独立的时钟,采样频率也不一样。如果不做时间戳对齐,融合出来的结果就是一团浆糊。

时间戳对齐的核心思路:

  • 统一时间基准:所有传感器的时间戳都转换到同一个时钟域。我习惯用IMU的时间作为主时钟。
  • 插值对齐:将低频传感器(如GPS,10Hz)的数据插值到IMU的时间轴上(如200Hz)。
  • 延迟补偿:不同传感器有固定的处理延迟,需要测量并补偿。

举个例子,GPS和IMU融合时:

def align_timestamps(imu_time, gps_time, gps_data):
    """将GPS数据插值到IMU时间轴上"""
    from scipy.interpolate import interp1d
    f = interp1d(gps_time, gps_data, kind='linear', 
                 bounds_error=False, fill_value='extrapolate')
    return f(imu_time)

这里有个细节:插值方法的选择要看应用场景。如果是实时系统,用线性插值就够了,计算快。如果是后处理分析,可以用三次样条,精度更高。

我的经验:时间戳对齐最容易被忽视的是延迟补偿。我曾经在车载导航项目中,发现GPS和IMU融合后的位置总有个固定的滞后。后来一查,GPS模块内部有50ms的处理延迟,补偿后效果立竿见影。

3.5 本章知识体系

下面这张图总结了时域预处理的完整流程,大家可以对照着梳理自己的处理流程:

时域预处理流程 原始IMU数据 数据清洗 异常值剔除 缺失值插补 时间戳对齐 关键要点 • 物理范围检查 • 变化率检查 • 零值检查 • 3σ准则 • 中位数绝对偏差 • 滑动窗口法 • 线性/样条插值 • 前向填充 • 模型预测 • 统一时间基准 • 延迟补偿

这张图把整个流程串起来了。从原始数据开始,先做数据清洗,把明显不对的点筛掉;然后做异常值剔除,把统计离群点处理掉;接着处理缺失值,把数据补全;最后做时间戳对齐,为后续的多传感器融合打好基础。

每一步都有对应的技术手段,大家在实际项目中可以根据数据质量灵活选择。比如数据质量好的时候,可以跳过清洗直接做异常检测;数据缺失严重的时候,插补方法要选保守一些的。

最后说一句:时域预处理没有标准答案,关键是要理解你的数据特点。我见过有人把预处理做得特别复杂,结果反而引入了新的误差。记住一个原则:够用就好,别过度处理

专注资料整理