Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android compass noise algorithm

Tags:

android

I am trying to filter out the noise from the orientation/compass sensor in my magic phone.

Some of the readings seem to be 90-180 degrees off and there is a lot of jiggle. I have tried different things with limited success, so I was wondering if anyone could recommend an algorithm to filter this sort of noise to get a stable output.

BR, Mads

like image 477
Mads Kristiansen Avatar asked Dec 10 '09 22:12

Mads Kristiansen


4 Answers

You need Low Pass Filter. There are explanation and simple algorithm on wikipedia

like image 129
db_ Avatar answered Nov 15 '22 16:11

db_


This is really late but it might help people like me who came to this question.

Use Type Rotation vector sensor. No need to use a low pass filter or calculate an average value of the last x sensor values.

Here's some code:

private float[] mMatrixR = new float[9];
private float[] mMatrixValues = new float[3];

@Override
public void onSensorChanged(SensorEvent event) {
    switch (event.sensor.getType()) {
        case Sensor.TYPE_ROTATION_VECTOR:

            // Get rotation matrix
            SensorManager.getRotationMatrixFromVector(mMatrixR, event.values);

            SensorManager.getOrientation(mMatrixR, mMatrixValues);

            // Use this value in degrees
            mAzimuth = Math.toDegrees(mMatrixValues[0]);

    }

I found the values very fast and smooth and use these in my app. I used accelerometer and magnetometer as a backup in case rotation type vector isn't present in the device, it's a software based sensor (Sensor fusion) which uses the magnetometer, accelerometer and gyro (if present).

like image 45
Rahul Sainani Avatar answered Nov 15 '22 15:11

Rahul Sainani


I got rid of most of the noise by just using a slower update time. I'm not sure if Android has a built-in filter for these, but it seems to stabalize a lot. Something like:

mSensorManager.registerListener( 
    mSensorListener, 
    mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION), 
    // SENSOR_DELAY_UI, instead of SENDOR_DELAY_FASTEST (or similar)
    //    seems to iron out a lot of the jitter
    SensorManager.SENSOR_DELAY_UI
);

SensorManager offers:

  • SENSOR_DELAY_FASTEST : get sensor data as fast as possible
  • SENSOR_DELAY_GAME : rate suitable for games
  • SENSOR_DELAY_NORMAL : rate (default) suitable for screen orientation changes
  • SENSOR_DELAY_UI : rate suitable for the user interface
like image 26
Jeremy Logan Avatar answered Nov 15 '22 16:11

Jeremy Logan


What have you tried? How many readings do you get per second?

I would suggest something along the lines of an average of the last X number of readings to get rid of the "jiggles" and throw away any readings that are wildly different from the current direction to stop any crazy "jumping" of values. Depending on how many readings you are getting, and how much averaging you are doing, your app may lose responsiveness.

The following link might be useful. http://www.chem.uoa.gr/applets/appletsmooth/appl_smooth2.html

like image 38
Loopo Avatar answered Nov 15 '22 15:11

Loopo