1. 程式人生 > >卡爾曼濾波及實現

卡爾曼濾波及實現

參考視訊 https://www.bilibili.com/video/av4356232/

參考部落格 https://blog.csdn.net/codesamer/article/details/81191487

目錄

1.預測值 與 狀態預測公式

1.1預測狀態的協方差P

1.2觀測值 與 觀測噪聲協方差R

2.1狀態更新

2.2預測值的噪聲分佈(協方差)P 的更新

整合

實現


1.預測值 與 狀態預測公式

假設有一個小車在行駛,它的狀態是x_{_{t}},包括它的 位置p 速度v加速度u

                                            

可知其上一時刻的狀態為

發現其輸出變數是輸入變數的線性組合

                                                      

轉化成矩陣的形式為

                                                     

令 為狀態轉移矩陣(從上一時刻的狀態推測這個時刻的狀態),為控制矩陣(控制量u如何作用當前狀態)

得到狀態預測公式

                                               


1.1預測狀態的協方差P

使用協方差矩陣來表示 預測的值 的不確定性

         

假設 x 、y 兩個維度的隨機變數相互獨立,其協方差為0 

假設 x 、y 兩個維度的隨機變數具有相關性,x 隨著 y 增大 協方差>0 。x 隨著 y 減小 協方差<0

協方差矩陣表示為  cov(x,x) 對角線表示兩個維度的 隨機變數的 方差。斜對角線的值相等,表示協方差

 

根據:                   

不確定性 在各個時刻的傳遞關係(預測狀態的協方差)

                                                        

加一個 協方差Q 表示預測模型本身帶來的噪聲


1.2觀測值 與 觀測噪聲協方差R

一個觀測量 Z  可以通過車輛當前的狀態 x · 觀測矩陣H  和一個誤差組成 

定義觀測噪聲的協方差矩陣為 R 

                                      


2.1狀態更新

有第一步等到帶 - 號的預測值,通過觀測量修正 x 的值,就可以得到一個最佳估計值

                                                 

括號裡面代表實際的觀測值預期的觀測值 的殘差。

K 是卡爾曼係數

                                                       

作用1:

權衡預測狀態協方差 P 觀測噪聲協方差 R 的大小。來決定相信預測多一些(K小) or  相信觀察多一些(K大)

作用2:

把殘差的表現形式 從觀察域 轉化到 狀態域


2.2預測值的噪聲分佈(協方差)P 的更新

更新  最佳預測值的噪聲分佈  未了 下一輪迭代

在不確定性變化(噪聲)中尋找一個平衡

                                                                   


整合

帶 - 的值是預測的值,但是缺少觀測值的修正。所以加入觀測值後,對每一時刻的狀態進行預測。 

                          

公式1:   X(k|k-1) = AX(k-1 | k-1) + BU(k) + W(k)

公式2:   P(k|k-1)  = AP(k-1|k-1)A' + Q(k)

公式3:   X(k|k)  = X(k|k-1) + Kg(k)[Z(k) - HX(k|k-1)

公式4:   Kg(k)  = P(k|k-1)H'/{HP(k|k-1)H' + R}        

公式5 :  P(k|k)   = (1- Kg(k) H) P(k|k-1)


實現

# -*- coding: utf-8 -*-
"""
Created on Tue Jan  1 15:54:48 2019

@author: aligo
"""
import numpy as np
import matplotlib.pyplot as plt
 
# 觀測值,1-100 每秒一部,就是速度為 1 的勻速行駛
z = [i for i in range(100)]
z_watch = np.mat(z)
 
# 建立一個方差為1的高斯噪聲,精確到小數點後兩位
noise = np.round(np.random.normal(0, 1, 100), 2)
noise_mat = np.mat(noise)
 
# 將z的觀測值和噪聲相加
z_mat = z_watch + noise_mat
#print(z_watch)
 

# 定義x的初始狀態
x_mat = np.mat([[0,], [0,]])
# 定義初始狀態協方差矩陣
p_mat = np.mat([[1, 0], [0, 1]])
# 定義狀態轉移矩陣,因為每秒鐘採一次樣,所以delta_t = 1
f_mat = np.mat([[1, 1], [0, 1]])
# 定義狀態轉移協方差矩陣,這裡我們把協方差設定的很小,因為覺得狀態轉移矩陣準確度高
q_mat = np.mat([[0.0001, 0], [0, 0.0001]])
# 定義觀測矩陣
h_mat = np.mat([1, 0])
# 定義觀測噪聲協方差
r_mat = np.mat([1])
 
for i in range(100):
    x_predict = f_mat * x_mat
    p_predict = f_mat * p_mat * f_mat.T + q_mat
    kalman = p_predict * h_mat.T / (h_mat * p_predict * h_mat.T + r_mat)
    x_mat = x_predict + kalman *(z_mat[0, i] - h_mat * x_predict)
    p_mat = (np.eye(2) - kalman * h_mat) * p_predict
    
    plt.xlabel("p")
    plt.ylabel("v")
    plt.plot(x_mat[0, 0], x_mat[1, 0], 'ro', markersize = 1)
    
plt.show()

                                                          

橫座標表示離初始位置的距離 p,縱座標表示在該位置的速度 v。

初始為0,在經過一段很短的時間後,速度預測值 與 實際值1 就很接近了