Фильтр KALMAN не реагирует на изменения

Я впервые применяю фильтр Калмана для получения значений напряжения от источника. Он работает и стабилизируется при значении напряжения источника, но если затем источник изменяет напряжение, фильтр не адаптируется к новому значению.

Я использую 3 шага:

  1. Получить усиление Калмана

    KG = previous_error_in_estimate / ( previous_error_in_estimate + Error_in_measurement )
    
  2. Получить текущую оценку

    Estimation = previous_estimation + KG*[measurement - previous_estimation]
    
  3. Рассчитать ошибку в оценке

    Error_in_estimate = [1-KG]*previous_error_in_estimate
    

Дело в том, что при 0 <= KG <= 1 Error_in_estimate уменьшается все больше и больше, и это заставляет KG также уменьшаться все больше и больше (error_in_measurement является постоянной величиной), поэтому в конце оценка зависит только от предыдущей оценки, а текущее измерение не учитывается.

Это предотвращает адаптацию фильтра к изменениям измерения.

Как я могу это сделать?

Спасибо


РЕДАКТИРОВАТЬ:

Отвечая Класу:

Я не уверен, что фильтр Калмана подходит для моей проблемы, так как у меня нет модели системы, у меня просто куча показаний с довольно шумного датчика, измеряющего не очень предсказуемую переменную.

Для простоты представьте, что вы читаете потенциометр (переменный резистор), измененный пользователем, вы не можете предсказать или смоделировать поведение пользователя.

Я реализовал очень простой алгоритм SMA ( Simple Moving Average), и мне было интересно, есть ли лучший способ сделать это.

Является ли фильтр Калмана действительным для такой проблемы?

Если нет, что бы вы предложили?

2-е РЕДАКТИРОВАНИЕ

Спасибо Claes за такую ​​полезную информацию

Я проводил некоторые числовые тесты в MathLab (без реальных данных), и свертка с гауссовым фильтром, похоже, дает наиболее точный результат.

Дисперсия Кальмана R=0,1 ^ 2 Плохой результат

С фильтром Калмана я не знаю, как оценить отклонения процесса и измерения, есть ли способ для этого? Только когда я значительно уменьшу дисперсию измерения, фильтр Калмана, кажется, адаптируется. На предыдущем изображении дисперсия измерения была R=0,1^2 (та, что в исходном примере). Это тот же тест с R=0,01^2

Дисперсия измерения Калмана R=0,01^2 Лучший результат

Конечно, это тесты MathLab без реальных данных. Завтра я постараюсь реализовать эти фильтры в реальной системе с реальными данными и посмотреть, смогу ли я получить аналогичные результаты

1 ответ

Для вашего примера, вероятно, достаточно простого фильтра МА. Если вы хотите использовать фильтр Калмана, есть отличный пример в кулинарной книге SciPy.

Я изменил код, включив в него изменение шага, чтобы вы могли видеть схождение.

# Kalman filter example demo in Python
# A Python implementation of the example given in pages 11-15 of "An
# Introduction to the Kalman Filter" by Greg Welch and Gary Bishop,
# University of North Carolina at Chapel Hill, Department of Computer
# Science, TR 95-041,
# http://www.cs.unc.edu/~welch/kalman/kalmanIntro.html

# by Andrew D. Straw

import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['figure.figsize'] = (10, 8)

# intial parameters
n_iter = 400
sz = (n_iter,) # size of array
x1 = -0.37727*np.ones(n_iter/2) # truth value 1
x2 = -0.57727*np.ones(n_iter/2) # truth value 2
x = np.concatenate((x1,x2),axis=0)
z = x+np.random.normal(0,0.1,size=sz) # observations (normal about x, sigma=0.1)

Q = 1e-5 # process variance

# allocate space for arrays
xhat=np.zeros(sz)      # a posteri estimate of x
P=np.zeros(sz)         # a posteri error estimate
xhatminus=np.zeros(sz) # a priori estimate of x
Pminus=np.zeros(sz)    # a priori error estimate
K=np.zeros(sz)         # gain or blending factor

R = 0.1**2 # estimate of measurement variance, change to see effect

# intial guesses
xhat[0] = 0.0
P[0] = 1.0

for k in range(1,n_iter):
    # time update
    xhatminus[k] = xhat[k-1]
    Pminus[k] = P[k-1]+Q

    # measurement update
    K[k] = Pminus[k]/( Pminus[k]+R )
    xhat[k] = xhatminus[k]+K[k]*(z[k]-xhatminus[k])
    P[k] = (1-K[k])*Pminus[k]

plt.figure()
plt.plot(z,'k+',label='noisy measurements')
plt.plot(xhat,'b-',label='a posteri estimate')
plt.plot(x,color='g',label='truth value')
plt.legend()
plt.title('Estimate vs. iteration step', fontweight='bold')
plt.xlabel('Iteration')
plt.ylabel('Voltage')

И вывод:

Другие вопросы по тегам