1 //==============================================================================
2 //
3 //  This file is part of GPSTk, the GPS Toolkit.
4 //
5 //  The GPSTk is free software; you can redistribute it and/or modify
6 //  it under the terms of the GNU Lesser General Public License as published
7 //  by the Free Software Foundation; either version 3.0 of the License, or
8 //  any later version.
9 //
10 //  The GPSTk is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU Lesser General Public License for more details.
14 //
15 //  You should have received a copy of the GNU Lesser General Public
16 //  License along with GPSTk; if not, write to the Free Software Foundation,
17 //  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
18 //
19 //  This software was developed by Applied Research Laboratories at the
20 //  University of Texas at Austin.
21 //  Copyright 2004-2020, The Board of Regents of The University of Texas System
22 //
23 //==============================================================================
24 
25 //==============================================================================
26 //
27 //  This software was developed by Applied Research Laboratories at the
28 //  University of Texas at Austin, under contract to an agency or agencies
29 //  within the U.S. Department of Defense. The U.S. Government retains all
30 //  rights to use, duplicate, distribute, disclose, or release this software.
31 //
32 //  Pursuant to DoD Directive 523024
33 //
34 //  DISTRIBUTION STATEMENT A: This software has been approved for public
35 //                            release, distribution is unlimited.
36 //
37 //==============================================================================
38 
39 /// @file GalEphemeris.cpp Encapsulates the GPS legacy broadcast ephemeris and clock.
40 /// Inherits OrbitEph, which does most of the work; this class adds health and
41 /// accuracy information, fit interval, ionospheric correction terms and data
42 /// flags.
43 
44 #include <string>
45 #include "Exception.hpp"
46 #include "TimeString.hpp"
47 #include "CivilTime.hpp"
48 #include "GALWeekSecond.hpp"
49 
50 #include "GalEphemeris.hpp"
51 
52 using namespace std;
53 
54 namespace gpstk
55 {
56    // Returns true if the time, ct, is within the period of validity of
57    // this OrbitEph object.
58    // @throw Invalid Request if the required data has not been stored.
isValid(const CommonTime & ct) const59    bool GalEphemeris::isValid(const CommonTime& ct) const
60    {
61       try {
62          if(ct >= beginValid && ct <= endValid) return true;
63          return false;
64       }
65       catch(Exception& e) { GPSTK_RETHROW(e); }
66    }
67 
68    // This function returns the health status of the SV.
isHealthy(void) const69    bool GalEphemeris::isHealthy(void) const
70    {
71       if (health==Xvt::Healthy)
72          return true;
73       return false;
74    }
75 
76    // adjustBeginningValidity determines the beginValid and endValid times.
77    // @throw Invalid Request if the required data has not been stored.
78    //
79    // NOTE: The Galileo ICD does not make the same sort of promises about
80    // the relationship of t-sub-oe and beginning time of transmission as
81    // GPS.  Therefore, we should NOT adjust the beginValid time to be
82    // anything other than the earliest tranmit time we recorded.
83    //
84    // The end of validity presents a problem also.  There is no guidance in
85    // the ICD.  The only guidance in the SDD is "do not use beyond four hours
86    // from initial time of transmission".   We don't KNOW that the transmission
87    // time we have in hand is the earliest transmission.  Typically, the toe is
88    // about ten minutes prior to the first time of transmission.   Therefore,
89    // we will go with that.
90    //
adjustValidity(void)91    void GalEphemeris::adjustValidity(void)
92    {
93       try {
94          OrbitEph::adjustValidity();   // for dataLoaded check
95          beginValid = transmitTime;
96          endValid = ctToe + (3600*4);  // Four hours
97       }
98       catch(Exception& e) { GPSTK_RETHROW(e); }
99    }
100 
101    // Dump the orbit, etc information to the given output stream.
102    // @throw Invalid Request if the required data has not been stored.
dumpBody(std::ostream & os) const103    void GalEphemeris::dumpBody(std::ostream& os) const
104    {
105       try {
106          OrbitEph::dumpBody(os);
107 
108          os << "           Galileo-SPECIFIC PARAMETERS\n"
109             << scientific << setprecision(8)
110             << "Tgd (E5a/E1) : " << setw(16) << Tgda << " meters" << endl
111             << "Tgd (E5b/E1) : " << setw(16) << Tgdb << " meters" << endl
112             << "HOW time     : " << setw(6) << HOWtime << " (sec of GAL week "
113             << setw(4) << static_cast<GALWeekSecond>(ctToe).getWeek() << ")" << endl
114             << "TransmitTime : " << OrbitEph::timeDisplay(transmitTime) << endl
115             << "IODNav: " << IODnav << fixed << setprecision(2)
116             << "  Accuracy : " << getAccuracy() << " meters"
117             << "  fitDuration: " << setw(2) << fitDuration << " hours" << endl
118             << "Healthy?     : 0x" << hex << setw(2) << health << dec << " :"
119             << " [E1b_D " << ((health & 0x1) ? "N":"Y") << "]"
120             << " [E1b_H " << ((health & 0x2) ? "N":"Y") << "]"
121             << " [E5a_D " << ((health & 0x4) ? "N":"Y") << "]"
122             << " [E5a_H " << ((health & 0x18) ? "N":"Y") << "]"
123             << " [E5b_D " << ((health & 0x20) ? "N":"Y") << "]"
124             << " [E5b_H " << ((health & 0xC0) ? "N":"Y") << "]"
125             << endl
126             << "Datasources  : " << setw(3) << datasources << " :"
127             << ((datasources & 0x1) ? " [I/NAV E1-B]" : "")
128             << ((datasources & 0x2) ? " [F/NAV E5a-I]" : "")
129             << ((datasources & 0x4) ? " [I/NAV E5b-I]" : "")
130             << ((datasources & 0x8) ? " [bit 3 reserved]" : "")
131             << ((datasources & 0x10) ? " [bit 4 reserved]" : "")
132             << ((datasources & 0x100) ? " [set clk/Toc/acc for E5a,E1]" : "")
133             << ((datasources & 0x200) ? " [set clk/Toc/acc for E5b,E1]" : "")
134             << endl;
135       }
136       catch(Exception& e) { GPSTK_RETHROW(e); }
137    }
138 
139    // Dump the overhead information as a string containing a single line.
140    // @throw Invalid Request if the required data has not been stored.
asString(void) const141    string GalEphemeris::asString(void) const
142    {
143       if(!dataLoadedFlag)
144          GPSTK_THROW(InvalidRequest("Data not loaded"));
145       try {
146          ostringstream os;
147          CivilTime ct;
148          os << "EPH E" << setfill('0') << setw(2) << satID.id << setfill(' ');
149          ct = CivilTime(beginValid);
150          os << printTime(ct," | %4Y %3j %02H:%02M:%02S |");
151          ct = CivilTime(ctToe);
152          os << printTime(ct," %3j %02H:%02M:%02S |");
153          ct = CivilTime(ctToc);
154          os << printTime(ct," %3j %02H:%02M:%02S |");
155          ct = CivilTime(endValid);
156          os << printTime(ct," %3j %02H:%02M:%02S |");
157          ct = CivilTime(transmitTime);
158          os << printTime(ct," %3j %02H:%02M:%02S | ");
159          os << setw(3) << IODnav;
160             //<< " | " << fixed << setprecision(2) << getAccuracy()
161          os << " | 0x" << hex << setw(3) <<setfill('0')<< health <<dec<<setfill(' ');
162          os << " | "
163             << ((datasources & 0x5) ? "E15b" : "")       // 1 or 4
164             << ((datasources & 0x2) ? "E5a " : "")
165             //<< ((datasources & 0x4) ? "E5b " : "")
166             << ((datasources & 0x100) ? " a1" : "")
167             << ((datasources & 0x200) ? " b1" : "")
168             << " |";
169          return os.str();
170       }
171       catch(Exception& e) { GPSTK_RETHROW(e);
172       }
173    }
174 
deriveHealth(const unsigned short SHS,const unsigned short DVS,const unsigned short SISA)175    Xvt::HealthStatus GalEphemeris::deriveHealth(const unsigned short SHS,
176                                   const unsigned short DVS,
177                                   const unsigned short SISA )
178    {
179       if (SHS==1 || SHS==3)
180          return Xvt::Unhealthy;
181 
182       if (SHS==2)
183          return Xvt::Degraded;
184 
185       if (SHS==0)
186       {
187          if (DVS==1)
188             return Xvt::Degraded;
189 
190          if (DVS==0)
191          {
192             if (SISA==255)
193                return Xvt::Degraded;
194             if (SISA<255)
195                return Xvt::Healthy;
196          }
197       }
198       return Xvt::Unknown;
199    }
200 
201 } // end namespace
202