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