PSINS工具箱卡尔曼滤波器
psins中一个15维状态量、3维位置观测量的卡尔曼滤波器示例:
% SINS/GPS intergrated navigation simulation using kalman filter. % Please run 'test_SINS_trj.m' to generate 'trj10ms.mat' beforehand!!! % See also test_SINS_trj, test_SINS, test_SINS_GPS_186, test_SINS_GPS_193. % Copyright(c) 2009-2014, by Gongmin Yan, All rights reserved. % Northwestern Polytechnical University, Xi An, P.R.China % 17/06/2011 glvs psinstypedef(153); %设定滤波器标识 trj = trjfile('trj10ms.mat'); % initial settings [nn, ts, nts] = nnts(2, trj.ts); imuerr = imuerrset(0.03, 100, 0.001, 5); % IMU误差设定 imu = imuadderr(trj.imu, imuerr); % 添加IMU误差 davp0 = avperrset([0.5;-0.5;20], 0.1, [1;1;3]); % 设定初始avp误差 ins = insinit(avpadderr(trj.avp0,davp0), ts); % 初始化INS % KF filter rk = poserrset([1;1;3]); % 设定Rk,位置观测误差 kf = kfinit(ins, davp0, imuerr, rk); % 初始化卡尔曼滤波器 kf.Pmin = [avperrset(0.01,1e-4,0.1); gabias(1e-3, [1,10])].^2; kf.pconstrain=1; % 设定P阵最小值 len = length(imu); [avp, xkpk] = prealloc(fix(len/nn), 10, 2*kf.n+1); timebar(nn, len, '15-state SINS/GPS Simulation.'); ki = 1; for k=1:nn:len-nn+1 k1 = k+nn-1; wvm = imu(k:k1,1:6); t = imu(k1,end); ins = insupdate(ins, wvm); % INS更新 kf.Phikk_1 = kffk(ins); % Phi阵更新 kf = kfupdate(kf); % 卡尔曼时间更新 if mod(t,1)==0 posGPS = trj.avp(k1,7:9)' + davp0(7:9).*randn(3,1); % GPS pos simulation with some white noise kf = kfupdate(kf, ins.pos-posGPS, 'M'); % 卡尔曼观测更新 [kf, ins] = kffeedback(kf, ins, 1, 'avp'); % 状态反馈 avp(ki,:) = [ins.avp', t]; xkpk(ki,:) = [kf.xk; diag(kf.Pxk); t]'; ki = ki+1; % 构建状态量和状态方差数据 end timebar; end avp(ki:end,:) = []; xkpk(ki:end,:) = []; % show results insplot(avp); avperr = avpcmpplot(trj.avp, avp); kfplot(xkpk, avperr, imuerr);
psinstypedef
该函数是一个标识器,主要用于设定全局结构体psinsdef,通过psinsdef中的kfinit、kffk、kfhk、kfplot四个字段来标记卡尔曼滤波模型和绘图参数。如153表示采用15维状态向量+3维位置观测模型,156表示采用18维状态向量+3维位置观测+3维速度观测模型。也可以对滤波模型进行修改和增加(需同时修改kfinit, kffk, kfhk, kfplot等函数)。
function psinstypedef(typestr, kffk, kfhk, kfplot) ...... psinsdef.kfinit = typestr; psinsdef.kffk = fix(psinsdef.kfinit/10); psinsdef.kfhk = psinsdef.kfinit; psinsdef.kfplot = psinsdef.kffk; ......
kfinit
根据psinsdef中设定的类型,对卡尔曼滤波器进行初始化。主要流程为先根据滤波器模型设定Q阵、R阵、初始P阵、H阵,然后再调用kfinit0函数完成全部初始化工作,返回卡尔曼滤波器结构体kf。
function kf = kfinit(ins, varargin) switch(psinsdef.kfinit) case psinsdef.kfinit153, psinsdef.kffk = 15; psinsdef.kfhk = 153; psinsdef.kfplot = 15; [davp, imuerr, rk] = setvals(varargin); kf.Qt = diag([imuerr.web; imuerr.wdb; zeros(9,1)])^2; % 连续域过程噪声矩阵 kf.Rk = diag(rk)^2; % 离散域观测噪声矩阵 kf.Pxk = diag([davp; imuerr.eb; imuerr.db]*1.0)^2; % 初始P阵 kf.Hk = kfhk(0); % 观测矩阵 ...... kf = kfinit0(kf, nts);
kfinit0
卡尔曼滤波器结构体初始化函数,为各状态量、矩阵分配内存空间,包含Q阵、G阵、P阵、K阵、状态量、状态反馈量等(这里的Q、G为离散域矩阵)。同时设置滤波器配置参数,如观测量掩码、自适应滤波开关等。
function kf = kfinit0(kf, nts) % Always called by kfinit and initialize the remaining fields of kf. % % See also kfinit, kfupdate, kffeedback, psinstypedef. kf.nts = nts; [kf.m, kf.n] = size(kf.Hk); % m,观测维数;n,状态维数 kf.I = eye(kf.n); kf.Kk = zeros(kf.n, kf.m); % 卡尔曼增益矩阵 kf.measmask = []; % measurement mask for no update 20/11/2022 kf.measstop = zeros(kf.m,1); % measurement stop time kf.measlost = zeros(kf.m,1); % measurement lost time kf.measlog = 0; % measurement log flag if ~isfield(kf, 'xk'), kf.xk = zeros(kf.n, 1); end % 状态向量 if ~isfield(kf, 'Qk'), kf.Qk = kf.Qt*kf.nts; end % 过程噪声矩阵 if ~isfield(kf, 'Gammak'), kf.Gammak = 1; kf.l = kf.n; end % 噪声传递矩阵 if ~isfield(kf, 'fading'), kf.fading = 1; end if ~isfield(kf, 'adaptive'), kf.adaptive = 0; end ...... kf.Pmax = (diag(kf.Pxk)+1)*1.0e10; kf.Pmin = kf.Pmax*0; % kf.Pykk_1 = kf.Hk*kf.Pxk*kf.Hk'+kf.Rk; kf.Pykk_1 = kf.Hk*kf.Pxk*kf.Hk'+0; % 计算卡尔曼增益的中间矩阵 kf.xfb = zeros(kf.n, 1); % 状态反馈量 % kf.coef_fb = (1.0-exp(-kf.T_fb./kf.xtau)); % kf.coef_fb = ar1coefs(kf.T_fb, kf.xtau); xtau = kf.xtau; xtau(kf.xtau<kf.T_fb) = kf.T_fb; kf.coef_fb = kf.T_fb./xtau;
kffk
根据滤波器模型调用etm函数更新F阵,并离散化为Phi阵。etm函数计算F阵的元素值。
function [Fk, Ft] = kffk(ins, varargin) global psinsdef %% get Ft if isstruct(ins), nts = ins.nts; else nts = ins; end switch(psinsdef.kffk) case 15 Ft = etm(ins); ...... end %% discretization,离散化 Fk = Ft*nts; if nts>0.1 % for large time interval, this may be more accurate. Fk = expm(Fk); else % Fk = I + Ft*nts + 1/2*(Ft*nts)^2 , 2nd order expension Fk = eye(size(Ft)) + Fk;% + Fk*Fk*0.5; end
kfhk
设置观测矩阵H。
function Hk = kfhk(ins, varargin) global psinsdef switch(psinsdef.kfhk) case 153, Hk = [zeros(3,6), eye(3), zeros(3,6)]; end ......
kfupdate
卡尔曼更新函数。输入参数kf结构体、观测量yk(可选参数,执行观测更新时需传入)、更新标识TimeMeasBoth。TimeMeasBoth为T时只进行时间更新,为M时只进行观测更新,为B时执行完整的时间更新和观测更新。
function kf = kfupdate(kf, yk, TimeMeasBoth) if nargin==1; TimeMeasBoth = 'T'; elseif nargin==2 TimeMeasBoth = 'B'; end if TimeMeasBoth=='T' % Time Updating kf.xk = kf.Phikk_1*kf.xk; kf.Pxk = kf.Phikk_1*kf.Pxk*kf.Phikk_1' + kf.Gammak*kf.Qk*kf.Gammak'; kf.measstop = kf.measstop - kf.nts; kf.measlost = kf.measlost + kf.nts; else if TimeMeasBoth=='M' % Meas Updating kf.xkk_1 = kf.xk; kf.Pxkk_1 = kf.Pxk; elseif TimeMeasBoth=='B' % Time & Meas Updating kf.xkk_1 = kf.Phikk_1*kf.xk; kf.Pxkk_1 = kf.Phikk_1*kf.Pxk*kf.Phikk_1' + kf.Gammak*kf.Qk*kf.Gammak'; kf.measstop = kf.measstop - kf.nts; kf.measlost = kf.measlost + kf.nts; else error('TimeMeasBoth input error!'); end ...... end
kffeedback
状态反馈,psins中的状态量均为误差量。执行卡尔曼滤波后,可将状态量通过kffeedback函数反馈值全状态。
function [kf, ins, xfb] = kffeedback(kf, ins, T_fb, fbstr) if nargin<4, fbstr=kf.fbstr; end if nargin<3, T_fb=1; end if kf.T_fb~=T_fb kf.T_fb = T_fb; idx = kf.T_fb>kf.xtau; % scale<vector kf.coef_fb(idx) = 1; kf.coef_fb(~idx) = kf.T_fb./kf.xtau(~idx); %2022-6-25 kf.coef_fb(kf.xtau<0.001 & kf.T_fb~=inf) = 1; end xfb_tmp = kf.coef_fb.*kf.xk; xfb = xfb_tmp*0; for k=1:length(fbstr) switch fbstr(k) case 'a', idx = 1:3; ins.qnb = qdelphi(ins.qnb, xfb_tmp(idx)); case 'v', idx = 4:6; ins.vn = ins.vn - xfb_tmp(idx); case 'p', idx = 7:9; ins.pos = ins.pos - xfb_tmp(idx); ...... end kf.xk(idx) = kf.xk(idx) - xfb_tmp(idx); % kf.xfb(idx) = kf.xfb(idx) + xfb_tmp(idx); % record total feedback xfb(idx) = xfb_tmp(idx); end [ins.qnb, ins.att, ins.Cnb] = attsyn(ins.qnb); ins.avp = [ins.att; ins.vn; ins.pos]; % 2015-2-22
posted on 2024-01-07 12:20 RandWalker 阅读(315) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!