You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

257 lines
9.5 KiB

function [gpsEph,iono] = ReadRinexNav(fileName)
% [gpsEph,iono] = ReadRinexNav(fileName)
%
% Read GPS ephemeris and iono data from an ASCII formatted RINEX 2.10 Nav file.
% Input:
% fileName - string containing name of RINEX formatted navigation data file
% Output:
% gpsEph: vector of ephemeris data, each element is an ephemeris structure
% structure order and orbit variable names follow RINEX 2.1 Table A4
% clock variable names af0, af1, af2 follow IS GPS 200
% gpsEph(i).PRN % SV PRN number
% gpsEph(i).Toc % Time of clock (seconds)
% gpsEph(i).af0 % SV clock bias (seconds)
% gpsEph(i).af1 % SV clock drift (sec/sec)
% gpsEph(i).af2 % SV clock drift rate (sec/sec2)
% gpsEph(i).IODE % Issue of data, ephemeris
% gpsEph(i).Crs % Sine harmonic correction to orbit radius (meters)
% gpsEph(i).Delta_n % Mean motion difference from computed value (radians/sec)
% gpsEph(i).M0 % Mean anomaly at reference time (radians)
% gpsEph(i).Cuc % Cosine harmonic correction to argument of lat (radians)
% gpsEph(i).e % Eccentricity (dimensionless)
% gpsEph(i).Cus % Sine harmonic correction to argument of latitude (radians)
% gpsEph(i).Asqrt % Square root of semi-major axis (meters^1/2)
% gpsEph(i).Toe % Reference time of ephemeris (seconds)
% gpsEph(i).Cic % Cosine harmonic correction to angle of inclination (radians)
% gpsEph(i).OMEGA % Longitude of ascending node at weekly epoch (radians)
% gpsEph(i).Cis % Sine harmonic correction to angle of inclination (radians)
% gpsEph(i).i0 % Inclination angle at reference time (radians)
% gpsEph(i).Crc % Cosine harmonic correction to the orbit radius (meters)
% gpsEph(i).omega % Argument of perigee (radians)
% gpsEph(i).OMEGA_DOT% Rate of right ascension (radians/sec)
% gpsEph(i).IDOT % Rate of inclination angle (radians/sec)
% gpsEph(i).codeL2 % codes on L2 channel
% gpsEph(i).GPS_Week % GPS week (to go with Toe), (NOT Mod 1024)
% gpsEph(i).L2Pdata % L2 P data flag
% gpsEph(i).accuracy % SV user range accuracy (meters)
% gpsEph(i).health % Satellite health
% gpsEph(i).TGD % Group delay (seconds)
% gpsEph(i).IODC % Issue of Data, Clock
% gpsEph(i).ttx % Transmission time of message (seconds)
% gpsEph(i).Fit_interval %fit interval (hours), zero if not known
%
% iono: ionospheric parameter structure
% iono.alpha = [alpha0, alpha1, alpha2, alpha3]
% iono.beta = [ beta0, beta1, beta2, beta3]
% if iono data is not present in the Rinex file, iono is returned empty.
fidEph = fopen(fileName);
[numEph,numHdrLines] = countEph(fidEph);
%Now read from the begining again, looking for iono parameters
frewind(fidEph);
iono = readIono(fidEph,numHdrLines);
%initialize ephemeris structure array:
gpsEph = InitializeGpsEph;
gpsEph = repmat(gpsEph,1,numEph);
%now read each ephemeris into gpsEph(j)
%RINEX defines the format in terms of numbers of characters, so that's how we
%read it, e.g. "gpsEph(j).PRN = str2num(line(1:2));" and so on
for j = 1:numEph
line = fgetl(fidEph);
gpsEph(j).PRN = str2num(line(1:2));
%NOTE: we use str2num, not str2double, since str2num handles 'D' for exponent
%% get Toc (Rinex gives this as UTC time yy,mm,dd,hh,mm,ss)
year = str2num(line(3:6));
%convert year to a 4-digit year, this code is good to the year 2080.
%From 2080 RINEX 2.1 is ambiguous and shouldnt be used, because is has a
%2-digit year, and 100 years will have passed since the GPS Epoch.
if year < 80,
year = 2000+year;
else
year = 1900+year;
end
month = str2num(line(7:9));
day = str2num(line(10:12));
hour = str2num(line(13:15));
minute = str2num(line(16:18));
second = str2num(line(19:22));
%convert Toc to gpsTime
gpsTime = Utc2Gps([year,month,day,hour,minute,second]);
gpsEph(j).Toc = gpsTime(2);
%% get all other parameters
gpsEph(j).af0 = str2num(line(23:41));
gpsEph(j).af1 = str2num(line(42:60));
gpsEph(j).af2 = str2num(line(61:79));
line = fgetl(fidEph);
gpsEph(j).IODE = str2num(line(4:22));
gpsEph(j).Crs = str2num(line(23:41));
gpsEph(j).Delta_n = str2num(line(42:60));
gpsEph(j).M0 = str2num(line(61:79));
line = fgetl(fidEph);
gpsEph(j).Cuc = str2num(line(4:22));
gpsEph(j).e = str2num(line(23:41));
gpsEph(j).Cus = str2num(line(42:60));
gpsEph(j).Asqrt = str2num(line(61:79));
line=fgetl(fidEph);
gpsEph(j).Toe = str2num(line(4:22));
gpsEph(j).Cic = str2num(line(23:41));
gpsEph(j).OMEGA = str2num(line(42:60));
gpsEph(j).Cis = str2num(line(61:79));
line = fgetl(fidEph);
gpsEph(j).i0 = str2num(line(4:22));
gpsEph(j).Crc = str2num(line(23:41));
gpsEph(j).omega = str2num(line(42:60));
gpsEph(j).OMEGA_DOT = str2num(line(61:79));
line = fgetl(fidEph);
gpsEph(j).IDOT = str2num(line(4:22));
gpsEph(j).codeL2 = str2num(line(23:41));
gpsEph(j).GPS_Week = str2num(line(42:60));
gpsEph(j).L2Pdata = str2num(line(61:79));
line = fgetl(fidEph);
gpsEph(j).accuracy = str2num(line(4:22));
gpsEph(j).health = str2num(line(23:41));
gpsEph(j).TGD = str2num(line(42:60));
gpsEph(j).IODC = str2num(line(61:79));
line = fgetl(fidEph);
gpsEph(j).ttx = str2num(line(4:22));
gpsEph(j).Fit_interval = str2num(line(23:41));
end
fclose(fidEph);
end %end of function ReadRinexNav
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [numEph,numHdrLines] = countEph(fidEph,fileName)
%utility function for ReadRinexNav
%Read past the header, and then read to the end, counting ephemerides:
numHdrLines = 0;
bFoundHeader = false;
while ~bFoundHeader %Read past the header
numHdrLines = numHdrLines+1;
line = fgetl(fidEph);
if ~ischar(line), break, end
k = strfind(line,'END OF HEADER');
if ~isempty(k),
bFoundHeader = true;
break
end
end
if ~bFoundHeader
error('Error reading file: %s\nExpected RINEX header not found',fileName);
end
%Now read to the end of the file
numEph = -1;
while 1
numEph = numEph+1;
line = fgetl(fidEph);
if line == -1,
break;
elseif length(line)~=79
%use this opportunity to check line is the right length
%because in the rest of ReadRinexNav we depend on line being this length
error('Incorrect line length encountered in RINEX file');
end
end;
%check that we read the expected number of lines:
if rem(numEph,8)~=0
error('Number of nav lines in %s should be divisible by 8',fileName);
end
numEph = numEph/8; %8 lines per ephemeris
end %end of function countEph
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function iono = readIono(fidEph,numHdrLines)
%utility function to read thru the header lines, and find iono parameters
iono = []; %return empty if iono not found
bIonoAlpha=false; bIonoBeta=false;
for i = 1:numHdrLines,
line = fgetl(fidEph);
% Look for iono parameters, and read them in
if ~isempty(strfind(line,'ION ALPHA')) %line contains iono alpha parameters
ii = strfind(line,'ION ALPHA');
iono.alpha=str2num(line(1:ii-1));
%If we have 4 parameters then we have the complete iono alpha
bIonoAlpha = (length(iono.alpha)==4);
end
if ~isempty(strfind(line,'ION BETA'))%line contains the iono beta parameters
ii = strfind(line,'ION BETA');
iono.beta=str2num(line(1:ii-1));
%If we have 4 parameters then we have the complete iono beta
bIonoBeta = (length(iono.beta)==4);
end
end
if ~(bIonoAlpha && bIonoBeta)
%if we didn't get both alpha and beta iono correctly, then return empty iono
iono=[];
end
end %end of function readIono
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function gpsEph = InitializeGpsEph
%utility function to initialize the ephemeris structure
gpsEph.PRN = 0;
gpsEph.Toc = 0;
gpsEph.af0 = 0;
gpsEph.af1 = 0;
gpsEph.af2 = 0;
gpsEph.IODE = 0;
gpsEph.Crs = 0;
gpsEph.Delta_n = 0;
gpsEph.M0 = 0;
gpsEph.Cuc = 0;
gpsEph.e = 0;
gpsEph.Cus = 0;
gpsEph.Asqrt = 0;
gpsEph.Toe = 0;
gpsEph.Cic = 0;
gpsEph.OMEGA = 0;
gpsEph.Cis = 0;
gpsEph.i0 = 0;
gpsEph.Crc = 0;
gpsEph.omega = 0;
gpsEph.OMEGA_DOT = 0;
gpsEph.IDOT = 0;
gpsEph.codeL2 = 0;
gpsEph.GPS_Week = 0;
gpsEph.L2Pdata = 0;
gpsEph.accuracy = 0;
gpsEph.health = 0;
gpsEph.TGD = 0;
gpsEph.IODC = 0;
gpsEph.ttx = 0;
gpsEph.Fit_interval= 0;
end %end of function InitializeEph
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Copyright 2016 Google Inc.
%
% Licensed under the Apache License, Version 2.0 (the "License");
% you may not use this file except in compliance with the License.
% You may obtain a copy of the License at
%
%     http://www.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS,
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
% See the License for the specific language governing permissions and
% limitations under the License.