主要内容

C代码生成的一种MATLAB卡尔曼滤波算法

这个例子展示了如何生成一个MATLAB®卡尔曼滤波函数的C代码,卡尔曼滤波,它根据过去的噪声测量值估计运动对象的位置。它还显示了如何为该MATLAB代码生成MEX函数,以提高算法在MATLAB中的执行速度。

先决条件

这个示例没有先决条件。

关于卡尔曼滤波函数

卡尔曼滤波函数根据移动对象的过去值预测其位置。它使用一个卡尔曼滤波器估计器,一个递归自适应滤波器,从一系列噪声测量估计动态系统的状态。卡尔曼滤波在信号和图像处理、控制设计和计算金融等领域有着广泛的应用。

关于卡尔曼滤波估计算法

卡尔曼估计器通过计算和更新卡尔曼状态向量来计算位置向量。状态向量定义为一个6乘1的列向量,其中包括二维笛卡尔空间中的位置(x和y)、速度(Vx Vy)和加速度(Ax和Ay)测量值。基于经典运动定律:

X X 0 + V x d t Y Y 0 + V y d t V x V x 0 + 一个 x d t V y V y 0 + 一个 y d t

捕捉这些规律的迭代公式反映在Kalman状态转移矩阵“A”中。请注意,通过编写大约10行MATLAB代码,您可以根据许多自适应滤波教科书中的理论数学公式实现Kalman估计器。

类型kalmanfilter.m
% Copyright 2010 The MathWorks, Inc. function y = kalmanfilter(z) %#codegen dt=1;初始化状态转移矩阵A=[1 0 dt 0 0 0;…% [x] 0 1 0 dt 0 0;…% [y] 0 0 1 0 dt 0;…% [Vx] 0 0 0 1 0 dt;…% [Vy] 0 0 0 0 1 0;…% [Ax] 0 0 0 0 1;% [Ay] H = [1 0 0 0 0 0;0 1 0 0 0 0];%初始化测量矩阵Q =眼(6); R = 1000 * eye(2); persistent x_est p_est % Initial state conditions if isempty(x_est) x_est = zeros(6, 1); % x_est=[x,y,Vx,Vy,Ax,Ay]' p_est = zeros(6, 6); end % Predicted state and covariance x_prd = A * x_est; p_prd = A * p_est * A' + Q; % Estimation S = H * p_prd' * H' + R; B = H * p_prd'; klm_gain = (S \ B)'; % Estimated state and covariance x_est = x_prd + klm_gain * (z - H * x_prd); p_est = p_prd - klm_gain * H * p_prd; % Compute the estimated measurements y = H * x_est; end % of the function

负载测试数据

要跟踪的对象的位置被记录为笛卡尔空间中的x和y坐标,保存在MAT文件中位置_data.mat.下面的代码加载MAT文件并绘制位置的轨迹。测试数据包括两个位置上的突然移动或不连续,用来检查卡尔曼滤波器能否快速地重新调整和跟踪目标。

负载位置_data.mat持有;网格;
当前绘图保持不变
idx=1:numPts z=位置(:,idx);绘图(z(1),z(2),“bx”);轴([-11-11]);结束头衔(“具有2个突然不连续的卡尔曼滤波的测试向量”);包含(“轴”);伊莱贝尔(“轴”);持有;

图中包含一个轴对象。带有标题的具有2个突发性不连续的卡尔曼滤波测试向量的轴对象包含310个线型对象。

目前公布的情节

检查并运行ObjTrack函数

ObjTrack.m函数调用Kalman filter算法,以蓝色绘制对象的轨迹,以绿色绘制Kalman filter估计的位置。最初,您会发现估计的位置需要很短的时间才能收敛到对象的实际位置。然后,位置会发生三次突然移动。每次Kalman filter重新调整并在几次迭代后跟踪对象。

类型ObjTrack
% Copyright 2010 The MathWorks, Inc. function ObjTrack(position) %#codegen %%处理并绘制300个样品图;保持;网格;% Prepare plot window % Main loop for idx = 1: numPts z = position(:,idx);%获取输入数据y = kalmanfilter(z);%调用卡尔曼滤波估计位置plot_trajectory(z,y);%绘制结果结束保持;函数的结束%
ObjTrack(位置)
当前绘图保持不变

图中包含一个轴对象。标题为“对象轨迹”的轴对象[蓝色]它的卡尔曼估计[绿色]包含600个类型为line的对象。

目前公布的情节

生成C代码

codegen指挥-配置:lib选项生成打包为独立C库的C代码。

因为C使用静态类型,codegen必须在编译时确定MATLAB文件中所有变量的属性。这里,这个arg游戏命令行选项提供了一个示例输入,以便codegen可以根据输入类型推断新的类型。

-报告选项生成编译报告,其中包含编译结果的摘要和到所生成文件的链接。编译MATLAB代码后,codegen提供到此报表的超链接。

z =位置(:1);codegen-配置:lib-报告- ckalmanfilter.marg游戏{z}
代码生成成功:要查看报告,打开('codegen/lib/kalmanfilter/html/report.mldatx')

检查生成的代码

生成的C代码位于codegen / lib / kalmanfilter /文件夹中。的文件是:

dircodegen / lib / kalmanfilter /
.kalmanfilter.h..kalmanfilter\u data.c.gitignore kalmanfilter\u data.h\u clang格式kalmanfilter\u initialize.c buildInfo.mat kalmanfilter\u initialize.h codeInfo.mat kalmanfilter\u rtw.mk codescriptor.dmr kalmanfilter\u terminate.c compileInfo.mat kalmanfilter\u terminate.h defines.txt kalmanfilter类型.h示例rtw项目html RTYpes.h接口卡尔曼过滤器

检查C代码kalmanfilter.c函数

类型codegen/lib/kalmanfilter/kalmanfilter.c
/**文件:kalmanfilter.c**MATLAB编码器版本:5.3*c/c++源代码生成日期:2021年9月1日08:20:37*/*包括文件*/#包括“kalmanfilter.h”#包括“kalmanfilter_data.h”#包括“kalmanfilter_initialize.h”#包括#包括/*变量定义*/静态双x_est[6];静态双p_est[36];/*函数定义*/**Arguments:const double z[2]*double y[2]*返回类型:void*/void kalmanfilter(const double z[2],double y y[2]){static const short R[4]={1000,0,0,0,1000};static const signed char a[36]={1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1}静态常量签名字符iv[36]{1,0,0,1,1,1,1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,0,0,1,0,0,0,0,0,4[36[36]第四[36]{{{{{{1,静态警察第四[36]第四[36]第四[36]号,静态警察字符第四[36]第四[36]第四[36]本人本人本人本人[36]第四[36]本人本人,静态,静态,静态警察警察,静态,静态警察签署字符第五五,第五,第四[36]第五,第五,第四[36[36]第五,第五,第四[36]第五,第五,第四[36[36]第五五,第五双Y[12] 双x_prd[6];双S[4];双b_z[2];双a21;双a22;双a22_tmp;双d;双d1;int i;int k;int r1;int r2;带符号字符Q[36];if(!isInitialized_kalmanfilter){kalmanfilter_initialize();}/*版权所有2010 MathWorks,Inc./*初始化状态转移矩阵*//*/*%[x]*//*/*%[y]/*/%[Vx]*/*%[Vy]*/*%[Ax]*/*/*[Ay]*/*初始化测量矩阵*/for(i=0;i<36;i++){Q[i]=0;}/*初始状态条件*/*预测状态和协方差*/for(k=0;k<6;k++){Q[k+6*k]=1;x_prd[k]=0.0;for(i=0;i<6;i++){k=6*i;xPRD[k]+=k=k=k+k=k+k+k+k+k+k=6*i;x=r1;x=r=0(r2=0;r2=0;r2=0;r2=0;r2<0;r2;r2<6;r2;r2;r2+0;r2+6*r2*r2)p_[r2+6*i \590;r2=0;r2(r2=0;r2<6;r2+0;r2++)及{(d)a[k+6*6*i[i [i ::::::::[r2=0;r2=0;r2=0;r2=0;r2=0;r2+5;r2+5;r2+5;r2+5;r2+5;r2+5;r2+5;r2+5;r2+5;r2+5;r2+5;r2+5;r2+6*r2+6*r2+5)R+5+及及+5.R+5.p.p.p.p.p.p.p.p.p.p.p.p.p.p.p.p.p.{for(r2=0;r2=0;r2=0;r2=0;r2=0;r1<6;r1++)以及(二)d++(双)c(双)CUA[i++(r1<<0 0 0;r2=0;r2=0;r1=0;r1=0;r1=0;r1=0;r1<6;r1;r1++)及(d)d++(双)c(双)c(双)U a[U a[i[i[i++(i++(i++(i(i++(1)(r1<1)(1)(1<1<1<1<1<1)(1<1<1<1<1)(r1<1<1<1<1<1))))))[1[1[1[1[1[1[1[1[1[1[1[1[1[1[1[1<<1[1[1[1[1[1[1[1[1[1<1])>晶圆厂(S[0]))(1)上述人士;2(1)(1)(1)(1)(1)(1)(2)(1)(2)(1)(1)(1)(1)(1)(1)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2)(2))r2+6*i]=Y[i+(r2<1)];}估计的国家及协方差*估计的国家及估计的状态及协方差*估计的国家及估计的国家及估计的国家及协方差*估计的国家及估计的国家及估计的国家及协方差*估计的国家及估计的国家及估计的国家及协方差*估计的国家及估计的国家及协方差*估计的国家及估计的国家及估计的国家及估计的国家及协方差*估计的估计的国家及协方差**估计的估计的国家及协方差**估计的估计的统计及协方差*估计国家及协方差***估计国家及协方差*估计.估计的估计的国家及协方差*估计国家及协方差*估计国家及协方差*估计国家及协方差*估计的估计国家及协方差*及协方差********估计国家及协方差*估计国家及协方差*估计国家及协方差...估计国家及协方差*估计的估计国家及协方差....估计国家及协方差....估计国家及协方差....估计的i+6*r2]=b[i]*(双)c_a[r1](r2=0;r1=0;0;r1=0;r1=0;r1=0;r1=0;r1=0;r1=0;r1=0;r1<0;r1<6;r1<6;r1++;r1++)和(r1=0;双)两个(双)c(双)c(双)c(U)c(U a[1[1+1+1+1[1[1[1[1[1[1[1[1[1[1[1[1[1[1;1;1;1;1;1;1;1;1;1;1;1;1;1;1[6;1[6;1;1[6;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1[1;1;1;1;1;1}y[i]=d;}}/**参数:void*返回类型:void*/void kalmanfilter_init(void){int i;for(i=0;i<6;i++){x_est[i]=0.0;}/*x_est=[x,y,Vx,Vy,Ax,Ay]*/memset(&p_est[0],0,36U*sizeof(double))}/**kalmanfilter.c**[EOF]的文件尾*/

加快MATLAB算法的执行速度

您可以加速的执行速度卡尔曼滤波函数,该函数使用codegen命令从MATLAB代码生成MEX函数。

调用kalman_loop处理大型数据集的函数

首先,在MATLAB中使用大量的数据样本运行卡尔曼算法。的kalman_loop函数运行卡尔曼滤波函数循环。循环迭代的次数等于函数输入的第二个维度。

类型kalman_loop
%版权所有2010 MathWorks,Inc.函数y=kalman_loop(z)%Call kalman estimator in The loop for large data set testing%#codegen[DIM,LEN]=size(z);y=zeros(DIM,LEN);%n=1的初始化输出:LEN%回路中的输出y(:,n)=kalman滤波器(z(:,n));结束;

没有编译的基线执行速度

现在用MATLAB算法计时。使用randn命令生成随机数并创建输入矩阵位置由100,000个(2x1)位置向量样本组成。从当前文件夹中删除所有MEX文件。使用MATLAB秒表定时器(抽搐toc命令)来测量在运行kalman_loop函数。

清晰的墨西哥人删除([“*”。mexext])位置=兰登(2100000);tic,kalman_环(位置);a=总有机碳;

生成一个用于测试的MEX函数

接下来,使用命令生成一个MEX函数codegen后跟MATLAB函数的名称kalman_loop.的codegen命令生成一个被调用的MEX函数kalman_loop_mex.然后可以比较这个MEX函数与原始MATLAB算法的执行速度。

codegenarg游戏{position}kalman_loop.m
代码生成成功。
哪一个kalman_loop_mex
/tmp/Bdoc21b_1757077_258750/tpe931db2c/coder-ex53054096/kalman_loop_mex.mexa64

MEX计时命令功能

现在,给MEX函数计时kalman_loop_mex.使用相同的信号位置如前所述的输入,以确保执行速度的公平比较。

tic,kalman\u loop\u mex(位置);b=toc;

执行速度的比较

注意使用生成的MEX函数时的速度执行差异。

显示(sprintf)('使用在基线MATLAB函数上生成的MEX,加速比为%.1f倍。'a / b));
在基线MATLAB函数上使用生成的MEX可以得到17.2倍的加速。