package com.nbs.client.assassins.sensors; public class BearingSmoother { //raw sensor data private float[] mAccelData = new float[3]; private float[] mMagnetData = new float[3]; //contains the results of getRotationMatrix private float[] mRotationMaxtrix = new float[16]; private float[] mInclinationMatrix = new float[16]; //contains the results of getOrientation: azimuth, pitch and roll //currently only using azimuth private float[] mOrientation = new float[3]; private final float rad2deg = (float)(180.0f/Math.PI); //provides rotation matrix and orientation methods private Spatial spatial; //a time smoothed bearing private float bearing; /* * time smoothing constant for low-pass filter * 0 ≤ alpha ≤ 1 ; a smaller value basically means more smoothing * See: http://en.wikipedia.org/wiki/Low-pass_filter#Discrete-time_realization */ private static final float ALPHA = 0.10f; public BearingSmoother(Spatial spatial) { this.spatial = spatial; } public float getBearing() { return bearing; } /* * @see http://www.codingforandroid.com/2011/01/using-orientation-sensors-simple.html * @see http://www.netmite.com/android/mydroid/cupcake/development/samples/ * Compass/src/com/example/android/compass/CompassActivity.java */ public void onMagnetometerChanged(float[] values) { mMagnetData = lowPass( values.clone(), mMagnetData ); computeBearing(); } public void onAccelerometerChanged(float[] values) { mAccelData = lowPass( values.clone(), mAccelData ); computeBearing(); } private void computeBearing() { //TODO landscape mode is not working //also, when bearing crosses 0, there seems to be a problem if(spatial.getRotationMatrix(mRotationMaxtrix, mInclinationMatrix, mAccelData, mMagnetData)) { spatial.getOrientation(mRotationMaxtrix, mOrientation); bearing = (mOrientation[0]*rad2deg); } } /** * @see http://en.wikipedia.org/wiki/Low-pass_filter#Algorithmic_implementation * @see http://developer.android.com/reference/android/hardware/SensorEvent.html#values * @see http://blog.thomnichols.org/2012/06/smoothing-sensor-data-part-2 */ private float[] lowPass( float[] newXYZ, float[] oldXYZ ) { if ( oldXYZ == null ) return newXYZ; float[] filtered = new float[newXYZ.length]; for ( int i=0; i<newXYZ.length; i++ ) { filtered[i] = oldXYZ[i] + ALPHA * (newXYZ[i] - oldXYZ[i]); } return filtered; } }