9、数据滤波基础:为什么需要滤波,简单的低频滤波实现
各位同学,欢迎来到第九章。
前面几章我们讲了怎么读陀螺仪的数据,怎么把原始数据转换成角度。但不知道你有没有发现——你拿到的数据,其实并不干净。
嗯,这里我要先泼一盆冷水:传感器数据天生就是脏的。
9.1 为什么需要滤波?
先说说我自己的经历。几年前我做了一个手机姿态跟踪的小项目,陀螺仪数据直接拿来用,结果呢?手机明明放在桌上不动,屏幕上那个小飞机却在疯狂抖动。我当时差点以为是传感器坏了。
后来一查,不是硬件问题。是噪声。
陀螺仪的噪声来源主要有这几个:
- 电子热噪声——芯片内部电子热运动产生的随机波动
- 量化噪声——ADC把模拟信号转成数字时,精度有限
- 机械振动——你手拿手机时,肌肉微颤也会被捕捉到
- 电源纹波——供电不稳定,数据就会跳
说白了,你读到的每一个数值,都是「真实信号 + 噪声」的混合体。如果不做处理,你的应用就会跟着噪声一起抽风。
核心结论:滤波的目的不是消除噪声——那做不到。滤波的目的是抑制噪声,保留有用信号。
9.2 滤波的分类,简单了解一下
滤波方法很多,但入门阶段你只需要知道两大类:
| 类型 | 特点 | 适用场景 |
|---|---|---|
| 低通滤波 | 允许低频信号通过,抑制高频噪声 | 陀螺仪、加速度计数据平滑 |
| 高通滤波 | 允许高频信号通过,抑制低频漂移 | 去除重力分量、检测快速动作 |
| 带通滤波 | 只保留某个频率范围的信号 | 特定频率检测(如步频) |
| 卡尔曼滤波 | 融合多传感器,最优估计 | 姿态解算、导航定位 |
对于陀螺仪入门,低通滤波是你第一个要掌握的。为什么?因为陀螺仪的噪声主要在高频段,而你要的姿态变化是低频的。一刀切下去,噪声就没了大半。
9.3 最简单的低通滤波——一阶RC低通滤波
你可能会想:滤波是不是要学一堆傅里叶变换、拉普拉斯变换?
别怕。最简单的低通滤波,只需要一行代码。
它的数学原理其实就是一个加权平均:
output = alpha * input + (1 - alpha) * last_output
其中 alpha 是一个0到1之间的系数,决定了滤波的强弱。
alpha越大,滤波越弱,响应越快,但噪声也多alpha越小,滤波越强,数据越平滑,但响应变慢
我个人的习惯是:alpha 取 0.1 ~ 0.3 之间。这个范围对大多数陀螺仪应用都够用。
9.4 Android 代码实现
下面是一个完整的低通滤波实现。你直接复制就能用:
public class LowPassFilter {
private float lastValue = 0f;
private boolean isFirst = true;
/**
* 对陀螺仪数据进行低通滤波
* @param input 当前原始数据
* @param alpha 滤波系数,推荐 0.1 ~ 0.3
* @return 滤波后的数据
*/
public float filter(float input, float alpha) {
if (isFirst) {
lastValue = input;
isFirst = false;
return input;
}
lastValue = alpha * input + (1 - alpha) * lastValue;
return lastValue;
}
// 重置滤波器(比如传感器断开重连时)
public void reset() {
isFirst = true;
lastValue = 0f;
}
}
用法也很简单:
LowPassFilter filterX = new LowPassFilter();
LowPassFilter filterY = new LowPassFilter();
LowPassFilter filterZ = new LowPassFilter();
// 在 onSensorChanged 里
float filteredX = filterX.filter(rawX, 0.2f);
float filteredY = filterY.filter(rawY, 0.2f);
float filteredZ = filterZ.filter(rawZ, 0.2f);
小技巧:三个轴最好各自用一个滤波器实例。不要共用一个,否则数据会串。
9.5 滤波效果对比
我曾经在调试时做过一个对比测试。手机静止放在桌上,分别采集原始数据和滤波后的数据:
| 指标 | 原始数据 | 滤波后 (alpha=0.2) |
|---|---|---|
| 均值 | 0.02 rad/s | 0.01 rad/s |
| 标准差 | 0.15 rad/s | 0.04 rad/s |
| 最大跳变 | 0.45 rad/s | 0.12 rad/s |
看到没?标准差从0.15降到了0.04,噪声抑制了将近4倍。而均值几乎没有变化——说明有用信号被保留下来了。
9.6 避坑指南
我曾经踩过的一个坑:alpha值设得太小(比如0.01),结果数据是平滑了,但手机转了个90度,滤波后的角度要等两三秒才跟上来。这种延迟在交互式应用里是完全不能接受的。
所以记住:滤波不是越强越好。你要在「平滑」和「响应速度」之间找平衡。
另外还有几点要注意:
- 滤波器要重置——传感器断开重连时,记得调用
reset(),否则初始值会污染新数据 - 不要对角度做滤波——如果你已经把角速度积分成了角度,再去滤波,会引入额外的相位延迟。滤波应该在原始数据上做
- alpha值可以动态调整——检测到剧烈运动时增大alpha,静止时减小alpha。这个技巧叫「自适应滤波」,后面章节会讲
9.7 本章知识结构图
下面这张图帮你理清本章的核心逻辑:
9.8 小结
这一章我们聊了:
- 为什么陀螺仪数据需要滤波——噪声无处不在
- 滤波的分类——低通滤波是入门首选
- 一阶RC低通滤波的原理——就是一个加权平均
- Android代码实现——三行核心代码搞定
- 避坑指南——alpha值别设太小,滤波器要重置
说实话,低通滤波看起来简单,但它是所有高级滤波算法的基础。你把这个搞明白了,后面学卡尔曼滤波、互补滤波都会轻松很多。
下一章我们会聊一个更实际的问题:如何用陀螺仪数据计算设备的姿态角。到时候你会看到,滤波只是第一步,真正的挑战还在后面。
公众号:蓝海资料掘金营,微信deep3321