Thom Nichols


Technology is evolution outside the gene pool

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
 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.

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!

Category: Android Java geo