Mark Gilchrist
Mark Gilchrist

Reputation: 2032

Smoothing algorithm that doesn't miss the bell curve

I am writing an android app which measure the Altitude on location change.

I want to see if the user is going up hill or down hill (on a lift or mountain biking). naturally when you are descending you will have small rises and when you are going up hill you can descend slightly.

I have a smoothing algorithm, which takes the average of the previous ten altitude readings and the average of the next ten then compares the two for an increase or decrease.

This roughly has the effect I am looking for apart from it misses the bell curve and there are still some areas where there is a dip in a general rise which I don't want to see.

statistics is not my strong point but is there a better way to smooth this data?

here is my code

qu="SELECT ID,SPEED,ALTITUDE,ISCLIMB from trip_data where tripid="+Tripid+" order by gmttimestamp;";
    c= db.rawQuery(qu, null);
    if(c!=null && c.moveToFirst())
    {
        int av=10;
        for(int i=av;i<c.getCount()-av;i++)
        {

            double prevAlt=0;
            double nxtAlt=0;
            for(int b=0;b<av;b++)
            {
                c.moveToPosition(i-b);
                prevAlt+=c.getDouble(2);
            }
            prevAlt/=av;
            lastAlt=curAlt;
            c.moveToPosition(i);
            int id=c.getInt(0);
            curSpeed=c.getDouble(1);
            curAlt=c.getDouble(2);
            for(int b=1;b<av+1;b++)
            {
                c.moveToPosition(i+b);
                nxtAlt+=c.getDouble(2);
            }
            nxtAlt/=av;
            int isC=0;
            Log.i("corrections", "preivous ="+prevAlt+" and the next is "+nxtAlt);
            db.execSQL("UPDATE TRIP_DATA set PREVALT ="+prevAlt+", NEXTALT="+nxtAlt+", DALT="+(curAlt-lastAlt)+" where id="+id+"");
            if(nxtAlt>prevAlt)
            {
                isC=1;
            }else
            {
                isC=0;
            }

            String ins="UPDATE trip_data set ISCLIMB="+isC+" where ID="+id+";";
            db.execSQL(ins);
            Log.i("corrections", ins);
        }

Upvotes: 1

Views: 154

Answers (1)

GvS
GvS

Reputation: 52518

Take a look at Savitsky-Golay filters. They give a weight to each point.

You can even use them to calculate the smoothed 1st derative directly.

For example to get the derative from point i using a 5 point quadratic filter (all point in an array):

// coefficients for 5 point 1ste derative
// -2, -1, 0, 1, 2
// factor = 10
double derative = (point[x - 2] * -2 + point[x - 1] * -1 + point[x] * 0 + point[x + 1] * 1 + point[x + 2] * 2) / 10;

Upvotes: 2

Related Questions