为 Apache Commons 卡尔曼滤波器 2D 定位估计指定起始位置
Specify Start Position for Apache Commons Kalman Filter 2D Positioning Estmation
我使用 apache 公共数学库的 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);
}
}
您问题的技术答案可能是在您的 Kalman()
构造函数中将 x
设置为初始状态。
实际上,当你初始化卡尔曼滤波器时,你不会总是有一个你知道的初始状态。在你自己的例子中,你碰巧知道初始位置是 20,20
,但是你应该在你的初始速度估计中输入什么?
一个常见的起点是初始化为 0
(或任何合理的平均值)并将初始 P
设置为 "wide open"。我没有看到 P
在您的代码中是如何初始化的。你会设置它说你的初始位置是 0,0
具有很大的不确定性。这将导致初始测量对 x
进行较大调整,因为 P
在多次测量后收敛到稳定状态。
我使用 apache 公共数学库的 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);
}
}
您问题的技术答案可能是在您的 Kalman()
构造函数中将 x
设置为初始状态。
实际上,当你初始化卡尔曼滤波器时,你不会总是有一个你知道的初始状态。在你自己的例子中,你碰巧知道初始位置是 20,20
,但是你应该在你的初始速度估计中输入什么?
一个常见的起点是初始化为 0
(或任何合理的平均值)并将初始 P
设置为 "wide open"。我没有看到 P
在您的代码中是如何初始化的。你会设置它说你的初始位置是 0,0
具有很大的不确定性。这将导致初始测量对 x
进行较大调整,因为 P
在多次测量后收敛到稳定状态。