如何在加速度计事故检测代码中应用低通滤波器并存储滤波后数据
整合低通滤波器到加速度计事故检测回调
Hey,我来帮你把低通滤波器完美整合到你的加速度计事故检测逻辑里。首先得搞明白,低通滤波需要保留上一次的输出结果才能发挥平滑效果,所以咱们得先在类里加个成员变量存滤波后的历史值,不然每次用新数组的话,滤波就白做啦。
第一步:准备滤波所需的成员变量与方法
先把低通滤波器的代码放到你的类中,同时添加一个成员变量来存储上一次滤波后的加速度值(初始化可以用全0,第一次传感器读数进来后会自动更新):
// 低通滤波系数,0.05的取值可以根据实际需求调整:值越小平滑效果越强,响应速度越慢 private static final float alpha = 0.05f; // 存储上一次滤波后的加速度值,保证滤波的连续性 private float[] mFilteredAccel = new float[3]; public float[] lowPass(float[] output, float[] input) { output[0] = output[0] + alpha * (input[0] - output[0]); output[1] = output[1] + alpha * (input[1] - output[1]); output[2] = output[2] + alpha * (input[2] - output[2]); return output; }
第二步:修改传感器回调逻辑,加入滤波处理
接下来修改onSensorChanged方法,在更新mLastX、mLastY、mLastZ之前,先对原始传感器读数做滤波处理,再把滤波后的值存入这三个变量里。另外这里有个细节:计算抖动速度的时候,你可以选择用原始读数还是滤波后的数据——用滤波后的数据能减少传感器噪声导致的误触发,我这里默认改成用滤波后的值,你也可以根据需求调整:
public void onSensorChanged(int sensor, float[] values) { if (sensor != SensorManager.SENSOR_ACCELEROMETER) return; // 对原始加速度值进行低通滤波,更新滤波后的结果 mFilteredAccel = lowPass(mFilteredAccel, values); long now = System.currentTimeMillis(); if ((now - mLastForce) > SHAKE_TIMEOUT) { mShakeCount = 0; } if ((now - mLastTime) > TIME_THRESHOLD) { long diff = now - mLastTime; // 用滤波后的加速度值计算抖动速度,减少噪声干扰 float speed = Math.abs(mFilteredAccel[0] + mFilteredAccel[1] + mFilteredAccel[2] - mLastX - mLastY - mLastZ) / diff * 10000; if (speed > FORCE_THRESHOLD) { if ((++mShakeCount >= SHAKE_COUNT) && (now - mLastShake > SHAKE_DURATION)) { mLastShake = now; mShakeCount = 0; if (mShakeListener != null) { mShakeListener.onShake(); } } mLastForce = now; } mLastTime = now; // 将滤波后的数值存入mLastX/Y/Z,供下一次计算速度使用 mLastX = mFilteredAccel[0]; mLastY = mFilteredAccel[1]; mLastZ = mFilteredAccel[2]; } }
小提示
如果你的需求只是让mLastX/Y/Z存储滤波后的值,而速度计算仍然想用原始传感器数据,只需要把速度计算那行改回原来的写法即可:
float speed = Math.abs(values[SensorManager.DATA_X] + values[SensorManager.DATA_Y] + values[SensorManager.DATA_Z] - mLastX - mLastY - mLastZ) / diff * 10000;
内容的提问来源于stack exchange,提问作者Daniel Kalalian
相关产品推荐
相关产品推荐

