|
filterpy中线性卡尔曼滤波算法_实战_可视化
- # -*- coding: utf-8 -*-
- __author__ = u'东方耀 微信:dfy_88888'
- __date__ = '2022/3/2 下午14:50'
- __product__ = 'PyCharm'
- __filename__ = '01_filterpy跟踪狗_实战完整'
- import math
- import numpy as np
- from filterpy.stats import plot_covariance
- from filterpy.kalman import KalmanFilter, EKF, UKF
- from filterpy.common import Q_discrete_white_noise
- import matplotlib.pyplot as plt
- import matplotlib.ticker as mticker
- import random
- from matplotlib.font_manager import FontProperties
- # font_fname = "C:\Windows\Fonts\simfang.ttf"
- font_fname = "/usr/share/fonts/wps-office/simfang.ttf"
- font = FontProperties(fname=font_fname)
- # filterpy中线性卡尔曼滤波算法_实战_可视化
- np.random.seed(88)
- def randomcolor():
- colorArr = ['1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F']
- color = ""
- for i in range(6):
- color += colorArr[random.randint(0, 14)]
- return "#" + color
- def compute_dog_data(z_var, process_var, count=1, dt=1.):
- "returns track, measurements 1D ndarrays"
- x, vel = 0., 1. # 这是构造数据的初始位置 与 理想速度
- # 观测值的 标准差
- z_std = math.sqrt(z_var)
- # p_std 速度变化的标准差
- p_std = math.sqrt(process_var)
- xs, zs = [], []
- for _ in range(count):
- # 每次的速度在1m/s上下波动
- v = vel + (np.random.randn() * p_std)
- # x为真实的位置
- x += v * dt
- xs.append(x)
- zs.append(x + np.random.randn() * z_std)
- # xs:狗真实的位置 zs:观测的位置
- return np.array(xs), np.array(zs)
- def pos_vel_filter(x, P, R, Q=0., dt=1.0):
- """ Returns a KalmanFilter which implements a
- constant velocity model for a state [x dx].T
- 位置position 速度vel 滤波器
- """
- # dim_x的状态向量的维度(位置 速度) dim_z是测量的维度(位置)
- # 带有dim_x的状态向量和测量向量的大小
- kf = KalmanFilter(dim_x=2, dim_z=1)
- kf.x = np.array([x[0], x[1]]) # 这是初始的location and velocity
- kf.F = np.array([[1., dt],
- [0., 1.]]) # state transition matrix
- kf.H = np.array([[1., 0]]) # Measurement function
- kf.R *= R # measurement uncertainty 因为R的维度为1
- if np.isscalar(P):
- kf.P *= P # covariance matrix
- else:
- kf.P[:] = P # [:] makes deep copy
- if np.isscalar(Q):
- kf.Q = Q_discrete_white_noise(dim=2, dt=dt, var=Q)
- print("Q过程噪声协方差矩阵kf.Q:", kf.Q)
- else:
- kf.Q[:] = Q
- return kf
- def run(x0=(0., 0.), P=500, R=0, Q=0, dt=1.0,
- track=None, zs=None,
- count=0, do_plot=True, **kwargs):
- """
- track is the actual position of the dog, zs are the
- corresponding measurements.
- """
- # Simulate dog if no data provided.
- if zs is None:
- # 生成 真实的track 测量值zs
- track, zs = compute_dog_data(z_var=R, process_var=Q, count=count, dt=dt)
- # create the Kalman filter
- kf = pos_vel_filter(x0, R=R, P=P, Q=Q, dt=dt)
- print("构建的卡尔曼滤波器对象:\n", kf.__repr__)
- # run the kalman filter and store the results
- xs, cov = [], []
- for z in zs:
- kf.predict()
- # # P = (I-KH)P(I-KH)' + KRK'
- # # This is more numerically stable
- # # and works for non-optimal K vs the equation
- # # P = (I-KH)P usually seen in the literature.
- kf.update(z)
- # xs是后验估计值 最优估计值
- xs.append(kf.x)
- # 看 P矩阵的变化
- cov.append(kf.P)
- xs, cov = np.array(xs), np.array(cov)
- # if do_plot:
- # plot_track(xs[:, 0], track, zs, cov, **kwargs)
- return track, zs, xs, cov
- x0 = (10., 10.) # 初始的位置与速度
- P = np.diag([500., 49.]) # 初始的误差协方差矩阵P
- frame_num = 50
- x_position_true, x_position_measure, X_kalman_est, all_P_cov_mat = run(x0=x0, count=frame_num, R=10, Q=1, P=P)
- print("所有的真实的位置:", x_position_true.shape)
- print("所有的测量的位置:", x_position_measure.shape)
- print("所有的后验估计值(位置与速度):", X_kalman_est.shape)
- print("所有的误差的协方差矩阵P:", all_P_cov_mat.shape)
- my_color = []
- for _ in range(frame_num):
- # 每一帧的颜色不一样
- my_color.append(randomcolor())
- # 画图展示
- plt.figure(figsize=(14, 12))
- plt.figure(1)
- plt.xlabel("位置", fontproperties=font, fontsize=15)
- plt.ylabel("速度", fontproperties=font, fontsize=15)
- # plot_covariance([20.0, 10.], np.diag([50, 50]), edgecolor='r')
- plot_covariance(x0, P, edgecolor='r', ls='dashed')
- for i in range(X_kalman_est.shape[0]):
- plt.title('误差的协方差矩阵P的变化(协方差椭圆)_第%d帧' % i, fontproperties=font, fontsize=16)
- # print("第%d帧的后验估计值:" % i, X_kalman_est[i, :])
- # print("第%d帧的误差协方差矩阵:" % i, all_P_cov_mat[i, :])
- plot_covariance(X_kalman_est[i, :], all_P_cov_mat[i, :], edgecolor=my_color[i])
- plt.pause(0.01)
- # if(i >= 3):
- # plt.pause(100000000)
- plt.figure(figsize=(14, 12))
- plt.figure(2)
- plt.xlabel("时间", fontproperties=font, fontsize=15)
- plt.ylabel("位置", fontproperties=font, fontsize=15)
- plt.title('线性kalman滤波算法', fontproperties=font, fontsize=16)
- # plt.ylim()
- plt.plot(x_position_true, color="g", linestyle=":", marker='o', markersize=6, label="x_position_true")
- plt.plot(x_position_measure, color="b", linestyle=":", marker='o', markersize=6, label="x_position_measure")
- print("看看位置改变的顺序:", X_kalman_est[:8, 0])
- plt.plot(X_kalman_est[:, 0], color="r", linestyle="-", marker='o', markersize=6, label="x_position_kalman_est")
- plt.legend()
- plt.show()
复制代码
|
|