Position_T.cpp
Go to the documentation of this file.
1 //==============================================================================
2 //
3 // This file is part of GNSSTk, the ARL:UT GNSS Toolkit.
4 //
5 // The GNSSTk 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 GNSSTk 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 GNSSTk; 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-2022, 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 "Position.hpp"
40 #include "TestUtil.hpp"
41 #include <iostream>
42 #include <iomanip>
43 #include "GalileoIonoEllipsoid.hpp"
44 
45 using namespace std;
46 using namespace gnsstk;
47 using namespace gnsstk::StringUtils;
48 
50 {
51 public:
52  Position_T(){eps = 1e-3;}// Default Constructor, set the precision value
53  ~Position_T() {} // Default Desructor
54  double eps;
55 
56  /* Test will check the transforms of Position Objects.
57  There are 4 position types. This test will take a
58  position starting in each type and transform it to
59  each of the remaining types. This is a one-way transform,
60  and comparisons will be performed using the range() function.
61 
62  Suppressing print lines from the test. */
63  unsigned transformTest()
64  {
65  TUDEF("Position", "Cartesian transformTo");
66  try
67  {
68  Position c,s,d,g; //An object for each of the Position types.
69 
70  // test transformTo
71 
72  // Start in ECEF (Cartesian)
73  c.setECEF(-1575232.0141,-4707872.2332, 3993198.4383);
74  Position t(c); // Comparison Object
75  t.transformTo(Position::Geodetic);
76  TUASSERTFEPS(0, range(t,c), eps);
77 
78  t = c; // Reset comparison object
79  t.transformTo(Position::Geocentric);
80  TUASSERTFEPS(0, range(t,c), eps);
81 
82  t = c; // Reset comparison object
83  t.transformTo(Position::Spherical);
84  TUASSERTFEPS(0, range(t,c), eps);
85 
86  //Start in Geodetic
87  TUCSM("Geodetic transformTo");
88  d.setGeodetic(39.000004186778,251.499999999370,1400.009066903964);
89  t = d;
90  t.transformTo(Position::Cartesian);
91  TUASSERTFEPS(0, range(t,d), eps);
92 
93  t = d; // Reset comparison object
94  t.transformTo(Position::Geocentric);
95  TUASSERTFEPS(0, range(t,d), eps);
96 
97  t = d; // Reset comparison object
98  t.transformTo(Position::Spherical);
99  TUASSERTFEPS(0, range(t,d), eps);
100 
101  //Start in Geocentric
102  TUCSM("Geocentric transformTo");
103  g.setGeocentric(38.811958506159,251.499999999370,6371110.627671023800);
104  t = g; // Reset comparison object
105  t.transformTo(Position::Cartesian);
106  TUASSERTFEPS(0, range(t,g), eps);
107 
108  t = g; // Reset comparison object
109  t.transformTo(Position::Geodetic);
110  TUASSERTFEPS(0, range(t,g), eps);
111 
112  t = g; // Reset comparison object
113  t.transformTo(Position::Spherical);
114  TUASSERTFEPS(0, range(t,g), eps);
115 
116  //Start in Spherical
117  TUCSM("Spherical transformTo");
118  s.setSpherical(51.188041493841,251.499999999370,6371110.627671023800);
119  t = s;
120  t.transformTo(Position::Cartesian);
121  TUASSERTFEPS(0, range(t,s), eps);
122 
123  t = s;
124  t.transformTo(Position::Geocentric);
125  TUASSERTFEPS(0, range(t,s), eps);
126 
127  t = s;
128  t.transformTo(Position::Geodetic);
129  TUASSERTFEPS(0, range(t,s), eps);
130  }
131  catch(...)
132  {
133  std::cout << "Exception encountered at: " << testFramework.countTests()
134  << std::endl
135  << "Test method failed" << std::endl;
136  }
137  TURETURN();
138  }
139 
140  /* Test will check the formatted printing of Position objects. */
141  unsigned printfTest()
142  {
143  TUDEF("Position", "printf");
144 
145  try
146  {
147  Position c;
148  c.setECEF(-1575232.0141,-4707872.2332, 3993198.4383);
149 
150  TUASSERTE(std::string,
151  "-1575232.0141 X() (meters)",
152  c.printf("%13.4x X() (meters)"));
153  TUASSERTE(std::string,
154  "-4707872.2332 Y() (meters)",
155  c.printf("%13.4y Y() (meters)"));
156  TUASSERTE(std::string,
157  " 3993198.4383 Z() (meters)",
158  c.printf("%13.4z Z() (meters)"));
159  TUASSERTE(std::string,
160  " -1575.2320 X()/1000 (kilometers)",
161  c.printf("%13.4X X()/1000 (kilometers)"));
162  TUASSERTE(std::string,
163  " -4707.8722 Y()/1000 (kilometers)",
164  c.printf("%13.4Y Y()/1000 (kilometers)"));
165  TUASSERTE(std::string,
166  " 3993.1984 Z()/1000 (kilometers)",
167  c.printf("%13.4Z Z()/1000 (kilometers)"));
168  TUASSERTE(std::string,
169  " 39.000004 geodeticLatitude() (degrees North)",
170  c.printf("%15.6A geodeticLatitude() (degrees North)"));
171  TUASSERTE(std::string,
172  " 38.811959 geocentricLatitude() (degrees North)",
173  c.printf("%15.6a geocentricLatitude() (degrees North)"));
174  TUASSERTE(std::string,
175  " 251.500000 longitude() (degrees East)",
176  c.printf("%15.6L longitude() (degrees East)"));
177  TUASSERTE(std::string,
178  " 251.500000 longitude() (degrees East)",
179  c.printf("%15.6l longitude() (degrees East)"));
180  TUASSERTE(std::string,
181  " 108.500000 longitude() (degrees West)",
182  c.printf("%15.6w longitude() (degrees West)"));
183  TUASSERTE(std::string,
184  " 108.500000 longitude() (degrees West)",
185  c.printf("%15.6W longitude() (degrees West)"));
186  TUASSERTE(std::string,
187  " 51.188041 theta() (degrees)",
188  c.printf("%15.6t theta() (degrees)"));
189  TUASSERTE(std::string,
190  " 0.893400 theta() (radians)",
191  c.printf("%15.6T theta() (radians)"));
192  TUASSERTE(std::string,
193  " 251.500000 phi() (degrees)",
194  c.printf("%15.6p phi() (degrees)"));
195  TUASSERTE(std::string,
196  " 4.389503 phi() (radians)",
197  c.printf("%15.6P phi() (radians)"));
198  TUASSERTE(std::string,
199  " 6371110.6277 radius() meters",
200  c.printf("%13.4r radius() meters"));
201  TUASSERTE(std::string,
202  " 6371.1106 radius()/1000 kilometers",
203  c.printf("%13.4R radius()/1000 kilometers"));
204  TUASSERTE(std::string,
205  " 1400.0091 height() meters",
206  c.printf("%13.4h height() meters"));
207  TUASSERTE(std::string,
208  " 1.4000 height()/1000 kilometers",
209  c.printf("%13.4H height()/1000 kilometers"));
210  }
211  catch(...)
212  {
213  std::cout << "Exception encountered at: " << testFramework.countTests()
214  << std::endl
215  << "Test method failed" << std::endl;
216  }
217  TURETURN();
218  }
219 
220  /* Test for scanning strings
221  Additional print lines are commented out. */
222  unsigned scanTest()
223  {
224  TUDEF("Position", "scan");
225 
226  try
227  {
228  Position c; // Initial position
229  c.setECEF(-1575232.0141,-4707872.2332, 3993198.4383);
230  string fmt[5]={ //Various string formats
231  "", //This one is left empty but is skipped in the loop
232  "%A degN %L degE %h m",
233  "%a degN %L degE %r m",
234  "%x m %y m %z m",
235  "%t deg %p deg %r M"};
236  for(int i=1; i<5; i++)
237  {
238  string str;
239  // A dummy Position initialized at c and another
240  // Position for comparison
241  Position t(c),tt;
242  t.transformTo(static_cast<Position::CoordinateSystem>(i));
243  {
244  ostringstream o;
245  o << t; //Output the Position object to stream
246  str = o.str(); //Store that output as a string
247  }
248  //Set the comparison object using the output string
249  tt.setToString(str,fmt[i]);
250 
251  TUASSERTFEPS(0, range(tt,t), eps);
252  }
253  }
254  catch(...)
255  {
256  std::cout << "Exception encountered at: " << testFramework.countTests()
257  << std::endl
258  << "Test method failed" << std::endl;
259  }
260  TURETURN();
261  }
262 
263  /* Elevation and Azimuth tests
264  Comparing these calculations from the ones in Triple
265  (which are tested in the Triple tests) */
267  {
268  TUDEF("Position", "elevationAzimuth");
269  try
270  {
271  Position c,s;
272  c.setECEF(-1575232.0141,-4707872.2332, 3993198.4383);
273  s.setECEF(3*6371110.62767,0,0);
274  TUASSERTFEPS(c.elvAngle(s), c.elevation(s), eps);
275  TUASSERTFEPS(c.azAngle(s), c.azimuth(s), eps);
276  }
277  catch(...)
278  {
279  std::cout << "Exception encountered at: " << testFramework.countTests()
280  << std::endl
281  << "Test method failed" << std::endl;
282  }
283  TURETURN();
284  }
285 
286  /* Transform tests at a pole. The pole is a unique location
287  which may cause the transforms to break. */
288  unsigned poleTransformTest()
289  {
290  TUDEF("Position", "poleTransform");
291  try
292  {
293  Position c,t;
294  //cout << "Try to break it at the pole\n";
295  c.setECEF(0,0,6371110.6277);
296  //c.setECEF(0,0,0.0001); // this will break it
297  t = c;
298 
299  // Code below tests every possible conversion from one
300  // coordinate system to the next at the pole.
301  // i.e. ECEF -> Geodetic
302  // ECEF -> Geocentric
303  // ECEF -> Spherical
304  // Spherical -> Geodetic
305  // Spherical -> Geocentric
306  // Spherical -> ECEF
307  // etc...
308 
309  t.transformTo(Position::Geodetic);
310  TUASSERTFEPS(0, range(t,c), eps);
311  t.transformTo(Position::Geocentric);
312  TUASSERTFEPS(0, range(t,c), eps);
313  t.transformTo(Position::Spherical);
314  TUASSERTFEPS(0, range(t,c), eps);
315  t.transformTo(Position::Cartesian);
316  TUASSERTFEPS(0, range(t,c), eps);
317  t.transformTo(Position::Geodetic);
318  TUASSERTFEPS(0, range(t,c), eps);
319  t.transformTo(Position::Cartesian);
320  TUASSERTFEPS(0, range(t,c), eps);
321  t.transformTo(Position::Spherical);
322  TUASSERTFEPS(0, range(t,c), eps);
323  t.transformTo(Position::Geodetic);
324  TUASSERTFEPS(0, range(t,c), eps);
325  t.transformTo(Position::Spherical);
326  TUASSERTFEPS(0, range(t,c), eps);
327  t.transformTo(Position::Geocentric);
328  TUASSERTFEPS(0, range(t,c), eps);
329  t.transformTo(Position::Cartesian);
330  TUASSERTFEPS(0, range(t,c), eps);
331  }
332  catch(...)
333  {
334  std::cout << "Exception encountered at: " << testFramework.countTests()
335  << std::endl
336  << "Test method failed" << std::endl;
337  }
338  TURETURN();
339  }
340 
341  /* Many of the tests above use the range() function to
342  measure the distances between two positions. It in turn
343  needs to be tested to ensure that it works. */
344  unsigned rangeTest()
345  {
346  TUDEF("Position", "range()");
347  try
348  {
349  Position c,t;
350  c.setECEF(0,0,6371110.6277);
351  t.setECEF(20,0,6371110.6277);
352  TUASSERTFEPS(20, range(c,t), eps);
353  t.setECEF(0,-20,6371110.6277);
354  TUASSERTFEPS(20, range(c,t), eps);
355  t.setECEF(0,0,6371210.6277);
356  TUASSERTFEPS(100, range(c,t), eps);
357  t.setECEF(300,400,6371610.6277);
358  TUASSERTFEPS(sqrt(500000.0), range(c,t), eps);
359  }
360  catch(...)
361  {
362  std::cout << "Exception encountered at: " << testFramework.countTests()
363  << std::endl
364  << "Test method failed" << std::endl;
365  }
366  TURETURN();
367  }
368 
369 
371  {
372  TUDEF("Position", "getZenithAngle");
373  // test data originated from EU Galileo iono model
374  // NeQuickG_JRC_ray_test.c (km converted to meters)
375  gnsstk::Position p1(82.494293510, 297.659539798, 78.107446,
377  gnsstk::Position p2(54.445029416, 241.529931024, 20370730.845002,
379  double expected = 0.713414;
380  gnsstk::AngleReduced delta, expectedDelta(0.52852299785161971357,
381  0.84891898361500717218);
383  p1.setEllipsoidModel(&ell);
384  p2.setEllipsoidModel(&ell);
385  gnsstk::Angle zeta = p1.getZenithAngle(p2, delta);
386  TUASSERTFEPS(expected, zeta.rad(), 1e-6);
387  TUASSERTFEPS(expectedDelta.sin(), delta.sin(), 1e-6);
388  TUASSERTFEPS(expectedDelta.cos(), delta.cos(), 1e-6);
389  TURETURN();
390  }
391 
392 
393  unsigned getRayPerigeeTest()
394  {
395  TUDEF("Position", "getRayPerigee");
396  // test data originated from EU Galileo iono model
397  // NeQuickG_JRC_ray_test.c (km converted to meters)
399  gnsstk::Position p1(82.494293510, 297.659539798, 78.107446,
401  gnsstk::Position p2(54.445029416, 241.529931024, 20370730.845002,
403  // 405 degrees longitude? Ok, Galileo.
404  gnsstk::Position expected(43.550617197, 405.289045373, 4169486.317342,
406  TUASSERTE(gnsstk::Position, expected, p1.getRayPerigee(p2));
407  gnsstk::Position f1(82.49, 297.66, 78.11, gnsstk::Position::Geodetic, &ell);
408  gnsstk::Position f2(54.29, 8.23, 20281546.18, gnsstk::Position::Geodetic,
409  &ell);
410  gnsstk::Position foo = f1.getRayPosition(1000, f2);
411  cerr << "radius=" << foo.radius() << " m" << endl;
412 // p1.getRayPosition do something here check against NeQuickG_JRC_ray and test for consistency in sigmap value
413  TURETURN();
414  }
415 };
416 
417 int main() //Main function to initialize and run all tests above
418 {
419  unsigned errorTotal = 0;
420  Position_T testClass;
421 
422  errorTotal += testClass.rangeTest();
423  errorTotal += testClass.transformTest();
424  errorTotal += testClass.printfTest();
425  errorTotal += testClass.scanTest();
426  errorTotal += testClass.elevationAzimuthTest();
427  errorTotal += testClass.poleTransformTest();
428  errorTotal += testClass.getZenithAngleTest();
429  errorTotal += testClass.getRayPerigeeTest();
430 
431  std::cout << "Total Failures for " << __FILE__ << ": " << errorTotal
432  << std::endl;
433 
434  return errorTotal; //Return the total number of errors
435 }
gnsstk::Position::Geodetic
@ Geodetic
geodetic latitude, longitude, and height above ellipsoid
Definition: Position.hpp:145
gnsstk::Position::setGeocentric
Position & setGeocentric(const double lat, const double lon, const double rad)
Definition: Position.cpp:531
Position_T
Definition: Position_T.cpp:49
TUCSM
#define TUCSM(METHOD)
Definition: TestUtil.hpp:59
Position_T::rangeTest
unsigned rangeTest()
Definition: Position_T.cpp:344
gnsstk::AngleReduced
Definition: AngleReduced.hpp:60
gnsstk::Angle::rad
double rad() const
Get the angle in radians.
Definition: Angle.hpp:94
Position_T::getRayPerigeeTest
unsigned getRayPerigeeTest()
Definition: Position_T.cpp:393
Position_T::eps
double eps
Definition: Position_T.cpp:54
gnsstk::Position::transformTo
Position & transformTo(CoordinateSystem sys) noexcept
Definition: Position.cpp:247
main
int main()
Definition: Position_T.cpp:417
TUASSERTE
#define TUASSERTE(TYPE, EXP, GOT)
Definition: TestUtil.hpp:81
gnsstk::AngleReduced::sin
double sin() const
Get the sine of this angle.
Definition: AngleReduced.hpp:94
Position.hpp
gnsstk::Position::setSpherical
Position & setSpherical(const double theta, const double phi, const double rad)
Definition: Position.cpp:566
gnsstk::Position::setToString
Position & setToString(const std::string &str, const std::string &fmt)
Definition: Position.cpp:658
gnsstk::Position::setEllipsoidModel
void setEllipsoidModel(const EllipsoidModel *ell)
Definition: Position.cpp:478
gnsstk
For Sinex::InputHistory.
Definition: BasicFramework.cpp:50
gnsstk::Angle
Definition: Angle.hpp:53
gnsstk::Position::azimuth
double azimuth(const Position &Target) const
Definition: Position.cpp:1365
gnsstk::Position::printf
std::string printf(const char *fmt) const
Definition: Position.cpp:982
Position_T::printfTest
unsigned printfTest()
Definition: Position_T.cpp:141
gnsstk::Position::setECEF
Position & setECEF(const double X, const double Y, const double Z) noexcept
Definition: Position.cpp:601
TestUtil.hpp
gnsstk::Position::getZenithAngle
Angle getZenithAngle(const Position &target, AngleReduced &delta) const
Definition: Position.cpp:1514
TURETURN
#define TURETURN()
Definition: TestUtil.hpp:232
Position_T::Position_T
Position_T()
Definition: Position_T.cpp:52
gnsstk::Position::radius
double radius() const noexcept
Definition: Position.cpp:444
Position_T::getZenithAngleTest
unsigned getZenithAngleTest()
Definition: Position_T.cpp:370
gnsstk::Position::Geocentric
@ Geocentric
geocentric (regular spherical coordinates)
Definition: Position.hpp:146
gnsstk::AngleReduced::cos
double cos() const
Get the cosine of this angle.
Definition: AngleReduced.hpp:98
TUASSERTFEPS
#define TUASSERTFEPS(EXP, GOT, EPS)
Definition: TestUtil.hpp:126
gnsstk::GalileoIonoEllipsoid
Definition: GalileoIonoEllipsoid.hpp:57
gnsstk::Position::CoordinateSystem
CoordinateSystem
The coordinate systems supported by Position.
Definition: Position.hpp:142
TUDEF
#define TUDEF(CLASS, METHOD)
Definition: TestUtil.hpp:56
GalileoIonoEllipsoid.hpp
gnsstk::StringUtils
Definition: IonexStoreStrategy.cpp:44
Position_T::scanTest
unsigned scanTest()
Definition: Position_T.cpp:222
std
Definition: Angle.hpp:142
Position_T::poleTransformTest
unsigned poleTransformTest()
Definition: Position_T.cpp:288
gnsstk::range
double range(const Position &A, const Position &B)
Definition: Position.cpp:1273
gnsstk::Position
Definition: Position.hpp:136
gnsstk::Position::setGeodetic
Position & setGeodetic(const double lat, const double lon, const double ht, const EllipsoidModel *ell=nullptr)
Definition: Position.cpp:495
gnsstk::Triple::elvAngle
double elvAngle(const Triple &right) const
Definition: Triple.cpp:185
Position_T::~Position_T
~Position_T()
Definition: Position_T.cpp:53
Position_T::transformTest
unsigned transformTest()
Definition: Position_T.cpp:63
Position_T::elevationAzimuthTest
unsigned elevationAzimuthTest()
Definition: Position_T.cpp:266
gnsstk::Position::getRayPosition
Position getRayPosition(double dist, const Position &target) const
Definition: Position.cpp:1604
gnsstk::Position::getRayPerigee
Position getRayPerigee(const Position &target) const
Definition: Position.cpp:1552
gnsstk::Triple::azAngle
double azAngle(const Triple &right) const
Definition: Triple.cpp:195
gnsstk::Position::elevation
double elevation(const Position &Target) const
Definition: Position.cpp:1308


gnsstk
Author(s):
autogenerated on Wed Oct 25 2023 02:40:40