|
一维线性kalman滤波算法实例_改进R变化
思考步骤:
1、状态变量 x1=距离/位置(米) 先写出一个系统的离散的状态空间方程表达
x1还是应该为 速度
2、线性kalman对数据要求很严格 要求整段数据的方差是固定的 Q R矩阵的取值问题
后验估计是:谁方差小 就更信任谁 但是这个问题的数据是 刚开始方差小 中间方差大 后面方差又小
改变:能不能让Q R 矩阵的方差 随这数据 在变 可以的 测量噪声:协方差矩阵R 可以根据测量结果改变
由于得不到真实的值 所以Q的方差 不好变 只能固定一个经验值
发现:初值很关键 很敏感啊
- # -*- coding: utf-8 -*-
- __author__ = u'东方耀 微信:dfy_88888'
- __date__ = '2022/2/23 上午11:45'
- __product__ = 'PyCharm'
- __filename__ = 'j04_kalman_filter_状态变量(动目标的距离)'
- import numpy as np
- import matplotlib.pyplot as plt
- import matplotlib.ticker as mticker
- from matplotlib.font_manager import FontProperties
- font_fname = "/usr/share/fonts/wps-office/simfang.ttf"
- # font_fname = "C:\Windows\Fonts\simfang.ttf"
- font = FontProperties(fname=font_fname)
- # plt.rcParams['font.sans-serif']=['simfang']#设置作图中文显示
- '''
- 一维线性kalman滤波算法实例_改进R变化
- 思考步骤:
- 1、状态变量 x1=距离/位置(米) 先写出一个系统的离散的状态空间方程表达
- x1还是应该为 速度
- 2、线性kalman对数据要求很严格 要求整段数据的方差是固定的 Q R矩阵的取值问题
- 后验估计是:谁方差小 就更信任谁 但是这个问题的数据是 刚开始方差小 中间方差大 后面方差又小
- 改变:能不能让Q R 矩阵的方差 随这数据 在变 可以的 测量噪声:协方差矩阵R 可以根据测量结果改变
- 由于得不到真实的值 所以Q的方差 不好变 只能固定一个经验值
- 发现:初值很关键 很敏感啊
- '''
- save_distance_csv_file = "/media/jiang/AI_Data/jjj_matlab_works/ZTR/actual_used_data/python/multi_frame_147_distance.csv"
- distance = np.loadtxt(save_distance_csv_file, delimiter=',')
- prt = 450 * 700e-6
- # 状态转移矩阵,上一时刻的状态转移到当前时刻
- # 数学模型中得到的 这是固定的
- A = np.array([[1]])
- # 测量矩阵 从测量或传感器的方程得到 也是固定的
- H = np.array([[1]])
- # 过程噪声:协方差矩阵Q, p(w)~N(0,Q),噪声来自真实世界中的不确定性
- # 位置与速度是相互独立的 所以只有对角线有值
- Q = np.array([[0.08]])
- # 测量噪声:协方差矩阵R, p(v)~N(0,R)
- R = np.array([[100.0]])
- len_counter_R_var = 5
- # 初始速度 0 行吗? 改为1呢?
- X0 = np.array([[1.0]])
- # 初始 误差的协方差矩阵
- P = np.array([[300.0]])
- # ---------------------------初始化-------------------------
- X_posterior_est = np.array(X0)
- P_posterior = np.array(P) # 不停在更新 在变
- # 真实值
- # speed_true = [] # 不可能知道
- speed_measure = [] # 测量值
- speed_prior_est = [] # prior 先验估计值
- speed_posterior_est = [] # posterior 后验估计值
- distance_kalman = distance.copy()
- distance_kalman[0] = 0
- distance_kalman[1] = distance[1]
- for i in range(2, len(distance)):
- # abs(distance[i] - distance[i-1])
- # w = np.array([[gaussian_distribution_generator(Q[0, 0])]])
- # X_true = np.dot(A, X_true) + w
- # speed_true.append(X_true[0, 0])
- Z_measure = np.array([[np.abs(distance[i] - distance[i - 1]) / prt]])
- speed_measure.append(Z_measure[0, 0])
- # assert 0 == 1, "停"
- # ----------------------进行先验估计 真正的kalman算法---------------------
- X_prior_est = np.dot(A, X_posterior_est) # X_posterior_est需要初值
- speed_prior_est.append(X_prior_est[0, 0])
- if (len(speed_measure) >= len_counter_R_var):
- print("(第%d次循环)测量系统的方差:" % i, np.var(np.array(speed_measure[-len_counter_R_var:])))
- # Q[0, 0] = np.var(np.array(speed_prior_est[-len_counter_R_var:])) 这样改不行 是真实值的方差
- R[0, 0] = np.var(np.array(speed_measure[-len_counter_R_var:]))
- # 计算先验误差的协方差矩阵P
- # print("第%d次使用的误差的协方差矩阵P(几次后会稳定下来)=\n" % i, P_posterior)
- P_prior_1 = np.dot(A, P_posterior) # P_posterior 需要初值
- P_prior = np.dot(P_prior_1, A.T) + Q
- # ----------------------计算卡尔曼增益,用numpy一步一步计算Prior and posterior
- k1 = np.dot(P_prior, H.T)
- k2 = np.dot(np.dot(H, P_prior), H.T) + R
- K = np.dot(k1, np.linalg.inv(k2)) # np.linalg.inv():矩阵求逆
- # print("第%d次计算得到的卡尔曼增益K(几次后会稳定下来)=\n" % i, K)
- # ---------------------后验估计------------
- X_posterior_est_1 = Z_measure - np.dot(H, X_prior_est)
- # X的后验估计 = X的先验估计 + 系数 * (测量值 - H * X的先验估计)
- X_posterior_est = X_prior_est + np.dot(K, X_posterior_est_1)
- print("第%d次循环的kalman滤波结果(Q=%.2f,R=%.2f):先验估计的速度=%.1f,测量的速度=%.1f,后验估计的速度=%.2f" % (i, Q[0, 0], R[0, 0], X_prior_est[0, 0], Z_measure[0, 0], X_posterior_est[0, 0]))
- # X_posterior_est 真正要的结果
- if (distance[i] - distance[i - 1] >= 0):
- distance_kalman[i] = distance_kalman[i - 1] + X_posterior_est[0, 0] * prt
- else:
- distance_kalman[i] = distance_kalman[i - 1] - X_posterior_est[0, 0] * prt
- speed_posterior_est.append(X_posterior_est[0, 0])
- # 更新(误差)协方差矩阵P
- P_posterior_1 = np.eye(1) - np.dot(K, H)
- P_posterior = np.dot(P_posterior_1, P_prior)
- # print("测量出来的速度:", speed_measure, np.var(np.array(speed_measure)))
- plt.figure(figsize=(14, 12))
- plt.figure(1)
- plt.plot(speed_measure, color='black', marker='o', markersize=6, label="speed_measure")
- plt.plot(speed_posterior_est, color='red', marker='o', markersize=6, label="speed_posterior_est")
- plt.plot(speed_prior_est, color='blue', marker='o', markersize=6, label="speed_prior_est")
- plt.xlabel("状态变化次数(积累帧数-1)", fontproperties=font, fontsize=15)
- plt.ylabel("动目标速度", fontproperties=font, fontsize=15)
- plt.title('卡尔曼滤波的1d实例_动目标速度(kalman状态变量)', fontproperties=font, fontsize=16)
- plt.legend()
- plt.figure(figsize=(14, 12))
- plt.figure(2)
- plt.xlabel("帧索引(slow_time)", fontproperties=font, fontsize=15)
- plt.ylabel("距离(米)", fontproperties=font, fontsize=15)
- plt.title('目标轨迹(径向距离变化_argmax算法)_kalman速度转距离', fontproperties=font, fontsize=16)
- plt.plot(distance, color='black', marker='o', markersize=6, label="distance_measure")
- plt.plot(distance_kalman, color='red', marker='o', markersize=6, label="distance_kalman")
- plt.legend()
- plt.show()
复制代码
|
|