gps_pvt 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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(