前面说到,安卓的加速度可以用Sensor.TYPE_ACCELEROMETER获取。
但是由于重力的影响,得到的数据都是加上了重力加速度在三个轴的分量。即在平放在水平桌面上,静止情况下加速度计的数据应该为9.8m2/sm^{2}/sm2/s.等于当地的重力加速度。
如何求得重力加速度?
安卓中可以使用Sensor.TYPE_GRAVITY来获取。其实这个重力也是通过加速度计计算得来的。
重力属于低频成分,所以可以使用一个低通滤波器来过滤出重力。在安卓中,实现了一个最简单的一阶低通滤波器,本质上是一个加权平均窗口:
public void onSensorChanged(SensorEvent event) { // alpha 由 t / (t + dT)得到 // t为滤波器时间常量,为传感器单次采样时间 // dT为采样频率 final float alpha = 0.8; //低通,分离出重力gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0]; gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1]; gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2]; //消除重力影响linear_acceleration[0] = event.values[0] - gravity[0]; linear_acceleration[1] = event.values[1] - gravity[1]; linear_acceleration[2] = event.values[2] - gravity[2]; }
event.values
为当前加速度的值。
gravity
为分离出的重力,减去重力的影响可以得到线性加速度linear_acceleration
在安卓中可以利用Sensor.TYPE_LINEAR_ACCELERATION
来直接得到。
把代码抽象一下,这个滤波的算法公式为
Y(n)=αY(n-1)+(1-α)X(n)
其中α=滤波系数。一阶低通滤波法采用本次采样值与上次滤波输出值进行加权,使得输出对输入有反馈作用。可以看到,α对滤波结果有很大影响。但α偏大,对当前值比较看重,系统灵敏度高,滤波效果不稳定,α偏小,对当前值抑制,系统滤波效果稳定,但对起伏变化不太敏感。
移动平均滤波器的频响曲线可以参考这里.