Kalman Filter - реалізація, параметри та налаштування


10

Перш за все, це перший раз, коли я намагаюся зробити фільтр Кальмана.

Раніше я розміщував наступне запитання Відфільтруйте шум та відхилення від значень швидкості на StackOverflow, де описується фон для цієї публікації. Це типовий зразок значень, який я намагаюся фільтрувати. Вони не обов'язково повинні зменшуватись, що стосується тут. Але швидкість змін зазвичай така

X ------- Y
16 --- 233,75
24 --- 234,01
26 --- 234,33
32 --- 234,12
36 --- 233,85
39 --- 233,42
47 --- 233,69
52 --- 233,68
55 --- 233,76
60 --- 232,97
66 --- 233,31
72 --- 233,99

Я реалізував свій фільтр Kalman відповідно до цього підручника: Kalman Filter for Dummies .

Моя реалізація виглядає приблизно так (псевдокод).

//Standard deviation is 0.05. Used in calculation of Kalman gain

void updateAngle(double lastAngle){
  if(firsTimeRunning==true)
     priorEstimate = 0;               //estimate is the old one here
     priorErrorVariance = 1.2;        //errorCovariance is the old one
  else
     priorEstimate = estimate;              //estimate is the old one here
     priorErrorVariance = errorCovariance;  //errorCovariance is the old one
  rawValue = lastAngle;          //lastAngle is the newest Y-value recieved
  kalmanGain = priorErrorVariance / (priorErrVariance + 0.05);
  estimate = priorEstimate + (kalmanGain * (rawValue - priorEstimate));
  errorCovariance = (1 - kalmanGain) * priorErrVariance;
  angle = estimate;              //angle is the variable I want to update
}                                //which will be lastAngle next time

Я починаю з попередньої оцінки 0. Це, здається, працює добре. Але я помічаю, що kalmanGain зменшуватиметься кожного разу, коли це оновлення запускається, це означає, що я довіряю своїм новим значенням менше, чим довше працює мій фільтр (?). Я цього не хочу.

Я перейшов від простого використання ковзної середньої (простої та експоненціальної зваженої) до використання цього. Зараз я навіть не можу отримати таких хороших результатів, як це було.

Моє запитання: чи це правильна реалізація, і якщо моя попередня відхилення помилок і стандартне відхилення виглядають добре відповідно до наведених нами зразків? Мої параметри насправді вибираються випадковим чином, щоб побачити, чи зможу я отримати хороші результати. Я спробував кілька різних діапазонів, але з поганими результатами. Якщо у вас є якісь пропозиції щодо змін, які я можу зробити, це буде дуже вдячно. Вибачте, якщо відсутні якісь очевидні речі. Перший раз також розміщую тут.

Відповіді:


5

Фільтри Кальмана корисні, коли ваш вхідний сигнал складається з галасливих спостережень за станом деякої лінійної динамічної системи. Враховуючи серію спостережень за системним станом, фільтр Калмана спрямований на рекурсивне надання кращих і кращих оцінок стану основної системи. Для того, щоб успішно його застосувати, потрібно мати модель для динаміки системи, стан якої ви оцінюєте. Як детально описано у Вікіпедії , ця модель описує, як очікується, що система, що лежить в основі стану, змінюється протягом одного кроку часу, враховуючи її попередній стан, будь-які входи в систему та розподілену Гауссом стохастичну складову, що називається технологічним шумом.

З урахуванням сказаного, з вашого питання не зрозуміло, чи є у вас така основна модель. Пов'язаний пост вказав, що ви використовуєте значення датчиків швидкості від датчика. Вони можуть бути змодельовані як прямі спостереження за станом системи (де стан - це швидкість), так і непрямі спостереження за її станом (наприклад, стан - це його положення). Але, щоб використовувати рамку Кальмана, вам потрібно вибрати модель для того, як очікується, що цей стан буде розвиватися з плином часу; ця додаткова інформація використовується для формування оптимальної оцінки. Фільтр Калмана - це не чарівна чорна скринька, яка просто "очистить" від поданого до нього сигналу.

З огляду на це, явище, на яке ви натякали, коли фільтр Калмана стане все більш впевненим у власному виході до того моменту, коли спостереження за входом прогресивно ігноруються, відбувається на практиці. Це можна зменшити, вручну збільшуючи значення в матриці коваріації шуму процесу. Тоді, якісно, ​​модель переходу стану системи містить більшу стохастичну складову, тому можливість оцінювача точно передбачити наступний стан з урахуванням поточного стану зменшується. Це зменшить її залежність від поточної оцінки стану системи та збільшить її залежність від наступних спостережень, запобігаючи ефекту "ігнорування вхідних даних".


+1: Особливо останній абзац. Подумайте про шумові коваріації в дизайні KF як "ручки", щоб закрутити.
Петро К.

4

Якщо я правильно це зрозумів, у вас є щось, що рухається, і ви можете спостерігати за швидкістю, і ця швидкість шумно. З ваших вимірювань ви спостерігаєте 2 різновиди варіацій. \

  1. Варіації, спричинені шумом
  2. Варіації, тому що об'єкт справді змінює швидкість (наприклад, поворот)

Причина, по якій ваш коефіцієнт виходу Кальмана доходить до нуля, полягає в тому, що ви неявно припустили, що швидкість об'єкта є постійною, і все, що вам потрібно зробити, - це оцінити цю справжню швидкість.

" Гей, у мене є об'єкт, який рухається зі сталою швидкістю, і я хочу оцінити цю постійну швидкість "

Ваша модель така, де xk - швидкість у часі k і yk - це відповідне вимірювання.

xk=xk1
yk=xk+qk

Але ваш об’єкт не рухається таким чином. Швидкість змінюється, і ви не знаєте, як і коли це зміниться.

Що ви повинні сказати замість цього:

" Гей, у мене є об'єкт, який рухається зі швидкістю, але я не впевнений у тому, як він змінює свою швидкість "

Є багато способів зробити це: Найпростіший спосіб - додати невпевненість у своєму стані.

xk=xk1+vk1you add uncertainty
yk=xk+qk
де qk і vk вважається білим шумом.

Ваші рівняння фільтра Калмана будуть виглядати приблизно так:

y^k|k1=x^k|k1
Kk=Pk|k1Pk|k1+Qo
x^k|k=x^k|k1+Kk(yky^k|k1)
Pk|k=Pk|k1KkPk|k1
Pk+1|k=Pk|k+Qs

У вашому випадку 0.05значення - коваріація спостереження за шумом,Qo. Щоб зробити цю зміну, все, що вам потрібно зробити, встановленоQs, стан коварінації шуму (невизначеність у вашому штаті) до деякої постійної величини.

У вашому коді незначною зміною було б:

stateVariance = 0.5

errorCovariance = (1 - kalmanGain) * priorErrVariance + stateVariance;

Не додаючи stateVarianceабоQs у своєму коді ви припустили, що він дорівнює нулю.

Це stateVarianceзначення може бути все, що завгодно. Це базується на вашій впевненості в тому, наскільки насправді зміниться швидкість. Якщо ви думаєте, що швидкість залишиться досить постійною, встановіть це на невелику кількість.

Таким чином ваш кальманський посилення не піде до нуля.


3

Вам потрібна динамічна система, щоб використовувати фільтр Kalman.

Я б запропонував

y=i=0naixi

a[k+1]=a[k]+w
cov(w)=Q
Вимірювання:
z=i=0naixi=y

Тож замість використання x як держави, введіть коефіцієнт (a) як держави


1

Я думаю, ви можете використовувати деякі ідеї з класичної теорії управління, наприклад, PID-контролер .

Ваш сигнал Y може бути заданим значенням контролера u (t). Завод технологічного процесу становить лише 1, і y (t) буде відфільтровано. Все, що вам потрібно зробити, - це встановити параметри (налаштування) P, I і D, щоб отримати те, що ви хочете.

Вихід y (t) намагатиметься "слідувати" за входом u (t), але параметри керують тим, яким буде це відстеження.

Диференціальний посилення D зробить вашу реакцію чутливою до швидких змін помилок. У вашому випадку я думаю, що D повинен бути малим. Ви не хочете, щоб y (t) змінювався, якщо u (t) різко змінюється.

Вбудований коефіцієнт "Я" зробить вашу реакцію чутливою до накопиченої помилки. Ви повинні поставити там високе значення. Якщо u (t) змінить рівень і збереже його там, помилка наробиться, і тоді ви хочете, щоб y (t) зробив те ж саме.

Підсилення P може дати тонку мелодію. У будь-якому випадку спробуйте пограти з параметрами і подивитися, що ви отримаєте.

Однак є складні методи настройки, але я не вірю, що вам це знадобиться.

Удачі.


Насправді, є кращий підхід. Дивіться цю публікацію .
Даніель Р. Піпа


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.