Smoothing Sensor Data, Part 2
After a query from an older blog entry, I figured I should properly follow-up since there were a couple questions about how to use the low-pass filter I described to smooth sensor data from Android.
So the question was "shouldn't the algorithm be output[i] = output[i-1] + ALPHA * (input[i] - output[i]);" Well, the answer is no, here's why:
So the wikipedia entry I referenced uses y[i-1] to represent the prior value in time. In my case, the index values of output represent 3 different dimensions (x,y,z) not sequential values in time. Maybe it's a little confusing, but to call to lowPass looks like this:
public void onSensorChanged(SensorEvent event) {
// thank you http://www.codingforandroid.com/2011/01/using-orientation-sensors-simple.html
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
accelVals = lowPass( event.values.clone(), accelVals );
if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
compassVals = lowPass( event.values.clone(), compassVals );
if (accelVals != null && compassVals != null) {
float R[] = new float[9];
float I[] = new float[9];
boolean success = SensorManager.getRotationMatrix(R, I, accelVals, compassVals);
if (success) {
float orientation[] = new float[3];
SensorManager.getOrientation(R, orientation);
// at this point, orientation contains the azimuth, pitch and roll values.
this.compassView.updateBearing(orientation[0]);
}
}
}
So two things to note here: First, event.values is an array of sensor values for different axes (see the Android docs.)
Second, accelVals and compassVals are instance variables that hold the
last set of smoothed values. I suppose the arguments to lowPass should
have been named newVals and oldVals - that would have made more
sense then.
Since it's apparent I didn't give enough detail in my original post, hopefully this will clear up any confusion!
0 Comments