KF精对准代码及个人理解注释

function [att0, attk, xkpk] = alignvn(imu, qnb, pos, phi0, imuerr, wvn, isfig)
%回来从这往下看,结合代码理解输入参数含义
%[att0v, attkv, xkpkv] = alignvn(imu, avp(1:3), avp(7:9), phi, imuerr1, wvn);
%         原型-实际输入-含义
%         imu - imu - IMU data 模拟的静基座imu数据
%         qnb - avp(1:3) -coarse attitude quaternion
%         粗略姿态四元数?加误差后的初始姿态,哪来的?是理解为初始化后能获得的粗略的qnb吗?
%         这里直接用的真值加初始误差?理解为粗对准后跟这个差不多?

%         pos - avp(7:9) -position
%         带误差的初始位置(实际应用中理解为初始化造成的误差,实际应用中可以通过GPS获得)
%         phi0 - phi -initial misalignment angles estimation
%         失准角(误差状态)初始值,怎么设的?书上好像有个初值选取?
%         imuerr - imuerr1 -IMU error setting 设置的imu数据误差
%         wvn - wvn -velocity measurement noise (3x1 vector)
%         量测的噪声,这个跟状态方程的imu噪声不应该相关吗?
%         isfig - figure flag

% SINS initial align uses Kalman filter with vn as measurement.
% Kalman filter states: 
%    [phiE,phiN,phiU, dvE,dvN,dvU, ebx,eby,ebz, dbx,dby,dbz]'.
%
% Prototype: [att0, attk, xkpk]    = alignvn(imu, qnb, pos, phi0, imuerr, wvn, isfig)
%            [att0v, attkv, xkpkv] = alignvn(imu, avp(1:3), avp(7:9), phi, imuerr1, wvn);


% Outputs: att0 - attitude align result
%         attk, xkpk - for debug
%
% Example:
%	avp0 = [[0;0;0], zeros(3,1), glv.pos0];
%	imuerr = imuerrset(0.03, 100, 0.001, 10);
%	imu = imustatic(avp0, 1, 300, imuerr);
%	phi = [.5; .5; 5]*glv.deg;
%	wvn = [0.01; 0.01; 0.01];
%	[att0, attk, xkpk] = alignvn(imu, avp0(1:3)', avp0(7:9)', phi, imuerr, wvn);
%
% See also  alignfn, aligngps, alignfn9, aligncmps, aligni0, alignWahba, alignsb, alignvndp, etm.

% Copyright(c) 2009-2014, by Gongmin Yan, All rights reserved.
% Northwestern Polytechnical University, Xi An, P.R.China
% 17/06/2011
global glv
    if nargin<4,  phi0 = [1.5; 1.5; 3]*glv.deg;  end
    if nargin<5,  imuerr = imuerrset(0.01, 100, 0.001, 1);  end
    if nargin<6,  wvn = 0.01;  end;  if length(wvn)==1, wvn=repmat(wvn,3,1); end
    if nargin<7,  isfig = 1; end
    if length(qnb)==3, qnb=a2qua(qnb); end  %if input qnb is Eular angles.
    [nn, ts, nts] = nnts(2, diff(imu(1:2,end)));
    %设置子样数及采样时间间隔
    len = fix(length(imu)/nn)*nn;
    %舍去多余采样数据
    eth = earth(pos);
    %计算当前位置处的的地理参数
    vn = zeros(3,1); 
    %静基座下设置初始vn为0
    Cnn = rv2m(-eth.wnie*nts/2);%姿态更新算法中间项,见式4.1.50右边第一项对应的旋转矩阵
    %两时刻间n系的相对转动
    kf = avnkfinit(nts, pos, phi0, imuerr, wvn);
    %根据输入生成并初始化kf结构体
    [attk, xkpk] = prealloc(fix(len/nn), 7, 2*kf.n+1);
    %预分配内存
    ki = timebar(nn, len, 'Initial align using vn as meas.');
    for k=1:nn:len-nn+1
        %设置为len-nn+1,保证恰好读完最后一个多子样内的数据
        %% 利用增量数据实现姿态和速度更新
        wvm = imu(k:k+nn-1,1:6);
        %读取增量输出形式 多子样imu数据
        t = imu(k+nn-1,end);
        %多子样内最后一个子样的时间
        [phim, dvbm] = cnscl(wvm);
        %计算并补偿圆锥划桨误差等,输出补偿后的用原始增量数据表示的等效旋转矢量phim和b系下的比力速度增量dvbm
        Cnb = q2mat(qnb);
        %将前一步粗对准结果的四元数转换为姿态矩阵形式,这理解的不对
        dvn = Cnn*Cnb*dvbm;
        %修正后的比力速度增量项,就是式4.1.50(大框一模一样,只是每个项中有因为静基座忽略的项,或是没有外推)
        vn = vn + dvn + eth.gn*nts;
        %速度更新,由于是静基座,这里的有害加速度项好像只考虑了重力加速度
        %比力加速度项应该是f=a-g包含了重力影响,后面借助有害加速度项消去影响
        qnb = qupdt2(qnb, phim, eth.wnin*nts);
        %四元数形式的姿态更新吗,qnb初值是avp(1:3),一个粗略的qnb
        %%
        Cnbts = Cnb*nts;
        %姿态阵*2倍采样时间,后面状态转移矩阵离散用
        
        %状态一步转移矩阵中也有部分需要不断更新:
        kf.Phikk_1(4:6,1:3) = askew(dvn);%直接对离散后一步状态转移矩阵进行赋值
            kf.Phikk_1(1:3,7:9) = -Cnbts;%离散和连续形式相比差一个nts,合理(没严谨推导,可以找一找严谨推导)
            kf.Phikk_1(4:6,10:12) = Cnbts;
            
        kf = kfupdate(kf, vn);
        %卡尔曼滤波更新,静基座下vn真值为0,所以这里输入vn相当于误差量deta vn
        %更新完成后xk是融合新一步观测后的状态估计
        %kf.xk(1:3)是更新后的失准角状态估计,至此出了最优误差(最优状态)
        qnb = qdelphi(qnb, 0.91*kf.xk(1:3)); 
        %由于上面是误差状态KF(间接),完成KF流程后估计出的是最优误差,还需要用惯导解算值减去最优误差
        %为什么用惯导解算值减?因为捷联惯导误差微分方程的误差就是指惯导解算值和真值之间的误差
        %还有个疑惑:为什么没直接减去最优误差,还加了个系数0.91
        kf.xk(1:3) = 0.09*kf.xk(1:3);
        %上一步减误差没减完,剩下0.09的误差,当做下一步误差KF的初值,应该是方便多次迭代至收敛?
        vn = vn-0.91*kf.xk(4:6);  kf.xk(4:6) = 0.09*kf.xk(4:6);
        %kf.xk(4:6)是估计出的最优速度误差,解算速度减最优速度误差得最优速度估计,
        %这里只减了部分最优误差,应该也是方便多次迭代至收敛?
        attk(ki,:) = [q2att(qnb); vn; t]';
        %存储每次更新后KF预测的qnb(四元数转欧拉角形式) vn
        xkpk(ki,:) = [kf.xk; diag(kf.Pxk); t];
        %存储每次KF后的误差状态量及均方差
        ki = timebar;
        %每次执行ki都+1
    end
    attk(ki:end,:) = []; xkpk(ki:end,:) = [];
    %清空多余行
    att0 = attk(end,1:3)';
    %将迭代最终的结果作为此次精对准结果att0,并输出
    resdisp('Initial align attitudes (arcdeg)', att0/glv.deg);
    if isfig, avnplot(attk, xkpk); end
    %结果作图
    
function kf = avnkfinit(nts, pos, phi0, imuerr, wvn)
%速度量测误差作为状态的KF中,kf结构体初始化,对应理论见psins说明书式10.4.5
    eth = earth(pos);
    %又计算了一遍当地处的地理参数
    wnie = eth.wnie;
    %计算地球自转角速度在当地导航系的投影
    kf = []; 
    %初始化kf结构体为空
    kf.s = 1; 
    %这是啥?
    kf.nts = nts;
    %kf的结构体采样时间间隔
	kf.Qk = diag([imuerr.web; imuerr.wdb; zeros(6,1)])^2*nts;
    %系统状态 的噪声的协方差矩阵(均方误差阵),表示系统状态之间的相关性及每个状态的噪声情况,12维对角阵
    kf.Gammak = 1;
    %好像是噪声分配矩阵?
	kf.Rk = diag(wvn)^2/nts;
    %量测噪声协方差阵   
	kf.Pxk = diag([phi0; [1;1;1]; imuerr.eb; imuerr.db])^2;
    %设置系统状态 初始的状态估计均方误差阵,这里还是迷糊,得回第五章KF推导 式5.3.3那区分理解一下,这是咋用的
	%phi0应该是状态(失准角)的初始误差
    Ft = zeros(12); 
    %Ft是连续形式状态转移矩阵,这里初始化为12维0阵
    Ft(1:3,1:3) = askew(-wnie);
    %askew输出向量对应的反对称矩阵,这里把连续形式状态转移矩阵Ft的设置前3*3
    %其他位置在主函数里进行赋值
    kf.Phikk_1 = eye(12)+Ft*nts;
    %状态一步转移矩阵中不需要更新的常值部分,形式上像离散化的公式
	kf.Hk = [zeros(3),eye(3),zeros(3,6)];
    %量测矩阵,这个形式跟说明书一样,有个疑问:这个哪来的?不需要离散吗?迷糊
%     [kf.m, kf.n] = size(kf.Hk);
%     kf.I = eye(kf.n);
%     kf.xk = zeros(kf.n, 1);
%     kf.adaptive = 0;
%     kf.xconstrain = 0; kf.pconstrain = 0;
%     kf.fading = 1;
    kf = kfinit0(kf, nts);
    %将kf结构体中没有设置的参数初始化,设置为默认参数
    
function avnplot(attk, xkpk)
global glv
    if glv.isfig==0, return; end
    t = attk(:,end);
    myfigure;
	subplot(421); plot(t, attk(:,1:2)/glv.deg); xygo('pr'); title('Xi');
	subplot(423); plot(t, attk(:,3)/glv.deg); xygo('y');
    %画出每步精对准KF的对qnb(欧拉角形式,单位转换为角度)的估算结果
	subplot(425); plot(t, xkpk(:,7:9)/glv.dph); xygo('eb'); 
	subplot(427); plot(t, xkpk(:,10:12)/glv.ug); xygo('db');
    %kf.xk 的eb和db,显示误差状态陀螺和加计的 常值零偏随时间变化
    %对这两个图的结果不是很理解
	subplot(422); plot(t, sqrt(xkpk(:,13:15))/glv.min); xygo('phi'); title('\surdPii');
	subplot(424); plot(t, sqrt(xkpk(:,16:18))); xygo('dV');
	subplot(426); plot(t, sqrt(xkpk(:,19:21))/glv.dph); xygo('eb');
 	subplot(428); plot(t, sqrt(xkpk(:,22:24))/glv.ug); xygo('db');   
    %画出状态量均方误差阵对角线元素(即所有误差状态的标准差)随时间的变化
    %好像是不管哪种随机过程,某个量的标准差(或者方差)都代表了这个量的集中分布程度
    %也就是可信程度,这几个误差的均方差最后都近似收敛到0
    %对此理解是:每次KF更新都把最优估计结果传递给下次(可信度最高,均方误差最小的结果,最优估计结果)
    %最后多轮KF下来,最后输出的结果则是越来越可信的最优结果

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Kalman滤波是一种常用于估计物理量的方法,对于惯性导航系统的确定位也十分有效。在Matlab中可以使用kalman函数进行滤波处理惯导对准。 首先,需要确定状态空间模型,即建立状态方程和观测方程。状态方程描述了系统的演进过程,包括状态量和外部干扰量之间的关系;观测方程描述了可测量的系统输出与状态的关系。 其次,设置协方差矩阵和初始估计值。协方差矩阵描述了状态量和干扰量的不确定性,初始估计值则是在没有真实测量值时的初始估计状态。通常情况下,初始估计状态可以设为0,协方差矩阵可以根据系统的测量误差和初始状态的不确定性进行设置。 最后,使用kalman函数进行滤波处理。kalman包含两个输入参数:状态方程和观测方程。在运行过程中,需要不断更新协方差矩阵和初始估计值,以得到更加确的估计结果。 总之,Kalman滤波处理惯导对准Matlab代码需要根据具体情况进行设置。通过建立状态方程和观测方程、设置初始估计值和协方差矩阵、运用Kalman函数进行滤波处理,可以实现惯导对准确估计。 ### 回答2: Kalman滤波是一种利用线性系统模型和部分信息观测数据进行状态估计的方法。在惯性导航系统中,Kalman滤波可以用来处理惯导对准问题。 Matlab是一种强大的数值计算软件,它支持Kalman滤波算法的实现。首先,需要根据系统模型和测量数据构建卡尔曼滤波器。也就是要定义状态向量、输入向量、测量向量和协方差矩阵等参数,根据这些参数可以编写滤波器的初始化函数。 然后,可以在MATLAB中编写主函数,在主函数中读取输入数据并调用Kalman滤波器对数据进行处理。Kalman滤波器会通过状态估计算法对输入数据进行预测和观测,得到滤波后的结果。 在惯导对准问题中,Kalman滤波可以通过陀螺仪和加速度计提供的姿态角速度和加速度数据,对惯性导航系统的姿态进行实时估计和校正。通过Kalman滤波处理的惯导对准结果具有高度和高可靠性,能够有效解决惯导系统长时间使用的问题。 ### 回答3: Kalman滤波是一种常用于传感器数据处理的方法,它可以将当前时刻的状态估计值和测量值进行融合,从而得到更准确的状态估计值。惯性导航系统中的对准问题可以借助Kalman滤波来解决。在Matlab中,可以使用Kalman滤波器来对惯导数据进行处理。 下面是Kalman滤波处理惯导对准Matlab代码: 1. 初始化滤波器 ```matlab % 初始状态、过程协方差矩阵和测量度矩阵 x = [0; 0; 0; 0; 0; 0]; P = 1000*eye(6); R = diag([0.1 0.1 0.1 0.1 0.1 0.1]); % 系统模型和观测模型(此处省略) F = eye(6); H = eye(6); % 过程噪声协方差和测量噪声协方差 Q = diag([0.001 0.001 0.001 0.001 0.001 0.001]); R = diag([0.1 0.1 0.1 0.1 0.1 0.1]); % 初始化滤波器 kf = ekf(F, H, x, P, Q, R); ``` 2. 惯导数据处理 ```matlab % 获取惯导数据 gx = imu_data(:, 1); gy = imu_data(:, 2); gz = imu_data(:, 3); % 转换为弧度制 gx = deg2rad(gx); gy = deg2rad(gy); gz = deg2rad(gz); % 获取采样时间间隔 dt = mean(diff(t)); % 处理惯导数据 for i = 2:length(t) % 计算旋转矩阵 R = rotation_matrix(gx(i), gy(i), gz(i), dt); % 更新状态估计值和过程协方差矩阵 kf.predict(dt, R); % 获取GPS数据并更新观测模型 z = [GPS_data(i, 1); GPS_data(i, 2); GPS_data(i, 3); GPS_data(i, 4); GPS_data(i, 5); GPS_data(i, 6)]; kf.update(z); % 获取状态估计值 x(i, :) = kf.x'; end ``` 在以上代码中,我们首先定义了需要的参数,然后初始化了Kalman滤波器。接着,我们获取了惯导数据,并使用该数据计算旋转矩阵,以更新状态估计值和过程协方差矩阵。然后,我们获取GPS数据,并使用该数据更新观测模型。最后,我们获取状态估计值,并存储到x数组中。通过以上步骤,我们可以使用Kalman滤波器对惯导数据进行处理,同时也可以使用该方法进行GPS数据的融合,从而得到更准确的姿态估计值。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值