滤波系列(一)卡尔曼滤波算法(KF):应用
程序员文章站
2022-04-18 10:22:38
...
滤波系列(一)卡尔曼滤波算法的应用
在本文,将直接给出卡尔曼滤波算法的具体应用,如果想了解卡尔曼滤波算法的详细数学推导过程,请看博客:卡尔曼滤波算法的详细数学推导
KF的应用
目标的运动模型
举一个物体做匀速直线运动的例子:
物体的状态由位置和速度组成定义为 ,根据匀速直线运动公式可知:
这里我们将最后一项 ,考虑为系统模型不准确带来的噪声(注意是一个随机变量,是一个确定的时间间隔),,我们可以将上面的公式合并在一起:
所以t时刻状态的均值为:
所以t时刻状态的方差为:
注:随机变量求方差公式
传感器的量测为 ,量测方程为 。
假设目标的初始时刻的状态为 、协方差矩阵为 ,采样时间间隔 ,传感器的量测噪声为 。由此产生的仿真数据如下图:
其中,蓝色的线表示加了噪声的量测数据,橘色的线表示真实的位置。
卡尔曼滤波的过程:
更新公式:
卡尔曼滤波代码
def kalmanfilter(A, H, Q, R, z, P, x):
n = A.shape[1]
#Predict
x = np.dot(A, x) #公式(7)
P = multi_dot([A, P, A.T]) + Q #公式(8)
#Update
y = z - np.dot(H, x)
S = np.matrix(multi_dot([H, P, H.T])+R)
K = multi_dot([P, H.T, inv(S)]) #公式(9)
x = x + np.dot(K, y) #公式(10)
I = np.eye(n)
P = np.dot(I - np.dot(K, H), P) #公式(11)
return x,P
完整代码
import numpy as np
from numpy.linalg import multi_dot,inv
import matplotlib.pyplot as plt
np.random.seed(2)
def kalmanfilter(A, H, Q, R, z, P, x):
n = A.shape[1]
#Predict
x = np.dot(A, x)
P = multi_dot([A, P, A.T]) + Q
#Update
y = z - np.dot(H, x)
S = np.matrix(R + multi_dot([H, P, H.T]))
K = multi_dot([P, H.T, inv(S)])
x = x + np.dot(K, y)
I = np.eye(n)
P = np.dot(I - np.dot(K, H), P)
return x,P
def demo():
dt = 0.1
F = np.array([[1, dt], [0, 1]])
H = np.array([1, 0]).reshape(1,2)
Q = 1e-2*np.array([[1/4*dt**4, 1/2*dt**3], [1/2*dt**3, dt**2]])
R = 2
itr = 100
real_state = []
x = np.array([10,5]).reshape(2,1)
for i in range(itr):
real_state.append(x[0,0])
x = np.dot(F,x)+np.random.multivariate_normal(mean=(0,0),cov=Q).reshape(2,1)
measurements = [x+np.random.normal(0,R) for x in real_state]
# initialization
P = np.array([[10,5],[5,10]])
x=np.random.multivariate_normal(mean=(10,5),cov=P).reshape(2,1)
#filter
filter_result=list()
filter_result.append(x)
for i in range(1,itr):
x,P = kalmanfilter(F, H, Q, R, measurements[i],P,x)
filter_result.append(x)
filter_result=np.squeeze(np.array(filter_result))
return measurements,real_state,filter_result
def plot_result(measurements,real_state,filter_result):
plt.figure(figsize=(8,4))
plt.plot(range(1,len(measurements)), measurements[1:], label = 'Measurements')
plt.plot(range(1,len(real_state)), real_state[1:], label = 'Real statement' )
plt.plot(range(1,len(filter_result)), np.array(filter_result)[1:,0], label = 'Kalman Filter')
plt.legend()
plt.xlabel('Time',fontsize=14)
plt.ylabel('velocity [m]',fontsize=14)
plt.show()
plt.figure(figsize=(8,4))
plt.axhline(5, label='Real statement') #, label='$GT_x(real)$'
plt.plot(range(1,len(filter_result)), np.array(filter_result)[1:,1], label = 'Kalman Filter')
plt.legend()
plt.xlabel('Time',fontsize=14)
plt.ylabel('velocity [m]',fontsize=14)
plt.show()
if __name__ == '__main__':
measurements,real_state,filter_result=demo()
plot_result(measurements,real_state,filter_result)
滤波后的结果如下图所示,图2表示目标位置的滤波结果,从图中可直观发现经过卡尔曼滤波后,消除了量测数据中的噪声,得到了更精确的目标位置;图3表示目标速度的滤波结果,从中可以发现经过卡尔曼滤波后,速度的估计越来越精确且逐渐收敛到了真实的速度。