首页 > 其他分享 >严恭敏老师PSINS工具箱学习笔记-3

严恭敏老师PSINS工具箱学习笔记-3

时间:2024-03-23 20:03:51浏览次数:29  
标签:end kf idx 严恭敏 xfb ins 工具箱 PSINS nts

惯性传感器测量误差模型

参考教材: 捷联惯导算法与组合导航原理-严恭敏、翁浚

insupdate函数里关于补偿的部分:

[phim, dvbm] = cnscl(imu,0);    % coning & sculling compensation
phim = ins.Kg*phim-ins.eb*nts; dvbm = ins.Ka*dvbm-ins.db*nts;  % calibration

ins.wib = phim/nts; ins.fb = dvbm/nts;  % same as trjsimu

coning & sculling compensation为旋转运动和划桨运动误差补偿,现仅了解。
得到的phimdvbm为角速度和速度增量,所以eb(gyro漂移)和db(acc零偏)这里乘了时间,在后面代码中角速度和比力又除了时间。
calibration为对准误差补偿,关于惯性器件的误差。
主要来自于四个部分:

  1. 失准角误差μ,因为惯性器件的坐标轴为非直角坐标系{bg},要使角速度和加速度在同一坐标系需要求坐标变换矩阵,详见教材附录D。其中中转的另一个坐标系{B}与载体坐标系{b}的等效旋转矢量即为失准角。
  2. 不正交误差φ,非直角坐标系到中转的直角坐标系的偏差角,可以反映{bg}坐标系的不正交程度,越小正交性越好。
  3. 刻度系数误差k,相当于直尺膨胀、紧缩带来的误差。与前三项包含在标定刻度误差矩阵KgKa中。下图为陀螺仪误差模型。
  4. 常值漂移(零漂)ε,上下标代表在某个坐标系中的投影。
    P89
    整理得到,加速度计同理:
    P89

kf相关函数的学习

kf = kfinit(ins, davp0, imuerr, rk);
kf.Pmin = [avperrset(0.01,1e-4,0.1); gabias(1e-3, [1,10])].^2;  kf.pconstrain=1;
len = length(imu); [avp, xkpk] = prealloc(fix(len/nn), 10, 2*kf.n+1);

kfinit初始化

模型建立:

function kf = kfinit(ins, varargin)
global glv psinsdef
[Re,deg,dph,ug,mg] = ... % just for short
    setvals(glv.Re,glv.deg,glv.dph,glv.ug,glv.mg); 
o33 = zeros(3); I33 = eye(3); 
kf = [];
if isstruct(ins),    nts = ins.nts;
else                 nts = ins;
end

定义全局变量glvpsinsdef,后者包含卡尔曼滤波的状态、测量维数类型。

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;
        kf.Hk = kfhk(0);

SINS_GPS_153.m中psinstypedef(153);定义了psinsdef.kfinit的值为153,此时switch语句根据该值执行相应的语句。根据输入变量定义对应大小的davp,immerr,rk。

  1. 过程噪声矩阵Qt与gyro和acc的随机游走白噪声webwdb相关,且对准的是状态的前六项(失准角偏差和速度偏差)。
  2. 测量噪声矩阵Rk与输入的gps位置误差rk有关。
  3. 协方差矩阵Pxk是【avp的误差】,【gyro和acc的漂移】的平方。
  4. 最后定义Hk使用函数kfhk。
function Hk = kfhk(ins, varargin)
global psinsdef
    switch(psinsdef.kfhk)
        case 153,
            Hk = [zeros(3,6), eye(3), zeros(3,6)];

至此kf结构体如下:
KF

kf = kfinit0(kf, nts);

定义好上面四个矩阵后,最后还有一个非常重要的kfinit0函数。

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);
    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

上面代码段记录了Hk矩阵的大小,定义增益矩阵Kk以及一系列的测量相关的空矩阵和变量。下面代码段定义了kf一系列cell,现在用上的是xkQk以及pconstrain

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;  else, kf.l=size(kf.Gammak,2);  end
    if ~isfield(kf, 'fading'),  kf.fading = 1;  end
    if ~isfield(kf, 'adaptive'),  kf.adaptive = 0;  end
%     if kf.adaptive==1
        if ~isfield(kf, 'b'),  kf.b = 0.5;  end
        if ~isfield(kf, 'beta'),  kf.beta = 1;  end
        if ~isfield(kf, 'Rmin'),  kf.Rmin = 0.01*kf.Rk;  end
        if ~isfield(kf, 'Rmax'),  kf.Rmax = 100*kf.Rk;  end
        if ~isfield(kf, 'Qmin'),  kf.Qmin = 0.01*kf.Qk;  end
        if ~isfield(kf, 'Qmax'),  kf.Qmax = 100*kf.Qk;  end
%     end
    if ~isfield(kf, 'xtau'),  kf.xtau = ones(size(kf.xk))*eps;   end
    if ~isfield(kf, 'T_fb'),  kf.T_fb = 1;   end
    if ~isfield(kf, 'fbstr'),  kf.fbstr = 'avped';  end
    if ~isfield(kf, 'xconstrain'),  kf.xconstrain = 0;  end
    if ~isfield(kf, 'pconstrain'),  kf.pconstrain = 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;  %2015-2-22
kf.Pmin = [avperrset(0.01,1e-4,0.1); gabias(1e-3, [1,10])].^2;  kf.pconstrain=1;
len = length(imu); [avp, xkpk] = prealloc(fix(len/nn), 10, 2*kf.n+1);

上面定义kf最小协方差矩阵,并将pconstrain设置为1,可以达到限制协方差矩阵发散的效果吗?
prealloc函数为滤波后的数据提前分配好空间。

kfupdate更新

进入滤波,先将ins的数据更新,得到更新后的ins。kffk函数创造转移矩阵。

转移矩阵
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);
    kf.Phikk_1 = kffk(ins);

下面为kffk函数,当kffk全局变量为15时,使用etm函数创造误差转移矩阵,可在严老师的教材和博士毕业论文学习。
得到Ft后再离散化,采样间隔大时指数运算离散化,采样间隔小时泰勒展开到一阶。

function [Fk, Ft] = kffk(ins, varargin)
%Create Kalman filter system transition matrix.
global psinsdef
    %% get Ft
    if isstruct(ins),    nts = ins.nts;
    else                 nts = ins;
    end
    switch(psinsdef.kffk)
        case 15,
            Ft = etm(ins);

 %% 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

这里涉及到avp更新方程和误差方程的推导

function Ft = etm(ins)
%SINS Error Transition Matrix (see my PhD dissertation p39

%%     fi     dvn    dpos    eb       db
Ft = [ Maa    Mav    Map    -ins.Cnb  O33 
       Mva    Mvv    Mvp     O33      ins.Cnb 
       O33    Mpv    Mpp     O33      O33
       zeros(6,9)  diag(-1./[ins.tauG;ins.tauA]) ];

%[ins.tauG, ins.tauA] = setvals(inf(3,1)); % gyro & acc correlation time
更新函数

注释部分介绍很详细。

TimeMeasBoth - described as follows,
            TimeMeasBoth='T' (or nargin==1) for time updating only, 
            TimeMeasBoth='M' for measurement updating only, 
            TimeMeasBoth='B' (or nargin==2) for both time and measurement updating.
  • (1) If kf.adaptive=1, then use Sage-Husa adaptive method (but only
    for measurement noise ‘Rk’), where minimum constrain ‘Rmin’
    and maximum constrain ‘Rmax’ are considered to avoid divergence.
  • (2) If kf.fading>1, then use fading memory filtering method.
  • (3) Using Pmax&Pmin to constrain Pxk, such that Pmin<=diag(Pxk)<=Pmax.

根据输入变量数目调整TimeMeasBoth的值。

if nargin==1;
    TimeMeasBoth = 'T';
elseif nargin==2
    TimeMeasBoth = 'B';
end

见代码部分,如果仅更新时间(也就是状态向前传播,协方差也向前传播),此处的Gammk设置为1,作用还未知;并记录下测量停止的时间,测量丢失的时间(还未知,后面可能在丢失测量值时能用上或者两者频率不一样时能用上),其初始值都是zeros(3,1),到此函数结束,步出kfupdate。

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

仅测量更新和两者都更新是并列的,TimeMeasBoth=='M' 就是将上一个时刻传播的状态和协方差矩阵更新; TimeMeasBoth=='B'就是状态向前传播,协方差也向前传播,并记录下测量停止的时间,测量丢失的时间。
然后将测量值yk用于更新状态和协方差。并且可以实现自适应卡尔曼滤波器、衰减记忆滤波器;限制xk,Pk的功能防止其发散以达到好的滤波效果。

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
kf.Pxykk_1 = kf.Pxkk_1*kf.Hk';
kf.Py0 = kf.Hk*kf.Pxykk_1;
kf.ykk_1 = kf.Hk*kf.xkk_1;
kf.rk = yk-kf.ykk_1;
idxbad = [];  % bad measurement index
if kf.adaptive==1  % for adaptive KF, make sure Rk is diag 24/04/2015
    for k=1:kf.m
        if yk(k)>1e10, idxbad=[idxbad;k]; continue; end  % 16/12/2019
        ry = kf.rk(k)^2-kf.Py0(k,k);
        if ry<kf.Rmin(k,k), ry = kf.Rmin(k,k); end
        if ry>kf.Rmax(k,k),     kf.Rk(k,k) = kf.Rmax(k,k);
        else                	kf.Rk(k,k) = (1-kf.beta)*kf.Rk(k,k) + kf.beta*ry;
        end
    end
    kf.beta = kf.beta/(kf.beta+kf.b);
end

应用例子:

function kf = kfupdate(kf, yk, TimeMeasBoth)

kf = kfupdate(kf);相当于TimeMeasBoth='T',仅向前传播xk、Pk,在没有接收到测量值yk之前一直传播。
kf = kfupdate(kf, ins.pos-posGPS, 'M');将GPS与ins的位置误差输入,同时将前面传播过来的xk、Pk赋值,后加入yk进行卡尔曼增益矩阵的计算以及xk、Pk的估计更新。
kf = kfupdate(kf, ins.pos-posGPS, 'B');将两个步骤合并,传播和更新合并在一起,在本例程中测量值和状态的频率不一致所以分开进行两个步骤。

kffeedback反馈

应用:

[kf, ins] = kffeedback(kf, ins, 1, 'avp');

function [kf, ins, xfb] = kffeedback(kf, ins, T_fb, fbstr)

T_fb为反馈时间间隔,fbstr为反馈字符串(反馈变量类型),输出反馈状态xfb
下面部分代码kf中的反馈时间间隔与输入的不一致时,如何调整的反馈相关系数。

    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;
%         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;  %2015-2-22
%         kf.coef_fb(kf.xtau>kf.T_fb) = 1;
        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为相关系数处理后的反馈缓存值,并创造等大小的零矩阵xfb
根据不同的fbstr,使用卡尔曼滤波和相关系数处理后的xk对ins中的相应变量进行修正并进行反馈记录。

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);
        case 'e',
            idx = 10:12; ins.eb = ins.eb + xfb_tmp(idx);
        case 'd',
            idx = 13:15; ins.db = ins.db + xfb_tmp(idx);
        case 'A',
            idx = 1:2; ins.qnb = qdelphi(ins.qnb, [xfb_tmp(idx);0]);
        case 'V',
            idx = 6; ins.vn(3) = ins.vn(3) - xfb_tmp(idx);
        case 'P',
            idx = 9; ins.pos(3) = ins.pos(3) - xfb_tmp(idx);
        case 'E',
            idx = 10:11; ins.eb(1:2) = ins.eb(1:2) + xfb_tmp(idx);
        case 'D',
            idx = 15; ins.db(3) = ins.db(3) + xfb_tmp(idx);
        case 'L',
            idx = 16:18; ins.lever = ins.lever + xfb_tmp(idx);
        case 'T',
            idx = 19; ins.tDelay = ins.tDelay + xfb_tmp(idx);
        case 'G',
            idx = 20:28; dKg = xfb_tmp(idx);  dKg = [dKg(1:3),dKg(4:6),dKg(7:9)];
            ins.Kg = (eye(3)-dKg)*ins.Kg;
        case 'C',
            idx = 29:34; dKa = xfb_tmp(idx);  dKa = [dKa(1:3),[0;dKa(4:5)],[0;0;dKa(6)]];
            ins.Ka = (eye(3)-dKa)*ins.Ka;
        case 'H',
            idx = [6,9,15];                         ins.vn(3) = ins.vn(3) - xfb_tmp(6);
            ins.pos(3) = ins.pos(3) - xfb_tmp(9);	ins.db(3) = ins.db(3) + xfb_tmp(15);
        otherwise,
            error('feedback string mismatch in kf_feedback');
    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);

a、v、p、e、d分别使用估计出来的误差对ins中四元数姿态、速度、位置、陀螺漂移、加表零偏进行补偿。
A、V、P分别对姿态的pitch、roll角、z方向的速度、z方向的位置进行补偿。
E、D分别对陀螺漂移的x、y方向角速度、加表零偏的z方向比力
L、T、G、C使用更多维数的状态估计补偿。
H为进行高度(z方向)上的avp补偿。

误差方程的推导

以下均参考严老师教材第四章。

姿态

attitude
误差产生原因:
P90
误差方程推导(在大多数情况下,比如在惯导系统标定比较准确的时候或者运载体机动不大时,可以忽略标度系数矩阵误差δKG、δKA的影响,过程噪声矩阵Q(t)对角线前三个元素为web陀螺角度随机游走/角速率白噪声:
误差方程推导
列状态转移矩阵:
在这里插入图片描述

速度

误差方程来自于更新方程,原因和姿态误差处类似。
velocity
列状态转移矩阵,过程噪声矩阵Q(t)对角线第4-6个元素为wdb加计速度随机游走/比力白噪声:
err

位置

![pos](/i/ll/?i=direct/9247a774524b41898a2055e693a9d272.jpeg

惯性器件模型误差:

在这里插入图片描述
状态转移矩阵Ft,在函数etm中,自己建模型时重新写一个函数即可:

%%     fi     dvn    dpos    eb       db
Ft = [ Maa    Mav    Map    -ins.Cnb  O33 
       Mva    Mvv    Mvp     O33      ins.Cnb 
       O33    Mpv    Mpp     O33      O33
       zeros(6,9)  diag(-1./[ins.tauG;ins.tauA]) ];

%[ins.tauG, ins.tauA] = setvals(inf(3,1)); % gyro & acc correlation time

标签:end,kf,idx,严恭敏,xfb,ins,工具箱,PSINS,nts
From: https://blog.csdn.net/weixin_57967772/article/details/136961367

相关文章

  • [ROS 系列学习教程] rqt可视化工具箱 - 日志工具
    ROS系列学习教程(总目录)本文目录零、rqt可视化工具箱一、rqt_console二、rqt_logger_level零、rqt可视化工具箱rqt是ROS的一个软件框架,以插件的形式实现各种GUI工具。可以在rqt中将所有现有的GUI工具作为子窗口运行,也可以以独立方法运行,但rqt可以更轻松地同......
  • 蓝队应急响应工具箱v10 [重要更新]
    / 蓝队工具箱V10 /1  简介蓝队工具箱是为打造一款专业级应急响应的集成多种工具的工具集,由真实应急响应环境所用到的工具进行总结打包而来,由ChinaRan404,W啥都学,清辉等开发者编写.把项目现场中所用到的工具连同环境一同打包,并实现“可移植性”“兼容性”“使用便......
  • Python工具箱系列(五十)
    使用PIL加工图片 常见的图片操作包括但不限于:•大小进行变化•旋转•翻转•使用滤镜进行处理•剪切   以下python代码演示了如何将一幅美女图进行多种加工处理,并且汇集在一起,形成一个类似于照片墙的相关操作。fromPILimportImagefromPILimportImageFilterf......
  • 基于CNN卷积网络的MNIST手写数字识别matlab仿真,CNN编程实现不使用matlab工具箱
    1.算法运行效果图预览    2.算法运行软件版本matlab2022a  3.算法理论概述       MNIST是一个手写数字的大型数据库,包含60,000个训练样本和10,000个测试样本。每个样本都是28x28像素的灰度图像,代表0到9之间的一个数字。 3.1卷积神经网络(CNN)   ......
  • 基于MATLAB深度学习工具箱的CNN卷积神经网络训练和测试
    一、理论基础    为了尽可能详细地介绍基于MATLAB深度学习工具箱的CNN卷积神经网络训练和测试,本文将按照以下内容进行说明:CNN卷积神经网络的基本原理深度学习工具箱的基本介绍CNN卷积神经网络训练的步骤和方法CNN卷积神经网络的优缺点1.CNN卷积神经网络的基本原理 ......
  • MATLAB深度学习工具箱的应用
    一、MATLAB深度学习工具箱    MATLAB深度学习工具箱是一个功能强大的工具包,用于构建、训练和部署深度学习模型。它提供了各种深度学习网络和算法,包括卷积神经网络、循环神经网络、自编码器、生成对抗网络等。    MATLAB深度学习工具箱还提供了许多有用的工具和函......
  • 基于自适应支持向量机的matlab建模与仿真,不使用matlab的SVM工具箱函数
    1.算法运行效果图预览 2.算法运行软件版本matlab2022a 3.算法理论概述        支持向量机是一种二分类模型,它的基本思想是在特征空间中寻找一个超平面,使得该超平面能够最大化地将两类样本分隔开。这个超平面由支持向量确定,支持向量是离超平面最近的样本点。自适......
  • Python工具箱系列(四十九)
    使用PIL进行图片格式与尺寸转换现实世界中,图片是经常需要处理的二进制文件类型。从计算机发展的历史来看,图片的格式丰富多彩,但大体来说分成两类:•位图格式•矢量格式矢量格式如svg等,能够随意放大缩小而不变形,原因在于矢量格式描述了如何产生图形的方法。而位图格式(例如BMP/JPEG/PN......
  • Python工具箱系列(四十九)
    使用PIL进行图片格式与尺寸转换现实世界中,图片是经常需要处理的二进制文件类型。从计算机发展的历史来看,图片的格式丰富多彩,但大体来说分成两类:•位图格式•矢量格式矢量格式如svg等,能够随意放大缩小而不变形,原因在于矢量格式描述了如何产生图形的方法。而位图格式(例如BMP/J......
  • Python工具箱系列(四十八)
    如何操作docx文档(下)   当要更细致的操作WORD文档时,python-docx库就有些力不从心了。这时强力的pythonwin32com库可以帮助我们完成更细致复杂的工作。笔者经常要组织大型文档的汇总(例如标书),此时文档中插入的图片各式各样,缩写时也无从知道图片在整个文档中的顺序,所以对所有......