卡尔曼滤波器设计及实例

1 卡尔曼滤波器基本原理

卡尔曼滤波常用于动态多变化系统中的状态估计,是一种通用性强的自回归滤波器。它的由来和NASA登月有关。其发明者鲁道夫.E.卡尔曼在一次访问NASA的时候,发现阿波罗计划中一个难点是轨道预测问题,因而提出了一种滤波器,可以帮助高效预测轨迹,辅助导航。NASA最终使用了这个滤波器,然后成功实现人类第一次登月计划。卡尔曼滤波器由此得名。

卡尔曼滤波器可以用来估计不确定信息,并给出状态量下一时刻的情况。即便在有噪声干扰的情况下,也可以较好的预测下一状态的情况,并找出多变量间不易察觉的相关性。因而卡尔曼滤波器可以很好适应不断变化的系统,并且内存占用量低,推理速度快,比较适合资源受限制的场景。

对于一个离散系统,其离散状态方程描述为:

其中u(k)是系统控制输入,w(k)是系统随机噪声。假设输出y(k)其测量值为z(k)。

则实施卡尔曼滤波器的步骤为:

1 初始化矩阵P,Q,R

其中P和Q是与转移矩阵A同秩的协方差方阵,R是1X1维的常量。

2 对于观测的每一拍k执行预测和更新操作:

Step1:按照状态方程计算新的状态变量X(k+1)

Step2:更新协方差矩阵P(k)

Step3:计算卡尔曼增益K(k+1)

Step4:利用测量值z(k)来更新状态变量X(k+1)

Step5:更新协方差矩阵P(k+1)

2 卡尔曼实例

假设有一辆小车,装有加速度传感器,可以测量小车的加速度a。并装有超声光学传感器,可以实时测量光从光源到达小车的时间Zt。采样时间间隔Ts,光速为c。请估计小车的速度和位置。

 对于这个例子,设状态变量为位置s和速度v。设控制变量u为加速度a。输出变量设置为观测时间Zt。根据关系式:

则可以写出如下状态方程:

用Ts采样时间离散化后状态方程为:

3 Python程序实现及仿真结果

 

import numpy as np
from matplotlib import pyplot as plt


C = 100  # velocity of light, just a simulation value
# generate perfect acceleration and corresponding velocity and distance
# 生成没有噪声的加速度信号,并用积分计算出对应的速度和距离 ---------------------------------
N_steps = 1000  # 1000 steps to estimate
Ts = 0.05  # time interval is 0.05s
timeline = np.arange(N_steps) * Ts  # \Delta t = 0.05s
accs_gt = np.sin(timeline)  # set accelerator as a log shape
vels_gt = np.cumsum(accs_gt*Ts)  # get the ground truth velocity;速度是加速度的积分
dists_gt = np.cumsum(vels_gt*Ts)  # get the ground truth distance; 距离是速度的积分
zs_gt = dists_gt/C
#----------------------------------

# add noise to acceleration signals and calculate the velocity and distance with simple integral
# 往加速度信号添加噪声模拟真实传感器信号,并用简单的积分计算速度和距离
accs_noise_var = 0.005  # set acceleration noise variation as 0.5
accs_noise = np.random.rand(N_steps) * accs_noise_var  # 注意,这里使用均匀分布模拟噪声,以模拟不知道真实噪声分布情况
accs_w_noise = accs_gt + accs_noise
vels_w_noise = np.cumsum(accs_w_noise*Ts)
# vels_w_noise = np.cumsum(accs_noise * Delta_t)
dists_w_noise = np.cumsum(vels_w_noise*Ts)
zs_noise_var = 0.001
zs_noise = np.random.rand(N_steps) * zs_noise_var  # 注意,这里使用均匀分布模拟噪声,以模拟不知道真实噪声分布情况
zs_w_noise = zs_gt + zs_noise
#---------------------------------
VIS_DATA = True
if VIS_DATA:
    fig = plt.figure()
    ax11 = fig.add_subplot(421)
    ax11.plot(timeline, accs_gt)
    ax11.set_title("Acceleration Ground Truth")

    ax12 = fig.add_subplot(422)
    ax12.plot(timeline, accs_w_noise)
    ax12.set_title("Acceleration With Noise")



    ax21 = fig.add_subplot(423)
    ax21.plot(timeline, vels_gt)
    ax21.set_title("Velocity Ground Truth")

    ax22 = fig.add_subplot(424)
    ax22.plot(timeline, vels_w_noise)
    ax22.set_title("Velocity With Noise")


    ax31 = fig.add_subplot(425)
    ax31.plot(timeline, dists_gt)
    ax31.set_title("Distance Ground Truth")

    ax32 = fig.add_subplot(426)
    ax32.plot(timeline, dists_w_noise)
    ax32.set_title("Distance With Noise")

    ax41 = fig.add_subplot(427)
    ax41.plot(timeline, zs_gt)
    ax41.set_title("Measurment Ground Truth")

    ax42 = fig.add_subplot(428)
    ax42.plot(timeline, zs_w_noise)
    ax42.set_title("Measurment With Noise")
    # plt.show()
    plt.subplots_adjust(wspace =0, hspace =0.5)#调整子图间距

# ------------------------------------------------------------------------------------------

A = np.array([
    [1, Ts],
    [0, 1]
])  # 状态转移矩阵
B = np.array([
    [Ts**2*0.5],
    [Ts]
])  # 控制转移矩阵
Q_var = 0.005
Q = np.array([
    [Q_var, 0],
    [0, Q_var]
])  # 预测噪声协方差矩阵
P0 = np.array([
    [0.0, 0],
    [0.0, 0]
])  # 状态向量协方差初始值
H = np.array([
1/C, 0
]).reshape((1,2))  # 测量转换矩阵
R_var = 0.001 
R = R_var  # 测量协方差矩阵,此时只有一个测量变量,因此只有一个值

x0 = np.array([
    [0],
    [0]
])  # 系统状态向量初始化,速度和距离均初始化为0

x_t_ = None  # predicted system state vector
x_t = None  # corrected system state vector
P_t_ = None  # covariance matrix of predicted state vector
P_t = None  # covariance matrix of corrected state vector
K = None

est_vel = [0]
est_dist = [0]
for i in range(N_steps):
    if i == 0:
        x_t = x0
        P_t = P0
        continue
    u = np.array([accs_w_noise[i]])
    x_t_ = A@x_t + B*u  # 预测方程
    P_t_ = A@P_t@(A.T) + Q  # 预测状态向量的协方差矩阵
    

    K = P_t_@H.T / (H@P_t_@H.T + R)  # 卡尔曼增益
    x_t = x_t_ + K*(zs_w_noise[i] - H@x_t_)  # 更新方程
    P_t = P_t_ - K@H@P_t_  # 更新状态向量协方差矩阵

    est_vel.append(x_t[1][0])
    est_dist.append(x_t[0][0])

est_vel = np.array(est_vel).reshape(-1)
est_dist = np.array(est_dist).reshape(-1)
diff_vel_est = est_vel - vels_gt
diff_dist_est = est_dist - dists_gt
diff_vel_sum = vels_w_noise - vels_gt
diff_dist_sum = dists_w_noise - dists_gt


# print(est_vel)
fig2 = plt.figure()
ax2_11 = fig2.add_subplot(231)
ax2_11.plot(timeline, est_vel)
ax2_11.set_title("Estimated velocity")

ax2_12 = fig2.add_subplot(232)
ax2_12.plot(timeline, diff_vel_est)
ax2_12.set_title("Error - Vel - KalmanFilter")

ax2_13 = fig2.add_subplot(233)
ax2_13.plot(timeline, diff_vel_sum)
ax2_13.set_title("Error - Vel - Simple integration")

ax2_21 = fig2.add_subplot(234)
ax2_21.plot(timeline, est_dist)
ax2_21.set_title("Estimated distance")

ax2_22 = fig2.add_subplot(235)
ax2_22.plot(timeline, diff_dist_est)
ax2_22.set_title("Error - Dist - KalmanFilter")

ax2_23 = fig2.add_subplot(236)
ax2_23.plot(timeline, diff_dist_sum)
ax2_23.set_title("Error - Dist - Simple integration")


plt.show()

参考:


卡尔曼滤波实战 | 形象化理解卡尔曼滤波(附源码)

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很抱歉,我无法提供具体的Matlab代码。但是,你可以在引用\[1\]中提供的链接中找到一个包含完整的Excel代码的卡尔曼滤波器二维实例。这个实例可以帮助你更好地理解和实现卡尔曼滤波器。此外,引用\[2\]中的视频也提供了关于递归算法卡尔曼滤波器的介绍,可能对你有所帮助。对于非线性系统滤波问题,你可以考虑使用扩展卡尔曼滤波(EKF)方法,它是一种常用的处理非线性系统滤波问题的方法。EKF的核心思想是将非线性函数进行线性化,并应用卡尔曼滤波完成对目标的滤波估计等处理。\[3\] #### 引用[.reference_title] - *1* [卡尔曼滤波实例 附matlab代码](https://blog.csdn.net/liujiwen1104/article/details/120666223)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [MATLAB实现卡尔曼滤波器仿真](https://blog.csdn.net/Master_0_/article/details/127813189)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [卡尔曼滤波应用及其matlab实现](https://blog.csdn.net/zhangquan2015/article/details/79264540)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值