当前位置:文档之家› 利用MATLAB编制的GPS单点定位程序

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

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

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

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) %删除重复数据

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,'%12.6f');

% y=num2str(y,'%12.6f');

% z=num2str(z,'%12.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);

相关主题
文本预览
相关文档 最新文档