Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing JKalman on Android

There are lots of questions about removing the noise from accelerometer data, other sensor's data, calculating spatio-temporal state, and using a Kalman filter in Android and in other devices.

Apparently, the easiest way of doing this is implementing the JKalman filter on Android for stable moving devices for example for cars.

But looking at the sample implementation in JKalman code package, it doesn't say much and it is actually very different from other Kalman implementations.

They instantiate a Kalman class like this:

JKalman kalman = new JKalman(4, 2);

Where according to the definition

public JKalman(int dynam_params, int measure_params) throws Exception {
    this(dynam_params, measure_params, 0);
}

dynam_params is "the number of measurement vector dimensions" and measure_params is "the number of state vector dimensions".

How should the sensor data read in Android be mapped to these?

Below is the data from accelerometer to be seen, that is sampled every 500ms. In other listeners there are data from gyroscope and compass. How should I transform this data to input to Kalman?

    @Override
    public void onSensorChanged(SensorEvent event) {
        actualTime = System.currentTimeMillis();
        if(actualTime - lastUpdateAcc < 500)
            return;
        else{
            lastUpdateAcc = actualTime;
            //update myPosition
            TextView tv = (TextView)findViewById(R.id.textView3);
            tv.setText(String.format("X: %8.4f -- Y: %8.4f -- Z: %8.4f",
                    event.values[0], event.values[1], event.values[2]));
            //draw on the screen

            //draw new path, if one exists
        }
    }
like image 537
duru Avatar asked Aug 06 '12 03:08

duru


2 Answers

It seems you need 3D JKalman filter. You may try this:

JKalman kalman = new JKalman(6, 3);

Matrix s = new Matrix(6, 1); // state [x, y, z, dx, dy, dz]        
Matrix c = new Matrix(6, 1); // corrected state
Matrix m = new Matrix(3, 1); // measurement [x, y, z]

// the initial values follow (sorry for programming in stackoverflow):
m.set(0, 0, x);
m.set(1, 0, y);
m.set(2, 0, z);

// transitions for x, y, z, dx, dy, dz (velocity transitions)
double[][] tr = { {1, 0, 0, 1, 0, 0}, 
                  {0, 1, 0, 0, 1, 0}, 
                  {0, 0, 1, 0, 0, 1}, 
                  {0, 0, 0, 1, 0, 0}, 
                  {0, 0, 0, 0, 1, 0}, 
                  {0, 0, 0, 0, 0, 1} };
kalman.setTransition_matrix(new Matrix(tr));

Follow then the example in KalmanTest.java and check this for errors, please.

like image 163
P3k Avatar answered Sep 30 '22 00:09

P3k


this is how I do it with 2 variables (GPS:LAT, LON):

import jkalman.JKalman;
import jama.Matrix;

public class KalmanFilter {
    private int variables;
    private JKalman kalman;
    private Matrix s; // state [x, y, dx, dy, dxy]
    private Matrix c; // corrected state [x, y, dx, dy, dxy]
    private Matrix m; // measurement [x]

    /*
     * Inicializa el filtro kalman con 2 variables
     */
    public void initialize2() throws Exception{
        double dx, dy;

        if(variables != 0){
             throw new RuntimeException();
        }
        variables = 2;
        kalman = new JKalman(4, 2);

        // constant velocity
        dx = 0.2;
        dy = 0.2;

        s = new Matrix(4, 1); // state [x, y, dx, dy, dxy]        
        c = new Matrix(4, 1); // corrected state [x, y, dx, dy, dxy]                

        m = new Matrix(2, 1); // measurement [x]
        m.set(0, 0, 0);
        m.set(1, 0, 0);

        // transitions for x, y, dx, dy
        double[][] tr = { {1, 0, dx, 0}, 
                          {0, 1, 0, dy}, 
                          {0, 0, 1, 0}, 
                          {0, 0, 0, 1} };
        kalman.setTransition_matrix(new Matrix(tr));

        // 1s somewhere?
        kalman.setError_cov_post(kalman.getError_cov_post().identity());

    }

    /*
     * Aplica Filtro a variables
     */
    public void push(double x,double y) throws Exception{
         m.set(0, 0, x);
         m.set(1, 0, y);

         c = kalman.Correct(m);
         s = kalman.Predict();
    }

    /*
     * obtiene arreglo con datos filtrados.
     */
    public double[] getKalmanPoint2() throws Exception{
        double[] point = new double[2];
        point[0] = c.get(0,0);
        point[1] = c.get(1,0);
        return point;
    }

    /*
     * obtiene arreglo con prediccion de punto.
     */
    public double[] getPredict2() throws Exception{
        double[] point = new double[2];
        point[0] = s.get(0,0);
        point[1] = s.get(1,0);
        return point;
    }

    /*
     * obtiene cantidad de variables del objeto
     */
    public int getNVariables() throws Exception{
        return this.variables;
    }

}

But I don't know how to set the first point, I always start from (0,0) and take 50 samples to reach the point, with a loop is not very elegant.

like image 31
Leo Avatar answered Sep 29 '22 23:09

Leo