Я использую MATH. NET реализацию фильтра Калмана
Мой пример похож на пример, описанный в этом очень полезном руководстве :
Представьте грузовик, движущийся по прямым рельсам без трения. Первоначально грузовик неподвижен в позиции 0, но на него в разных направлениях действуют случайные неконтролируемые силы. Мы измеряем положение грузовика каждые Δt секунд, но эти измерения неточны; мы хотим сохранить модель положения и скорости грузовика.
Положение и скорость грузовика описываются линейным пространством состояний
where x' is the velocity,
that is, the derivative of position with respect to time.
Math details can be found by the mentioned link.
Finally, I have this very simple .NET implementation with 2 filter parameters (_measurementCovariance and _plantNoiseVar):
//set up filter
var xState = Matrix.Build.Dense(2, 1, new[] { x0, v0 });
var measurementCovarianceMatrix = Matrix.Build.Dense(2, 2,
new[] { _measurementCovariance, _measurementCovariance / dt,
_measurementCovariance / dt, 2 * _measurementCovariance / (dt * dt) });
_dkf = new DiscreteKalmanFilter(xState, measurementCovarianceMatrix);
_stateTransitionMatrixF = Matrix.Build.Dense(2, 2, new[] { 1d, 0d, dt, 1 });
_plantNoiseMatrixG = Matrix.Build.Dense(2, 1, new[] { (dt * dt) / 2, dt});
_plantNoiseVarianceQ = (_plantNoiseMatrixG.Transpose() * _plantNoiseMatrixG) * _plantNoiseVar;
_measurementVarianceMatrixR = Matrix.Build.Dense(1, 1, new[] { _measurementCovariance });
_measurementMatrixH = Matrix.Build.Dense(1, 2, new[] { 1d, 0d });
//update function
private void Update(double newPosition, double dt)
{
var z = Matrix.Build.Dense(1, 1, new[] { newPosition });
_stateTransitionMatrixF[0, 1] = dt;
_plantNoiseMatrixG[0, 0] = (dt* dt) / 2;
_plantNoiseMatrixG[1, 0] = dt;
_dkf.Predict(_stateTransitionMatrixF, _plantNoiseMatrixG, _plantNoiseVarianceQ);
_dkf.Update(z, _measurementMatrixH, _measurementVarianceMatrixR);
}
Then I tested this implementation for real data I have:
For each X position I invoked Update function and stored Kalman Velocity prediction via:
kalmanPosition = _dkf.State[0, 0];
kalmanVelocity = _dkf.State[1, 0];
kalmanSpeedInstant = (kalmanPosition - _prevPosition) / dt;
_prevPosition = kalmanPosition;
Here is a plot with results:
введите описание изображения здесь
Чего я не могу понять, почему для моего примера так мала калмановская скорость. Может ли кто-нибудь помочь мне с этим примером.
- Правильно ли я интерпретирую результаты?
- Это _dkf.State [1, 0] скорость или я ошибаюсь?
- Были ли ошибки в моих предположениях?
- Как я могу получить более точную скорость?
I использовал параметры:
_measurementCovariance = 1.5 и _plantNoiseVar = 3.0.
Данные, которые я использовал: