Фильтр Калмана, Не могу настроить степень фильтрации. библиотека MathNet.Filtering.Kalman

Здравствуйте для Indoor navigation понадобился фильтр Калмана, стал разбираться с наиболее простой одномерной реализацией, которая должна фильтровать double значения. Требования к библиотеки - netstandard2.1, поэтому не так много "новых" либ реализующих разные версии фильтра Калмана я нашел. Использую библиотеку MathNet.Filtering.Kalman. https://github.com/mathnet/mathnet-filtering/blob/master/src/Kalman.Tests/KalmanFilterTest.cs

Написал у себя аналогичный тест - TestDiscreteKalmanFilter() Начал разбираться с настройками, вот как я понял:

// Test constants
double r = 30.0;  //Measurement covariance (Ковариация измерения)
double T = 20.0;  //Time interval between measurements  (интервал между измерениями)
double q =0.1;    //Plant noise constant (Постоянная шума)


Почему r= 30?
T = 20.0? в чем измерять это T, если это временной промежуток между измерениями.
q =0.1? я так понял Чем больше Q тем сильнее мы доверяем входным данным (Update)


// Initial estimate based on two point differencing  (Первоначальная оценка на основе разности 2-ух точек)
double z0 = zs[0];
double z1 = zs[1];
Matrix<double> x0 = Matrix<double>.Build.Dense(2, 1, new[] { z1, (z1 - z0)/T });
Matrix<double> P0 = Matrix<double>.Build.Dense(2, 2, new[] { r, r/T, r/T, 2*r/(T*T) });


// Setup a DiscreteKalmanFilter to filter
DiscreteKalmanFilter dkf = new DiscreteKalmanFilter(x0, P0);
Matrix<double> F = Matrix<double>.Build.Dense(2, 2, new[] { 1d, 0d, T, 1 });   // State transition matrix
Matrix<double> G = Matrix<double>.Build.Dense(2, 1, new[] { (T * T) / 2d, T });   // Plant noise matrix
Matrix<double> Q = Matrix<double>.Build.Dense(1, 1, new[] { q }); // Plant noise variance
Matrix<double> R = Matrix<double>.Build.Dense(1, 1, new[] { r }); // Measurement variance matrix
Matrix<double> H = Matrix<double>.Build.Dense(1, 2, new[] { 1d, 0d }); // Measurement matrix

Матрицы в тесте имеют такие значения, без пояснений почему так, можете дать краткий комментарий?

Входные данные для теста имеют примерно одинаковую дельту между значениями

// Reference Measurements
double[] zs = { 290.16851039,654.55633793,968.97141280,1325.09197161,1636.35947675,1974.39053148,2260.80770553,2574.36119750,2901.32285462,3259.14709098};

я добавил большое предпоследнее значение 6666,0 в надежде на то, что значение после фильтра вырастет, но не настолько сильно, т.е. мы больше доверяем стадии предсказания, чем стадии обновления. Предсказанное значение 2978.94381631, а в Update приходит 6666, т.е. State должен вырасти по сравнению с предсказанием но не сильно, например до 3500,0 Это то поведение которое я ожидаю, чтобы отсекать сильно отличающиеся значения (экстремумы измерений).

double[] zs = { 290.16851039,654.55633793,968.97141280,1325.09197161,1636.35947675,1974.39053148,2260.80770553,2574.36119750,2901.32285462, 6666.0, 3259.14709098};

После фильтра два последних значения:

r=30  T=20   q=0.1
[7] = 6646.6976456596558
[8] = 3312.4160564787853

r=30  T=20   q=0.01
[7] = 6551.1190606348246
[8] = 3533.6463112421743

r=30  T=20   q=0.001
[7] = 6225.962893910646
[8] = 4043.1079529696608

r=50  T=20   q=0.1
[7] = 6636.51298520405
[8] = 3338.9318698595798

r=300  T=20   q=0.1
[7] = 6551.1190606348246
[8] = 3533.6463112421734

Я покрутил константы фильтра и не смог, сильнее "зафильтровать" значение 6666,0 Прошу помочь разобраться). Возможно есть какие-то другие решения фильтра Калмана?


Ответы (0 шт):