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 #include "AlmOrbit.hpp"
40 #include "Xvt.hpp"
41 #include "GPSWeekSecond.hpp"
42 #include "CommonTime.hpp"
43 #include "TestUtil.hpp"
44 #include <iostream>
45 #include <sstream>
46 
47 using namespace std;
48 using namespace gpstk;
49 
50 /** Threshold for how much different our velocities can be between
51  * being computed directly via svXvt and computed via differencing
52  * svXvt positions over time. */
53 double velDiffThresh = 0.0008;
54 
55 class AlmOrbit_T: public AlmOrbit
56 {
57 public:
AlmOrbit_T()58    AlmOrbit_T()
59    {
60       eps = 1E-12;  // Default Constructor, set the precision value
61    }
~AlmOrbit_T()62    ~AlmOrbit_T() {} // Default Desructor
63 
64 //=============================================================================
65 // Test will check the initialization of AlmOrbit objects
66 //=============================================================================
initializationTest(void)67    int initializationTest(void)
68    {
69       TUDEF("AlmOrbit", "Default Constructor");
70       std::string testMesg;
71 
72       gpstk::AlmOrbit empty;
73 
74          //--------------------------------------------------------------------
75          //Does the default constructor function correctly?
76          //--------------------------------------------------------------------
77       testMesg = "PRN not initialized to 0";
78       TUASSERTE(short, 0, empty.getPRN());
79       testMesg = "Ecc not initialized to 0";
80       TUASSERTFEPS(0, empty.getecc(), eps);
81       testMesg = "Offset not initialized to 0";
82       TUASSERTFEPS(0, empty.geti_offset(), eps);
83       testMesg = "OMEGAdot not initialized to 0";
84       TUASSERTFEPS(0, empty.getOMEGAdot(), eps);
85       testMesg = "Ahalf not initialized to 0";
86       TUASSERTFEPS(0, empty.getAhalf(), eps);
87       testMesg = "OMEGA0 not initialized to 0";
88       TUASSERTFEPS(0, empty.getOMEGA0(), eps);
89       testMesg = "W not initialized to 0";
90       TUASSERTFEPS(0, empty.getw(), eps);
91       testMesg = "M0 not initialized to 0";
92       TUASSERTFEPS(0, empty.getM0(), eps);
93       testMesg = "AF0 not initialized to 0";
94       TUASSERTFEPS(0, empty.getAF0(), eps);
95       testMesg = "AF1 not initialized to 0";
96       TUASSERTFEPS(0, empty.getAF1(), eps);
97       testMesg = "Toa not initialized to 0";
98       TUASSERTE(long, 0, empty.getToaSOW());
99       testMesg = "Xmit_time not initialized to 0";
100       TUASSERTE(long, 0, empty.getxmit_time());
101       testMesg = "Week not initialized to 0";
102       TUASSERTE(short, 0, empty.getToaWeek());
103 // No SV health get method
104 //  testMesg = "SV_health not initialized to 0";
105 //  TUASSERTE(short, 0, empty.getSV_health());
106 
107 //============================================================================
108 
109 //  Should be tested by testing the inhereted members as comparison points
110 //  instead of using the get methods, but compare.PRN doesn't work due to
111 //  inheritance issues
112 
113 //============================================================================
114 
115       gpstk::AlmOrbit compare(1, 0.00346661, 0.00388718, -8.01176E-09, 5153.58,
116                               -0.296182, -1.31888, 2.79387, 0.000148773,
117                               7.63976E-11, 466944, 250560, 797, 0);
118 
119       TUCSM("Explicit Constructor");
120          //----------------------------------------------------------------
121          //Does the explicit constructor function correctly?
122          //----------------------------------------------------------------
123       testMesg = "PRN value was not initialized correctly";
124       TUASSERTE(short, 1, compare.getPRN());
125       testMesg = "Ecc value was not initialized correctly";
126       TUASSERTFEPS(0.00346661, compare.getecc(), eps);
127       testMesg = "Offset value was not initialized correctly";
128       TUASSERTFEPS(0.00388718, compare.geti_offset(), eps);
129       testMesg = "OMEGAdot value was not initialized correctly";
130       TUASSERTFEPS(-8.01176E-09, compare.getOMEGAdot(), eps);
131       testMesg = "Ahalf value was not initialized correctly";
132       TUASSERTFEPS(5153.58, compare.getAhalf(), eps);
133       testMesg = "OMEGA0 value was not initialized correctly";
134       TUASSERTFEPS(-0.296182, compare.getOMEGA0(), eps);
135       testMesg = "W value was not initialized correctly";
136       TUASSERTFEPS(-1.31888, compare.getw(), eps);
137       testMesg = "M0 value was not initialized correctly";
138       TUASSERTFEPS(2.79387, compare.getM0(), eps);
139       testMesg = "AF0 value was not initialized correctly";
140       TUASSERTFEPS(0.000148773, compare.getAF0(), eps);
141       testMesg = "AF1 value was not initialized correctly";
142       TUASSERTFEPS(7.63976E-11, compare.getAF1(), eps);
143       testMesg = "Toa value was not initialized correctly";
144       TUASSERTE(long, 466944, compare.getToaSOW());
145       testMesg = "Xmit_time value was not initialized correctly";
146       TUASSERTE(long, 250560, compare.getxmit_time());
147       testMesg = "Week value was not initialized correctly";
148       TUASSERTE(short, 797, compare.getToaWeek());
149 // No SV health get method
150 //  testMesg = "SV_health value was not initialized correctly";
151 //  TUASSERTE(short, 0, AlmOrbit::SV_health);
152 
153       TURETURN();
154    }
155 //=============================================================================
156 // Test will check the dump method for various verbosities
157 //=============================================================================
dumpTest(void)158    int dumpTest(void)
159    {
160       TUDEF("AlmOrbit", "Dump");
161       std::string testMesg;
162 
163       gpstk::AlmOrbit compare(1, 0.00346661, 0.00388718, -8.01176E-09, 5153.58,
164                               -0.296182, -1.31888, 2.79387, 0.000148773,
165                               7.63976E-11, 466944, 250560, 797, 0);
166 
167 
168       std::stringstream outputStream1, outputStream2, outputStream3;
169       std::string outputString1, referenceString1, outputString2,
170           referenceString2, outputString3, referenceString3;
171 
172       referenceString1 = "1, 466944, 797, 0, 1.4877e-04, 7.6398e-11,"
173                          " 3.4666e-03, -1.3189e+00, 5.1536e+03, 2.7939e+00, -2.9618e-01, "
174                          "-8.0118e-09, 3.8872e-03\n";
175       compare.dump(outputStream1, 0);
176       outputString1 = outputStream1.str();
177 
178          //-----------------------------------------------------------------
179          //Did the least verbose dump method function correctly?
180          //-----------------------------------------------------------------
181       testMesg = "Least-verbose dump method did not function correctly";
182       TUASSERTE(std::string, referenceString1, outputString1);
183 
184       referenceString2 = "PRN:1 Toa:466944 H:0 AFO:1.4877e-04 AF1:7.6398e-11 "
185                          "Ecc:3.4666e-03\n   w:-1.3189e+00 Ahalf:5.1536e+03 "
186                          "M0:2.7939e+00\n   OMEGA0:-2.9618e-01 "
187                          "OMEGAdot:-8.0118e-09 Ioff:3.8872e-03\n";
188       compare.dump(outputStream2, 1);
189       outputString2 = outputStream2.str();
190 
191          //-----------------------------------------------------------------
192          //Did the mid-level verbose dump method function correctly?
193          //-----------------------------------------------------------------
194       testMesg = "Medium-verbose dump method did not function correctly";
195       TUASSERTE(std::string, referenceString2, outputString2);
196 
197 
198       referenceString3 = "PRN:                   1\n"
199                          "Toa:                   466944\n"
200                          "xmit_time:             250560\n"
201                          "week:                  797\n"
202                          "SV_health:             0\n"
203                          "AFO:                     1.4877e-04 sec\n"
204                          "AF1:                     7.6398e-11 sec/sec\n"
205                          "Sqrt A:                  5.1536e+03 sqrt meters\n"
206                          "Eccentricity:            3.4666e-03\n"
207                          "Arg of perigee:         -1.3189e+00 rad\n"
208                          "Mean anomaly at epoch:   2.7939e+00 rad\n"
209                          "Right ascension:        -2.9618e-01 rad"
210                          "         -8.0118e-09 rad/sec\n"
211                          "Inclination offset:      3.8872e-03 rad    \n";
212       compare.dump(outputStream3, 2);
213       outputString3 = outputStream3.str();
214 
215          //-----------------------------------------------------------------
216          //Did the most verbose dump method function correctly?
217          //-----------------------------------------------------------------
218       testMesg = "High-verbose dump method did not function correctly";
219       TUASSERTE(std::string, referenceString3, outputString3);
220 
221       TURETURN();
222 
223    }
224 //=============================================================================
225 // Test will check the various operators
226 //=============================================================================
operatorTest(void)227    int operatorTest(void)
228    {
229       TUDEF("AlmOrbit", "operator<<");
230       std::string testMesg;
231 
232       std::stringstream outputStream;
233       std::string outputString, referenceString;
234 
235       gpstk::AlmOrbit compare(1, 0.00346661, 0.00388718, -8.01176E-09, 5153.58,
236                               -0.296182, -1.31888, 2.79387, 0.000148773,
237                               7.63976E-11, 466944, 250560, 797, 0);
238 
239       referenceString = "PRN:1 Toa:466944 H:0 AFO:1.4877e-04 AF1:7.6398e-11 "
240                         "Ecc:3.4666e-03\n   w:-1.3189e+00 Ahalf:5.1536e+03 "
241                         "M0:2.7939e+00\n   OMEGA0:-2.9618e-01 "
242                         "OMEGAdot:-8.0118e-09 Ioff:3.8872e-03\n";
243 
244       outputStream << compare;
245       outputString = outputStream.str();
246 
247 
248          //-----------------------------------------------------------------
249          //Did the << operator function correctly?
250          //-----------------------------------------------------------------
251       testMesg = "The redirection operator << did not function correctly";
252       TUASSERTE(std::string, referenceString, outputString);
253 
254       TURETURN();
255 
256    }
257 //=============================================================================
258 // Test will check the various get methods
259 //=============================================================================
getTest(void)260    int getTest(void)
261    {
262       TUDEF("AlmOrbit", "get Methods");
263       std::string testMesg;
264 
265       gpstk::AlmOrbit compare(1, 0.00346661, 0.00388718, -8.01176E-09, 5153.58,
266                               -0.296182, -1.31888, 2.79387, 0.000148773,
267                               7.63976E-11, 466944, 250560, 797, 0);
268 
269       gpstk::GPSWeekSecond reference1(797,466944);
270       gpstk::CommonTime cRef1 (reference1);
271 
272          //------------------------------------------------------------------
273          //Did the getToaTime method function correctly?
274          //------------------------------------------------------------------
275       testMesg = "getToaTime method did not function correctly";
276       TUASSERTE(gpstk::CommonTime, cRef1, compare.getToaTime());
277 
278       gpstk::GPSWeekSecond reference2(797, 250560);
279       gpstk::CommonTime cRef2 (reference2);
280          //------------------------------------------------------------------
281          //Did the getTransmitTime method function correctly?
282          //------------------------------------------------------------------
283       testMesg = "getTransmitTime method did not function correctly";
284       TUASSERTE(gpstk::CommonTime, cRef2, compare.getTransmitTime());
285 
286          //------------------------------------------------------------------
287          //Did the getFullWeek method function correctly?
288          //------------------------------------------------------------------
289       testMesg = "getFullWeek method did not function correctly";
290       TUASSERTE(short, 797, compare.getFullWeek());
291 
292          //setting Toa to < -302400 & xmit_time to 0
293       gpstk::AlmOrbit compare1(1, 0.00346661, 0.00388718, -8.01176E-09,
294                                5153.58, -0.296182, -1.31888, 2.79387,
295                                0.000148773, 7.63976E-11, -302401, 0, 797, 0);
296 
297          //------------------------------------------------------------------
298          //Did the getFullWeek method round the week down?
299          //------------------------------------------------------------------
300       testMesg = "getFullWeek method did not round the week down";
301       TUASSERTE(short, 796, compare1.getFullWeek());
302 
303          //setting Toa to > 302400 & xmit_time to 0
304       gpstk::AlmOrbit compare2(1, 0.00346661, 0.00388718, -8.01176E-09,
305                                5153.58, -0.296182, -1.31888, 2.79387,
306                                0.000148773, 7.63976E-11, 302401, 0, 797, 0);
307 
308          //------------------------------------------------------------------
309          //Did the getFullWeek method round the week up?
310          //------------------------------------------------------------------
311       testMesg = "getFullWeek method did not round the week up";
312       TUASSERTE(short, 798, compare2.getFullWeek());
313 
314       TURETURN();
315    }
316 //=============================================================================
317 // Test will check the svXvt method
318 //=============================================================================
svXvtTest(void)319    int svXvtTest(void)
320    {
321       TUDEF("AlmOrbit", "svXvt");
322       gpstk::AlmOrbit oe(2, .146582192974e-01,
323                          .941587707856e+00 - (0.3*gpstk::PI),
324                          -.804390648956e-08, .515359719276e+04,
325                          -.296605403382e+01, -.224753761329e+01,
326                          -.136404614938e+01, .579084269702e-03,
327                          .227373675443e-11, 7168, 3600, 1854, 0);
328       bool testFailed = false;
329       try
330       {
331             // first compute Xvt
332          static const unsigned SECONDS = 7200;
333          gpstk::Xvt zeroth_array[SECONDS];
334          for (unsigned ii = 0; ii < SECONDS; ii++)
335          {
336             zeroth_array[ii] = oe.svXvt(oe.getToaTime() + ii);
337          }
338             // then compute first derivative of position, i.e. velocity
339          gpstk::Triple deriv[SECONDS];
340          double h = 1; // time step size in seconds
341          for (unsigned ii = 0; ii < SECONDS; ii++)
342          {
343             if (ii == 0)
344             {
345                deriv[ii] = (1/h)*(-1.5*zeroth_array[ii].getPos() +
346                                   2.0*zeroth_array[ii+1].getPos() -
347                                   0.5*zeroth_array[ii+2].getPos());
348             }
349             else if ((ii == 1) || (ii == (SECONDS-2)))
350             {
351                deriv[ii] = (1/h)*(-0.5*zeroth_array[ii-1].getPos() +
352                                   0.5*zeroth_array[ii+1].getPos());
353             }
354             else if (ii == (SECONDS-1))
355             {
356                deriv[ii] = (1/h)*(0.5*zeroth_array[ii-2].getPos() -
357                                   2.0*zeroth_array[ii-1].getPos() +
358                                   1.5*zeroth_array[ii].getPos());
359             }
360             else
361             {
362                deriv[ii] = (1/h)*((1.0/12.0)*zeroth_array[ii-2].getPos() -
363                                   (2.0/3.0)*zeroth_array[ii-1].getPos() +
364                                   (2.0/3.0)*zeroth_array[ii+1].getPos() -
365                                   (1.0/12.0)*zeroth_array[ii+2].getPos());
366             }
367          }
368             // then check the difference between derived and computed velocity
369          for (unsigned ii = 0; ii < SECONDS; ii++)
370          {
371             double derivedMag = deriv[ii].mag();
372             double computedMag = zeroth_array[ii].getVel().mag();
373                // If you want to print the data e.g. to plot, uncomment
374                // this stream output statement and comment out tbe break
375                // statement below.
376                // Just don't check it in that way, please.
377                // cerr << ii << " " << (computedMag - derivedMag) << endl;
378             if (fabs(computedMag - derivedMag) > velDiffThresh)
379             {
380                   // no sense in printing 7200 success/fail messages.
381                testFailed = true;
382                break;
383             }
384          }
385          if (testFailed)
386          {
387             TUFAIL("computed velocity is significantly different from derived"
388                    " velocity");
389          }
390          else
391          {
392             TUPASS("velocity check");
393          }
394       }
395       catch (gpstk::Exception& exc)
396       {
397          cerr << exc;
398          TUFAIL("Exception");
399       }
400       catch (...)
401       {
402          TUFAIL("Exception");
403       }
404       TURETURN();
405    }
406 
407 
408 private:
409    double eps;
410 };
411 
412 
main()413 int main() //Main function to initialize and run all tests above
414 {
415    int errorTotal = 0;
416    AlmOrbit_T testClass;
417 
418    errorTotal += testClass.initializationTest();
419    errorTotal += testClass.dumpTest();
420    errorTotal += testClass.operatorTest();
421    errorTotal += testClass.getTest();
422    errorTotal += testClass.svXvtTest();
423 
424    std::cout << "Total Failures for " << __FILE__ << ": " << errorTotal
425              << std::endl;
426 
427    return errorTotal; //Return the total number of errors
428 }
429