⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 navigation.m

📁 本压缩文件包含GPS量测数据仿真和惯性导航解算以及卡尔曼滤波在导航解算中的应用
💻 M
字号:
%%%%%%%%%%%%%导航解算程序北天东%%%%%%%%%%%%%%
clear all
close all
clc
deg_rad=pi/180;   %由度转化成弧度
rad_deg=180/pi;   %由弧度转化成度
%-----------------------常值定义区----------------------
Omega_ie=0.00007272205216643040;   %地球自转角速度 单位:弧度每妙
g0=9.78;
Wiee = [0 0 Omega_ie]';  %地球速率在地球系中的投影
Re=6378245.0; %地球长轴 《惯性导航系统》  P28
e=1/298.3;

%-------------------从文件中读取数据----------------------
fid_IMUout=fopen('IMUout.txt','r');    %读取惯性器件的输出 无误差
[AllData NumofAllData]=fscanf(fid_IMUout,'%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g',[17 inf]);
AllData=AllData';
NumofEachData=fix(NumofAllData/17);
%惯性器件误差的设定  惯性器件误差由常值误差和随机漂移误差组成
delta_ax=1e-4*g0+0.5e-4*randn(NumofEachData,1)*g0;      %加速度计误差为常值1e-4g,随机偏差为0.5e-4g
delta_ay=1e-4*g0+0.5e-4*randn(NumofEachData,1)*g0;
delta_az=1e-4*g0+0.5e-4*randn(NumofEachData,1)*g0;
epslon_x=0.2*pi/180/3600+0.2*pi/180/3600*randn(NumofEachData,1);    %陀螺仪的误差常值为0.2度/小时,
epslon_y=0.2*pi/180/3600+0.2*pi/180/3600*randn(NumofEachData,1);    %随机漂移为0.2度/小时
epslon_z=0.2*pi/180/3600+0.2*pi/180/3600*randn(NumofEachData,1);


TimeSINS=AllData(:,1);
longitude=AllData(:,2);     %经度   单位:弧度
latitude=AllData(:,3);      %纬度   单位:弧度
High=AllData(:,4);      %高度 单位:米

Vn=AllData(:,5);
Vu=AllData(:,7);
Ve=-AllData(:,6);  

fb_x=AllData(:,8);      %比力
fb_y=-AllData(:,10);      %
fb_z=AllData(:,9);     %

pitch=AllData(:,11);  %俯仰角(向上为正)
roll=AllData(:,12);   %滚转角(向右为正)
head=-AllData(:,13);   %偏航角(偏西为正)

omigax=AllData(:,14);   %陀螺输出
omigay=-AllData(:,16);
omigaz=AllData(:,15);

fb_x=fb_x+delta_ax;
fb_y=fb_y+delta_ay;
fb_z=fb_z+delta_az;       %加表加入误差
omigax=omigax+epslon_x;
omigay=omigay+epslon_y;
omigaz=omigaz+epslon_z;      %陀螺加入误差

%%%%%%%%%%%%输出导航解算结果文件%%%%%%%%%%%%
fid_Nav=fopen('Navigation.txt','w');

%%%%%%%%%%%%导航初始化%%%%%%%%%%%%%%%
T_SINS=TimeSINS(2)-TimeSINS(1);   %惯导程序的解算周期
TimeAll=(NumofEachData-1)*T_SINS; 

latitude0=latitude(1);
longitude0=longitude(1);     %初始位置  
High0=High(1);

Vn0=Vn(1);      %初始速度
Vu0=Vu(1);
Ve0=Ve(1);

pitch0=pitch(1);
head0=head(1);      %初始姿态
roll0=roll(1);

%初始对准误差设置
pitch_err0=pitch0+1*deg_rad;
head_err0=head0+1*deg_rad;
roll_err0=roll0+1*deg_rad;
%初始捷联矩阵的计算
Tbn(1,1)=cos(pitch_err0)*cos(head_err0);     %地理坐标系 北天东
Tbn(1,2)=sin(pitch_err0);                    %载体坐标系 前上右
Tbn(1,3)=-cos(pitch_err0)*sin(head_err0);    %旋转顺序  head-pitch-roll                                           
Tbn(2,1)=sin(roll_err0)*sin(head_err0)-sin(pitch_err0)*cos(roll_err0)*cos(head_err0);   
Tbn(2,2)=cos(roll_err0)*cos(pitch_err0);                                                
Tbn(2,3)=cos(roll_err0)*sin(head_err0)*sin(pitch_err0)+sin(roll_err0)*cos(head_err0);
Tbn(3,1)=cos(roll_err0)*sin(head_err0)+sin(roll_err0)*sin(pitch_err0)*cos(head_err0);
Tbn(3,2)=-sin(roll_err0)*cos(pitch_err0);
Tbn(3,3)=-sin(roll_err0)*sin(head_err0)*sin(pitch_err0)+cos(roll_err0)*cos(head_err0);
Tnb=Tbn';
%位置矩阵的初始化 
Cne(1,1) = - sin(latitude(1)) * cos(longitude(1));
Cne(1,2) = - sin(latitude(1)) * sin(longitude(1));    %地理坐标系:北天东方向
Cne(1,3) = cos(latitude(1));
Cne(2,1) = cos(latitude(1)) * cos(longitude(1));
Cne(2,2) = cos(latitude(1)) * sin(longitude(1));
Cne(2,3) = sin(latitude(1));
Cne(3,1) = - sin(longitude(1));
Cne(3,2) = cos(longitude(1));
Cne(3,3) = 0;
Cen=Cne';
%初始四元数的确定  《捷联惯导系统》 P151-152  方法本身保证了q1^2+q2^2+q3^2+q4^2=1
q(2,1) = sqrt(abs(1.0 + Tnb(1,1) - Tnb(2,2) - Tnb(3,3))) / 2.0;            
q(3,1) = sqrt(abs(1.0 - Tnb(1,1) + Tnb(2,2) - Tnb(3,3))) / 2.0;            
q(4,1) = sqrt(abs(1.0 - Tnb(1,1) - Tnb(2,2) + Tnb(3,3))) / 2.0;
q(1,1) = sqrt(abs(1.0 - q(2,1) ^2 - q(3,1) ^2 - q(4,1) ^2));
% 判断q(1,1)的符号
flag_q11=cos(head_err0/2.0)*cos(pitch_err0/2.0)*cos(roll_err0/2.0)-sin(head_err0/2.0)*sin(pitch_err0/2.0)*sin(roll_err0/2.0);
if (flag_q11 >0)  %此时q(1,1)取正
    if (Tnb(3,2) < Tnb(2,3))
        q(2,1) = - q(2,1);
    end
    if (Tnb(1,3) < Tnb(3,1))
        q(3,1) = - q(3,1);
    end
    if (Tnb(2,1) < Tnb(1,2))
        q(4,1) = - q(4,1);
    end
else      %此时q(1,1)取负 或0
    q(1,1) = - q(1,1);
    if (Tnb(3,2) > Tnb(2,3))
        q(2,1) = - q(2,1);
    end
    if (Tnb(1,3) > Tnb(3,1))
        q(3,1) = - q(3,1);
    end
    if (Tnb(2,1) > Tnb(1,2))
        q(4,1) = - q(4,1);
    end
end
%递推初始化
Lat_err(1)=latitude0;
Lon_err(1)=longitude0;      %无初始位置误差
High_err(1)=High0;

Vn_err(1)=Vn0;
Vu_err(1)=Vu0;              %无初始速度误差
Ve_err(1)=Ve0;

pitch_err(1)=pitch_err0;
head_err(1)=head_err0;      %初始姿态误差
roll_err(1)=roll_err0;
%%%%%%%%%%%%导航解算开始%%%%%%%%%%%%%%%%%
for i=1:NumofEachData
        Wibb(1,1)=omigax(i);
        Wibb(2,1)=omigay(i);
        Wibb(3,1)=omigaz(i);
        
        fb(1,1)=fb_x(i);
        fb(2,1)=fb_y(i);
        fb(3,1)=fb_z(i);
        %计算在姿态矩阵和位置矩阵更新时用到的参数
        RM=Re*(1.0-2.0*e+3.0*e*Cne(2,3)^2)+High_err(i);
        RN=Re*(1.0+e*Cne(2,3)^2)+High_err(i);
        %实验当地重力加速度计算  《捷联惯导系统》P150 《惯性导航系统》 P35
        %g=g0*((1.0+0.0052884*Cne(2,3)^2)-0.0000059*(1-(1-2*Cne(2,3)^2)^2))*(1.0-2.0*High_err(i+(ii-1)*NUM)/Re);
           g=g0*((1.0+0.0052884*Cne(2,3)^2)-0.0000059*4*Cne(2,3)^2*(1-Cne(2,3)^2))*(1.0-2.0*High_err(i)/Re);
        Wien = Cne * Wiee;    %地球速率在导航系中的投影

        Wenn(1,1) =  Ve_err(i)/RN;
        Wenn(2,1) =  Ve_err(i)*tan(Lat_err(i))/RN;
        Wenn(3,1) = -Vn_err(i)/RM;

        Winn=Wien+Wenn;
        Winb=Tbn*Winn; 
        Wnbb=Wibb-Winb;       %姿态速率  在姿态更新时用到
        
        fn=Tnb*fb;
        % 速度的更新
        difVn_err=fn(1,1)+(2*Wien(3,1)+Wenn(3,1))*Vu_err(i)-(2*Wien(2,1)+Wenn(2,1))*Ve_err(i);
        difVu_err=fn(2,1)-(2*Wien(3,1)+Wenn(3,1))*Vn_err(i)+(2*Wien(1,1)+Wenn(1,1))*Ve_err(i)-g;
        difVe_err=fn(3,1)+(2*Wien(2,1)+Wenn(2,1))*Vn_err(i)-(2*Wien(1,1)+Wenn(1,1))*Vu_err(i);

        Vn_err(i+1)=Vn_err(i)+difVn_err*T_SINS;
        Vu_err(i+1)=Vu_err(i)+difVu_err*T_SINS;
        Ve_err(i+1)=Ve_err(i)+difVe_err*T_SINS;
        
        High_err(i+1)=High_err(i)+Vu_err(i)*T_SINS;
        % 位置矩阵的实时更新 《惯性导航系统》  P190
        Mat_Wenn(1,1)=0;
        Mat_Wenn(1,2)=Wenn(3,1);
        Mat_Wenn(1,3)=-Wenn(2,1);    %Wenn的反对阵矩阵取负
        Mat_Wenn(2,1)=-Wenn(3,1);    %这里位置矩阵的及时修正为: dCne/dt=Mat_Wenn*Cne
        Mat_Wenn(2,2)=0;
        Mat_Wenn(2,3)=Wenn(1,1);
        Mat_Wenn(3,1)=Wenn(2,1);
        Mat_Wenn(3,2)=-Wenn(1,1);
        Mat_Wenn(3,3)=0;

        Mat_Wenn=Mat_Wenn*Cne*T_SINS;
        Cne=Cne+Mat_Wenn;
        Cen=Cne';
        %计算经纬度
        Lat_err(i+1)=asin(Cne(2,3));
        Lon_err(i+1)=atan(Cne(2,2)/Cne(2,1));  %这是经度的主值
        if (Cne(2,1) < 0)
            if (Lon_err(i+1) > 0)
                Lon_err(i+1) = Lon_err(i+1) - pi;
            else
                Lon_err(i+1) = Lon_err(i+1) + pi;
            end
        end   
        % 四元数的及时修正  《惯性导航系统》 P194
        Mat_Wnbb=[  0,       -Wnbb(1,1),      -Wnbb(2,1),       -Wnbb(3,1);
                Wnbb(1,1),      0,            Wnbb(3,1),       -Wnbb(2,1);
                Wnbb(2,1),  -Wnbb(3,1),          0,             Wnbb(1,1);
                Wnbb(3,1),   Wnbb(2,1),      -Wnbb(1,1),           0];
        q=q+Mat_Wnbb*q*T_SINS/2.0;
        % 四元数归一化处理
        q_norm=sqrt(sum(q.*q));
        q=q/q_norm; 
        % 计算姿态矩阵 Tnb
        Tnb(1,1) = q(1,1) ^2 + q(2,1) ^2 - q(3,1)^2 - q(4,1)^2;
        Tnb(1,2) = 2.0 * (q(2,1) * q(3,1) - q(1,1) * q(4,1));
        Tnb(1,3) = 2.0 * (q(2,1) * q(4,1) + q(1,1) * q(3,1));
        Tnb(2,1) = 2.0 * (q(2,1) * q(3,1) + q(1,1) * q(4,1));
        Tnb(2,2) = q(1,1)^2 - q(2,1)^2 + q(3,1)^2 - q(4,1)^2;
        Tnb(2,3) = 2.0 * (q(3,1) * q(4,1) - q(1,1) * q(2,1));
        Tnb(3,1) = 2.0 * (q(2,1) * q(4,1) - q(1,1) * q(3,1));
        Tnb(3,2) = 2.0 * (q(3,1) * q(4,1) + q(1,1) * q(2,1));
        Tnb(3,3) = q(1,1)^2 - q(2,1)^2 - q(3,1)^2 + q(4,1)^2;
        Tbn=Tnb';
        %解算姿态角
        flag_pitch=asin(Tnb(2,1));
        flag_roll=atan(-Tnb(2,3)/Tnb(2,2));
        flag_head=atan(-Tnb(3,1)/Tnb(1,1));
        if(Tnb(2,2)<0)
            if(flag_roll<0)
                flag_roll=flag_roll+pi;
            else
                flag_roll=flag_roll-pi;
            end
        end
        % 偏航角范围 -180度——180度  北偏西为正
        if(Tnb(1,1)<0)
            if(flag_head<0)
                flag_head=flag_head+pi;
            else
                flag_head=flag_head-pi;
            end
        end
        % 姿态角更新
        head_err(i+1)=flag_head;
        pitch_err(i+1)=flag_pitch;
        roll_err(i+1)=flag_roll;
        %----------------------计算解算误差------------------
        ddpitch(i)=(pitch_err(i)-pitch(i))*rad_deg*60;
        ddhead(i)=(head_err(i)-head(i))*rad_deg*60;
        ddroll(i)=(roll_err(i)-roll(i))*rad_deg*60;           %角分
        
        ddLat(i)=(Lat_err(i)-latitude(i));     %单位:弧度
        ddLon(i)=(Lon_err(i)-longitude(i));
        ddHigh(i)=High_err(i)-High(i);   %高度误差 单位:米
             
        ddVn(i)=Vn_err(i)-Vn(i);   % 速度误差 单位:米/妙2
        ddVu(i)=Vu_err(i)-Vu(i);
        ddVe(i)=Ve_err(i)-Ve(i);
        
        fprintf(fid_Nav,'%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g \n',TimeSINS(i),...
            Lon_err(i), Lat_err(i),High_err(i),Vn_err(i),Vu_err(i),Ve_err(i),pitch_err(i),roll_err(i),head_err(i),...
            omigax(i), omigay(i),omigaz(i),fb_x(i),fb_y(i),fb_z(i));               %导航解算结果,加表和陀螺的输出是加入误差之后的
end;
fclose(fid_IMUout);
fclose(fid_Nav);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -