欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

卡尔曼滤波示例

程序员文章站 2022-04-16 20:29:36
...

卡尔曼滤波5个公式,看起来简单,但想弄明白并不容易。从直接理解上,个人感觉比较有帮助的是这篇博客:http://blog.csdn.net/u013453604/article/details/50301477 ;但卡尔曼滤波本质上是一种linear dynamical systems,想理解透彻最好还是搞清楚这个东西,可参考PRML第13章。


现在先把最简单的示例传上来,后续根据linear dynamical systems的内容还需要进一步研究其参数配置优化方法。


如下是根据网上流传(百度百科)的温度预测范例程序修改后的结果,主要改进是:原程序中温度一直保持24度不变,这种情况下预测量是1维(温度);本程序修改温度为时变值,这种情况下要求预测量成为2维(温度和变化间隔),状态转移矩阵A也成为矩阵,而不是简单的1。


计算结果如下:

卡尔曼滤波示例


主程序:

clear all; close all; clc;

%% 
% web: http://blog.csdn.net/foreseerwang
% QQ: 50834

%% 初始化参数
n_iter = 300;       % 计算连续n_iter个时刻
n = 2;              % [温度,变化间隔]
m = 1;              % 温度

x = zeros(n, n_iter);           % 状态量,每个时刻包含两个值:温度,变化间隔
P = zeros(n, n, n_iter);        % 文档及变化间隔的方差
z = zeros(m, n_iter);           % 观测量

xrate=0.01;                     % 温度变化率
xreal = 24+(0:n_iter-1)*xrate;  % 温度变化间隔为1
z = xreal + randn(m,n_iter);    % 观测到的温度,误差方差为1

kf_para.A=[1,xrate;0,1];        % 状态转移矩阵,根据上一时刻预测当前时刻值
kf_para.H = zeros(m,n);         % 观测矩阵,把m维观测量转换成n维状态量
kf_para.H(1)=1;
kf_para.Q = [4e-4, 0; 0, 1e-4]; % 预测误差的方差
kf_para.R = 0.25;               % 观察误差的方差

x(:,1)=[23.5; 0.9];             % 初始化,第一个时刻的温度及变化间隔
P(:,:,1)=diag(rand(n,1));

%% 卡尔曼滤波迭代
for ii = 2:n_iter,

    [x(:,ii), P(:,:,ii)]=kf_iter(kf_para, x(:,ii-1), P(:,:,ii-1), z(ii));

end

%% 结果打印
figure;
plot(x(1,:),'r*'); hold; plot(z,'bo'); plot(xreal, 'k.');
legend('卡尔曼滤波后的温度', '观测温度', '真实温度');
title('温度对比');
ylabel('温度');

figure;
plot(x(2,:));
title('滤波后的温度变化间隔(真实值为1)');

fprintf('观测误差均值为:%5.3f;均方差为:%5.3f\n', mean(abs(z-xreal)), std(z-xreal));
fprintf('滤波误差均值为:%5.3f;均方差为:%5.3f\n', mean(abs(x(1,:)-xreal)), std(x(1,:)-xreal));

卡尔曼滤波函数:

function [ x, P ] = kf_iter( kf_para, x_k_1, P_k_1, z )
% kf_para:卡尔曼滤波器的参数,A、H、Q、R
% x_k_1,P_k_1:上一观测时刻的最优预测值及方差
% z:当前时刻的观测值
% x, P:当前时刻的最优预测值及方差

n=size(x_k_1,1);

% 根据前值预测当前值
xbar = kf_para.A*x_k_1;
Pbar=kf_para.A*P_k_1*kf_para.A' + kf_para.Q;

%计算卡尔曼增益
K = Pbar*kf_para.H'*pinv(kf_para.H*Pbar*kf_para.H'+kf_para.R); 

% 根据卡尔曼增益和当前观测值修订预测值,获得当前最优预测值
x=xbar+K*(z-kf_para.H*xbar);
P=(diag(ones(n,1))-K*kf_para.H)*Pbar;

end