26

How do I filter noise of the accelerometer data in Android? I would like to create a high-pass filter for my sample data so that I could eliminate low frequency components and focus on the high frequency components. I have read that Kalman filter might be the best candidate for this, but how do I integrate or use this method in my application which will mostly written in Android Java? or can it be done in the first place? or through Android NDK? Is there by any chance that this can be done in real-time?

Any idea will be much appreciated. Thank you!

Faiz
  • 517
  • 2
  • 7
  • 10

5 Answers5

28

The samples from Apple's SDK actually implement the filtering in an even simpler way which is by using ramping:

//ramp-speed - play with this value until satisfied
const float kFilteringFactor = 0.1f;

//last result storage - keep definition outside of this function, eg. in wrapping object
float accel[3]; 

//acceleration.x,.y,.z is the input from the sensor

//result.x,.y,.z is the filtered result

//high-pass filter to eliminate gravity
accel[0] = acceleration.x * kFilteringFactor + accel[0] * (1.0f - kFilteringFactor);
accel[1] = acceleration.y * kFilteringFactor + accel[1] * (1.0f - kFilteringFactor);
accel[2] = acceleration.z * kFilteringFactor + accel[2] * (1.0f - kFilteringFactor);
result.x = acceleration.x - accel[0];
result.y = acceleration.y - accel[1];
result.z = acceleration.z - accel[2];
Pierre-Antoine LaFayette
  • 24,222
  • 8
  • 54
  • 58
Till
  • 27,559
  • 13
  • 88
  • 122
  • 1
    I'm not sure I follow what is happening here... if acceleration.x is constant ( in theory this can happen), than result.x =0; accel[0] looks like the filtered output; not sure what result.x is. – Pandrei Apr 20 '15 at 13:54
14

Here's the code for Android, adapted from the apple adaptive high pass filter example. Just plug this in and implement onFilteredAccelerometerChanged()

private static final boolean ADAPTIVE_ACCEL_FILTER = true;
float lastAccel[] = new float[3];
float accelFilter[] = new float[3];

public void onAccelerometerChanged(float accelX, float accelY, float accelZ) {
    // high pass filter
    float updateFreq = 30; // match this to your update speed
    float cutOffFreq = 0.9f;
    float RC = 1.0f / cutOffFreq;
    float dt = 1.0f / updateFreq;
    float filterConstant = RC / (dt + RC);
    float alpha = filterConstant; 
    float kAccelerometerMinStep = 0.033f;
    float kAccelerometerNoiseAttenuation = 3.0f;

    if(ADAPTIVE_ACCEL_FILTER)
    {
        float d = clamp(Math.abs(norm(accelFilter[0], accelFilter[1], accelFilter[2]) - norm(accelX, accelY, accelZ)) / kAccelerometerMinStep - 1.0f, 0.0f, 1.0f);
        alpha = d * filterConstant / kAccelerometerNoiseAttenuation + (1.0f - d) * filterConstant;
    }

    accelFilter[0] = (float) (alpha * (accelFilter[0] + accelX - lastAccel[0]));
    accelFilter[1] = (float) (alpha * (accelFilter[1] + accelY - lastAccel[1]));
    accelFilter[2] = (float) (alpha * (accelFilter[2] + accelZ - lastAccel[2]));

    lastAccel[0] = accelX;
    lastAccel[1] = accelY;
    lastAccel[2] = accelZ;
    onFilteredAccelerometerChanged(accelFilter[0], accelFilter[1], accelFilter[2]);
}
rbgrn
  • 304
  • 2
  • 6
  • 4
    What should norm() and clamp() do? – Matthew Runo Dec 02 '11 at 05:37
  • I would say 'norm' reffers to computing the norm of the given vector (sqrt([0]^2+[1]^2´[2]^2)) and clamp is a limiting function with an upper and lower boundary (in this case, the first arg is limited between 0.0f and 1.0f). Also, thanks alot for the adaptive example, I think I am going some form of it. – ravemir Feb 15 '13 at 11:24
  • How do I determine the value of those vars? (RC, dt, cutOffFreq, and so on..) – keinabel Jan 06 '17 at 00:02
3

For those wondering what norm() and clamp() methods do in the answer from rbgrn, you can see them here: http://developer.apple.com/library/IOS/samplecode/AccelerometerGraph/Listings/AccelerometerGraph_AccelerometerFilter_m.html

double norm(double x, double y, double z)
{
    return Math.sqrt(x * x + y * y + z * z);
}

double clamp(double v, double min, double max)
{
    if(v > max)
        return max;
    else if(v < min)
        return min;
    else
        return v;
}
Shumoapp
  • 1,489
  • 16
  • 15
1

I seem to remember this being done in Apple's sample code for the iPhone. Let's see...

Look for AccelerometerFilter.h / .m on Google (or grab Apple's AccelerometerGraph sample) and this link: http://en.wikipedia.org/wiki/High-pass_filter (that's what Apple's code is based on).

There is some pseudo-code in the Wiki, too. But the math is fairly simple to translate to code.

inked
  • 624
  • 4
  • 3
0

IMO, designing a Kalman filter as your first attempt is over-complicating what's probably a fairly simple problem. I'd start with a simple FIR filter, and only try something more complex when/if you've tested that and found with reasonable certainty that it can't provide what you want. My guess, however, is that it will be able to do everything you need, and do it much more easily and efficiently.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • I'm currently exploring different filtering mechanisms. What are the advantages of FIR filter in comparison with the above accepted answer? – Nazerke Mar 27 '13 at 19:54
  • @Nazerke: It looks like the accepted answer *is* a (really simple) FIR filter. More poles in the filter will give you more control over the rate at which the filter rolls off, and especially the ability to have a faster roll off (if you want it). – Jerry Coffin Mar 27 '13 at 20:21
  • @JerryCoffin The accepted answer is a simple IIR, and is also a very simple KF. – Neil Townsend Jan 08 '15 at 13:27