指定Apache Commons卡尔曼滤波器2D定位预测的起始位置

时间:2016-01-17 09:01:39

标签: java android kalman-filter indoor-positioning-system apache-commons-math

我使用apache commons数学库的kalmanfilter实现来提高我的室内定位框架的准确性。我认为我已经为2D定位正确设置了矩阵,而状态由位置(x,y)和速度(vx,vy)组成。我使用“estimatePosition()”方法中的新传入位置设置状态“x”。过滤器似乎工作:这是我的小JUnit测试的输出,它在带有模拟位置的循环中调用方法estimatePosition()[20,20]:

  • 第一次递归:位置:{20; 20} 估计:{0,0054987503; 0,0054987503}
  • ...
  • 第100次递归:位置:{20; 20} 估计:{20,054973733; 20,054973733}

我想知道为什么初始位置似乎在[0,0]。我在哪里设置[20,20]的初始位置?

public class Kalman {

    //A - state transition matrix
    private RealMatrix A;
    //B - control input matrix
    private RealMatrix B;
    //H - measurement matrix
    private RealMatrix H;
    //Q - process noise covariance matrix (error in the process)
    private RealMatrix Q;
    //R - measurement noise covariance matrix (error in the measurement)
    private RealMatrix R;
    //x state
    private RealVector x;

    // discrete time interval (100ms) between to steps
    private final double dt = 0.1d;
    // position measurement noise (1 meter)
    private final double measurementNoise = 1d;

    // constant control input, increase velocity by 0.1 m/s per cycle
    private RealVector u = new ArrayRealVector(new double[] { 0.1d });
    //private RealVector u = new ArrayRealVector(new double[] { 10d });
    private KalmanFilter filter;

    public Kalman(){
        //A and B describe the physic model of the user moving specified as matrices
        A = new Array2DRowRealMatrix(new double[][] {
                                                        { 1d, 0d, dt, 0d },
                                                        { 0d, 1d, 0d, dt },
                                                        { 0d, 0d, 1d, 0d },
                                                        { 0d, 0d, 0d, 1d }
                                                    });
        B = new Array2DRowRealMatrix(new double[][] {
                                                        { Math.pow(dt, 2d) / 2d },
                                                        { Math.pow(dt, 2d) / 2d },
                                                        { dt},
                                                        { dt }
                                                    });
        //only observe first 2 values - the position coordinates
        H = new Array2DRowRealMatrix(new double[][] {
                                                        { 1d, 0d, 0d, 0d },
                                                        { 0d, 1d, 0d, 0d },
                                                    });
        Q = new Array2DRowRealMatrix(new double[][] {
                                                        { Math.pow(dt, 4d)/4d, 0d, Math.pow(dt, 3d)/2d, 0d },
                                                        { 0d, Math.pow(dt, 4d)/4d, 0d, Math.pow(dt, 3d)/2d },
                                                        { Math.pow(dt, 3d)/2d, 0d, Math.pow(dt, 2d), 0d },
                                                        { 0d, Math.pow(dt, 3d)/2d, 0d, Math.pow(dt, 2d) }
                                                    });

        R = new Array2DRowRealMatrix(new double[][] {
                { Math.pow(measurementNoise, 2d), 0d },
                { 0d, Math.pow(measurementNoise, 2d) }
        });

        ProcessModel pm = new DefaultProcessModel(A, B, Q, x, null);
        MeasurementModel mm = new DefaultMeasurementModel(H, R);
        filter = new KalmanFilter(pm, mm);
    }


    /**
     * Use Kalmanfilter to decrease measurement errors
     * @param position
     * @return
     */
    public Position<Euclidean2D> esimatePosition(Position<Euclidean2D> position){

        double[] pos = position.toArray();
        // x = [ 0 0 0 0] state consists of position and velocity[pX, pY, vX, vY]
        x = new ArrayRealVector(new double[] { pos[0], pos[1], 0, 0 });

        // predict the state estimate one time-step ahead
        filter.predict(u);

        // x = A * x + B * u (state prediction)
        x = A.operate(x).add(B.operate(u));

        // z = H * x  (measurement prediction)
        RealVector z = H.operate(x);

        // correct the state estimate with the latest measurement
        filter.correct(z);

        //get the corrected state - the position
        double pX = filter.getStateEstimation()[0];
        double pY = filter.getStateEstimation()[1];

        return new Position2D(pX, pY);
    }
}

1 个答案:

答案 0 :(得分:3)

您的问题的技术答案可能是将x设置为Kalman()构造函数中的初始状态。

实际上,当您初始化卡尔曼滤波器时,您并不总是拥有您知道的初始状态。在您自己的情况下,您碰巧知道初始位置是20,20,但您应该在初始速度估算中加入什么?

一个常见的起点是初始化为0(或任何合理的平均值)并将初始P设置为“全开”。我没看到代码中如何初始化P。您可以将其设置为表示您的初始位置为0,0且具有非常大的不确定性。这会导致初始测量值对x进行大的调整,因为P会在多次测量后收敛到稳态。