gps_pvt 0.5.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -452,7 +452,7 @@ struct GPS_Time {
452
452
  struct {
453
453
  int week;
454
454
  float_t seconds;
455
- } uncorrected; // to work around of "incomplete type" error within g++
455
+ } uncorrected, corrected; // to work around of "incomplete type" error within g++
456
456
  leap_second_event_t(
457
457
  const int &year, const int &month, const int &day,
458
458
  const int &leap)
@@ -462,9 +462,11 @@ struct GPS_Time {
462
462
  t.tm_year = tm_year;
463
463
  t.tm_mon = tm_mon;
464
464
  t.tm_mday = tm_mday;
465
- GPS_Time t_gps(t);
466
- uncorrected.week = t_gps.week;
467
- uncorrected.seconds = t_gps.seconds;
465
+ GPS_Time t_gps_uc(t), t_gps(t_gps_uc + leap);
466
+ uncorrected.week = t_gps_uc.week;
467
+ uncorrected.seconds = t_gps_uc.seconds;
468
+ corrected.week = t_gps.week;
469
+ corrected.seconds = t_gps.seconds;
468
470
  }
469
471
  };
470
472
  static const leap_second_event_t leap_second_events[];
@@ -484,6 +486,92 @@ struct GPS_Time {
484
486
  }
485
487
  return 0;
486
488
  }
489
+
490
+ int leap_seconds() const {
491
+ // Treat *this as (normal) GPS time, to which leap seconds are added when it is converted from std::tm
492
+ for(const leap_second_event_t *i(&leap_second_events[0]); i->leap_seconds > 0; ++i){
493
+ if(*this >= GPS_Time(i->corrected.week, i->corrected.seconds)){return i->leap_seconds;}
494
+ }
495
+ return 0;
496
+ }
497
+ float_t julian_date() const {
498
+ struct conv_t {
499
+ static int ymd2jd(const int &year, const int &month, const int &day){
500
+ // @see https://en.wikipedia.org/wiki/Julian_day#Converting_Gregorian_calendar_date_to_Julian_Day_Number
501
+ return std::div(1461 * (year + 4800 + std::div(month - 14, 12).quot), 4).quot
502
+ + std::div(367 * (month - 2 - 12 * std::div((month - 14), 12).quot), 12).quot
503
+ - std::div(3 * std::div((year + 4900 + std::div(month - 14, 12).quot), 100).quot, 4).quot
504
+ + day - 32075;
505
+ }
506
+ };
507
+ // origin of Julian day is "noon (not midnight)" BC4713/1/1
508
+ static const float_t t0(conv_t::ymd2jd(1980, 1, 6) - 0.5);
509
+ // GPS Time is advanced by leap seconds compared with UTC.
510
+ // The following calculation is incorrect for a day in which a leap second is inserted or truncated.
511
+ // @see https://en.wikipedia.org/wiki/Julian_day#Julian_date_calculation
512
+ return t0 + week * 7 + (seconds - leap_seconds()) / seconds_day;
513
+ }
514
+ float_t julian_date_2000() const {
515
+ static const std::tm tm_2000 = {0, 0, 12, 1, 0, 2000 - 1900};
516
+ static const float_t jd2000(GPS_Time(tm_2000, 13).julian_date());
517
+ return julian_date() - jd2000;
518
+ }
519
+ std::tm utc() const {return c_tm(leap_seconds());}
520
+
521
+ float_t greenwich_mean_sidereal_time_sec_ires1996(const float_t &delta_ut1 = float_t(0)) const {
522
+ float_t jd2000(julian_date_2000() + delta_ut1 / seconds_day);
523
+ float_t jd2000_day(float_t(0.5) + std::floor(jd2000 - 0.5)); // +/-0.5, +/-1.5, ...
524
+
525
+ // @see Chapter 2 of Orbits(978-3540785217) by Xu Guochang
526
+ // @see Chapter 5 of IERS Conventions (1996) https://www.iers.org/IERS/EN/Publications/TechnicalNotes/tn21.html
527
+ float_t jc(jd2000_day / 36525), // Julian century
528
+ jc2(std::pow(jc, 2)), jc3(std::pow(jc, 3));
529
+ float_t gmst0(24110.54841 // = 6h 41m 50.54841s
530
+ + jc * 8640184.812866
531
+ + jc2 * 0.093104
532
+ - jc3 * 6.2E-6);
533
+ // ratio of universal to sidereal time as given by Aoki et al. (1982)
534
+ float_t r(1.002737909350795 // 7.2921158553E-5 = 1.002737909350795 / 86400 * 2pi
535
+ + jc * 5.9006E-11 // 4.3E-15 = 5.9E-11 / 86400 * 2pi
536
+ - jc2 * 5.9E-15); // in seconds
537
+ return gmst0 + r * (jd2000 - jd2000_day) * seconds_day;
538
+ }
539
+
540
+ /**
541
+ * ERA (Earth rotation rate) defined in Sec. 5.5.3 in IERS 2010(Technical Note No.36)
542
+ */
543
+ float_t earth_rotation_angle(const float_t &delta_ut1 = float_t(0),
544
+ const float_t &scale_factor = float_t(M_PI * 2)) const {
545
+ float_t jd2000(julian_date_2000() + delta_ut1 / seconds_day);
546
+ return (jd2000 * 1.00273781191135448 + 0.7790572732640) * scale_factor; // Eq.(5.14)
547
+ }
548
+
549
+ float_t greenwich_mean_sidereal_time_sec_ires2010(const float_t &delta_ut1 = float_t(0)) const {
550
+ float_t era(earth_rotation_angle(delta_ut1, seconds_day));
551
+
552
+ float_t t(julian_date_2000() / 36525);
553
+ // @see Eq.(5.32) Chapter 5 of IERS Conventions (2010)
554
+ #define AS2SEC(as) (((float_t)seconds_day / (360 * 3600)) * (as))
555
+ return era
556
+ + AS2SEC(0.014506)
557
+ + t * AS2SEC(4612.156534)
558
+ + std::pow(t, 2) * AS2SEC(1.3915817)
559
+ - std::pow(t, 3) * AS2SEC(0.00000044)
560
+ - std::pow(t, 4) * AS2SEC(0.000029956)
561
+ - std::pow(t, 5) * AS2SEC(0.0000000368);
562
+ #undef AS2SEC
563
+ }
564
+
565
+ /**
566
+ * Calculate Greenwich mean sidereal time (GMST) in seconds
567
+ * Internally, greenwich_mean_sidereal_time_sec_ired2010() is called.
568
+ * @param delta_ut1 time difference of UTC and UT1; UT1 = UTC + delta_UT1,
569
+ * @return GMST in seconds. 86400 seconds correspond to one rotation
570
+ * @see greenwich_mean_sidereal_time_sec_ires2010()
571
+ */
572
+ float_t greenwich_mean_sidereal_time_sec(const float_t &delta_ut1 = float_t(0)) const {
573
+ return greenwich_mean_sidereal_time_sec_ires2010(delta_ut1);
574
+ }
487
575
  };
488
576
 
489
577
  template <class FloatT>
@@ -248,7 +248,15 @@ struct GPS_Solver_Base {
248
248
  return impl_clock_error_dot(impl, t, pseudo_range);
249
249
  }
250
250
  static const satellite_t &unavailable() {
251
- static const satellite_t res = {NULL};
251
+ struct impl_t {
252
+ static xyz_t v3(const void *, const gps_time_t &, const float_t &){
253
+ return xyz_t(0, 0, 0);
254
+ }
255
+ static float_t v(const void *, const gps_time_t &, const float_t &){
256
+ return float_t(0);
257
+ }
258
+ };
259
+ static const satellite_t res = {NULL, impl_t::v3, impl_t::v3, impl_t::v, impl_t::v};
252
260
  return res;
253
261
  }
254
262
  };
@@ -52,6 +52,7 @@
52
52
  #include <cstring>
53
53
  #include <limits>
54
54
 
55
+ #include "util/text_helper.h"
55
56
  #include "GPS.h"
56
57
  #include "SBAS.h"
57
58
  #include "GLONASS.h"
@@ -61,56 +62,12 @@ class RINEX_Reader {
61
62
  public:
62
63
  typedef RINEX_Reader<U> self_t;
63
64
  typedef std::map<std::string, std::vector<std::string> > header_t;
64
-
65
- struct src_stream_t : public std::istream {
66
- src_stream_t(std::istream &is) : std::istream(is.rdbuf()) {}
67
- /**
68
- * getline() for multi-platform (in addition to \n, \r\n and \r are supported)
69
- *
70
- * @see https://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf
71
- * @see https://en.cppreference.com/w/cpp/io/basic_istream/getline
72
- * TODO gcount() mismatch
73
- */
74
- std::istream& getline(
75
- typename std::istream::char_type* s,
76
- std::streamsize n){
77
- std::streamsize i(1), consumed(0);
78
- typename std::istream::sentry se(*this, true);
79
- if((bool)se){
80
- std::streambuf* sb(this->rdbuf());
81
- for(; i < n; ++i){
82
- int c(sb->sbumpc());
83
- if(c == std::streambuf::traits_type::eof()){
84
- this->setstate(std::ios::eofbit);
85
- break;
86
- }
87
- ++consumed;
88
- if(c == '\n'){
89
- break;
90
- }else if(c == '\r'){
91
- if(sb->sgetc() == '\n'){
92
- sb->sbumpc();
93
- ++consumed;
94
- }
95
- break;
96
- }
97
- *(s++) = (typename std::istream::char_type)c;
98
- }
99
- }
100
- if(((i == 1) && (consumed == 0)) || (i == n)){
101
- this->setstate(std::ios::failbit);
102
- }else{
103
- *s = '\0';
104
- }
105
- return *this;
106
- }
107
- };
108
65
 
109
66
  protected:
110
67
  header_t _header;
111
- src_stream_t src;
68
+ typename TextHelper<>::crlf_stream_t src;
112
69
  bool _has_next;
113
-
70
+
114
71
  public:
115
72
  struct version_type_t {
116
73
  int version;
@@ -186,57 +143,8 @@ class RINEX_Reader {
186
143
  bool has_next() const {return _has_next;}
187
144
 
188
145
  template <class T, bool is_integer = std::numeric_limits<T>::is_integer>
189
- struct conv_t {
190
- static bool d(
191
- std::string &buf, const int &offset, const int &length, void *value, const int &opt = 0, const bool &str2val = true){
192
- if(str2val){
193
- std::stringstream ss(buf.substr(offset, length));
194
- ss >> *(T *)value;
195
- return (ss.rdstate() & std::ios_base::failbit) == 0;
196
- }else{
197
- std::stringstream ss;
198
- ss << std::setfill(opt == 1 ? '0' : ' ') << std::right << std::setw(length) << *(T *)value;
199
- buf.replace(offset, length, ss.str());
200
- return true;
201
- }
202
- }
203
- static bool f_pure(
204
- std::string &buf, const int &offset, const int &length, void *value, const int &precision = 0, const bool &str2val = true){
205
- if(str2val){
206
- std::stringstream ss(buf.substr(offset, length));
207
- ss >> *(T *)value;
208
- return (ss.rdstate() & std::ios_base::failbit) == 0;
209
- }else{
210
- std::stringstream ss;
211
- ss << std::setfill(' ') << std::right << std::setw(length)
212
- << std::setprecision(precision) << std::fixed
213
- << *(T *)value;
214
- buf.replace(offset, length, ss.str());
215
- return true;
216
- }
217
- }
218
- static bool f(
219
- std::string &buf, const int &offset, const int &length, void *value, const int &precision = 0, const bool &str2val = true){
220
- bool res(f_pure(buf, offset, length, value, precision, str2val));
221
- if((!str2val) && res){
222
- if((*(T *)value) >= 0){
223
- if((*(T *)value) < 1){
224
- int i(length - precision - 2);
225
- // 0.12345 => .12345
226
- if(i >= 0){buf[i + offset] = ' ';}
227
- }
228
- }else{
229
- if((*(T *)value) > -1){
230
- int i(length - precision - 2);
231
- // -0.12345 => -.12345
232
- if(i >= 0){buf[i + offset] = '-';}
233
- if(--i >= 0){buf[i + offset] = ' ';}
234
- }
235
- }
236
- }
237
- return res;
238
- }
239
- static bool e(
146
+ struct conv_t : public TextHelper<>::template format_t<T> {
147
+ static bool e_dot_head(
240
148
  std::string &buf, const int &offset, const int &length, void *value, const int &precision = 0, const bool &str2val = true){
241
149
  if(str2val){
242
150
  std::string s(buf.substr(offset, length));
@@ -272,66 +180,25 @@ class RINEX_Reader {
272
180
  }
273
181
  }
274
182
  };
183
+
275
184
  template <class T>
276
- struct conv_t<T, true> {
277
- static bool d(
278
- std::string &buf, const int &offset, const int &length, void *value, const int &opt = 0, const bool &str2val = true){
279
- return conv_t<T, false>::d(buf, offset, length, value, opt, str2val);
280
- }
281
- static bool f_pure(
282
- std::string &buf, const int &offset, const int &length, void *value, const int &precision = 0, const bool &str2val = true){
283
- double v(*(T *)value);
284
- bool res(
285
- conv_t<double, false>::f_pure(buf, offset, length, &v, precision, str2val));
286
- *(T *)value = static_cast<T>(v);
287
- return res;
288
- }
289
- static bool f(
290
- std::string &buf, const int &offset, const int &length, void *value, const int &precision = 0, const bool &str2val = true){
291
- double v(*(T *)value);
292
- bool res(
293
- conv_t<double, false>::f(buf, offset, length, &v, precision, str2val));
294
- *(T *)value = static_cast<T>(v);
295
- return res;
296
- }
297
- static bool e(
185
+ struct conv_t<T, true> : public TextHelper<>::template format_t<T> {
186
+ static bool e_dot_head(
298
187
  std::string &buf, const int &offset, const int &length, void *value, const int &precision = 0, const bool &str2val = true){
299
188
  double v(*(T *)value);
300
189
  bool res(
301
- conv_t<double, false>::e(buf, offset, length, &v, precision, str2val));
190
+ conv_t<double, false>::e_dot_head(buf, offset, length, &v, precision, str2val));
302
191
  *(T *)value = static_cast<T>(v);
303
192
  return res;
304
193
  }
305
194
  };
306
195
 
307
- struct convert_item_t {
308
- bool (*func)(
309
- std::string &buf, const int &offset, const int &length, void *value,
310
- const int &opt, const bool &str2val);
311
- int offset;
312
- int length;
313
- int value_offset;
314
- int opt;
315
- };
316
-
317
- /**
318
- * @param recovery if conversion fails, then this functor is invoked.
319
- * If recovery is successfully performed, this functor should return true.
320
- * The return value of this function reflects it.
321
- * @return (bool) if all conversion are successfully performed, true is returned; otherwise false.
322
- */
323
- static bool convert(
196
+ typedef typename TextHelper<>::convert_item_t convert_item_t;
197
+
198
+ static inline bool convert(
324
199
  const convert_item_t *items, const int &size, const std::string &buf, void *values,
325
200
  bool (*recovery)(const int &, const std::string &, void *) = NULL){
326
- // str => value
327
- bool res(true);
328
- for(int i(0); i < size; ++i){
329
- if((*items[i].func)(
330
- const_cast<std::string &>(buf), items[i].offset, items[i].length, (char *)values + items[i].value_offset,
331
- items[i].opt, true)){continue;}
332
- res &= (recovery ? (*recovery)(i, buf, values) : false);
333
- }
334
- return res;
201
+ return TextHelper<>::str2val(items, size, buf, values, recovery);
335
202
  }
336
203
  template <int N>
337
204
  static inline bool convert(
@@ -1426,10 +1293,10 @@ class RINEX_OBS_Reader : public RINEX_Reader<> {
1426
1293
  {super_t::template conv_t<value_type>::d, offset, length, \
1427
1294
  offsetof(container_type, container_member), 1}
1428
1295
  #define GEN_F2(offset, length, precision, container_type, container_member, value_type) \
1429
- {super_t::template conv_t<value_type>::f, offset, length, \
1296
+ {super_t::template conv_t<value_type>::f_dot_head, offset, length, \
1430
1297
  offsetof(container_type, container_member), precision}
1431
1298
  #define GEN_E2(offset, length, precision, container_type, container_member, value_type) \
1432
- {super_t::template conv_t<value_type>::e, offset, length, \
1299
+ {super_t::template conv_t<value_type>::e_dot_head, offset, length, \
1433
1300
  offsetof(container_type, container_member), precision}
1434
1301
  #define GEN_F(offset, length, precision, container_type, container_member) \
1435
1302
  GEN_F2(offset, length, precision, container_type, container_member, FloatT)
@@ -1958,14 +1825,14 @@ class RINEX_Writer {
1958
1825
  static std::string RINEX_Float(
1959
1826
  const FloatT &value, const int width = 19, const int precision = 12){
1960
1827
  std::string s;
1961
- RINEX_Reader<U>::template conv_t<FloatT>::f(s, 0, width, &const_cast<FloatT &>(value), precision, false);
1828
+ RINEX_Reader<U>::template conv_t<FloatT>::f_dot_head(s, 0, width, &const_cast<FloatT &>(value), precision, false);
1962
1829
  return s;
1963
1830
  }
1964
1831
  template <class FloatT>
1965
1832
  static std::string RINEX_FloatD(
1966
1833
  const FloatT &value, const int width = 19, const int precision = 12){
1967
1834
  std::string s;
1968
- RINEX_Reader<U>::template conv_t<FloatT>::e(s, 0, width, &const_cast<FloatT &>(value), precision, false);
1835
+ RINEX_Reader<U>::template conv_t<FloatT>::e_dot_head(s, 0, width, &const_cast<FloatT &>(value), precision, false);
1969
1836
  return s;
1970
1837
  }
1971
1838
  template <class T>
@@ -1975,20 +1842,10 @@ class RINEX_Writer {
1975
1842
  return s;
1976
1843
  }
1977
1844
 
1978
- /**
1979
- * @return If all conversion are successfully performed, then true; otherwise false;
1980
- */
1981
1845
  static bool convert(
1982
1846
  const typename RINEX_Reader<U>::convert_item_t *items, const int &size,
1983
1847
  std::string &buf, const void *values){
1984
- // value => string
1985
- bool res(true);
1986
- for(int i(0); i < size; ++i){
1987
- res &= (*items[i].func)(
1988
- buf, items[i].offset, items[i].length, (char *)(const_cast<void *>(values)) + items[i].value_offset,
1989
- items[i].opt, false);
1990
- }
1991
- return res;
1848
+ return TextHelper<>::val2str(items, size, buf, values);
1992
1849
  }
1993
1850
  template <int N>
1994
1851
  static inline bool convert(