Фильтр Калмана дает странные результаты - PullRequest
1 голос
/ 30 апреля 2020

Я изучаю Kalman Filters и пытался реализовать следующую проблему в Python ( описание постановки задачи ) Мой подход:

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

Может кто-нибудь помочь мне с векторами состояния и другими матрицами, необходимыми для оценки?

from numpy import identity
from numpy.linalg import inv
import numpy as np
import matplotlib.pyplot as plt


class KalmanFilter:
    def __init__(self, state_estimate, error_cov, transition_model,
                 control_model, obser_model, process_cov, obser_cov):
        self.state_estimate = state_estimate
        self.error_cov = error_cov
        self.transition_model = transition_model
        self.control_model = control_model
        self.obser_model = obser_model
        self.process_cov = process_cov
        self.obser_cov = obser_cov

    def predict(self, control_input):
        self.state_estimate = self.transition_model * self.state_estimate \
                + self.control_model * control_input

        self.error_cov = self.process_cov \
            + self.transition_model * self.error_cov * self.transition_model.T

        return self.state_estimate

    def update(self, obser):
        innovation = obser - self.obser_model * self.state_estimate
        innovation_cov = self.obser_cov \
            + self.obser_model * self.error_cov * self.obser_model.T
        kalman_gain = self.error_cov * self.obser_model.T * inv(innovation_cov)

        self.state_estimate = self.state_estimate + kalman_gain * innovation

        n = self.error_cov.shape[0]
        self.error_cov = (identity(n) - kalman_gain * self.obser_model) \
            * self.error_cov

        return self.state_estimate


class Process:
    acc_std_dev = 1
    obs_std_dev = (0.010)*(0.010)

    def __init__(self, initial_state, transition_model):
        self.state = initial_state
        self.transition_model = transition_model

    def update(self):
        rand_acc = np.random.normal(0, Process.acc_std_dev)
        G = np.array([[0.25, 1]]).T
        self.state = self.transition_model * self.state + G * rand_acc
        return self.state

    def observe(self):
        return self.state[0, 0] + np.random.normal(0, Process.obs_std_dev)

if __name__ == '__main__':
    # delta time
    dt = 1

    initial_state = np.array([[0, 0]]).T

    # Assuming perfect initial state estimate
    error_cov = np.matrix([[0, 0],
                          [0, 0]])

    transition_model = np.matrix([[1, 0],
                                 [0, (1/200)]])

    # Assuming no input control
    control_model = np.array([[0, 0]]).T

    # Making observations of the position
    obser_model = np.matrix([[1, 0]])


    G = np.array([[1, 0]]).T
    process_cov = G * G.T * Process.acc_std_dev

    kf = KalmanFilter(initial_state, error_cov, transition_model,
                      control_model, obser_model, process_cov,
                      Process.obs_std_dev**2)
    p = Process(initial_state, transition_model)

    positions = list()
    velocities = list()

    observations = list()

    positionEstimates = list()
    velocityEstimates = list()

    for i in range(0, 100):
        state = p.update()
        positions.append(state[0, 0])
        velocities.append(state[1, 0])

        obs = p.observe()
        observations.append(obs)

        kf.predict(np.array([[0, 0]]))
        estimate = kf.update(obs)

        positionEstimates.append(kf.update(obs)[0, 0])
        velocityEstimates.append(kf.update(obs)[1, 0])

    xs = np.arange(len(observations))

    # Position - State, Observations, Estimate
    pStates, = plt.plot(xs, positions, color='k')
    pObs, = plt.plot(xs, observations, color='r')
    pEstimates, = plt.plot(xs, positionEstimates, color='g')
    plt.legend((pObs, pStates, pEstimates),
               ('observations', 'true state', 'estimates'))
    plt.title("Kalman Filter - Position Observations vs Estimates")
    plt.ylabel('x', rotation=90)
    plt.xlabel('t')
    plt.show()

    # Velocity - State, Estimate
    pStates, = plt.plot(xs, velocities, color='k')
    pEstimates, = plt.plot(xs, velocityEstimates, color='g')
    plt.legend((pStates, pEstimates),
               ('true state', 'estimates'))
    plt.title("Kalman Filter - Velocity")
    plt.ylabel('ẋ', rotation=90)
    plt.xlabel('t')
    plt.show()
...