MATLAB实现卡尔曼滤波器(KF、EKF)

卡尔曼滤波器

        卡尔曼滤波器是一个 ”optimal recursive data processing algorithm”(最优化自回归数据处理算法)。


先说一个例子:

        假设我们要研究的对象是一个房间的温度。

        1.根据经验,温度是恒定的,即上一分钟的温度等于现在这一分钟的温度,经验即预测,但这并不是完全可信的,即存在一定的误差。我们假设成高斯白噪声。

        2.另外在房间里放一个温度计,实时检测房间的温度,这是观测值。同样地也存在误差,也是高斯白噪声。

        我们现在的目标就是,用这两个值,结合它们各自的噪声,估算出房间的实际温度。假设要估算k时刻的实际温度值,首先需要知道k-1时刻的温度值。

        1)预测值,假设k-1时刻房间温度为23度,则k时刻的温度应该也为23度(恒定)。同时该值的偏差为5(5是3的平方加上4的平方再开方,其中3为k-1时刻估算出的最优温度值的偏差3,4为对预测的偏差)。

        2)测量值,假设为25度,同时偏差为4度。

        那么实际值为多少?相信谁多一点,可用它们的协方差来判断:

Kg = 0.78

        则实际的温度值是:23+0.78*(25-23) = 24.56度。可以看出温度计测量的covariance较小,所以实际值比较偏向温度计。

        在进入k+1时刻估算前,需要算出k时刻最优值(24.56)的偏差。算法,5即k时刻估算所用k-1时刻23度温度值的偏差。得出的2.35即k时刻最优值的偏差(对应上面k-1时刻的3)。

        这样卡尔曼滤波器就不断得把covariance递归,从而估算出最优值。而且它只保留上一刻的covariance。上面的Kg就是卡尔曼增益(Kalman Gain)。


真正工程系统上的卡尔曼滤波器算法

        首先引入一个离散控制过程的系统,改系统可用一个线性随机微分方程(linear stochastic difference equation)来描述:


         再加上系统的测量值:


         其中:X(k)是k时刻的系统状态,U(k)是k时刻对系统的控制量。A和B是系统参数,对于多模系统,它们为矩阵。

        Z(k)是k时刻的测量值,H是测量参数,对于多模系统,H为矩阵。W(k)和V(k)分别表示过程和测量的噪声,它们被假设成高斯白噪声,它们的covariance分别是Q,R。

        对于满足上面条件(线性随机微分系统,过程和测量都是高斯白噪声),卡尔曼滤波器是最优的信息处理器。


卡尔曼滤波器算法流程及核心公式

        首先利用系统过程模型,来预测下一个状态的系统:


        X(k | k-1) 是利用上一状态预测的结果,X(k-1 | k-1) 是上一状态最优结果。U(k)为现在状态的控制量,若没有,可为0.

        现在更新 X(k | k-1) 的covariance,用P表示:


        其中 P(k | k-1) 是 X(k | k-1) 对应的covariance;P(k-1 | k-1) 是 X(k-1 | k-1) 对应的covariance。A' 表示A的转置矩阵,Q是系统的covariance。

        式(1)(2)是5各公式的前两个,用来对系统进行预测。

        然后再收集系统的观测值 Z(k),则最优值:


        其中Kg为卡尔曼增益(Kalman Gain):


        到目前为止,已经得到k状态下最优的估算值 X(k | k-1)

        但是为了要卡尔曼滤波器不断得运行下去直到系统过程结束,需要更新k状态下 X(k | k-1) 的covariance:


        其中I为1的矩阵,对于单模系统I = 1。

        当系统进入k+1状态时,P(k | k) 就是式(2)中的  P(k-1 | k-1)。这样,算法就可以自回归地运算下去。


扩展卡尔曼滤波器

        由上述的介绍可以得知,卡尔曼滤波器只适用于线性系统模型,然而实际中的系统往往都是非线性模型。所示必须对卡尔曼滤波器进行修改。

        首先要了解一下线性化卡尔曼滤波。它和线性卡尔曼滤波器在滤波器的算法方面有同样的算法结构。不一样的地方在于这两者的系统模型不同。线性卡尔曼滤波器的系统本身就是线性系统,而线性化卡尔曼滤波器的系统本身是非线性系统,但是机智的大神们将非线性的系统进行了线性化,于是卡尔曼滤波就可以用在非线性系统中了。对于一个卡尔曼滤波器的设计者,就可以不管模型到底是一开始就是线性系统还是非线性系统线性化得到的线性系统,反正只要是线性系统就好了。

        但是线性化卡尔曼滤波器会发散。为什么会发散呢?是这样,我们在对非线性系统进行线性化的过程中,只有被线性化的那个点附近的线性化模型和真实的模型相近,远的误差就大了,那么这个时候卡尔曼滤波器的效果就不好。所以线性化的这个限制要时刻考虑,这也就是为什么要把线性卡尔曼滤波器和线性化卡尔曼滤波器区分开的理由。而决定一个线性化滤波器成功与否的关键就在于这个滤波器系统模型线性化得好不好

        EKF基于线性化系统的思想,将系统函数的非线性函数作一阶Taylor展开,得到线性化系统方程。扩展的卡尔曼滤波器算法就是适用于非线性系统的卡尔曼滤波器。它与经典的线性卡尔曼滤波器很相似,算法步骤和结构都相同。不同在于系统模型和矩阵A和H。


MATLAB实现卡尔曼滤波器(房间温度例子)

% Kalman filter example of temperature measurement in Matlab implementation of Kalman filter algorithm.
% 房间当前温度真实值为24度,认为下一时刻与当前时刻温度相同,误差为0.02度(即认为连续的两个时刻最多变化0.02度)。
% 温度计的测量误差为0.5度。
% 开始时,房间温度的估计为23.5度,误差为1度。
close all;

% intial parameters
% 计算连续n_iter个时刻
n_iter = 100;
% size of array. n_iter行,1列
sz = [n_iter, 1];
% 温度的真实值
x = 24;
% 过程方差,反应连续两个时刻温度方差。更改查看效果
Q = 4e-4;
% 测量方差,反应温度计的测量精度。更改查看效果
R = 0.25;
% z是温度计的测量结果,在真实值的基础上加上了方差为0.25的高斯噪声。
z = x + sqrt(R)*randn(sz);
% 对数组进行初始化
% 对温度的后验估计。即在k时刻,结合温度计当前测量值与k-1时刻先验估计,得到的最终估计值
xhat = zeros(sz); 
% 后验估计的方差
P = zeros(sz); 
% 温度的先验估计。即在k-1时刻,对k时刻温度做出的估计
xhatminus = zeros(sz);
% 先验估计的方差
Pminus = zeros(sz);
% 卡尔曼增益,反应了温度计测量结果与过程模型(即当前时刻与下一时刻温度相同这一模型)的可信程度
K = zeros(sz); 
% intial guesses
xhat(1) = 23.5; %温度初始估计值为23.5度
P(1) =1; % 误差方差为1

for k = 2:n_iter
    % 时间更新(预测)
    % 用上一时刻的最优估计值来作为对当前时刻的温度的预测
    xhatminus(k) = xhat(k-1);
    % 预测的方差为上一时刻温度最优估计值的方差与过程方差之和
    Pminus(k) = P(k-1)+Q;
    % 测量更新(校正)
    % 计算卡尔曼增益
    K(k) = Pminus(k)/( Pminus(k)+R );
    % 结合当前时刻温度计的测量值,对上一时刻的预测进行校正,得到校正后的最优估计。该估计具有最小均方差
    xhat(k) = xhatminus(k)+K(k)*(z(k)-xhatminus(k));
    % 计算最终估计值的方差
    P(k) = (1-K(k))*Pminus(k);
end

FontSize = 14;
LineWidth = 3;
figure();
plot(z,'k+'); %画出温度计的测量值
hold on;
plot(xhat,'b-','LineWidth',LineWidth) %画出最优估计值
hold on;
plot(x*ones(sz),'g-','LineWidth',LineWidth); %画出真实值
legend('温度计的测量结果', '后验估计', '真实值');
xl = xlabel('时间(分钟)');
yl = ylabel('温度');
set(xl,'fontsize',FontSize);
set(yl,'fontsize',FontSize);
hold off;
set(gca,'FontSize',FontSize);

figure();
valid_iter = 2:n_iter; % Pminus not valid at step 1
% 画出最优估计值的方差
plot(valid_iter,P(valid_iter),'LineWidth',LineWidth);
legend('后验估计的误差估计');
xl = xlabel('时间(分钟)');
yl = ylabel('℃^2');
set(xl,'fontsize',FontSize);
set(yl,'fontsize',FontSize);
set(gca,'FontSize',FontSize);


MATLAB实现扩展卡尔曼滤波器

% function: simulating the process of EKF
N = 50;           % 计算连续N个时刻
n = 3;             % 状态维度
q = 0.1;          % 过程标准差
r = 0.2;           % 测量标准差
% eye函数产生单位矩阵
Q = q^2*eye(n);   % 过程方差
R = r^2;               % 测量值的方差

%{
     FUNHANDLE = @FUNCTION_NAME returns a handle to the named function,
     FUNCTION_NAME. A function handle is a MATLAB value that provides a
     means of calling a function indirectly. 
%}
f = @(x)[x(2);x(3);0.05*x(1)*(x(2)+x(3))];  % 状态方程
h = @(x)[x(1);x(2);x(3)];                          % 测量方程
s = [0;0;1];                                            % 初始状态

% 初始化状态
x = s+q*randn(3,1); 
% eye返回单位矩阵
P = eye(n);
% 3行50列,一列代表一个数据
% 最优估计值
xV = zeros(n,N);
% 真实值
sV = zeros(n,N);
% 状态测量值
zV = zeros(n,N);

for k = 1:N
    z = h(s) + r * randn;
    % 实际状态
    sV(:,k) = s;
    % 状态测量值
    zV(:,k) = z;
    
    % 计算f的雅可比矩阵,其中x1对应黄金公式line2
    [x1,A] = jaccsd(f,x);
    % 过程方差预测,对应line3
    P = A*P*A'+Q;
    % 计算h的雅可比矩阵
    [z1,H] = jaccsd(h,x1);
    
    % 卡尔曼增益,对应line4
    % inv返回逆矩阵
    K = P*H'*inv(H*P*H'+R);
    % 状态EKF估计值,对应line5
    x = x1+K*(z-z1);
    % EKF方差,对应line6
    P = P-K*H*P;
    
    % save
    xV(:,k) = x;
    % update process 
    s = f(s) + q*randn(3,1);
end

for k = 1:3
    FontSize = 14;
    LineWidth = 1;
    
    figure();
    % 画出真实值
    plot(sV(k,:),'g-');
    hold on;
    
    % 画出最优估计值
    plot(xV(k,:),'b-','LineWidth',LineWidth);
    hold on;
    
    % 画出状态测量值
    plot(zV(k,:),'k+');
    hold on;
    
    legend('真实状态', 'EKF最优估计估计值','状态测量值');
    xl = xlabel('时间(分钟)');
    % 把数值转换成字符串, 转换后可以使用fprintf或disp函数进行输出。
    t = ['状态 ',num2str(k)] ;
    yl = ylabel(t);
    set(xl,'fontsize',FontSize);
    set(yl,'fontsize',FontSize);
    hold off;
    set(gca,'FontSize',FontSize);
end
function [z, A] = jaccsd(fun, x)
% JACCSD Jacobian through complex step differentiation
% [z J] = jaccsd(f,x)
% z = f(x)
% J = f'(x)
%
z = fun(x);
% numel返回数组中元素个数。若是一幅图像,则numel(A)将给出它的像素数。
n = numel(x);
m = numel(z);
A = zeros(m,n);
h = n*eps;
for k = 1:n
    x1 = x;
    x1(k) = x1(k)+h*1i;
    % imag返回复数的虚部
    A(:,k) = imag(fun(x1))/h;
end




  • 54
    点赞
  • 431
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
1.项目代码功能经验证ok,确保稳定可靠运行。欢迎下载使用! 2.主要针对各个计算机相关专业,包括计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网等领域的在校学生、专业教师或企业员工使用。 3.项目具有丰富的拓展空间,不仅可作为入门进阶,也可直接作为毕设、课程设计、大作业、初期项目立项演示等用途。 4.当然也鼓励大家基于此进行二次开发。在使用过程中,如有问题或建议,请及时私信沟通。 5.期待你能在项目中找到乐趣和灵感,也欢迎你的分享和反馈! 【资源说明】 基于matlab实现卡尔曼滤波KF、无迹卡尔曼滤波UKF、拓展卡尔曼滤波EKF等源码+超详细注释.zip基于matlab实现卡尔曼滤波KF、无迹卡尔曼滤波UKF、拓展卡尔曼滤波EKF等源码+超详细注释.zip基于matlab实现卡尔曼滤波KF、无迹卡尔曼滤波UKF、拓展卡尔曼滤波EKF等源码+超详细注释.zip基于matlab实现卡尔曼滤波KF、无迹卡尔曼滤波UKF、拓展卡尔曼滤波EKF等源码+超详细注释.zip基于matlab实现卡尔曼滤波KF、无迹卡尔曼滤波UKF、拓展卡尔曼滤波EKF等源码+超详细注释.zip基于matlab实现卡尔曼滤波KF、无迹卡尔曼滤波UKF、拓展卡尔曼滤波EKF等源码+超详细注释.zip基于matlab实现卡尔曼滤波KF、无迹卡尔曼滤波UKF、拓展卡尔曼滤波EKF等源码+超详细注释.zip基于matlab实现卡尔曼滤波KF、无迹卡尔曼滤波UKF、拓展卡尔曼滤波EKF等源码+超详细注释.zip 基于matlab实现卡尔曼滤波KF、无迹卡尔曼滤波UKF、拓展卡尔曼滤波EKF等源码+超详细注释.zip 基于matlab实现卡尔曼滤波KF、无迹卡尔曼滤波UKF、拓展卡尔曼滤波EKF等源码+超详细注释.zip
【资源说明】 1、该资源包括项目的全部源码,下载可以直接使用! 2、本项目适合作为计算机、数学、电子信息等专业的课程设计、期末大作业和毕设项目,作为参考资料学习借鉴。 3、本资源作为“参考资料”如果需要实现其他功能,需要能看懂代码,并且热爱钻研,自行调试。 基于Matlab实现扩展卡尔曼滤波(EKF)源码+项目说明+超详细注释.zip # 基于Matlab实现扩展卡尔曼滤波(EKF) 使用混合型扩展卡尔曼滤波器估计双摆模型在噪声干扰下的两个旋转角度(使用四阶龙格库塔法求解微分方程)。 ## 1. 状态空间方程 在现代控制中,使用状态空间方程描述系统 $$\left\{\begin{matrix} \dot{x}=f(x,u)\\ y = h(x,u) \end{matrix}\right.$$ 由于实际物理模型运行时系统可能受到扰动,并且测量存在误差(干扰),真实的状态空间方程为: $$\left\{\begin{matrix} \dot{x}=f(x,u)+\omega\\ y = h(x,u)+\nu \end{matrix}\right.$$ $\omega, \nu$均为噪声且相互独立,$\omega \sim N(0, Q), \nu \sim N(0, R)$。 我们无法对噪声进行准确建模,如果可以,那么将噪声作为已知项带入状态空间方程可以准确得到系统的状态。但是我们拥有噪声的统计学信息,卡尔曼滤波正是利用了这些信息,通过预测-校正两大步骤得到系统状态的**最优估计**。 卡尔曼滤波器分为线性卡尔曼滤波器(KF)、扩展卡尔曼滤波器(EKF)、无迹卡尔曼滤波器(UKF),后两种用于非线性系统的状态估计。 根据状态方程和测量方程的形式分为标准型(两个方程均为连续或者离散形式)和混合型(一个为连续方程,另一个为离散方程)。 ## 2. 线性卡尔曼滤波 ### 2.1 标准型 #### 2.1.1 连续型 连续且含噪声的线性状态空间方程为: ......
MATLAB实现扩展卡尔曼滤波(EKF),你可以按照以下步骤进行: 1. 定义系统模型:首先,你需要定义你的系统模型,包括状态方程和观测方程。状态方程描述了系统的动态演化,而观测方程表示如何从系统状态中获取观测值。 2. 初始化滤波器:在开始滤波之前,你需要初始化滤波器的状态和协方差矩阵。这些初始化值可以根据具体问题进行选择。 3. 预测步骤:在每个时间步骤中,首先进行预测步骤。使用状态方程预测下一个时间步骤的状态和协方差。 4. 更新步骤:在预测步骤之后,进行更新步骤。通过计算卡尔曼增益和观测残差,将预测的状态和协方差更新为最优估计。 5. 重复预测和更新:重复进行预测和更新步骤,以实时更新状态估计。 这里是一个简单的示例代码,演示了如何在MATLAB实现扩展卡尔曼滤波: ```matlab % 系统模型 A = [1 1; 0 1]; % 状态转移矩阵 C = [1 0]; % 观测矩阵 Q = [0.01 0; 0 0.01]; % 状态噪声协方差 R = 1; % 观测噪声方差 % 初始化滤波器状态和协方差 x = [0; 0]; % 初始状态估计 P = eye(2); % 初始状态协方差矩阵 % 数据 data = [1.2 2.4 3.6 4.8 6.0]; % 扩展卡尔曼滤波 for i = 1:length(data) % 预测步骤 x_pred = A * x; P_pred = A * P * A' + Q; % 更新步骤 y = data(i) - C * x_pred; S = C * P_pred * C' + R; K = P_pred * C' * inv(S); x = x_pred + K * y; P = (eye(2) - K * C) * P_pred; disp(['Step ' num2str(i) ':']); disp(['State estimate: ' num2str(x')]); disp(['Covariance matrix:']); disp(P); end ``` 请注意,这只是一个简单的示例代码,实际应用中可能需要根据具体问题进行更复杂的调整和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值