# ## Copyright (c) 1995-2020 University Corporation for Atmospheric Research ## All rights reserved # #/**---------------------------------------------------------------------- # @file SatInfo.pm # # This contains utility routines for dealing with the Bernese SATELLIT. file. # # @author Doug Hunt # @since 03/31/2014 # @version $URL$ $Id$ # -----------------------------------------------------------------------*/ package SatInfo; use lib qw(.); use BJConstants (); #/**---------------------------------------------------------------------- # @sub new # # Create an object based on parsing at SATELLIT. file. # # @parameter $infile -- The full path name of the gloNav file # @return $satinfo -- SatInfo object # @exception Exception Returned # ----------------------------------------------------------------------*/ sub new { my $class = shift; my $satfile = shift; my %opts = @_; return bless {SATFILE => $satfile, %opts}, $class; } #/**---------------------------------------------------------------------- # @sub parse # # Parse the SATELLIT. file contained in the object. # # @parameter $self -- SatInfo object # @return none (header parsed, info stored in object) # ----------------------------------------------------------------------*/ sub parse { my $self = shift; my $f = $self->{SATFILE}; open my $fh, '<', $f or die "Cannot open $f for reading"; while (<$fh>) { last if (/PART 2: ON-BOARD SENSORS/) } <$fh>; <$fh>; <$fh>; <$fh>; my %data; while (<$fh>) { last if (/PART 3: RPR PARAMETERS/); next if (length($_) < 170); # skip SLR records my ($prn, $type, $name, $svn, $num, $start, $end, $dx, $dy, $dz, $bx, $by, $bz, $ax, $ay, $az, $antex_name, $freq_slot) = unpack ("a3 x2 a3 x3 a16 x a3 x7 a x2 a19 x2 a19 x6 a7 x3 a7 x3 a7 x4 a7 x a7 x a7 x4 a7 x a7 x a7 x3 a20 x3 a2", $_); next if ($prn >= 300); # skip GEOs and LEOs my $ts = TimeClass->new->set_ymdhms_gps(split ' ', $start)->get_gps; # For empty ending dates, set $te large my $te = ($end =~ /^\s*$/) ? 9e99 : TimeClass->new->set_ymdhms_gps(split ' ', $end)->get_gps; $prn =~ s/\s//g; # get rid of whitespace push (@{$data{$prn}}, [$ts, $te, $svn, $freq_slot]); } close $fh; $self->{SVNMAP} = \%data; return $self; } #/**---------------------------------------------------------------------- # @sub find_svn # # Return the correct SVN and frequency slot given a PRN and a time # # @parameter $self -- SatInfo object # @ $prn -- PRN eg. 'G15' or 'R07'; # @ $time -- Time in GPS seconds # @return ($svn, $slot) # @exception Thrown if no info found # ----------------------------------------------------------------------*/ sub find_svn { my $self = shift; my $prn = shift; my $time = shift; my ($conid, $prnnum) = ($prn =~ /([GRCJE])(\d+)/); die "illegal PRN $prn" unless (defined($conid)); $prnnum += 0; # canonicalize if ($conid eq 'R') { $prnnum += 100; } # Incomplete Beidou support. I do not currently know how to find the # Beidou SVN. if ($conid eq 'C') { return ($Dplib::err, 0, $BJConstants::B1, $BJConstants::B2); } # Incomplete Galileo support. I do not currently know how to find the # Galileo SVN. if ($conid eq 'E') { $prnnum += 200; # Jun modified #return ($Dplib::err, 0, $BJConstants::E1, $BJConstants::E5b); # original } # Incomplete QZSS support. Must verify. Supposedly QZSS frequencies are the same as GPS if ($conid eq 'J') { return ($Dplib::err, 0, $BJConstants::F1, $BJConstants::F2); } my $list = $self->{SVNMAP}{$prnnum}; die "No info found for PRN $prn" if (!defined($list)); foreach my $entry (@$list) { my ($ts, $te, $svn, $freq_slot) = @$entry; if ($ts <= $time && $te >= $time) { my ($f1, $f2); if ($conid eq 'R') { ($f1, $f2) = glonass_freq ($freq_slot); } elsif ($conid eq 'G') { ($f1, $f2) = ($BJConstants::F1, $BJConstants::F2); } elsif ($conid eq 'E') { ($f1, $f2) = ($BJConstants::E1, $BJConstants::E5a); } return ($svn, $freq_slot, $f1, $f2); } } die "Cannot find entry for PRN $prn at time $time"; } #/**---------------------------------------------------------------------- # @sub glonass_freq # # This routine takes a GLONASS slot number, as returned by 'find_svn' and computes # the corresponding freqencies. # # @parameter $slotnum -- GLONASS slot number -7 to 7 # @return $freq1, $freq2, Mhz # @exception Exception Returned # ----------------------------------------------------------------------*/ sub glonass_freq { my $slotnum = shift; my $f1_glo = 1.602e9; my $f2_glo = 1.246e9; # GLONASS Center Frequencies my $f1_delta = 5.625e5; my $f2_delta = 4.375e5; # GLONASS Frequency offsets # Older GLONASS (as opposed to GLONASS-M, etc) satellites operated in a wider frequency range # allowing slots up to 23. Newer GLONASS only use up to slot 7. # Needed for DITL test with 2008 data. D. Hunt 2/18/2016 die "Illegal slotnum $slotnum" if ($slotnum < -7 || $slotnum > 23); my $f1 = $f1_glo + $slotnum * $f1_delta; my $f2 = $f2_glo + $slotnum * $f2_delta; return ($f1, $f2); } 1; # make 'use' happy