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 "ObsRngDev.hpp"
40 #include "TestUtil.hpp"
41 #include <iostream>
42 
43 #include "RinexEphemerisStore.hpp"
44 
45 #include "EphemerisRange.hpp"
46 #include "SimpleTropModel.hpp"
47 
48 //=====================================================================================
49 // Test Structure
50 // Begin with generating ObsRngDev objects using every constructor and test the basic
51 // initialization of these objects. Then verify that each of the objects constructed have
52 // calculated the ORD correctly, in addition to the elevation and azimuth. By testing
53 // the value of the ORD, the different calculations such as generating Tropospheric models
54 // and calculating ionospheric and tropospheric delays are tested implicitly. These tests
55 // are entirely dependent on the Ephemeris Range class calculating the range correctly.
56 //======================================================================================
57 
ionoModelStoreGen(std::vector<gpstk::CommonTime> & cTimeVec)58 gpstk::IonoModelStore ionoModelStoreGen(std::vector<gpstk::CommonTime>& cTimeVec)
59 {
60    double a[] = {1,2,3,4}; double b[] = {4,3,2,1};
61 
62    gpstk::IonoModelStore ims;
63 
64    for (int i=0; i < cTimeVec.size(); i++)
65       ims.addIonoModel(cTimeVec[i], gpstk::IonoModel(a,b));
66 
67    return ims;
68 }
69 
70 class ObsRngDev_T
71 {
72 public:
ObsRngDev_T()73    ObsRngDev_T()
74    {
75       receiverPos.setGeodetic(30.387577, -97.727607, 240);
76 
77       prange.push_back(21665483.747f);
78       prange.push_back(21662553.318f);
79       prange.push_back(21659650.826f);
80       prange2.push_back(21665487.640f);
81       prange2.push_back(21662557.419f);
82       prange2.push_back(21659655.019f);
83 
84       id.id = 1;
85       id.system = gpstk::SatelliteSystem::GPS;
86 
87       gpstk::CommonTime ct1 = gpstk::CivilTime(2006, 1, 31, 2, 0, 0, gpstk::TimeSystem::GPS).convertToCommonTime();
88       gpstk::CommonTime ct2 = gpstk::CivilTime(2006, 1, 31, 4, 0, 0, gpstk::TimeSystem::GPS).convertToCommonTime();
89       gpstk::CommonTime ct3 = gpstk::CivilTime(2006, 1, 31, 6, 0, 0, gpstk::TimeSystem::GPS).convertToCommonTime();
90       cTimeVec.push_back(ct1);
91       cTimeVec.push_back(ct2);
92       cTimeVec.push_back(ct3);
93 
94       std::string path = gpstk::getPathData() + "/test_input_rinex_nav_ephemerisData.031";
95       ephemStore.loadFile(path);
96    };
97 
~ObsRngDev_T()98    ~ObsRngDev_T() {}
99 
BasicConstructorTest(void)100    int BasicConstructorTest(void)
101    {
102       TUDEF("ObsRngDev", "BasicConstructor");
103 
104       try
105       {
106          for (int i=0; i < cTimeVec.size(); i++)
107          {
108             gpstk::ObsRngDev ord(prange[i], id, cTimeVec[i], receiverPos, ephemStore, em);
109             ordVec.push_back(ord);
110          }
111       }
112       catch(gpstk::Exception e)
113       {
114          TUFAIL("unexpected exception");
115       }
116 
117       failCount = 0;
118       for (int i=0; i < ordVec.size(); i++)
119          if(!(ordVec[i].obstime == cTimeVec[i]))
120             failCount++;
121       TUASSERT(failCount == 0);
122       TUASSERT(ordVec.size() == 3);
123 
124       failCount = 0;
125       for (int i=0; i < ordVec.size(); i++)
126          if(!(ordVec[i].svid == id))
127             failCount++;
128       TUASSERT(failCount == 0);
129 
130       failCount = 0;
131       for (int i=0; i < ordVec.size(); i++)
132          if(!(ordVec[i].health.get_value() == 0))
133             failCount++;
134       TUASSERT(failCount == 0);
135 
136       TURETURN();
137    }
138 
IonosphericConstructorTest(void)139    int IonosphericConstructorTest(void)
140    {
141       TUDEF("ObsRngDev", "IonosphericConstructor");
142 
143       gpstk::IonoModelStore ims = ionoModelStoreGen(cTimeVec);
144       gpstk::CarrierBand L1 = gpstk::CarrierBand::L1;
145 
146       try
147       {
148          for (int i=0; i < cTimeVec.size(); i++)
149          {
150             gpstk::ObsRngDev ord(prange[i], id, cTimeVec[i], receiverPos,
151                                  ephemStore, em, ims, L1);
152             ordVecIon.push_back(ord);
153          }
154       }
155       catch (gpstk::Exception e)
156       {
157          std::cout << e << std::endl;
158          TUFAIL("unexpected exception");
159       }
160 
161       failCount = 0;
162       for (int i=0; i < ordVecIon.size(); i++)
163          if(!(ordVecIon[i].obstime == cTimeVec[i]))
164             failCount++;
165       TUASSERT(failCount == 0);
166       TUASSERT(ordVecIon.size() == 3);
167 
168       failCount = 0;
169       for (int i=0; i < ordVecIon.size(); i++)
170          if(!(ordVecIon[i].svid == id))
171             failCount++;
172       TUASSERT(failCount == 0);
173 
174       failCount = 0;
175       for (int i=0; i < ordVecIon.size(); i++)
176          if(!(ordVecIon[i].health.get_value() == 0))
177             failCount++;
178       TUASSERT(failCount == 0);
179 
180       TURETURN();
181    }
182 
TroposphericConstructorTest(void)183    int TroposphericConstructorTest(void)
184    {
185       TUDEF("ObsRngDev", "TroposphericConstructor");
186 
187       gpstk::SimpleTropModel stm(18.8889, 1021.2176, 77.7777); // Celsius, mmBar, %humidity
188 
189       try
190       {
191          for (int i=0; i < cTimeVec.size(); i++)
192          {
193             gpstk::ObsRngDev ord(prange[i], id, cTimeVec[i],
194                                  receiverPos, ephemStore, em, stm);
195             ordVecTrop.push_back(ord);
196          }
197       }
198       catch (gpstk::Exception e)
199       {
200          TUFAIL("unexpected exception");
201       }
202 
203       failCount = 0;
204       for (int i=0; i < ordVecTrop.size(); i++)
205             //Have same timeVec for every 10 instances of ordVecTrop
206          if(!(ordVecTrop[i].obstime == cTimeVec[i]))
207             failCount++;
208       TUASSERT(failCount == 0);
209       TUASSERT(ordVecTrop.size() == 3);
210 
211       failCount = 0;
212       for (int i=0; i < ordVecTrop.size(); i++)
213          if(!(ordVecTrop[i].svid == id))
214             failCount++;
215       TUASSERT(failCount == 0);
216 
217       failCount = 0;
218       for (int i=0; i < ordVecTrop.size(); i++)
219          if(!(ordVecTrop[i].health.get_value() == 0))
220             failCount++;
221       TUASSERT(failCount == 0);
222 
223       TURETURN();
224    }
225 
IonosphericTroposphericConstructorTest(void)226    int IonosphericTroposphericConstructorTest(void)
227    {
228       TUDEF("ObsRngDev", "IonosphericTroposphericConstructor");
229 
230       gpstk::SimpleTropModel stm(18.8889, 1021.2176, 77.7777);
231       gpstk::IonoModelStore ims = ionoModelStoreGen(cTimeVec);
232       gpstk::CarrierBand L1 = gpstk::CarrierBand::L1;
233 
234       try
235       {
236          for (int i=0; i < cTimeVec.size(); i++)
237          {
238             gpstk::ObsRngDev ord(prange[i], id, cTimeVec[i], receiverPos,
239                                  ephemStore, em, stm, ims, L1);
240             ordVecTropIon.push_back(ord);
241          }
242       }
243       catch (gpstk::Exception e)
244       {
245          TUFAIL("unexpected exception");
246       }
247 
248       failCount = 0;
249       for (int i=0; i < ordVecTropIon.size(); i++)
250          if(!(ordVecTropIon[i].obstime == cTimeVec[i]))
251             failCount++;
252       TUASSERT(failCount == 0);
253       TUASSERT(ordVecTropIon.size() == 3);
254 
255       failCount = 0;
256       for (int i=0; i < ordVecTropIon.size(); i++)
257          if(!(ordVecTropIon[i].svid == id))
258             failCount++;
259       TUASSERT(failCount == 0);
260 
261       failCount = 0;
262       for (int i=0; i < ordVecTropIon.size(); i++)
263          if(!(ordVecTropIon[i].health.get_value() == 0))
264             failCount++;
265       TUASSERT(failCount == 0);
266 
267       TURETURN();
268    }
269 
GammaConstructorTest(void)270    int GammaConstructorTest(void)
271    {
272       TUDEF("ObsRngDev", "GammaConstructor");
273 
274       try
275       {
276          for (int i=0; i < cTimeVec.size(); i++)
277          {
278             gpstk::ObsRngDev ord(prange[i], prange2[i], id, cTimeVec[i],
279                                  receiverPos, ephemStore, em);
280             ordVecGamma.push_back(ord);
281          }
282       }
283       catch (gpstk::Exception e)
284       {
285          TUFAIL("unexpected exception");
286       }
287 
288       failCount = 0;
289       for (int i=0; i < ordVecGamma.size(); i++)
290          if(!(ordVecGamma[i].obstime == cTimeVec[i]))
291             failCount++;
292       TUASSERT(failCount == 0);
293       TUASSERT(ordVecGamma.size() == 3);
294 
295       failCount = 0;
296       for (int i=0; i < ordVecGamma.size(); i++)
297          if(!(ordVecGamma[i].svid == id))
298             failCount++;
299       TUASSERT(failCount == 0);
300 
301       failCount = 0;
302       for (int i=0; i < ordVecGamma.size(); i++)
303          if(!(ordVecGamma[i].health.get_value() == 0))
304             failCount++;
305       TUASSERT(failCount == 0);
306 
307       TURETURN();
308    }
309 
GammaTroposphericConstructorTest(void)310    int GammaTroposphericConstructorTest(void)
311    {
312       TUDEF("ObsRngDev", "GammaTroposphericConstructor");
313 
314       gpstk::SimpleTropModel stm(18.8889, 1021.2176, 77.7777);
315       try
316       {
317          for (int i=0; i < cTimeVec.size(); i++)
318          {
319             gpstk::ObsRngDev ord(prange[i], prange2[i], id, cTimeVec[i],
320                                  receiverPos, ephemStore, em, stm);
321             ordVecTropGamma.push_back(ord);
322          }
323       }
324       catch (gpstk::Exception e)
325       {
326          TUFAIL("unexpected exception");
327       }
328 
329       failCount = 0;
330       for (int i=0; i < ordVecTropGamma.size(); i++)
331          if(!(ordVecTropGamma[i].obstime == cTimeVec[i]))
332             failCount++;
333       TUASSERT(failCount == 0);
334       TUASSERT(ordVecTropGamma.size() == 3);
335 
336       failCount = 0;
337       for (int i=0; i < ordVecTropGamma.size(); i++)
338          if(!(ordVecTropGamma[i].svid == id))
339             failCount++;
340       TUASSERT(failCount == 0);
341 
342       failCount = 0;
343       for (int i=0; i < ordVecTropGamma.size(); i++)
344          if(!(ordVecTropGamma[i].health.get_value() == 0))
345             failCount++;
346       TUASSERT(failCount == 0);
347 
348       TURETURN();
349    }
350 
351 //===================================================================================
352 // Begin Get Functions Test
353 //===================================================================================
354 
getFunctionsTest(void)355    int getFunctionsTest(void)
356    {
357       TUDEF("ObsRngDev", "Get Methods");
358 
359       TUASSERT(ordVec.size() > 0);
360 
361       failCount = 0;
362       for(int i=0; i<ordVec.size(); i++)
363          if (!(ordVec[i].getTime() == ordVec[i].obstime))
364             failCount++;
365       TUASSERT(failCount == 0);
366 
367       failCount = 0;
368       for(int i=0; i<ordVec.size(); i++)
369          if (!(ordVec[i].getSvID() == ordVec[i].svid))
370             failCount++;
371       TUASSERT(failCount == 0);
372 
373       failCount = 0;
374       for(int i=0; i<ordVec.size(); i++)
375          if (!(ordVec[i].getAzimuth().get_value() == ordVec[i].azimuth.get_value()))
376             failCount++;
377       TUASSERT(failCount == 0);
378 
379       failCount = 0;
380       for(int i=0; i<ordVec.size(); i++)
381          if (!(ordVec[i].getElevation().get_value() == ordVec[i].elevation.get_value()))
382             failCount++;
383       TUASSERT(failCount == 0);
384 
385       failCount = 0;
386       for(int i=0; i<ordVec.size(); i++)
387          if (!(ordVec[i].getHealth().get_value() == ordVec[i].health.get_value()))
388             failCount++;
389       TUASSERT(failCount == 0);
390 
391       failCount = 0;
392       for(int i=0; i<ordVec.size(); i++)
393          if (!(ordVec[i].getIODC().get_value() == ordVec[i].iodc.get_value()))
394             failCount++;
395       TUASSERT(failCount == 0);
396 
397       failCount = 0;
398       for(int i=0; i<ordVec.size(); i++)
399          if (!(ordVec[i].getORD() == ordVec[i].ord))
400             failCount++;
401       TUASSERT(failCount == 0);
402 
403       failCount = 0;
404       for(int i=0; i<ordVec.size(); i++)
405          if (!(ordVec[i].getIono().get_value() == ordVec[i].iono.get_value()))
406             failCount++;
407       TUASSERT(failCount == 0);
408 
409       failCount = 0;
410       for(int i=0; i<ordVec.size(); i++)
411          if (!(ordVec[i].getTrop().get_value() == ordVec[i].trop.get_value()))
412             failCount++;
413       TUASSERT(failCount == 0);
414 
415       TURETURN();
416    }
417 
BasicCalculationTest(void)418    int BasicCalculationTest(void)
419    {
420       TUDEF("ObsRngDev", "BasicCalculation");
421       TUASSERT(ordVec.size() > 0);
422 
423       for (int i=0; i < ordVec.size(); i++)
424       {
425          gpstk::CorrectedEphemerisRange cer;
426          double rho = cer.ComputeAtTransmitTime(ordVec[i].obstime, prange[i], receiverPos, ordVec[i].svid, ephemStore);
427          TUASSERTFE(prange[i] - rho - ordVec[i].trop, ordVec[i].ord);
428          TUASSERTFE(ordVec[i].rho, rho);
429          TUASSERTE(int, ordVec[i].azimuth, cer.azimuth);
430          TUASSERTE(int, ordVec[i].elevation, cer.elevation);
431       }
432 
433       TURETURN();
434    }
435 
IonosphericCalculationTest(void)436    int IonosphericCalculationTest(void)
437    {
438       TUDEF("ObsRngDev", "IonosphericCalculation");
439       TUASSERT(ordVecIon.size() > 0);
440 
441       for (int i=0; i < ordVecIon.size(); i++)
442       {
443          gpstk::CorrectedEphemerisRange cer;
444          double rho = cer.ComputeAtTransmitTime(ordVecIon[i].obstime, prange[i], receiverPos, ordVecIon[i].svid, ephemStore);
445          TUASSERTFEPS(prange[i] - rho - ordVecIon[i].trop - ordVecIon[i].iono, ordVecIon[i].ord, 1e-6);
446          TUASSERTFE(ordVecIon[i].rho, rho);
447          TUASSERTE(int, ordVecIon[i].azimuth, cer.azimuth);
448          TUASSERTE(int, ordVecIon[i].elevation, cer.elevation);
449       }
450 
451       TURETURN();
452    }
453 
TroposphericCalculationTest(void)454    int TroposphericCalculationTest(void)
455    {
456       TUDEF("ObsRngDev", "TroposphericCalculation");
457       TUASSERT(ordVecTrop.size() > 0);
458 
459       for (int i=0; i < ordVecTrop.size(); i++)
460       {
461          gpstk::CorrectedEphemerisRange cer;
462          double rho = cer.ComputeAtTransmitTime(ordVecTrop[i].obstime, prange[i], receiverPos, ordVecTrop[i].svid, ephemStore);
463          double CompareOrd = prange[i] - rho - ordVec[i].trop;
464          TUASSERTFEPS(prange[i] - rho - ordVecTrop[i].trop, ordVecTrop[i].ord, 1e-6);
465          TUASSERTFE(ordVecTrop[i].rho, rho);
466          TUASSERTE(int, ordVecTrop[i].azimuth, cer.azimuth);
467          TUASSERTE(int, ordVecTrop[i].elevation, cer.elevation);
468       }
469 
470       TURETURN();
471    }
472 
IonosphericTroposphericCalculationTest(void)473    int IonosphericTroposphericCalculationTest(void)
474    {
475       TUDEF("ObsRngDev", "IonosphericTroposphericCalculation");
476       TUASSERT(ordVecTropIon.size() > 0);
477 
478       for (int i=0; i < ordVecTropIon.size(); i++)
479       {
480          gpstk::CorrectedEphemerisRange cer;
481          double rho = cer.ComputeAtTransmitTime(ordVecTropIon[i].obstime, prange[i], receiverPos, ordVecTropIon[i].svid, ephemStore);
482          TUASSERTFEPS(prange[i] - rho - ordVecTropIon[i].trop - ordVecTropIon[i].iono, ordVecTropIon[i].ord, 1e-6);
483          TUASSERTFE(ordVecTropIon[i].rho, rho);
484          TUASSERTE(int, ordVecTropIon[i].azimuth, cer.azimuth);
485          TUASSERTE(int, ordVecTropIon[i].elevation, cer.elevation);
486       }
487 
488       TURETURN();
489    }
490 
GammaCalculationTest(void)491    int GammaCalculationTest(void)
492    {
493       TUDEF("ObsRngDev", "GammaCalculation");
494       TUASSERT(ordVecGamma.size() > 0);
495 
496       for (int i=0; i < ordVecGamma.size(); i++)
497       {
498          gpstk::CorrectedEphemerisRange cer;
499          double rho = cer.ComputeAtTransmitTime(ordVecGamma[i].obstime, prange[i], receiverPos, ordVecGamma[i].svid, ephemStore);
500          TUASSERTFEPS(prange[i] - rho - ordVecGamma[i].trop - ordVecGamma[i].iono, ordVecGamma[i].ord, 1e-4);
501          TUASSERTFEPS(ordVecGamma[i].rho, rho, 1e-4);
502          TUASSERTE(int, ordVecGamma[i].azimuth, cer.azimuth);
503          TUASSERTE(int, ordVecGamma[i].elevation, cer.elevation);
504       }
505 
506       TURETURN();
507    }
508 
TroposphericGammaCalculationTest(void)509    int TroposphericGammaCalculationTest(void)
510    {
511       TUDEF("ObsRngDev", "TroposphericGammaCalculation");
512       TUASSERT(ordVecTropGamma.size() > 0);
513 
514       for (int i=0; i < ordVecTropGamma.size(); i++)
515       {
516          gpstk::CorrectedEphemerisRange cer;
517          double rho = cer.ComputeAtTransmitTime(ordVecTropGamma[i].obstime, prange[i], receiverPos, ordVecTropGamma[i].svid, ephemStore);
518          TUASSERTFEPS(prange[i] - rho - ordVecTropGamma[i].trop - ordVecTropGamma[i].iono, ordVecTropGamma[i].ord, 1e-4);
519          TUASSERTFEPS(ordVecTropGamma[i].rho, rho, 1e-4);
520          TUASSERTE(int, ordVecTropGamma[i].azimuth, cer.azimuth);
521          TUASSERTE(int, ordVecTropGamma[i].elevation, cer.elevation);
522       }
523 
524       TURETURN();
525    }
526 
527 private:
528    int failCount;
529    gpstk::SatID id;
530    std::vector<float> prange;
531    std::vector<float> prange2;
532 
533    char *buff;
534 
535    std::vector<gpstk::ObsRngDev> ordVec;
536    std::vector<gpstk::ObsRngDev> ordVecIon;
537    std::vector<gpstk::ObsRngDev> ordVecTrop;
538    std::vector<gpstk::ObsRngDev> ordVecTropIon;
539    std::vector<gpstk::ObsRngDev> ordVecGamma;
540    std::vector<gpstk::ObsRngDev> ordVecTropGamma;
541 
542    std::vector< std::map<int, float> > prnPrange;
543    std::vector<gpstk::CommonTime> cTimeVec;
544    gpstk::Position receiverPos;
545    gpstk::RinexEphemerisStore ephemStore;
546    gpstk::WGS84Ellipsoid em;
547 };
548 
549 
main()550 int main() //Main function to initialize and run all tests above
551 {
552    int errorCounter = 0;
553    ObsRngDev_T testClass;
554 
555    errorCounter += testClass.BasicConstructorTest();
556    errorCounter += testClass.IonosphericConstructorTest();
557    errorCounter += testClass.TroposphericConstructorTest();
558    errorCounter += testClass.IonosphericTroposphericConstructorTest();
559    errorCounter += testClass.GammaConstructorTest();
560    errorCounter += testClass.GammaTroposphericConstructorTest();
561    errorCounter += testClass.getFunctionsTest();
562    errorCounter += testClass.BasicCalculationTest();
563    errorCounter += testClass.IonosphericCalculationTest();
564    errorCounter += testClass.TroposphericCalculationTest();
565    errorCounter += testClass.IonosphericTroposphericCalculationTest();
566    errorCounter += testClass.GammaCalculationTest();
567    errorCounter += testClass.TroposphericGammaCalculationTest();
568 
569    std::cout << "Total Failures for " << __FILE__ << ": " << errorCounter << std::endl;
570 
571    return errorCounter;
572 }
573