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 /**
40  * @file SEMData.cpp
41  * Encapsulate SEM almanac file data, including I/O
42  */
43 
44 #include "StringUtils.hpp"
45 #include "GNSSconstants.hpp"
46 
47 #include "SEMData.hpp"
48 #include "SEMStream.hpp"
49 
50 
51 using namespace gpstk::StringUtils;
52 using namespace std;
53 
54 namespace gpstk
55 {
SEMData()56    SEMData::SEMData()
57          : ecc(0, FFLead::Zero, 15, 4, 0, 'E', FFSign::NegSpace),
58            i_offset(0, FFLead::Zero, 15, 4, 0, 'E', FFSign::NegSpace),
59            OMEGAdot(0, FFLead::Zero, 15, 4, 0, 'E', FFSign::NegSpace),
60            Ahalf(0, FFLead::Zero, 15, 4, 0, 'E', FFSign::NegSpace),
61            OMEGA0(0, FFLead::Zero, 15, 4, 0, 'E', FFSign::NegSpace),
62            w(0, FFLead::Zero, 15, 4, 0, 'E', FFSign::NegSpace),
63            M0(0, FFLead::Zero, 15, 4, 0, 'E', FFSign::NegSpace),
64            AF0(0, FFLead::Zero, 15, 4, 0, 'E', FFSign::NegSpace),
65            AF1(0, FFLead::Zero, 15, 4, 0, 'E', FFSign::NegSpace)
66    {
67    }
68 
69 
reallyPutRecord(FFStream & ffs) const70    void SEMData::reallyPutRecord(FFStream& ffs) const
71    {
72       string line;
73 
74       SEMStream& strm = dynamic_cast<SEMStream&>(ffs);
75 
76       //First output blank line to mark between records
77       strm << std::endl;
78 
79       //PRN output
80       strm << asString<short>(PRN) << endl;
81 
82       //SVNnum
83       strm << asString<short>(SVNnum) << endl;
84 
85       //URAnum
86       strm << asString<short>(URAnum) << endl;
87 
88       //Ecc, i_offset, OMEGAdot
89       strm << ecc << " " << (i_offset / gpstk::PI) << " "
90            << (OMEGAdot / gpstk::PI) << endl;
91 
92       //Ahalf, OMEGA0, w
93       strm << Ahalf << " " << (OMEGA0/gpstk::PI) << " " << (w/gpstk::PI)
94            << endl;
95 
96       //M0, AF0, AF1
97       strm << (M0/gpstk::PI) << " " << AF0 << " " << AF1 << endl;
98 
99       //SV_health
100       strm << asString<short>(SV_health) << endl;
101 
102       //satConfig
103       strm << asString<short>(satConfig) << endl;
104 
105 
106    }   // end SEMData::reallyPutRecord
107 
108 
reallyGetRecord(FFStream & ffs)109    void SEMData::reallyGetRecord(FFStream& ffs)
110    {
111       string line;
112 
113       SEMStream& strm = dynamic_cast<SEMStream&>(ffs);
114 
115       //if(!strm.headerRead)
116       //    strm >> strm.header;
117 
118       SEMHeader& hdr = strm.header;
119 
120       //Don't need first line - empty space
121       strm.formattedGetLine(line, true);
122 
123       // Second line - PRN
124       strm.formattedGetLine(line, true);
125       PRN = asInt(line);
126 
127       // Third line - SVN Number
128       // HACKHACKHACK This information might not be here??? Find out more info
129       strm.formattedGetLine(line, true);
130       SVNnum = (short) asInt(line);
131 
132       // Fourth line - Average URA Number as defined in ICD-GPS-200
133       strm.formattedGetLine(line, true);
134       URAnum = (short) asInt(line);
135 
136       string whitespace = " \t\r\n";
137 
138       // Fifth line - Eccentricity, Inclination Offset, and Rate of Right Ascension
139       strm.formattedGetLine(line, true);
140       string::size_type front = line.find_first_not_of(whitespace);
141       string::size_type end = line.find_first_of(whitespace,front);
142       string::size_type length = end - front;
143       ecc = line.substr(front,length);
144 
145       front = line.find_first_not_of(whitespace,end);
146       end = line.find_first_of(whitespace,front);
147       length = end - front;
148       i_offset = line.substr(front,length);
149       i_total = i_offset + 54.0 * (gpstk::PI / 180.0);
150 
151       front = line.find_first_not_of(whitespace,end);
152       length = line.length() - front;
153       OMEGAdot = line.substr(front,length);
154       i_offset *= gpstk::PI;
155       OMEGAdot *= gpstk::PI;
156 
157       // Sixth line - Sqrt of A, Omega0, and Arg of Perigee
158       strm.formattedGetLine(line, true);
159 
160       front = line.find_first_not_of(whitespace);
161       end = line.find_first_of(whitespace,front);
162       length = end - front;
163       Ahalf = line.substr(front,length);
164 
165       front = line.find_first_not_of(whitespace,end);
166       end = line.find_first_of(whitespace,front);
167       length = end - front;
168       OMEGA0 = line.substr(front,length);
169 
170       front = line.find_first_not_of(whitespace,end);
171       length = line.length() - front;
172       OMEGA0 *= gpstk::PI;
173       w = line.substr(front,length);
174       w *= gpstk::PI;
175 
176       // Seventh Line - M0, AF0, AF1
177       strm.formattedGetLine(line, true);
178 
179       front = line.find_first_not_of(whitespace);
180       end = line.find_first_of(whitespace,front);
181       length = end - front;
182       M0 = line.substr(front,length);
183       M0 *= gpstk::PI;
184 
185       front = line.find_first_not_of(whitespace,end);
186       end = line.find_first_of(whitespace,front);
187       length = end - front;
188       AF0 = line.substr(front,length);
189 
190       front = line.find_first_not_of(whitespace,end);
191       length = line.length() - front;
192       AF1 = line.substr(front,length);
193 
194       // Eigth line - Satellite Health
195       strm.formattedGetLine(line, true);
196       SV_health = (short) asInt(line);
197 
198       // Ninth line - Satellite Config
199       strm.formattedGetLine(line, true);
200       satConfig = (short) asInt(line);
201 
202       week = hdr.week;
203       Toa = hdr.Toa;
204 
205       xmit_time = 0;
206 
207    } // end of reallyGetRecord()
208 
dump(ostream & s) const209    void SEMData::dump(ostream& s) const
210    {
211       s << "PRN = " << PRN << std::endl;
212       s << "SVNnum = " << SVNnum << std::endl;
213       s << "URAnum = " << URAnum << std::endl;
214       s << "ecc = " << ecc << std::endl;
215       s << "i_offset = " << i_offset << std::endl;
216       s << "OMEGAdot = " << OMEGAdot << std::endl;
217       s << "Ahalf = " << Ahalf << std::endl;
218       s << "OMEGA0 = " << OMEGA0 << std::endl;
219       s << "w = " << w << std::endl;
220       s << "M0 = " << M0 << std::endl;
221       s << "AF0 = " << AF0 << std::endl;
222       s << "AF1 = " << AF1 << std::endl;
223       s << "SV_health = " << SV_health << std::endl;
224       s << "satConfig = " << satConfig << std::endl;
225       s << "xmit_time = " << xmit_time << std::endl;
226       s << "week = " << week << std::endl;
227       s << "toa = " << Toa << std::endl;
228    }
229 
operator AlmOrbit() const230    SEMData::operator AlmOrbit() const
231    {
232 
233       AlmOrbit ao(PRN, ecc,i_offset, OMEGAdot, Ahalf, OMEGA0,
234                    w, M0, AF0, AF1, Toa, xmit_time, week, SV_health);
235 
236       return ao;
237    }
238 
operator OrbAlmGen() const239    SEMData::operator OrbAlmGen() const
240    {
241      OrbAlmGen oag;
242 
243      oag.AHalf    = Ahalf;
244      oag.A        = Ahalf * Ahalf;
245      oag.af1      = AF1;
246      oag.af0      = AF0;
247      oag.OMEGA0   = OMEGA0;
248      oag.ecc      = ecc;
249      oag.deltai   = i_offset;
250      oag.i0       = i_total;
251      oag.OMEGAdot = OMEGAdot;
252      oag.w        = w;
253      oag.M0       = M0;
254      oag.toa      = Toa;
255      oag.health   = SV_health;
256 
257      // At this writing Yuma almanacs only exist for GPS
258      oag.subjectSV = SatID(PRN, SatelliteSystem::GPS);
259 
260      // Unfortunately, we've NO IDEA which SV transmitted
261      // these data.
262      oag.satID = SatID(0,SatelliteSystem::GPS);
263 
264      //
265      oag.ctToe = GPSWeekSecond(week,Toa,TimeSystem::GPS);
266 
267      // There is no transmit time in the SEM alamanc format.
268      // Therefore, beginValid and endvalid are estimated.  The
269      // estimate is based on IS-GPS-200 Table 20-XIII.
270      oag.beginValid = oag.ctToe - (70 * 3600.0);
271      oag.endValid   = oag.beginValid + (144 * 3600.0);
272 
273      oag.dataLoadedFlag = true;
274      oag.setHealthy(false);
275      if (oag.health==0)
276         oag.setHealthy(true);
277 
278         // It is assumed that the data were broadcast on
279         // each of L1 C/A, L1 P(Y), and L2 P(Y).   We'll
280         // load obsID with L1 C/A for the sake of completeness,
281         // but this will probably never be examined.
282      oag.obsID = ObsID(ObservationType::NavMsg,CarrierBand::L1,TrackingCode::CA);
283 
284      return oag;
285    }
286 
287 
288 } // namespace
289