gps_pvt 0.1.5 → 0.2.1

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.
@@ -50,8 +50,10 @@
50
50
  #include <algorithm>
51
51
  #include <cstddef>
52
52
  #include <cstring>
53
+ #include <limits>
53
54
 
54
55
  #include "GPS.h"
56
+ #include "SBAS.h"
55
57
 
56
58
  template <class U = void>
57
59
  class RINEX_Reader {
@@ -180,22 +182,27 @@ class RINEX_Reader {
180
182
  const header_t &header() const {return const_cast<self_t *>(this)->header();}
181
183
  bool has_next() const {return _has_next;}
182
184
 
183
- template <class T>
185
+ template <class T, bool is_integer = std::numeric_limits<T>::is_integer>
184
186
  struct conv_t {
185
- static void d(
187
+ static bool d(
186
188
  std::string &buf, const int &offset, const int &length, void *value, const int &opt = 0, const bool &str2val = true){
187
189
  if(str2val){
188
- std::stringstream(buf.substr(offset, length)) >> *(T *)value;
190
+ std::stringstream ss(buf.substr(offset, length));
191
+ ss >> *(T *)value;
192
+ return (ss.rdstate() & std::ios_base::failbit) == 0;
189
193
  }else{
190
194
  std::stringstream ss;
191
195
  ss << std::setfill(opt == 1 ? '0' : ' ') << std::right << std::setw(length) << *(T *)value;
192
196
  buf.replace(offset, length, ss.str());
197
+ return true;
193
198
  }
194
199
  }
195
- static void f(
200
+ static bool f(
196
201
  std::string &buf, const int &offset, const int &length, void *value, const int &precision = 0, const bool &str2val = true){
197
202
  if(str2val){
198
- std::stringstream(buf.substr(offset, length)) >> *(T *)value;
203
+ std::stringstream ss(buf.substr(offset, length));
204
+ ss >> *(T *)value;
205
+ return (ss.rdstate() & std::ios_base::failbit) == 0;
199
206
  }else{
200
207
  std::stringstream ss;
201
208
  ss << std::setfill(' ') << std::right << std::setw(length)
@@ -215,9 +222,10 @@ class RINEX_Reader {
215
222
  }
216
223
  }
217
224
  buf.replace(offset, length, s);
225
+ return true;
218
226
  }
219
227
  }
220
- static void e(
228
+ static bool e(
221
229
  std::string &buf, const int &offset, const int &length, void *value, const int &precision = 0, const bool &str2val = true){
222
230
  if(str2val){
223
231
  std::string s(buf.substr(offset, length));
@@ -225,7 +233,9 @@ class RINEX_Reader {
225
233
  if(pos != std::string::npos){
226
234
  s.replace(pos, 1, "E");
227
235
  }
228
- std::stringstream(s) >> *(T *)value;
236
+ std::stringstream ss(s);
237
+ ss >> *(T *)value;
238
+ return (ss.rdstate() & std::ios_base::failbit) == 0;
229
239
  }else{
230
240
  int w((std::max)(length, precision + 6)); // parentheses of std::max mitigates error C2589 under Windows VC
231
241
 
@@ -247,12 +257,36 @@ class RINEX_Reader {
247
257
  ss.str("");
248
258
  ss << std::setfill(' ') << std::right << std::setw(w) << s;
249
259
  buf.replace(offset, length, ss.str());
260
+ return true;
250
261
  }
251
262
  }
252
263
  };
264
+ template <class T>
265
+ struct conv_t<T, true> {
266
+ static bool d(
267
+ std::string &buf, const int &offset, const int &length, void *value, const int &opt = 0, const bool &str2val = true){
268
+ return conv_t<T, false>::d(buf, offset, length, value, opt, str2val);
269
+ }
270
+ static bool f(
271
+ std::string &buf, const int &offset, const int &length, void *value, const int &precision = 0, const bool &str2val = true){
272
+ double v(*(T *)value);
273
+ bool res(
274
+ conv_t<double, false>::f(buf, offset, length, &v, precision, str2val));
275
+ *(T *)value = static_cast<T>(v);
276
+ return res;
277
+ }
278
+ static bool e(
279
+ std::string &buf, const int &offset, const int &length, void *value, const int &precision = 0, const bool &str2val = true){
280
+ double v(*(T *)value);
281
+ bool res(
282
+ conv_t<double, false>::e(buf, offset, length, &v, precision, str2val));
283
+ *(T *)value = static_cast<T>(v);
284
+ return res;
285
+ }
286
+ };
253
287
 
254
288
  struct convert_item_t {
255
- void (*func)(
289
+ bool (*func)(
256
290
  std::string &buf, const int &offset, const int &length, void *value,
257
291
  const int &opt, const bool &str2val);
258
292
  int offset;
@@ -261,17 +295,30 @@ class RINEX_Reader {
261
295
  int opt;
262
296
  };
263
297
 
264
- static void convert(const convert_item_t *items, const int &size, const std::string &buf, void *values){
298
+ /**
299
+ * @param recovery if conversion fails, then this functor is invoked.
300
+ * If recovery is successfully performed, this functor should return true.
301
+ * The return value of this function reflects it.
302
+ * @return (bool) if all conversion are successfully performed, true is returned; otherwise false.
303
+ */
304
+ static bool convert(
305
+ const convert_item_t *items, const int &size, const std::string &buf, void *values,
306
+ bool (*recovery)(const int &, const std::string &, void *) = NULL){
265
307
  // str => value
308
+ bool res(true);
266
309
  for(int i(0); i < size; ++i){
267
- (*items[i].func)(
310
+ if((*items[i].func)(
268
311
  const_cast<std::string &>(buf), items[i].offset, items[i].length, (char *)values + items[i].value_offset,
269
- items[i].opt, true);
312
+ items[i].opt, true)){continue;}
313
+ res &= (recovery ? (*recovery)(i, buf, values) : false);
270
314
  }
315
+ return res;
271
316
  }
272
317
  template <int N>
273
- static inline void convert(const convert_item_t (&items)[N], const std::string &buf, void *values){
274
- convert(items, N, buf, values);
318
+ static inline bool convert(
319
+ const convert_item_t (&items)[N], const std::string &buf, void *values,
320
+ bool (*recovery)(const int &, const std::string &, void *) = NULL){
321
+ return convert(items, N, buf, values, recovery);
275
322
  }
276
323
  };
277
324
 
@@ -404,10 +451,8 @@ struct RINEX_NAV {
404
451
  std::tm t_oc_tm;
405
452
  int t_oc_year4, t_oc_year2, t_oc_mon12;
406
453
  FloatT t_oc_sec;
407
- FloatT iodc_f, iode_f; // originally int type
408
454
  FloatT t_oe_WN;
409
455
  FloatT ura_meter;
410
- FloatT SV_health_f;
411
456
  FloatT t_ot; ///< Transmitting time [s]
412
457
  FloatT fit_interval_hr;
413
458
  FloatT dummy;
@@ -420,10 +465,8 @@ struct RINEX_NAV {
420
465
  t_oc_year2(t_oc_tm.tm_year % 100),
421
466
  t_oc_mon12(t_oc_tm.tm_mon + 1),
422
467
  t_oc_sec(std::fmod(eph.t_oc, 60)),
423
- iodc_f(eph.iodc), iode_f(eph.iode),
424
468
  t_oe_WN(eph.WN),
425
469
  ura_meter(ephemeris_t::URA_meter(eph.URA)),
426
- SV_health_f(((eph.SV_health & 0x20) && (eph.SV_health & 0x1F == 0)) ? 1 : eph.SV_health),
427
470
  t_ot(0), // TODO
428
471
  fit_interval_hr(eph.fit_interval / (60 * 60)),
429
472
  dummy(0) {
@@ -434,9 +477,6 @@ struct RINEX_NAV {
434
477
  eph.WN = t_oc.week;
435
478
  eph.t_oc = t_oc.seconds;
436
479
 
437
- eph.iodc = iodc_f;
438
- eph.iode = iode_f;
439
-
440
480
  eph.URA = ephemeris_t::URA_index(ura_meter); // meter to index
441
481
 
442
482
  /* @see ftp://igs.org/pub/data/format/rinex210.txt
@@ -444,17 +484,69 @@ struct RINEX_NAV {
444
484
  * RINEX Value: 0 Health OK
445
485
  * RINEX Value: 1 Health not OK (bits 18-22 not stored)
446
486
  * RINEX Value: >32 Health not OK (bits 18-22 stored)
487
+ * eph.SV_health may have a value greater than 32
447
488
  */
448
- eph.SV_health = (unsigned int)SV_health_f;
449
- if(eph.SV_health > 32){
450
- eph.SV_health &= 0x3F; // 0b111111
451
- }else if(eph.SV_health > 0){
452
- eph.SV_health = 0x20; // 0b100000
453
- }
454
489
 
455
490
  // At least 4 hour validity, then, hours => seconds;
456
491
  eph.fit_interval = ((fit_interval_hr < 4) ? 4 : fit_interval_hr) * 60 * 60;
457
492
  }
493
+ static message_t from_qzss(const ephemeris_t &eph_){
494
+ message_t res(eph_);
495
+ res.eph.svid -= 192;
496
+ res.fit_interval_hr = (res.fit_interval_hr) > 2 ? 1 : 0;
497
+ return res;
498
+ }
499
+ ephemeris_t eph_qzss() const {
500
+ ephemeris_t res(eph);
501
+ res.svid += 192;
502
+ res.fit_interval = ((fit_interval_hr > 0) ? 4 : 2) * 60 * 60;
503
+ return res;
504
+ }
505
+ };
506
+ struct message_sbas_t {
507
+ typedef typename SBAS_SpaceNode<FloatT>
508
+ ::SatelliteProperties::Ephemeris eph_t;
509
+ int svid;
510
+ std::tm date_tm;
511
+ int t_year4, t_year2, t_mon12;
512
+ FloatT t_sec;
513
+ FloatT a_Gf0, a_Gf1;
514
+ FloatT t_t; // Transmission time of message (start of the message) in GPS seconds of the week
515
+ FloatT x_km, dx_km_s, ddx_km_s2;
516
+ FloatT y_km, dy_km_s, ddy_km_s2;
517
+ FloatT z_km, dz_km_s, ddz_km_s2;
518
+ unsigned int health;
519
+ FloatT URA;
520
+ unsigned int iodn;
521
+ message_sbas_t() {}
522
+ message_sbas_t(const eph_t &eph)
523
+ : svid((int)eph.svid - 100),
524
+ date_tm(eph.base_time().c_tm()),
525
+ t_year4(date_tm.tm_year + 1900),
526
+ t_year2(date_tm.tm_year % 100),
527
+ t_mon12(date_tm.tm_mon + 1),
528
+ t_sec(date_tm.tm_sec),
529
+ a_Gf0(eph.a_Gf0), a_Gf1(eph.a_Gf1),
530
+ t_t(eph.t_0), // TODO maybe differ from t_e slightly
531
+ x_km(1E-3 * eph.x), dx_km_s(1E-3 * eph.dx), ddx_km_s2(1E-3 * eph.ddx),
532
+ y_km(1E-3 * eph.y), dy_km_s(1E-3 * eph.dy), ddy_km_s2(1E-3 * eph.ddy),
533
+ z_km(1E-3 * eph.z), dz_km_s(1E-3 * eph.dz), ddz_km_s2(1E-3 * eph.ddz),
534
+ health(0), URA(eph.URA), iodn(0) {
535
+ }
536
+ operator eph_t() const {
537
+ eph_t eph = {0};
538
+ eph.svid = (unsigned int)svid + 100;
539
+ typename space_node_t::gps_time_t t(date_tm);
540
+ t += (t_sec - date_tm.tm_sec);
541
+ eph.WN = t.week;
542
+ eph.t_0 = t.seconds;
543
+ eph.a_Gf0 = a_Gf0; eph.a_Gf1 = a_Gf1;
544
+ eph.x = 1E3 * x_km; eph.dx = 1E3 * dx_km_s; eph.ddx = 1E3 * ddx_km_s2;
545
+ eph.y = 1E3 * y_km; eph.dy = 1E3 * dy_km_s; eph.ddy = 1E3 * ddy_km_s2;
546
+ eph.z = 1E3 * z_km; eph.dz = 1E3 * dz_km_s; eph.ddz = 1E3 * ddz_km_s2;
547
+ eph.URA = URA;
548
+ return eph;
549
+ }
458
550
  };
459
551
  };
460
552
 
@@ -466,6 +558,7 @@ class RINEX_NAV_Reader : public RINEX_Reader<> {
466
558
  public:
467
559
  typedef typename RINEX_NAV<FloatT>::space_node_t space_node_t;
468
560
  typedef typename RINEX_NAV<FloatT>::message_t message_t;
561
+ typedef typename RINEX_NAV<FloatT>::message_sbas_t message_sbas_t;
469
562
  typedef typename space_node_t::Ionospheric_UTC_Parameters iono_utc_t;
470
563
 
471
564
  static const typename super_t::convert_item_t eph0_v2[10], eph0_v3[10];
@@ -477,14 +570,22 @@ class RINEX_NAV_Reader : public RINEX_Reader<> {
477
570
  static const typename super_t::convert_item_t eph6_v2[4], eph6_v3[4];
478
571
  static const typename super_t::convert_item_t eph7_v2[2], eph7_v3[2];
479
572
 
573
+ static const typename super_t::convert_item_t eph0_sbas_v2[10], eph0_sbas_v3[10];
574
+ static const typename super_t::convert_item_t eph1_sbas_v2[4], eph1_sbas_v3[4];
575
+ static const typename super_t::convert_item_t eph2_sbas_v2[4], eph2_sbas_v3[4];
576
+ static const typename super_t::convert_item_t eph3_sbas_v2[4], eph3_sbas_v3[4];
577
+
480
578
  protected:
579
+ typename super_t::version_type_t::sat_system_t sys_of_msg;
481
580
  message_t msg;
581
+ message_sbas_t msg_sbas;
482
582
 
483
- void seek_next_v2() {
583
+ void seek_next_v2_gps() {
484
584
  char buf[256];
485
585
 
486
- for(int i = 0; (i < 8) && (super_t::src.good()); i++){
487
- if(super_t::src.getline(buf, sizeof(buf)).fail()){return;}
586
+ for(int i(0); i < 8; i++){
587
+ if((!super_t::src.good())
588
+ || super_t::src.getline(buf, sizeof(buf)).fail()){return;}
488
589
  std::string line(buf);
489
590
 
490
591
  switch(i){
@@ -505,25 +606,69 @@ class RINEX_NAV_Reader : public RINEX_Reader<> {
505
606
  }
506
607
  }
507
608
  msg.update();
609
+ sys_of_msg = super_t::version_type_t::SYS_GPS;
508
610
  super_t::_has_next = true;
509
611
  }
510
612
 
511
- void seek_next_v3() {
613
+ void seek_next_v2_glonass() {
512
614
  char buf[256];
513
615
 
514
- for(int i = 0; (i < 8) && (super_t::src.good()); i++){
515
- if(super_t::src.getline(buf, sizeof(buf)).fail()){return;}
616
+ for(int i(0); i < 4; i++){
617
+ if((!super_t::src.good())
618
+ || super_t::src.getline(buf, sizeof(buf)).fail()){return;}
619
+ }
620
+ //sys_of_msg = super_t::version_type_t::SYS_GLONASS; // TODO currently not implemented
621
+ sys_of_msg = super_t::version_type_t::SYS_UNKNOWN;
622
+ super_t::_has_next = true;
623
+ }
624
+
625
+ void seek_next_v2_sbas() {
626
+ char buf[256];
627
+
628
+ for(int i(0); i < 4; i++){
629
+ if((!super_t::src.good())
630
+ || super_t::src.getline(buf, sizeof(buf)).fail()){return;}
516
631
  std::string line(buf);
517
632
 
518
633
  switch(i){
519
634
  case 0: {
520
- // if(line_data[0] != 'G'){} // TODO check GPS before parsing
521
- super_t::convert(eph0_v3, line, &msg);
522
- msg.t_oc_tm.tm_year = msg.t_oc_year4 - 1900; // tm_year base is 1900
523
- msg.t_oc_tm.tm_mon = msg.t_oc_mon12 - 1; // month [0, 11]
524
- msg.t_oc_sec = msg.t_oc_tm.tm_sec;
635
+ super_t::convert(eph0_sbas_v2, line, &msg_sbas);
636
+ msg_sbas.date_tm.tm_year = msg_sbas.t_year2 + (msg_sbas.t_year2 < 80 ? 100 : 0); // greater than 1980
637
+ msg_sbas.date_tm.tm_mon = msg_sbas.t_mon12 - 1; // month [0, 11]
638
+ msg_sbas.date_tm.tm_sec = (int)msg_sbas.t_sec;
525
639
  break;
526
640
  }
641
+ case 1: super_t::convert(eph1_sbas_v2, line, &msg_sbas); break;
642
+ case 2: super_t::convert(eph2_sbas_v2, line, &msg_sbas); break;
643
+ case 3: super_t::convert(eph3_sbas_v2, line, &msg_sbas); break;
644
+ }
645
+ }
646
+ sys_of_msg = super_t::version_type_t::SYS_SBAS;
647
+ super_t::_has_next = true;
648
+ }
649
+
650
+ void seek_next_v2() {
651
+ switch(super_t::version_type.sat_system){
652
+ case super_t::version_type_t::SYS_GPS: seek_next_v2_gps(); return;
653
+ case super_t::version_type_t::SYS_GLONASS: seek_next_v2_glonass(); return;
654
+ case super_t::version_type_t::SYS_SBAS: seek_next_v2_sbas(); return;
655
+ default: break;
656
+ }
657
+ }
658
+
659
+ template <std::size_t N>
660
+ void seek_next_v3_gps(char (&buf)[N]) {
661
+ super_t::convert(eph0_v3, std::string(buf), &msg);
662
+ msg.t_oc_tm.tm_year = msg.t_oc_year4 - 1900; // tm_year base is 1900
663
+ msg.t_oc_tm.tm_mon = msg.t_oc_mon12 - 1; // month [0, 11]
664
+ msg.t_oc_sec = msg.t_oc_tm.tm_sec;
665
+
666
+ for(int i(1); i < 8; i++){
667
+ if((!super_t::src.good())
668
+ || super_t::src.getline(buf, sizeof(buf)).fail()){return;}
669
+ std::string line(buf);
670
+
671
+ switch(i){
527
672
  case 1: super_t::convert(eph1_v3, line, &msg); break;
528
673
  case 2: super_t::convert(eph2_v3, line, &msg); break;
529
674
  case 3: super_t::convert(eph3_v3, line, &msg); break;
@@ -534,10 +679,71 @@ class RINEX_NAV_Reader : public RINEX_Reader<> {
534
679
  }
535
680
  }
536
681
  msg.update();
682
+ sys_of_msg = super_t::version_type_t::SYS_GPS;
683
+ super_t::_has_next = true;
684
+ }
685
+
686
+ template <std::size_t N>
687
+ void seek_next_v3_sbas(char (&buf)[N]) {
688
+ super_t::convert(eph0_sbas_v3, std::string(buf), &msg_sbas);
689
+ msg_sbas.date_tm.tm_year = msg_sbas.t_year4 - 1900; // tm_year base is 1900
690
+ msg_sbas.date_tm.tm_mon = msg_sbas.t_mon12 - 1; // month [0, 11]
691
+ msg_sbas.t_sec = msg_sbas.date_tm.tm_sec;
692
+
693
+ for(int i(1); i < 4; i++){
694
+ if((!super_t::src.good())
695
+ || super_t::src.getline(buf, sizeof(buf)).fail()){return;}
696
+ std::string line(buf);
697
+
698
+ switch(i){
699
+ case 1: super_t::convert(eph1_sbas_v3, line, &msg_sbas); break;
700
+ case 2: super_t::convert(eph2_sbas_v3, line, &msg_sbas); break;
701
+ case 3: super_t::convert(eph3_sbas_v3, line, &msg_sbas); break;
702
+ }
703
+ }
704
+ sys_of_msg = super_t::version_type_t::SYS_SBAS;
705
+ super_t::_has_next = true;
706
+ }
707
+
708
+ template <std::size_t N>
709
+ void seek_next_v3_qzss(char (&buf)[N]) {
710
+ seek_next_v3_gps(buf);
711
+ if(!super_t::_has_next){return;}
712
+ sys_of_msg = super_t::version_type_t::SYS_QZSS;
713
+ }
714
+
715
+ template <std::size_t N>
716
+ void seek_next_v3_not_implemented(char (&buf)[N], const int &lines) {
717
+ for(int i(1); i < lines; i++){
718
+ if((!super_t::src.good())
719
+ || super_t::src.getline(buf, sizeof(buf)).fail()){return;}
720
+ }
721
+ sys_of_msg = super_t::version_type_t::SYS_UNKNOWN;
537
722
  super_t::_has_next = true;
538
723
  }
539
724
 
725
+ void seek_next_v3() {
726
+ char buf[256];
727
+
728
+ while(super_t::src.good()
729
+ && (!super_t::src.getline(buf, sizeof(buf)).fail())){
730
+
731
+ switch(buf[0]){
732
+ case 'G': seek_next_v3_gps(buf); return; // GPS
733
+ case 'E': seek_next_v3_not_implemented(buf, 8); return; // Galileo
734
+ case 'R': seek_next_v3_not_implemented(buf, 4); return; // Glonass
735
+ case 'J': seek_next_v3_qzss(buf); return; // QZSS
736
+ case 'C': seek_next_v3_not_implemented(buf, 8); return; // Beido
737
+ case 'S': seek_next_v3_sbas(buf); return; // SBAS
738
+ case 'T': seek_next_v3_not_implemented(buf, 8); return; // IRNSS
739
+ default: break;
740
+ }
741
+ }
742
+ }
743
+
540
744
  void seek_next() {
745
+ super_t::_has_next = false;
746
+ sys_of_msg = super_t::version_type_t::SYS_UNKNOWN;
541
747
  super_t::version_type.version >= 300 ? seek_next_v3() : seek_next_v2();
542
748
  }
543
749
 
@@ -547,11 +753,8 @@ class RINEX_NAV_Reader : public RINEX_Reader<> {
547
753
  }
548
754
  ~RINEX_NAV_Reader(){}
549
755
 
550
- typename space_node_t::Satellite::Ephemeris next() {
551
- typename space_node_t::Satellite::Ephemeris current(msg.eph);
552
- super_t::_has_next = false;
756
+ void next() {
553
757
  seek_next();
554
- return current;
555
758
  }
556
759
 
557
760
  static const typename super_t::convert_item_t iono_alpha_v2[4];
@@ -569,19 +772,19 @@ class RINEX_NAV_Reader : public RINEX_Reader<> {
569
772
  bool alpha, beta, utc, leap;
570
773
  super_t::header_t::const_iterator it;
571
774
 
572
- if(alpha = ((it = _header.find("ION ALPHA")) != _header.end())){
775
+ if((alpha = ((it = _header.find("ION ALPHA")) != _header.end()))){
573
776
  super_t::convert(iono_alpha_v2, it->second.front(), &iono_utc);
574
777
  }
575
778
 
576
- if(beta = ((it = _header.find("ION BETA")) != _header.end())){
779
+ if((beta = ((it = _header.find("ION BETA")) != _header.end()))){
577
780
  super_t::convert(iono_beta_v2, it->second.front(), &iono_utc);
578
781
  }
579
782
 
580
- if(utc = ((it = _header.find("DELTA-UTC: A0,A1,T,W")) != _header.end())){
783
+ if((utc = ((it = _header.find("DELTA-UTC: A0,A1,T,W")) != _header.end()))){
581
784
  super_t::convert(utc_v2, it->second.front(), &iono_utc);
582
785
  }
583
786
 
584
- if(leap = ((it = _header.find("LEAP SECONDS")) != _header.end())){
787
+ if((leap = ((it = _header.find("LEAP SECONDS")) != _header.end()))){
585
788
  super_t::convert(utc_leap_v2, it->second.front(), &iono_utc);
586
789
  }
587
790
 
@@ -623,6 +826,7 @@ class RINEX_NAV_Reader : public RINEX_Reader<> {
623
826
  }
624
827
 
625
828
  if((it = _header.find("LEAP SECONDS")) != _header.end()){
829
+ iono_utc.delta_t_LSF = iono_utc.WN_LSF = iono_utc.DN = 0;
626
830
  if(version_type.version >= 301){
627
831
  super_t::convert(utc_leap_v301, it->second.front(), &iono_utc);
628
832
  }else{
@@ -635,19 +839,60 @@ class RINEX_NAV_Reader : public RINEX_Reader<> {
635
839
  return alpha && beta && utc && leap;
636
840
  }
637
841
 
638
- static int read_all(std::istream &in, space_node_t &space_node){
639
- int res(-1);
842
+ struct space_node_list_t {
843
+ space_node_t *gps;
844
+ SBAS_SpaceNode<FloatT> *sbas;
845
+ space_node_t *qzss;
846
+ };
847
+
848
+ static int read_all(std::istream &in, space_node_list_t &space_nodes = {0}){
640
849
  RINEX_NAV_Reader reader(in);
641
- (reader.version_type.version >= 300)
642
- ? reader.extract_iono_utc_v3(space_node)
643
- : reader.extract_iono_utc_v2(space_node);
644
- res++;
645
- for(; reader.has_next(); ++res){
646
- typename space_node_t::Satellite::Ephemeris eph(reader.next());
647
- space_node.satellite(eph.svid).register_ephemeris(eph);
850
+ if(reader.version_type.file_type != version_type_t::FTYPE_NAVIGATION){
851
+ return -1;
852
+ }
853
+ if(space_nodes.gps){
854
+ (reader.version_type.version >= 300)
855
+ ? reader.extract_iono_utc_v3(*space_nodes.gps)
856
+ : reader.extract_iono_utc_v2(*space_nodes.gps);
857
+ }
858
+ if(space_nodes.qzss && (space_nodes.gps != space_nodes.qzss)
859
+ && (reader.version_type.version >= 302)){
860
+ reader.extract_iono_utc_v3(*space_nodes.qzss);
861
+ }
862
+ int res(0);
863
+ for(; reader.has_next(); reader.next()){
864
+ switch(reader.sys_of_msg){
865
+ case super_t::version_type_t::SYS_GPS:
866
+ if(!space_nodes.gps){break;}
867
+ space_nodes.gps->satellite(reader.msg.eph.svid).register_ephemeris(reader.msg.eph);
868
+ res++;
869
+ break;
870
+ case super_t::version_type_t::SYS_SBAS: {
871
+ if(!space_nodes.sbas){break;}
872
+ typename message_sbas_t::eph_t eph(reader.msg_sbas);
873
+ space_nodes.sbas->satellite(eph.svid).register_ephemeris(eph);
874
+ res++;
875
+ break;
876
+ }
877
+ case super_t::version_type_t::SYS_QZSS: {
878
+ if(!space_nodes.qzss){break;}
879
+ typename RINEX_NAV<FloatT>::ephemeris_t eph(reader.msg.eph_qzss());
880
+ space_nodes.qzss->satellite(eph.svid).register_ephemeris(eph);
881
+ res++;
882
+ break;
883
+ }
884
+ default: break;
885
+ }
648
886
  }
649
887
  return res;
650
888
  }
889
+
890
+ static int read_all(std::istream &in, space_node_t &space_node){
891
+ space_node_list_t list = {
892
+ &space_node,
893
+ };
894
+ return read_all(in, list);
895
+ }
651
896
  };
652
897
 
653
898
  template <class FloatT>
@@ -897,6 +1142,9 @@ class RINEX_OBS_Reader : public RINEX_Reader<> {
897
1142
  RINEX_OBS_Reader(std::istream &in)
898
1143
  : super_t(in, self_t::modify_header),
899
1144
  obs_types() {
1145
+ if(super_t::version_type.file_type != version_type_t::FTYPE_OBSERVATION){
1146
+ return;
1147
+ }
900
1148
  typedef super_t::header_t::const_iterator it_t;
901
1149
  typedef super_t::header_t::mapped_type::const_iterator it2_t;
902
1150
  it_t it;
@@ -964,12 +1212,16 @@ class RINEX_OBS_Reader : public RINEX_Reader<> {
964
1212
  #define GEN_I(offset, length, container_type, container_member, value_type) \
965
1213
  {super_t::template conv_t<value_type>::d, offset, length, \
966
1214
  offsetof(container_type, container_member), 1}
967
- #define GEN_F(offset, length, precision, container_type, container_member) \
968
- {super_t::template conv_t<FloatT>::f, offset, length, \
1215
+ #define GEN_F2(offset, length, precision, container_type, container_member, value_type) \
1216
+ {super_t::template conv_t<value_type>::f, offset, length, \
969
1217
  offsetof(container_type, container_member), precision}
970
- #define GEN_E(offset, length, precision, container_type, container_member) \
971
- {super_t::template conv_t<FloatT>::e, offset, length, \
1218
+ #define GEN_E2(offset, length, precision, container_type, container_member, value_type) \
1219
+ {super_t::template conv_t<value_type>::e, offset, length, \
972
1220
  offsetof(container_type, container_member), precision}
1221
+ #define GEN_F(offset, length, precision, container_type, container_member) \
1222
+ GEN_F2(offset, length, precision, container_type, container_member, FloatT)
1223
+ #define GEN_E(offset, length, precision, container_type, container_member) \
1224
+ GEN_E2(offset, length, precision, container_type, container_member, FloatT)
973
1225
 
974
1226
  template <class FloatT>
975
1227
  const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph0_v2[] = {
@@ -1000,17 +1252,17 @@ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>
1000
1252
 
1001
1253
  template <class FloatT>
1002
1254
  const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph1_v2[] = {
1003
- GEN_E( 3, 19, 12, message_t, iode_f),
1004
- GEN_E(22, 19, 12, message_t, eph.c_rs),
1005
- GEN_E(41, 19, 12, message_t, eph.delta_n),
1006
- GEN_E(60, 19, 12, message_t, eph.M0),
1255
+ GEN_E2( 3, 19, 12, message_t, eph.iode, int),
1256
+ GEN_E (22, 19, 12, message_t, eph.c_rs),
1257
+ GEN_E (41, 19, 12, message_t, eph.delta_n),
1258
+ GEN_E (60, 19, 12, message_t, eph.M0),
1007
1259
  };
1008
1260
  template <class FloatT>
1009
1261
  const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph1_v3[] = {
1010
- GEN_E( 4, 19, 12, message_t, iode_f),
1011
- GEN_E(23, 19, 12, message_t, eph.c_rs),
1012
- GEN_E(42, 19, 12, message_t, eph.delta_n),
1013
- GEN_E(61, 19, 12, message_t, eph.M0),
1262
+ GEN_E2( 4, 19, 12, message_t, eph.iode, int),
1263
+ GEN_E (23, 19, 12, message_t, eph.c_rs),
1264
+ GEN_E (42, 19, 12, message_t, eph.delta_n),
1265
+ GEN_E (61, 19, 12, message_t, eph.M0),
1014
1266
  };
1015
1267
 
1016
1268
  template <class FloatT>
@@ -1075,17 +1327,17 @@ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>
1075
1327
 
1076
1328
  template <class FloatT>
1077
1329
  const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph6_v2[] = {
1078
- GEN_E( 3, 19, 12, message_t, ura_meter),
1079
- GEN_E(22, 19, 12, message_t, SV_health_f),
1080
- GEN_E(41, 19, 12, message_t, eph.t_GD),
1081
- GEN_E(60, 19, 12, message_t, iodc_f),
1330
+ GEN_E ( 3, 19, 12, message_t, ura_meter),
1331
+ GEN_E2(22, 19, 12, message_t, eph.SV_health, unsigned int),
1332
+ GEN_E (41, 19, 12, message_t, eph.t_GD),
1333
+ GEN_E2(60, 19, 12, message_t, eph.iodc, int),
1082
1334
  };
1083
1335
  template <class FloatT>
1084
1336
  const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph6_v3[] = {
1085
- GEN_E( 4, 19, 12, message_t, ura_meter),
1086
- GEN_E(23, 19, 12, message_t, SV_health_f),
1087
- GEN_E(42, 19, 12, message_t, eph.t_GD),
1088
- GEN_E(61, 19, 12, message_t, iodc_f),
1337
+ GEN_E ( 4, 19, 12, message_t, ura_meter),
1338
+ GEN_E2(23, 19, 12, message_t, eph.SV_health, unsigned int),
1339
+ GEN_E (42, 19, 12, message_t, eph.t_GD),
1340
+ GEN_E2(61, 19, 12, message_t, eph.iodc, int),
1089
1341
  };
1090
1342
 
1091
1343
  template <class FloatT>
@@ -1099,6 +1351,80 @@ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>
1099
1351
  GEN_E(23, 19, 12, message_t, fit_interval_hr),
1100
1352
  };
1101
1353
 
1354
+
1355
+ template <class FloatT>
1356
+ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph0_sbas_v2[] = {
1357
+ GEN_D( 0, 2, message_sbas_t, svid, int),
1358
+ GEN_D( 3, 2, message_sbas_t, t_year2, int),
1359
+ GEN_D( 6, 2, message_sbas_t, t_mon12, int),
1360
+ GEN_D( 9, 2, message_sbas_t, date_tm.tm_mday, int),
1361
+ GEN_D(12, 2, message_sbas_t, date_tm.tm_hour, int),
1362
+ GEN_D(15, 2, message_sbas_t, date_tm.tm_min, int),
1363
+ GEN_F(17, 5, 1, message_sbas_t, t_sec),
1364
+ GEN_E(22, 19, 12, message_sbas_t, a_Gf0),
1365
+ GEN_E(41, 19, 12, message_sbas_t, a_Gf1),
1366
+ GEN_E(60, 19, 12, message_sbas_t, t_t),
1367
+ };
1368
+ template <class FloatT>
1369
+ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph0_sbas_v3[] = {
1370
+ GEN_I( 1, 2, message_sbas_t, svid, int),
1371
+ GEN_I( 4, 4, message_sbas_t, t_year4, int),
1372
+ GEN_I( 9, 2, message_sbas_t, t_mon12, int),
1373
+ GEN_I(12, 2, message_sbas_t, date_tm.tm_mday, int),
1374
+ GEN_I(15, 2, message_sbas_t, date_tm.tm_hour, int),
1375
+ GEN_I(18, 2, message_sbas_t, date_tm.tm_min, int),
1376
+ GEN_I(21, 2, message_sbas_t, date_tm.tm_sec, int),
1377
+ GEN_E(23, 19, 12, message_sbas_t, a_Gf0),
1378
+ GEN_E(42, 19, 12, message_sbas_t, a_Gf1),
1379
+ GEN_E(61, 19, 12, message_sbas_t, t_t),
1380
+ };
1381
+
1382
+ template <class FloatT>
1383
+ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph1_sbas_v2[] = {
1384
+ GEN_E( 3, 19, 12, message_sbas_t, x_km),
1385
+ GEN_E(22, 19, 12, message_sbas_t, dx_km_s),
1386
+ GEN_E(41, 19, 12, message_sbas_t, ddx_km_s2),
1387
+ GEN_E2(60, 19, 12, message_sbas_t, health, unsigned int),
1388
+ };
1389
+ template <class FloatT>
1390
+ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph1_sbas_v3[] = {
1391
+ GEN_E( 4, 19, 12, message_sbas_t, x_km),
1392
+ GEN_E(23, 19, 12, message_sbas_t, dx_km_s),
1393
+ GEN_E(42, 19, 12, message_sbas_t, ddx_km_s2),
1394
+ GEN_E2(61, 19, 12, message_sbas_t, health, unsigned int),
1395
+ };
1396
+
1397
+ template <class FloatT>
1398
+ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph2_sbas_v2[] = {
1399
+ GEN_E( 3, 19, 12, message_sbas_t, y_km),
1400
+ GEN_E(22, 19, 12, message_sbas_t, dy_km_s),
1401
+ GEN_E(41, 19, 12, message_sbas_t, ddy_km_s2),
1402
+ GEN_E(60, 19, 12, message_sbas_t, URA),
1403
+ };
1404
+ template <class FloatT>
1405
+ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph2_sbas_v3[] = {
1406
+ GEN_E( 4, 19, 12, message_sbas_t, y_km),
1407
+ GEN_E(23, 19, 12, message_sbas_t, dy_km_s),
1408
+ GEN_E(42, 19, 12, message_sbas_t, ddy_km_s2),
1409
+ GEN_E(61, 19, 12, message_sbas_t, URA),
1410
+ };
1411
+
1412
+ template <class FloatT>
1413
+ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph3_sbas_v2[] = {
1414
+ GEN_E( 3, 19, 12, message_sbas_t, z_km),
1415
+ GEN_E(22, 19, 12, message_sbas_t, dz_km_s),
1416
+ GEN_E(41, 19, 12, message_sbas_t, ddz_km_s2),
1417
+ GEN_E2(60, 19, 12, message_sbas_t, iodn, unsigned int),
1418
+ };
1419
+ template <class FloatT>
1420
+ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph3_sbas_v3[] = {
1421
+ GEN_E( 4, 19, 12, message_sbas_t, z_km),
1422
+ GEN_E(23, 19, 12, message_sbas_t, dz_km_s),
1423
+ GEN_E(42, 19, 12, message_sbas_t, ddz_km_s2),
1424
+ GEN_E2(61, 19, 12, message_sbas_t, iodn, unsigned int),
1425
+ };
1426
+
1427
+
1102
1428
  template <class FloatT>
1103
1429
  const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::iono_alpha_v2[] = {
1104
1430
  GEN_E( 2, 12, 4, iono_utc_t, alpha[0]),
@@ -1224,7 +1550,7 @@ class RINEX_Writer {
1224
1550
  for(typename super_t::reverse_iterator it(header.rbegin()), it_end(header.rend());
1225
1551
  it != it_end; ++it){
1226
1552
  if(it->first != key){continue;}
1227
- it_tail = it.base() - 1;
1553
+ it_tail = it.base(); // it_tail points to the next element of an element having the smae key
1228
1554
  break;
1229
1555
  }
1230
1556
  }
@@ -1235,14 +1561,16 @@ class RINEX_Writer {
1235
1561
  const typename super_t::value_type::second_type &value){
1236
1562
  if(it_head == header.end()){
1237
1563
  header.push_back(typename super_t::value_type(key, value));
1238
- it_head = it_tail = header.rbegin().base();
1564
+ it_tail = header.end(); // in case of invalidation
1565
+ it_head = it_tail - 1;
1239
1566
  return *this;
1240
1567
  }
1241
1568
  it_head->second = value;
1242
- for(; it_tail != it_head; --it_tail){
1243
- if(it_tail->first == key){continue;}
1569
+ for(--it_tail; it_tail != it_head; --it_tail){
1570
+ if(it_tail->first != key){continue;}
1244
1571
  header.erase(it_tail);
1245
1572
  }
1573
+ it_tail = it_head + 1;
1246
1574
  return *this;
1247
1575
  }
1248
1576
  /**
@@ -1250,14 +1578,24 @@ class RINEX_Writer {
1250
1578
  */
1251
1579
  bracket_accessor_t &operator<<(
1252
1580
  const typename super_t::value_type::second_type &value){
1253
- if(it_tail == header.end()){
1254
- header.push_back(typename super_t::value_type(key, value));
1255
- it_head = it_tail = header.rbegin().base();
1256
- return *this;
1257
- }
1258
- header.insert(++it_tail, typename super_t::value_type(key, value));
1581
+ super_t::size_type i_head(it_head - header.begin()), i_tail(it_tail - header.begin());
1582
+ header.insert(it_tail, typename super_t::value_type(key, value));
1583
+ it_head = header.begin() + i_head; // in case of invalidation
1584
+ it_tail = header.begin() + i_tail + 1;
1259
1585
  return *this;
1260
1586
  }
1587
+ unsigned int entries() const {
1588
+ return it_tail - it_head;
1589
+ }
1590
+ typename super_t::iterator find(
1591
+ const typename super_t::value_type::second_type &value) const {
1592
+ for(typename super_t::iterator it(it_head); it != it_tail; ++it){
1593
+ if(it->second.find(value) != super_t::value_type::second_type::npos){
1594
+ return it;
1595
+ }
1596
+ }
1597
+ return header.end();
1598
+ }
1261
1599
  };
1262
1600
  bracket_accessor_t operator[]( // mimic of std::map::operator[]=
1263
1601
  const typename super_t::value_type::first_type &key){
@@ -1336,20 +1674,25 @@ class RINEX_Writer {
1336
1674
  return s;
1337
1675
  }
1338
1676
 
1339
- static void convert(
1677
+ /**
1678
+ * @return If all conversion are successfully performed, then true; otherwise false;
1679
+ */
1680
+ static bool convert(
1340
1681
  const typename RINEX_Reader<U>::convert_item_t *items, const int &size,
1341
1682
  std::string &buf, const void *values){
1342
1683
  // value => string
1684
+ bool res(true);
1343
1685
  for(int i(0); i < size; ++i){
1344
- (*items[i].func)(
1686
+ res &= (*items[i].func)(
1345
1687
  buf, items[i].offset, items[i].length, (char *)(const_cast<void *>(values)) + items[i].value_offset,
1346
1688
  items[i].opt, false);
1347
1689
  }
1690
+ return res;
1348
1691
  }
1349
1692
  template <int N>
1350
- static inline void convert(
1693
+ static inline bool convert(
1351
1694
  const typename RINEX_Reader<U>::convert_item_t (&items)[N], std::string &buf, const void *values){
1352
- convert(items, N, buf, values);
1695
+ return convert(items, N, buf, values);
1353
1696
  }
1354
1697
 
1355
1698
  void pgm_runby_date(
@@ -1380,6 +1723,7 @@ class RINEX_NAV_Writer : public RINEX_Writer<> {
1380
1723
  public:
1381
1724
  typedef typename RINEX_NAV<FloatT>::space_node_t space_node_t;
1382
1725
  typedef typename RINEX_NAV<FloatT>::message_t message_t;
1726
+ typedef typename RINEX_NAV<FloatT>::message_sbas_t message_sbas_t;
1383
1727
 
1384
1728
  static const typename super_t::header_item_t default_header[];
1385
1729
  static const int default_header_size;
@@ -1426,6 +1770,9 @@ class RINEX_NAV_Writer : public RINEX_Writer<> {
1426
1770
  std::string s(60, ' ');
1427
1771
  if(super_t::_version_type.version >= 301){
1428
1772
  super_t::convert(reader_t::utc_leap_v301, s, &space_node.iono_utc());
1773
+ if(space_node.iono_utc().WN_LSF == 0){
1774
+ s.replace(6, 18, 18, ' ');
1775
+ }
1429
1776
  }else{
1430
1777
  super_t::convert(reader_t::utc_leap_v2, s, &space_node.iono_utc());
1431
1778
  }
@@ -1435,7 +1782,7 @@ class RINEX_NAV_Writer : public RINEX_Writer<> {
1435
1782
  : super_t(out, default_header, default_header_size) {}
1436
1783
  ~RINEX_NAV_Writer(){}
1437
1784
 
1438
- self_t &operator<<(const message_t &msg){
1785
+ self_t &dump(const message_t &msg, const bool &is_qzss = false){
1439
1786
  std::stringstream buf;
1440
1787
  switch(super_t::_version_type.version / 100){
1441
1788
  case 2:
@@ -1458,7 +1805,8 @@ class RINEX_NAV_Writer : public RINEX_Writer<> {
1458
1805
  for(int i(0); i < 8; ++i){
1459
1806
  std::string s(80, ' ');
1460
1807
  switch(i){
1461
- case 0: super_t::convert(reader_t::eph0_v3, s, &msg); s[0] = 'G'; break;
1808
+ case 0: super_t::convert(reader_t::eph0_v3, s, &msg);
1809
+ s[0] = is_qzss ? 'J' : 'G'; break;
1462
1810
  case 1: super_t::convert(reader_t::eph1_v3, s, &msg); break;
1463
1811
  case 2: super_t::convert(reader_t::eph2_v3, s, &msg); break;
1464
1812
  case 3: super_t::convert(reader_t::eph3_v3, s, &msg); break;
@@ -1474,16 +1822,40 @@ class RINEX_NAV_Writer : public RINEX_Writer<> {
1474
1822
  dist << buf.str();
1475
1823
  return *this;
1476
1824
  }
1477
-
1478
- protected:
1479
- struct WriteAllFunctor {
1480
- RINEX_NAV_Writer &w;
1481
- int &counter;
1482
- void operator()(const typename space_node_t::Satellite::Ephemeris &eph) {
1483
- w << message_t(eph);
1484
- counter++;
1825
+ self_t &operator<<(const message_t &msg){
1826
+ return dump(msg);
1827
+ }
1828
+ self_t &operator<<(const message_sbas_t &msg){
1829
+ std::stringstream buf;
1830
+ switch(super_t::_version_type.version / 100){
1831
+ case 2:
1832
+ for(int i(0); i < 8; ++i){
1833
+ std::string s(80, ' ');
1834
+ switch(i){
1835
+ case 0: super_t::convert(reader_t::eph0_sbas_v2, s, &msg); break;
1836
+ case 1: super_t::convert(reader_t::eph1_sbas_v2, s, &msg); break;
1837
+ case 2: super_t::convert(reader_t::eph2_sbas_v2, s, &msg); break;
1838
+ case 3: super_t::convert(reader_t::eph3_sbas_v2, s, &msg); break;
1839
+ }
1840
+ buf << s << std::endl;
1841
+ }
1842
+ break;
1843
+ case 3:
1844
+ for(int i(0); i < 8; ++i){
1845
+ std::string s(80, ' ');
1846
+ switch(i){
1847
+ case 0: super_t::convert(reader_t::eph0_sbas_v3, s, &msg); s[0] = 'S'; break;
1848
+ case 1: super_t::convert(reader_t::eph1_sbas_v3, s, &msg); break;
1849
+ case 2: super_t::convert(reader_t::eph2_sbas_v3, s, &msg); break;
1850
+ case 3: super_t::convert(reader_t::eph3_sbas_v3, s, &msg); break;
1851
+ }
1852
+ buf << s << std::endl;
1853
+ }
1854
+ break;
1485
1855
  }
1486
- };
1856
+ dist << buf.str();
1857
+ return *this;
1858
+ }
1487
1859
 
1488
1860
  public:
1489
1861
  void set_version(
@@ -1493,31 +1865,127 @@ class RINEX_NAV_Writer : public RINEX_Writer<> {
1493
1865
  version, super_t::version_type_t::FTYPE_NAVIGATION, sys));
1494
1866
  }
1495
1867
 
1496
- int write_all(const space_node_t &space_node, const int &version = 304){
1868
+ struct space_node_list_t {
1869
+ const space_node_t *gps;
1870
+ const SBAS_SpaceNode<FloatT> *sbas;
1871
+ const space_node_t *qzss;
1872
+ };
1873
+ int write_all(
1874
+ const space_node_list_t &space_nodes,
1875
+ const int &version = 304){
1497
1876
  int res(-1);
1498
- set_version(version);
1499
- if(space_node.is_valid_iono_utc()){
1500
- iono_alpha(space_node);
1501
- iono_beta(space_node);
1502
- utc_params(space_node);
1503
- leap_seconds(space_node);
1877
+ int systems(0);
1878
+ set_version(version, super_t::version_type_t::SYS_UNKNOWN);
1879
+ do{
1880
+ if(!space_nodes.gps){break;}
1881
+ ++systems;
1882
+ set_version(version, super_t::version_type_t::SYS_GPS);
1883
+ if(!space_nodes.gps->is_valid_iono_utc()){break;}
1884
+ switch(version / 100){
1885
+ case 2:
1886
+ if(_header["ION ALPHA"].entries() == 0){iono_alpha(*space_nodes.gps);}
1887
+ if(_header["ION BETA"].entries() == 0){iono_beta(*space_nodes.gps);}
1888
+ if(_header["DELTA-UTC: A0,A1,T,W"].entries() == 0){utc_params(*space_nodes.gps);}
1889
+ if(_header["LEAP SECONDS"].entries() == 0){leap_seconds(*space_nodes.gps);}
1890
+ break;
1891
+ case 3:
1892
+ if(_header["IONOSPHERIC CORR"].find("GPSA") == _header.end()){iono_alpha(*space_nodes.gps);}
1893
+ if(_header["IONOSPHERIC CORR"].find("GPSB") == _header.end()){iono_beta(*space_nodes.gps);}
1894
+ if(_header["TIME SYSTEM CORR"].find("GPUT") == _header.end()){utc_params(*space_nodes.gps);}
1895
+ if(_header["LEAP SECONDS"].entries() == 0){leap_seconds(*space_nodes.gps);}
1896
+ break;
1897
+ }
1898
+ }while(false);
1899
+ do{
1900
+ if(!space_nodes.sbas){break;}
1901
+ ++systems;
1902
+ set_version(version, super_t::version_type_t::SYS_SBAS);
1903
+ }while(false);
1904
+ do{
1905
+ if((version < 302) || (!space_nodes.qzss)){break;}
1906
+ ++systems;
1907
+ set_version(version, super_t::version_type_t::SYS_QZSS);
1908
+ if(!space_nodes.qzss->is_valid_iono_utc()){break;}
1909
+ switch(version / 100){
1910
+ case 3:
1911
+ if(_header["IONOSPHERIC CORR"].find("GPSA") == _header.end()){iono_alpha(*space_nodes.qzss);}
1912
+ if(_header["IONOSPHERIC CORR"].find("GPSB") == _header.end()){iono_beta(*space_nodes.qzss);}
1913
+ if(_header["TIME SYSTEM CORR"].find("QZUT") == _header.end()){utc_params(*space_nodes.qzss);}
1914
+ if(_header["LEAP SECONDS"].entries() == 0){leap_seconds(*space_nodes.qzss);}
1915
+ break;
1916
+ }
1917
+ }while(false);
1918
+ if(systems > 1){
1919
+ set_version(version, super_t::version_type_t::SYS_MIXED);
1504
1920
  }
1505
1921
  super_t::dist << header();
1506
1922
  res++;
1507
1923
 
1508
- WriteAllFunctor functor = {*this, res};
1509
- for(typename space_node_t::satellites_t::const_iterator
1510
- it(space_node.satellites().begin()), it_end(space_node.satellites().end());
1511
- it != it_end; ++it){
1512
- it->second.each_ephemeris(
1513
- functor,
1514
- space_node_t::Satellite::eph_list_t::EACH_ALL_INVERTED);
1924
+ struct {
1925
+ RINEX_NAV_Writer &w;
1926
+ int &counter;
1927
+ bool gps, qzss;
1928
+ void operator()(const typename space_node_t::Satellite::Ephemeris &eph) {
1929
+ if(gps && (eph.svid <= 32)){
1930
+ w << message_t(eph);
1931
+ }else if(qzss && (eph.svid >= 193) && (eph.svid < 202)){
1932
+ w.dump(message_t::from_qzss(eph), true);
1933
+ }else{
1934
+ return;
1935
+ }
1936
+ counter++;
1937
+ }
1938
+ void operator()(const typename message_sbas_t::eph_t &eph) {
1939
+ w << message_sbas_t(eph);
1940
+ counter++;
1941
+ }
1942
+ } functor = {*this, res, false, false};
1943
+ if(space_nodes.gps){
1944
+ functor.gps = true;
1945
+ if(space_nodes.gps == space_nodes.qzss){functor.qzss = true;}
1946
+ for(typename space_node_t::satellites_t::const_iterator
1947
+ it(space_nodes.gps->satellites().begin()), it_end(space_nodes.gps->satellites().end());
1948
+ it != it_end; ++it){
1949
+ it->second.each_ephemeris(
1950
+ functor,
1951
+ space_node_t::Satellite::eph_list_t::EACH_ALL_INVERTED);
1952
+ }
1953
+ }
1954
+ if(space_nodes.sbas){
1955
+ for(typename SBAS_SpaceNode<FloatT>::satellites_t::const_iterator
1956
+ it(space_nodes.sbas->satellites().begin()),
1957
+ it_end(space_nodes.sbas->satellites().end());
1958
+ it != it_end; ++it){
1959
+ it->second.each_ephemeris(
1960
+ functor,
1961
+ SBAS_SpaceNode<FloatT>::Satellite::eph_list_t::EACH_ALL_INVERTED);
1962
+ }
1963
+ }
1964
+ if((version >= 302) && (!functor.qzss) && (space_nodes.qzss)){
1965
+ functor.qzss = true;
1966
+ functor.gps = false;
1967
+ for(typename space_node_t::satellites_t::const_iterator
1968
+ it(space_nodes.qzss->satellites().begin()), it_end(space_nodes.qzss->satellites().end());
1969
+ it != it_end; ++it){
1970
+ it->second.each_ephemeris(
1971
+ functor,
1972
+ space_node_t::Satellite::eph_list_t::EACH_ALL_INVERTED);
1973
+ }
1515
1974
  }
1516
1975
  return res;
1517
1976
  }
1977
+ static int write_all(
1978
+ std::ostream &out,
1979
+ const space_node_list_t &space_nodes,
1980
+ const int &version = 304){
1981
+ return RINEX_NAV_Writer(out).write_all(space_nodes, version);
1982
+ }
1983
+ int write_all(const space_node_t &space_node, const int &version = 304){
1984
+ space_node_list_t list = {&space_node};
1985
+ return write_all(list, version);
1986
+ }
1518
1987
  static int write_all(std::ostream &out, const space_node_t &space_node, const int &version = 304){
1519
- RINEX_NAV_Writer writer(out);
1520
- return writer.write_all(space_node, version);
1988
+ return RINEX_NAV_Writer(out).write_all(space_node, version);
1521
1989
  }
1522
1990
  };
1523
1991
  template <class FloatT>