我使用apache commons数学库的kalmanfilter实现来提高我的室内定位框架的准确性。我认为我已经为2D定位正确设置了矩阵,而状态由位置(x,y)和速度(vx,vy)组成。我使用“estimatePosition()”方法中的新传入位置设置状态“x”。过滤器似乎工作:这是我的小JUnit测试的输出,它在带有模拟位置的循环中调用方法estimatePosition()[20,20]:
我想知道为什么初始位置似乎在[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);
}
}
答案 0 :(得分:3)
您的问题的技术答案可能是将x
设置为Kalman()
构造函数中的初始状态。
实际上,当您初始化卡尔曼滤波器时,您并不总是拥有您知道的初始状态。在您自己的情况下,您碰巧知道初始位置是20,20
,但您应该在初始速度估算中加入什么?
一个常见的起点是初始化为0
(或任何合理的平均值)并将初始P
设置为“全开”。我没看到代码中如何初始化P
。您可以将其设置为表示您的初始位置为0,0
且具有非常大的不确定性。这会导致初始测量值对x
进行大的调整,因为P
会在多次测量后收敛到稳态。