卡尔曼滤波

卡尔曼滤波 Kalman Filter

视频教程地址:https://space.bilibili.com/230105574/channel/detail?cid=139198&ctype=0

卡尔曼滤波五个公式各参数意义:https://blog.csdn.net/wccsu1994/article/details/84643221

image-20211121212609532

image-20211121212701116

第一讲 递归算法

最初的引入

image-20211120202524044

卡尔曼增益系数分析

image-20211120202442837

卡尔曼滤波基本步骤、小案例

image-20211120202905489

案例手算演示

image-20211120203118039

案例excel演算结果

image-20211120203239474

第二讲 数学基础

数据融合、协方差矩阵、状态空间方程

数据融合

数据融合的原理:使得融合后数据的误差方差最小

image-20211120203653141

融合数据方差推算

image-20211120204347570

协方差矩阵

协方差矩阵概念、矩阵计算方式

image-20211120211344073

excel演示协方差矩阵

image-20211120205516430

状态空间方程

弹簧振动系统案例

image-20211120213548403

连续变量和离散型变量的矩阵形式表达

image-20211120213916548

第三讲 卡尔曼增益数学推导

画红框的是书上给出的卡尔曼滤波器公式

image-20211121161436600

目标:寻找合适的k_k,使得P的迹最小

image-20211121161852537

推出符合目标的卡尔曼增益k_k

image-20211121164223698

第四讲 误差协方差矩阵数学推导

梳理

image-20211121171509996

P_k先验推导

image-20211121171917274

P_k后验更新、完整公式整理

image-20211121172209639

第五讲 二维实例演算

excel程序下载链接:https://pan.baidu.com/s/1GdJe2eWIlaQrk2nrjemRCQ 提取码:txn3 (已放进asset文件夹) $6.5 + (0.22 / (0.22 + 0.4**2)) * (7.3 - 6.5) = 6.66$

image-20211120225536532

一个简单而又不简单的例子(一个人在走路,同时通过天上卫星可观测其位置和速度)

image-20211120231344535

基础公式

image-20211120232119734

excel演示

image-20211120232744596

个人任务:python实现一下

别人写的:https://github.com/liuchangji/2D-Kalman-Filter-Example_Dr_CAN_in_python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#! python3
# -- encoding: utf-8 --
# @Author: qizidog
# @Time: 2021/11/21 22:10:07

import numpy as np
from matplotlib import pyplot as plt


def disturb(scale):
"""
返回一个指定标准差的正太扰动
:param scale: 标准差
:return:
"""
return np.random.normal(0, scale)


def calc_prior_hx(A, hx_k_1, B, u_k_1):
"""
计算先验估计值
:param A: 预测使用的状态转移矩阵
:param hx_k_1: 上一次的后验估计值
:param B: 将输入转为状态的转移矩阵
:param u_k_1: 系统输入
:return: 先验估计值
"""
hx_prior_k = np.dot(A, hx_k_1)
if B is not None and u_k_1 is not None:
hx_prior_k += np.dot(B, u_k_1)
return hx_prior_k


def calc_prior_P(A, P_k_1, Q):
"""
计算先验状态估计协方差矩阵
:param A: 预测使用的状态转移矩阵
:param P_k_1: 上一次的后验状态估计协方差矩阵
:param Q: 预测过程的噪声协方差矩阵
:return: 先验的状态估计协方差矩阵
"""
P_prior_k = np.dot(A, P_k_1)
P_prior_k = np.dot(P_prior_k, A.T) + Q
return P_prior_k


def kalman_gain(P_prior_k, H, R):
"""
计算kalman gain卡尔曼增益
:param P_prior_k: 先验的状态估计协方差矩阵
:param H: 状态变量到测量值的转换矩阵
:param R: 测量噪声协方差矩阵
:return: 卡尔曼增益系数矩阵
"""
up = np.dot(P_prior_k, H.T)
down = np.dot(H, P_prior_k)
down = np.dot(down, H.T) + R
K_k = np.dot(up, np.linalg.inv(down)) # 矩阵除法等于乘以逆矩阵
return K_k


def calc_posterior_hx(hx_prior_k, K_k, z_k, H):
"""
计算后验估计值
:param hx_prior_k: 先验估计值
:param K_k: 卡尔曼增益系数矩阵
:param z_k: 测量值
:param H: 状态变量到测量值的转换矩阵
:return: 后验估计值
"""
hx_k = hx_prior_k + np.dot(K_k, (z_k - np.dot(H, hx_prior_k)))
return hx_k


def update_posterior_P(K_k, H, P_prior_k):
"""
更新后验状态估计协方差矩阵
:param K_k: 卡尔曼增益
:param H: 状态变量到测量值的转换矩阵
:param P_prior_k: 先验的状态估计协方差矩阵
:return: 后验状态估计协方差矩阵
"""
P_k = P_prior_k - np.dot(np.dot(K_k, H), P_prior_k)
return P_k


if __name__ == "__main__":
"""
kalman filter 案例实践
"""
# -----初始化用于画图的数据列表-----
position_true = []
position_measure = []
position_prior_est = []
position_posterior_est = []

speed_true = []
speed_measure = []
speed_prior_est = []
speed_posterior_est = []

# -----一些初始值-----
# A 用于计算预测值的状态转移矩阵
A = np.array([1, 1, 0, 1]).reshape([2, 2])
B, u_k_1 = None, None
# 初始的位置和速度估计值
hx_k_1 = np.array([0, 1]).reshape([2, 1])
# 状态估计协方差矩阵P初始化
P_k_1 = np.array([1, 0, 0, 1]).reshape([2, 2])
# 过程噪声协方差矩阵Q,p(w)~N(0,Q),噪声来自预测的不确定性
Q = np.array([5, 0, 0, 5]).reshape((2, 2)) # 个人认为预测的误差较大
# 状态观测矩阵
H = np.array([1, 0, 0, 1]).reshape([2, 2])
# 测量噪声协方差矩阵R,p(v)~N(0,R)
R = np.array([[1, 0, 0, 1]]).reshape([2, 2]) # 个人认为测量的误差比较小

# 初始位置、速度的真值(随便取的 x=3, v=3)
x_k = np.array([3, 3]).reshape([2, 1]) + np.array([disturb(Q[0][0]), disturb(Q[1][1])]) # 加点扰动

for i in range(30):
# -----------------------生成真实值----------------------
if i != 0: # 第一次时,使用上面指定的初始真值
x_k = np.dot(A, x_k) + np.array([disturb(Q[0][0]), disturb(Q[1][1])]) # 上次的真值计算后加点扰动当作真值
position_true.append(x_k[0][0])
speed_true.append(x_k[1][0])
# -----------------------生成观测值----------------------
z_k = x_k + np.array([disturb(R[0][0]), disturb(R[1][1])]) # 真值叠加扰动当作观测值
position_measure.append(z_k[0][0])
speed_measure.append(z_k[1][0])
# ---------------------kalman filter--------------------
hx_prior_k = calc_prior_hx(A, hx_k_1, B, u_k_1)
P_prior_k = calc_prior_P(A, P_k_1, Q)
K_k = kalman_gain(P_prior_k, H, R)
hx_k = calc_posterior_hx(hx_prior_k, K_k, z_k, H) # 估计值
P_k = update_posterior_P(K_k, H, P_prior_k)
position_prior_est.append(hx_prior_k[0][0])
speed_prior_est.append(hx_prior_k[1][0])
position_posterior_est.append(hx_k[0][0])
speed_posterior_est.append(hx_k[1][0])
# ----------------------更新值,下次用---------------------
hx_k_1 = hx_k
P_k_1 = P_k

# 可视化显示
if True:
fig, axs = plt.subplots(1, 2)
axs[0].plot(speed_true, "-", label="speed_true", linewidth=1)
axs[0].plot(speed_measure, "-", label="speed_measure", linewidth=1)
axs[0].plot(speed_prior_est, "-", label="speed_prior_est", linewidth=1)
axs[0].plot(speed_posterior_est, "-", label="speed_posterior_est", linewidth=1)
axs[0].set_title("speed")
axs[0].set_xlabel('k') # Add an x-label to the axes.
axs[0].legend() # Add a legend.

axs[1].plot(position_true, "-", label="position_true", linewidth=1)
axs[1].plot(position_measure, "-", label="position_measure", linewidth=1)
axs[1].plot(position_prior_est, "-", label="position_prior_est", linewidth=1)
axs[1].plot(position_posterior_est, "-", label="position_posterior_est", linewidth=1)
axs[1].set_title("position")
axs[1].set_xlabel('k') # Add an x-label to the axes.
axs[1].legend() # Add a legend.

plt.show()

第六讲 拓展卡尔曼滤波器

kalman filter 只能用于线性系统

image-20211122114739985

正态分布的误差在非线性系统中就不再是正态分布了,需要做线性化泰勒展开

image-20211122115631993

image-20211122120251925

修改为 extended kalman filter

image-20211122120555423


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!