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

  • 第一次递归:位置:{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);
        }
    }
    

    最佳答案

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

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

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

    10-07 19:35
    查看更多