在Android上实现JKalman

8
有许多关于如何去除加速度计数据、其他传感器数据、计算时空状态以及在Android和其他设备上使用Kalman过滤器的问题。
显然,最简单的方法是为稳定移动设备(例如汽车)在Android上实现JKalman过滤器。
但是,在查看JKalman代码包中的示例实现时,它并没有提供很多信息,而且实际上与其他Kalman实现非常不同。他们像这样实例化一个Kalman类:
JKalman kalman = new JKalman(4, 2);

根据定义,

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

dynam_params 是“测量向量维度的数量”,measure_params 是“状态向量维度的数量”。

在Android中,传感器数据应该如何映射到这些参数?

下面是来自加速度计的数据,每500ms采样一次。在其他监听器中,还有来自陀螺仪和指南针的数据。我应该如何将这些数据转换为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
        }
    }

“Kalman滤波器和内部状态变量的质量”(https://dev59.com/imDVa4cB1Zd3GeqPb0mj)表明他们已经实现了JKalman,使他们比我更聪明。 - duru
而且Ali在每个与传感器或卡尔曼相关的问题下都有一个答案或一条评论。因此,我将他的个人资料作为这个主题的参考。 - duru
我很荣幸 :) 你想要实现什么?你想要跟踪方向还是位置?据我所知,Android已经有类似卡尔曼滤波器的东西了,为什么你要自己实现呢? - Ali
嗨,阿里 :) 我想要跟踪位置。你是指“融合”传感器,就像这里所说的吗?它们本身并不能做到,因为你无论如何都需要对下一步进行累积近似。 - duru
你在Android上实现了卡尔曼滤波吗?我已经实现了...但是我无法正确初始化加速度计和陀螺仪的过程噪声方差...你能帮我吗? - jion
显示剩余2条评论
3个回答

1
这是我使用两个变量(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;
    }

}

但我不知道如何设置第一个点,我总是从(0,0)开始并取50个样本来到达该点,使用循环并不十分优雅。


1

看起来你需要一个3D JKalman滤波器。你可以尝试这个:

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));

请按照KalmanTest.java中的示例进行操作,并检查是否存在错误。

非常感谢。我还没有找到实现代码的机会。一旦我尝试了,我会回复你的。 - duru
哈哈哈哈。不行。:( - duru

0

1
谢谢Ali :) 我之前也看过那个问题以及其他相关的内容。但在没有实际体验之前,我不想做出决定。现在我需要实现卡尔曼滤波器。 - duru
关于陀螺仪。当它们如此嘈杂且您拥有三轴加速度计时,为什么您需要陀螺仪呢?加速度计可以提供三个轴上的加速度向量,因此您可以估计自己的前进方向,甚至可以计算出您的位置。 - duru
你说Android已经有类似卡尔曼滤波器的东西了,对此有什么线索吗? - duru
我真的很想帮忙,但现在我必须要求您仔细观看/阅读链接的材料,特别是视频和链接的UCAM-CL-TR-696.pdf文件,第6.2.3小节。如果您这样做,您将理解为什么需要陀螺仪。您还将了解为什么不能进行通用位置跟踪。如果您观看视频,您将知道在实现卡尔曼滤波器(或类似方法)的Android平台上要寻找什么。 - Ali
我看到你在SO上尽力帮助别人,我真的很感激。再次感谢你 :) 我已经看了几遍文件(虽然没有真正看),David Sachs建议在27:13使用卡尔曼滤波器对模型动态进行建模比使用高通滤波器更好,两者都可以以自己的方式纠正漂移(如果你在行走,则有pedofilter)。在你提到的论文中,他们说漂移的来源是双重积分。由于我找不到实现JKalman的方法,所以我正在尝试通过x = 1/2 at^2 (...>)计算距离。 - duru
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接