Как то так повелось, что очень нравятся мне всякие алгоритмы, имеющие четкое и логичное математическое обоснование. Но зачастую их описание в интернете настолько перегружено формулами и расчетами, что общий смысл понять просто невозможно. А ведь понимание сути и принципа работы устройства/механизма/алгоритма намного важнее, чем заучивание формул. Как это ни банально, но запоминание даже сотни формул ничем не поможет, если не знать, как и где их применить.
Собственно, к чему все это. Решил я сделать описание некоторых алгоритмов, с которыми мне приходилось сталкиваться на практике. Постараюсь не перегружать математическими выкладками, чтобы материал был понятным, а чтение легким. И сегодня мы поговорим о фильтре Калмана, разберемся, что это такое, для чего и как он применяется.
Фильтр Калмана.
Начнем с небольшого примера. Пусть перед нами стоит задача определять координату летящего самолета. Причем, естественно, координата (обозначим ее x_k) должна определяться максимально точно:
На самолете мы заранее установили датчик, который и дает нам искомые данные о местоположении, но, как и все в этом мире, наш датчик неидеален. Поэтому вместо значения x_k мы получаем:
y_k = x_k + e_k
Здесь e_k - ошибка датчика, то есть случайная величина. Таким образом, из неточных показаний измерительного оборудования мы должны получить значение координаты (x_{k,o}), максимально близкое к реальному положению самолета.
Задача поставлена, перейдем к ее решению!
Пусть мы знаем управляющее воздействие (s_k), благодаря которому летит самолет (пилот сообщил нам о своих действиях). Тогда, зная координату на k-ом шаге, мы можем получить значение x_{k+1} на (k+1) шаге:
x_{k+1} = x_k + s_k
Казалось бы, вот оно, то что надо, и никакой фильтр Калмана тут не нужен. Но не все так просто... В реальности мы не можем учесть все внешние факторы, влияющие на полет, поэтому формула принимает следующий вид:
x_{k+1} = x_k + s_k + n_k
где n_k - ошибка, вызванная внешним воздействием, неидеальностью двигателя и т п.
Итак, что же получается? На шаге (k+1) мы имеем, во-первых, неточное показание датчика y_{k+1}, а во-вторых, неточно рассчитанное значение x_{k+1}, полученное из значения x_{k,o} на предыдущем шаге.
x_{k+1} = x_{k,o} + s_k
Идея фильтра Калмана заключается в том, чтобы из двух неточных значений (взяв их с разными весовыми коэффициентами) получить точную оценку искомой координаты (для нашего случая). В общем случае, измеряемая величина можем быть абсолютно любой (температура, скорость...). Вот, что получается:
x_{k+1,o} = K_{k+1}\medspace y_{k+1} + (1-K_{k+1})\medspace x_{k+1}
Путем математических вычислений мы можем получить формулу для расчета коэффициента Калмана на каждом шаге, но, как условились в начале статьи, не будем углубляться в вычисления, тем более, что на практике установлено, что коэффициент Калмана с ростом k всегда стремится к определенному значению. Получаем первое упрощение нашей формулы:
x_{k+1,o} = Ky_{k+1} + (1\medspace-\medspace K)\medspace x_{k+1},\enspace где\enspace x_{k+1} =\medspace x_{k,o} + s_k
А теперь предположим, что связи с пилотом нет, и мы не знаем управляющее воздействие s_k. Казалось бы, в этом случае фильтр Калмана мы использовать не можем, но это не так. Упрощаем формулу:
x_{k+1,o} = Ky_{k+1} + (1\medspace-\medspace K)\medspace x_{k,o}
Получаем максимально "облегченную" формулу Калмана, которая тем не менее, несмотря на такие "жесткие" упрощения, прекрасно справляется со своей задачей. Если представить результаты графически, то результат может иметь, например, такой вид:
В том случае, когда наш датчик очень точный, то естественно весовой коэффициент K должен быть близок к единице. А если ситуация обратная, то есть датчик не очень хорош, то K должен быть ближе к нулю.
На этом, пожалуй, все, вот так просто мы разобрались с алгоритмом фильтрации Калмана, надеюсь, что статья оказалась полезной и понятной 🤝
Лучше заменить красный или тёмно красный на другой цвет,так как сразу трудно разобрать где "показания датчика", а где "реальное значение координаты"
Да, что-то я не подумал об этом..постараюсь переделать на днях)
если к=0.5 получаем тупо среднее арифметическое
К(+1)=(К+Y)/2 помоему самый наглядный пример, половину данных взяли с датчика, половину от предыдущего значения.
Также этот фильтр работает как фильтр низких частот, можно обработать mp3 или wav файл и усилить басы хоть в 100500 раз, или задавить ВЧ помеху 🙂
Классный фильтр для давки ВЧ. Если канеш у людей динамики взрослые, мона басы душить по полной )))
Фильтр кальмана полезен если с измерениями туго, например акселерометр с чипом где период измерения 850 милисек ла ёщё и шифрование ноля. А где измерений прорва то пойдёт альфа-бета фильтр.
А можно ли подытожить для непонятливых?
X(k+1) = K * Y + (1-K)*X
То есть мы прогнозируем, что в настоящий момент измерения, координата Х равна некоему коэффициенту K умноженному на показание прибора + коэффициент (1-К) умноженному на значение Х на прошлом шаге.
При этом мы не уверены, что Х на прошлом шаге был верен? Не будет ли накапливаться ошибка?
Как собственно подобрать К? Может ли он корректироваться в процессе расчета, если мы понимаем, что можно делать вычисления точнее на следующем шаге?
Спасибо за хорошую статью! Однако, расшифруйте пожалуйста фразу "Здесь e_... — ошибка датчика, то есть случайная величина". Но ведь ошибка, как правило, это смесь - это и случайное, и плюс детерминированное,... То есть датчик может постоянно завышать (или занижать) значение. То есть выдавать смещенные показания. Как быть в таком случае?
Добрый день! Если есть постоянная составляющая, то ее просто вычитаем из сигнала.
Статья реально помогла решить проблему. Столкнулся с задачей фильтрации на практике. Автору большой риспэкт.
Благодарю )
А не ФНЧ ли это часом? Я что-то подобное писал для обработки аудио. K, 1-K. И в зависимости от К получал нужную частоту среза. Или я путаю?
В некотором смысле, слишком быстрые изменения сигнала не проходят на выход.