利用MATLAB编制的GPS单点定位程序

更新时间:2023-10-24 12:40:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

function t=TimetoJD(Y,M,D,h,f,s) if(Y>=80)

Y=Y+1900; else

Y=Y+2000; end if M<=2 Y=Y-1; M=M+12; end

JD=fix(365.25*Y)+fix(30.6001*(M+1))+D+h/24+f/1440+s/24/3600+1720981.5; t=JD-2444244.5;

function [head,obs]=ReadObsData

%读接收机观测数据文件

%HeadODat :a structure stores header information if o-file

% .ApproXYZ[3]; //approximate coordinate % .interval; //intervals of two adjacent epochs % .SiteName; //point name % .Ant_H; //antenna height

% .Ant_E; //east offset of the antenna center % .Ant_N; //north offset of then antenna center

% .TimeOB; //first epoch time in modifuied Julian time % .TimeOE; //last epoch time in modifuied Julian time % .SumOType; //number of types of observables

% .SumOO[SumOType]; //type of observables 0-L1,1-L2,2-C1,3-P1,4-P2,5-D1,6-D2,

%ObsODat :a structure stores observables by one and one epoch % .TimeOEpp[2]; //reciever time of epoch % .SatSum; //number of satellites % .SatCode[SatSum]; //satellites' PRN % .Obs_FreL1[SatSum]; % .Obs_FreL2[SatSum]; % .Obs_RangeC1[SatSum]; % .Obs_RangeP1[SatSum]; % .Obs_RangeP2[SatSum]; global HeadODat; global ObsODat;

[fname,fpath]=uigetfile('*.*','选择一个O文件'); O_filename=strcat(fpath,fname);

fid1=fopen(O_filename,'rt'); if (fid1==-1)

msgbox('file invalide','warning','warn'); return; end

%将文件头数据存入结构体HeadODat中 t=0;

while(t<100)

s=fgets(fid1); t=t+1; L=size(s,2); if L<81

s(L+1:81)=' '; end

instrS=s(61:81);

%测站点近似坐标

if strncmp(instrS,'APPROX POSITION XYZ',19) HeadODat.ApproXYZ=zeros(1,3);

HeadODat.ApproXYZ(1,1)=str2num(s(1:14)); HeadODat.ApproXYZ(1,2)=str2num(s(15:28)); HeadODat.ApproXYZ(1,3)=str2num(s(29:42));

%历元间隔;

elseif strncmp(instrS,'INTERVAL',8)

HeadODat.interval=str2num(s(5:11)); %测站点号

elseif strncmp(instrS,'MARKER NAME',11) HeadODat.SiteName=s(1:4) %天线中心改正

elseif strncmp(instrS,'ANTENNA: DELTA H/E/N',20) HeadODat.Ant_H=str2num(s(1:14)); HeadODat.Ant_E=str2num(s(15:28)); HeadODat.Ant_N=str2num(s(29:42)); %第一个历元时间

elseif strncmp(instrS,'TIME OF FIRST OBS',17) year=str2num(s(1:6)); month=str2num(s(7:12)); day=str2num(s(13:18)); hour=str2num(s(19:24)); minute=str2num(s(25:30)); second=str2num(s(31:42));

HeadODat.TimeOB=TimetoJD(year,month,day,hour,minute,second); %最后一个历元时间

elseif strncmp(instrS,'TIME OF LAST OBS',16) year=str2num(s(1:6)); month=str2num(s(7:12));

day=str2num(s(13:18)); hour=str2num(s(19:24)); minute=str2num(s(25:30)); second=str2num(s(31:42));

HeadODat.TimeOE=TimetoJD(year,month,day,hour,minute,second); %观测值类型

elseif strncmp(instrS,'# / TYPES OF OBSERV',19) HeadODat.SumOType=str2num(s(1:6));

HeadODat.SumOO=ones(1,HeadODat.SumOType)*-1; for k=1:HeadODat.SumOType f=s(k*6+5:k*6+6); if strcmp(f,'L1')

HeadODat.SumOO(1,k)=0; elseif strcmp(f,'L2')

HeadODat.SumOO(1,k)=1; elseif strcmp(f,'C1')

HeadODat.SumOO(1,k)=2; elseif strcmp(f,'P1')

HeadODat.SumOO(1,k)=3; elseif strcmp(f,'P2')

HeadODat.SumOO(1,k)=4; elseif strcmp(f,'D1')

HeadODat.SumOO(1,k)=5; elseif strcmp(f,'D2')

HeadODat.SumOO(1,k)=6; end end

%头文件结束

elseif strncmp(instrS,'END OF HEADER',13) break; else

continue; end end

%观测数据结构体%观测数据结构 t=0;

while ~feof(fid1)

%每个历元的第一行数据,时间和观测到的卫星号 s=fgets(fid1); t=t+1;

year=str2num(s(1:3)); month=str2num(s(4:6));

day=str2num(s(7:9)); hour=str2num(s(10:12)); minute=str2num(s(13:15)); second=str2num(s(16:26));

%历元时间

ObsODat(t).TimeOEp=[year,month,day,hour,minute,second]; ObsODat(t).TimeOEpp=TimetoJD(year,month,day,hour,minute,second); %该历元观测到的卫星数

ObsODat(t).SatSum=str2num(s(30:32));

%该历元观测到的卫星号

ObsODat(t).SatCode=zeros(1,ObsODat(t).SatSum); ObsODat(t).Obs_FreL1=zeros(1,ObsODat(t).SatSum); ObsODat(t).Obs_FreL2=zeros(1,ObsODat(t).SatSum); ObsODat(t).Obs_RangeC1=zeros(1,ObsODat(t).SatSum); ObsODat(t).Obs_RangeP1=zeros(1,ObsODat(t).SatSum); ObsODat(t).Obs_RangeP2=zeros(1,ObsODat(t).SatSum); for k=1:ObsODat(t).SatSum f=s(31+k*3:32+k*3);

ObsODat(t).SatCode(1,k)=str2num(f); end

%每个历元的观测数据,按卫星号先后顺序分行存 for k=1:ObsODat(t).SatSum s=fgets(fid1);

%判断一个卫星的观测数据是否分两行存储,如果为两行,则再读入一行 if HeadODat.SumOType>5 sg=fgets(fid1); s=strcat(s,sg); end

L=size(s,2);

%补充数据长度

if L

s(L+1:HeadODat.SumOType*16)=' '; end

%对观测数据判断其类型,并存储到相应的数组中 for j=1:HeadODat.SumOType stemp=s(j*16-15:j*16); stemp=deblank(stemp);

if isempty(stemp) continue; end

stempNum=str2num(stemp); stempLength=size(stempNum,2); if stempLength>1

stempNum=stempNum(1,1);

end

if HeadODat.SumOO(1,j)==0

ObsODat(t).Obs_FreL1(1,k)=stempNum; elseif HeadODat.SumOO(1,j)==1

ObsODat(t).Obs_FreL2(1,k)=stempNum; elseif HeadODat.SumOO(1,j)==2

ObsODat(t).Obs_RangeC1(1,k)=stempNum; elseif HeadODat.SumOO(1,j)==3

ObsODat(t).Obs_RangeP1(1,k)=stempNum; elseif HeadODat.SumOO(1,j)==4

ObsODat(t).Obs_RangeP2(1,k)=stempNum; else

continue; end end

%完成一个卫星的所有观测数据存储 end

%完成一个历元的数据存储 end

%完成所有历元的数据存储

head=HeadODat; obs=ObsODat; return

function EphDat=ReadGpsData global EphDat EphDat=struct;

[filename,pathname]=uigetfile('*.**N','读取GPS广播星历文件'); fid1=fopen(strcat(pathname,filename),'rt'); if(fid1==-1)

msgbox('Input File or Path is not correct','warning ','warn'); return; end while(1)

temp=fgetl(fid1);

header=findstr(temp,'END OF HEADER'); if(~isempty(header)) break; end end i=1; while(1)

temp=fgetl(fid1);

if(temp==-1) break; end

EphDat(i).PRN=str2double(temp(1:2)); year=str2double(temp(3:5));

EphDat(i).toc=TimetoJD(year,str2double(temp(6:8)),str2double(temp(9:11)),str2double(temp(12:14)),str2double(temp(15:17)),str2double(temp(18:22))); EphDat(i).a0=str2num(temp(23:41)); EphDat(i).a1=str2num(temp(42:60)); EphDat(i).a2=str2num(temp(61:79)); temp=fgetl(fid1);

EphDat(i).idoe=str2num(temp(4:22)); EphDat(i).Crs=str2num(temp(23:41)); EphDat(i).dn=str2num(temp(42:60)); EphDat(i).M0=str2num(temp(61:79)); temp=fgetl(fid1);

EphDat(i).Cuc=str2num(temp(4:22)); EphDat(i).e=str2num(temp(23:41)); EphDat(i).Cus=str2num(temp(42:60)); EphDat(i).sqa=str2num(temp(61:79)); temp=fgetl(fid1);

EphDat(i).toe=str2num(temp(4:22)); EphDat(i).Cic=str2num(temp(23:41)); EphDat(i).omg0=str2num(temp(42:60)); EphDat(i).Cis=str2num(temp(61:79)); temp=fgetl(fid1);

EphDat(i).i0=str2num(temp(4:22)); EphDat(i).Crc=str2num(temp(23:41)); EphDat(i).w=str2num(temp(42:60)); EphDat(i).omg=str2num(temp(61:79)); temp=fgetl(fid1);

EphDat(i).iDot=str2num(temp(4:22)); EphDat(i).cflgl2=str2num(temp(23:41)); EphDat(i).weekno=str2num(temp(42:60)); EphDat(i).pflgl2=str2num(temp(61:79)); temp=fgetl(fid1);

EphDat(i).svacc=str2num(temp(4:22)); EphDat(i).svhlth=str2num(temp(23:41)); EphDat(i).tgd=str2num(temp(42:60)); EphDat(i).aodc=str2num(temp(61:79)); temp=fgetl(fid1);

EphDat(i).ttm=str2num(temp(4:22)); if(i~=1) %删除重复数据

for k= i-1:i

if (EphDat(i-1).PRN~=EphDat(i).PRN) break;

elseif abs(EphDat(i-1).toc-EphDat(i).toc)<0.001 i=i - 1; end end end i=i + 1; end

function DDDW format long clear all tic

global HeadODat; global ObsODat; global EphDat;

%先读N文件,再读O文件 EphDat=ReadGpsData;

[HeadODat,ObsODat]=ReadObsData; %多个历元加权平均求测站点坐标 N = size(EphDat,2); c=299792458;

epochNUM=size(ObsODat,2);

%观测数据的个数

Xk0=HeadODat.ApproXYZ(1,1); %测站点的近似坐标 Yk0=HeadODat.ApproXYZ(1,2); Zk0=HeadODat.ApproXYZ(1,3); for k=1:epochNUM

tr=ObsODat(k).TimeOEp;

%历元接收数据时间

Snum=ObsODat(1,k).SatSum; %该历元观测到的卫星数 if Snum<4

break; %去除无解的历元 end

Code=ObsODat(k).SatCode; %该历元观测到的卫星号组

R=ObsODat(k).Obs_RangeC1 ; %取出C1观测值,列向量 %卫星发射时间的迭代计算 for j=1:Snum if R(j) == 0

continue; end

t=TimetoJD(tr(1),tr(2),tr(3),tr(4),tr(5),tr(6)); t2 = mod(t,7)*24*3600;%gps second

%卫星钟差 dd=-1;

for i=1:N

if(EphDat(i).PRN==Code(j)&abs(t-EphDat(i).toc)<0.0417*2)%读入时间相近的星历文件

a0= EphDat(i).a0; a1=EphDat(i).a1; a2= EphDat(i).a2; toe=EphDat(i).toe;

dt=a0+(t2-toe)*a1+(t2-toe)^2*a2;%卫星钟差 dd=1;

break; end end

if dd==-1

msgbox('没有相关星历文件'); return; end tt = tr;

ts = tr(6) - R(j)/c;%用秒进行迭代 sign = 1;

while(sign>1E-8) tt(6) = ts;

[Xs1,Ys1,Zs1]= CalPos(Code(j),tt);

ss1 = sqrt((Xk0-Xs1)^2+(Yk0-Ys1)^2+(Zk0-Zs1)*(Zk0-Zs1)); %卫星位置加地球自转改正

qe=0.000072921151467; %地球自转角速度 delt=ss1/c;

Rotation=[cos(qe*delt),sin(qe*delt),0;-sin(qe*delt),cos(qe*delt),0;0,0,1]; h=Rotation*[Xs1;Ys1;Zs1] ; Xs=h(1); Ys=h(2); Zs=h(3);

ss = sqrt((Xk0-Xs)^2+(Yk0-Ys)^2+(Zk0-Zs)*(Zk0-Zs)); ts = tr(6)-ss/c;

sign = norm(ts-tt(6)); end

axk = (Xk0-Xs)/ss; ayk = (Yk0-Ys)/ss;

azk = (Zk0-Zs)/ss;

EAB=CAL2POL(Xk0,Yk0,Zk0,Xs,Ys,Zs); if j==1

A = [axk,ayk,azk,1];

L = R(j)-ss++c*dt-2.47/(sin(EAB)+0.0121); else

A = [A;axk,ayk,azk,1]; %构造误差方程

L = [L;(R(j)-ss++c*dt)-2.47/(sin(EAB)+0.0121)];%常数项 end end

if Snum==4 dx=inv(A)*L;

aaaa(k).Q=inv(A'*A); Px(k) = 1/aaaa(k).Q(1,1); Py(k) = 1/aaaa(k).Q(2,2); Pz(k) = 1/aaaa(k).Q(3,3); xchange(k) = dx(1); ychange(k) = dx(2); zchange(k) = dx(3); elseif Snum > 4

dx = inv(A'*A)*A'*L; %构造法方程并求解 aaaa(k).Q=inv(A'*A); Px(k) = 1/aaaa(k).Q(1,1); Py(k) = 1/aaaa(k).Q(2,2); Pz(k) = 1/aaaa(k).Q(3,3); xchange(k) = dx(1); ychange(k) = dx(2); zchange(k) = dx(3); end end

Xp=sum(Px.*(Xk0+xchange))/sum(Px) Yp=sum(Py.*(Yk0+ychange))/sum(Py) Zp=sum(Pz.*(Zk0+zchange))/sum(Pz)

figure(1);

subplot(3,1,1);plot(xchange,'black--'); subplot(3,1,2);plot(ychange,'black--'); subplot(3,1,3);plot(zchange,'black--'); toc

function [x,y,z]= CalPos(PRN,time)

global EphDat

t1=TimetoJD(time(1),time(2),time(3),time(4),time(5),time(6));

t2=TimetoJD(time(1),time(2),time(3),0,0,0);

if isempty(EphDat)

EphDat=ReadGpsData; end

sz=size(EphDat,2); gg=0;

%判断最近的时间

for i=1:sz

if(EphDat(i).PRN==PRN & abs(EphDat(i).toc-t1)<0.0417*2) G=EphDat(i); gg=1; break; end end

t3=t2-G.weekno*7; % 减整周 数

t=t3*24*3600+time(4)*3600+time(5)*60+time(6);

%化为GPS秒

u=3.986004418E+14; %地球引力常数 we=7.2921151467E-5; %地球自转速度 a=G.sqa^2; %地球长半轴 n0=sqrt(u/a^3); %计算的平运动

tk=t-G.toe; %从参考历元开始的时间 if tk>=302400

tk=tk-604800; elseif tk<-302400 tk=tk + 604800; end

n=n0+G.dn; %改正后的运动 Mk=G.M0+n*tk;

Ek=Mk; %偏近点角for i=1:4

Ek=Mk+G.e*sin(Ek); end

fk=2*atan((sqrt((1+G.e)/(1-G.e))*tan(Ek/2))); %真近点角 if(fk<0)

fk=fk+2*pi; end

cosf=(cos(Ek)-G.e)/(1-G.e*cos(Ek));

sinf=(sqrt(1-G.e^2)*sin(Ek))/(1-G.e*cos(Ek));

弧度

uk=fk+G.w; %升交角矩及轨道摄动改正项 iuk=G.Cuc*cos(2*uk)+G.Cus*sin(2*uk); irk=G.Crc*cos(2*uk)+G.Crs*sin(2*uk); iik=G.Cic*cos(2*uk)+G.Cis*sin(2*uk);

uk=uk+iuk ; %改正后的升角距

r=a*(1-G.e*cos(Ek))+irk; %改正后的地心相径 i=G.i0+iik+G.iDot*tk; %改正后的倾角

xx=r*cos(uk); %在轨道面中的位置 yy=r*sin(uk);

omg=G.omg0+(G.omg-we)*tk-we*G.toe; %改正后的升交点经度 x=xx*cos(omg)-yy*cos(i)*sin(omg); y=xx*sin(omg)+yy*cos(i)*cos(omg); z=yy*sin(i); CalPos=[x,y,z];

%打印结果

% x=num2str(x,'.6f'); % y=num2str(y,'.6f'); % z=num2str(z,'.6f');

% fprintf('卫星号PRN:%2.0f',PRN); fprintf('\\n');

% fprintf('时间time:%4.0f%4.0f%4.0f%4.0f%4.0f%4.1f',time); fprintf('\\n'); % fprintf('所求卫星在地心坐标系中的空间坐标为:\\n'); % fprintf('X = ');fprintf(x,'\\n');fprintf('m\\n'); % fprintf('Y = ');fprintf(y,'\\n');fprintf('m\\n'); % fprintf('Z = ');fprintf(z,'\\n');fprintf('m\\n'); %

return

function EAB=CAL2POL(X,Y,Z,XB,YB,ZB) format long L=atan(Y/X);

R=sqrt(X*X+Y*Y+Z*Z); a=6378137;

e=sqrt(0.0066943799013); seta=atan(Z/sqrt(X*X+Y*Y));

B=asin(sqrt((a*a-R*R*cos(seta)*cos(seta))/(a*a-R*R*cos(seta)*cos(seta)*e*e))) B1=atan(tan(seta)*(1+a*e*e*sin(B)/Z/sqrt(1-e*e*sin(B)*sin(B)))); while abs(B1-B)>0.01*pi/180/3600 B=B1;

B1=atan(tan(seta)*(1+a*e*e*sin(B)/Z/sqrt(1-e*e*sin(B)^2))); end

H=R*cos(seta)/cos(B)-(a/sqrt(1-e*e*sin(B)*sin(B))); L=L*180/pi; B=B*180/pi; DX=XB-X;

DY=YB-Y; DZ=ZB-Z;

NB=-sin(B)*cos(L)*DX-sin(B)*sin(L)*DY+cos(B)*DZ; EB=-sin(L)*DX+cos(L)*DY;

UB=cos(B)*cos(L)*DX+cos(B)*sin(L)*DY+sin(B)*DZ; SAB=sqrt(NB*NB+UB*UB+EB*EB); EAB=asin(UB/SAB);

本文来源:https://www.bwwdw.com/article/vxc2.html

Top