gps_pvt 0.1.4 → 0.2.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.
@@ -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;
537
705
  super_t::_has_next = true;
538
706
  }
539
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;
722
+ super_t::_has_next = true;
723
+ }
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,58 @@ 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){
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}){
639
849
  int res(-1);
640
850
  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);
851
+ if(space_nodes.gps){
852
+ (reader.version_type.version >= 300)
853
+ ? reader.extract_iono_utc_v3(*space_nodes.gps)
854
+ : reader.extract_iono_utc_v2(*space_nodes.gps);
855
+ }
856
+ if(space_nodes.qzss && (space_nodes.gps != space_nodes.qzss)
857
+ && (reader.version_type.version >= 302)){
858
+ reader.extract_iono_utc_v3(*space_nodes.qzss);
859
+ }
644
860
  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);
861
+ for(; reader.has_next(); reader.next()){
862
+ switch(reader.sys_of_msg){
863
+ case super_t::version_type_t::SYS_GPS:
864
+ if(!space_nodes.gps){break;}
865
+ space_nodes.gps->satellite(reader.msg.eph.svid).register_ephemeris(reader.msg.eph);
866
+ res++;
867
+ break;
868
+ case super_t::version_type_t::SYS_SBAS: {
869
+ if(!space_nodes.sbas){break;}
870
+ typename message_sbas_t::eph_t eph(reader.msg_sbas);
871
+ space_nodes.sbas->satellite(eph.svid).register_ephemeris(eph);
872
+ res++;
873
+ break;
874
+ }
875
+ case super_t::version_type_t::SYS_QZSS: {
876
+ if(!space_nodes.qzss){break;}
877
+ typename RINEX_NAV<FloatT>::ephemeris_t eph(reader.msg.eph_qzss());
878
+ space_nodes.qzss->satellite(eph.svid).register_ephemeris(eph);
879
+ res++;
880
+ break;
881
+ }
882
+ default: break;
883
+ }
648
884
  }
649
885
  return res;
650
886
  }
887
+
888
+ static int read_all(std::istream &in, space_node_t &space_node){
889
+ space_node_list_t list = {
890
+ &space_node,
891
+ };
892
+ return read_all(in, list);
893
+ }
651
894
  };
652
895
 
653
896
  template <class FloatT>
@@ -964,12 +1207,16 @@ class RINEX_OBS_Reader : public RINEX_Reader<> {
964
1207
  #define GEN_I(offset, length, container_type, container_member, value_type) \
965
1208
  {super_t::template conv_t<value_type>::d, offset, length, \
966
1209
  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, \
1210
+ #define GEN_F2(offset, length, precision, container_type, container_member, value_type) \
1211
+ {super_t::template conv_t<value_type>::f, offset, length, \
969
1212
  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, \
1213
+ #define GEN_E2(offset, length, precision, container_type, container_member, value_type) \
1214
+ {super_t::template conv_t<value_type>::e, offset, length, \
972
1215
  offsetof(container_type, container_member), precision}
1216
+ #define GEN_F(offset, length, precision, container_type, container_member) \
1217
+ GEN_F2(offset, length, precision, container_type, container_member, FloatT)
1218
+ #define GEN_E(offset, length, precision, container_type, container_member) \
1219
+ GEN_E2(offset, length, precision, container_type, container_member, FloatT)
973
1220
 
974
1221
  template <class FloatT>
975
1222
  const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph0_v2[] = {
@@ -1000,17 +1247,17 @@ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>
1000
1247
 
1001
1248
  template <class FloatT>
1002
1249
  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),
1250
+ GEN_E2( 3, 19, 12, message_t, eph.iode, int),
1251
+ GEN_E (22, 19, 12, message_t, eph.c_rs),
1252
+ GEN_E (41, 19, 12, message_t, eph.delta_n),
1253
+ GEN_E (60, 19, 12, message_t, eph.M0),
1007
1254
  };
1008
1255
  template <class FloatT>
1009
1256
  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),
1257
+ GEN_E2( 4, 19, 12, message_t, eph.iode, int),
1258
+ GEN_E (23, 19, 12, message_t, eph.c_rs),
1259
+ GEN_E (42, 19, 12, message_t, eph.delta_n),
1260
+ GEN_E (61, 19, 12, message_t, eph.M0),
1014
1261
  };
1015
1262
 
1016
1263
  template <class FloatT>
@@ -1075,17 +1322,17 @@ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>
1075
1322
 
1076
1323
  template <class FloatT>
1077
1324
  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),
1325
+ GEN_E ( 3, 19, 12, message_t, ura_meter),
1326
+ GEN_E2(22, 19, 12, message_t, eph.SV_health, unsigned int),
1327
+ GEN_E (41, 19, 12, message_t, eph.t_GD),
1328
+ GEN_E2(60, 19, 12, message_t, eph.iodc, int),
1082
1329
  };
1083
1330
  template <class FloatT>
1084
1331
  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),
1332
+ GEN_E ( 4, 19, 12, message_t, ura_meter),
1333
+ GEN_E2(23, 19, 12, message_t, eph.SV_health, unsigned int),
1334
+ GEN_E (42, 19, 12, message_t, eph.t_GD),
1335
+ GEN_E2(61, 19, 12, message_t, eph.iodc, int),
1089
1336
  };
1090
1337
 
1091
1338
  template <class FloatT>
@@ -1099,6 +1346,80 @@ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>
1099
1346
  GEN_E(23, 19, 12, message_t, fit_interval_hr),
1100
1347
  };
1101
1348
 
1349
+
1350
+ template <class FloatT>
1351
+ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph0_sbas_v2[] = {
1352
+ GEN_D( 0, 2, message_sbas_t, svid, int),
1353
+ GEN_D( 3, 2, message_sbas_t, t_year2, int),
1354
+ GEN_D( 6, 2, message_sbas_t, t_mon12, int),
1355
+ GEN_D( 9, 2, message_sbas_t, date_tm.tm_mday, int),
1356
+ GEN_D(12, 2, message_sbas_t, date_tm.tm_hour, int),
1357
+ GEN_D(15, 2, message_sbas_t, date_tm.tm_min, int),
1358
+ GEN_F(17, 5, 1, message_sbas_t, t_sec),
1359
+ GEN_E(22, 19, 12, message_sbas_t, a_Gf0),
1360
+ GEN_E(41, 19, 12, message_sbas_t, a_Gf1),
1361
+ GEN_E(60, 19, 12, message_sbas_t, t_t),
1362
+ };
1363
+ template <class FloatT>
1364
+ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph0_sbas_v3[] = {
1365
+ GEN_I( 1, 2, message_sbas_t, svid, int),
1366
+ GEN_I( 4, 4, message_sbas_t, t_year4, int),
1367
+ GEN_I( 9, 2, message_sbas_t, t_mon12, int),
1368
+ GEN_I(12, 2, message_sbas_t, date_tm.tm_mday, int),
1369
+ GEN_I(15, 2, message_sbas_t, date_tm.tm_hour, int),
1370
+ GEN_I(18, 2, message_sbas_t, date_tm.tm_min, int),
1371
+ GEN_I(21, 2, message_sbas_t, date_tm.tm_sec, int),
1372
+ GEN_E(23, 19, 12, message_sbas_t, a_Gf0),
1373
+ GEN_E(42, 19, 12, message_sbas_t, a_Gf1),
1374
+ GEN_E(61, 19, 12, message_sbas_t, t_t),
1375
+ };
1376
+
1377
+ template <class FloatT>
1378
+ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph1_sbas_v2[] = {
1379
+ GEN_E( 3, 19, 12, message_sbas_t, x_km),
1380
+ GEN_E(22, 19, 12, message_sbas_t, dx_km_s),
1381
+ GEN_E(41, 19, 12, message_sbas_t, ddx_km_s2),
1382
+ GEN_E2(60, 19, 12, message_sbas_t, health, unsigned int),
1383
+ };
1384
+ template <class FloatT>
1385
+ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph1_sbas_v3[] = {
1386
+ GEN_E( 4, 19, 12, message_sbas_t, x_km),
1387
+ GEN_E(23, 19, 12, message_sbas_t, dx_km_s),
1388
+ GEN_E(42, 19, 12, message_sbas_t, ddx_km_s2),
1389
+ GEN_E2(61, 19, 12, message_sbas_t, health, unsigned int),
1390
+ };
1391
+
1392
+ template <class FloatT>
1393
+ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph2_sbas_v2[] = {
1394
+ GEN_E( 3, 19, 12, message_sbas_t, y_km),
1395
+ GEN_E(22, 19, 12, message_sbas_t, dy_km_s),
1396
+ GEN_E(41, 19, 12, message_sbas_t, ddy_km_s2),
1397
+ GEN_E(60, 19, 12, message_sbas_t, URA),
1398
+ };
1399
+ template <class FloatT>
1400
+ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph2_sbas_v3[] = {
1401
+ GEN_E( 4, 19, 12, message_sbas_t, y_km),
1402
+ GEN_E(23, 19, 12, message_sbas_t, dy_km_s),
1403
+ GEN_E(42, 19, 12, message_sbas_t, ddy_km_s2),
1404
+ GEN_E(61, 19, 12, message_sbas_t, URA),
1405
+ };
1406
+
1407
+ template <class FloatT>
1408
+ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph3_sbas_v2[] = {
1409
+ GEN_E( 3, 19, 12, message_sbas_t, z_km),
1410
+ GEN_E(22, 19, 12, message_sbas_t, dz_km_s),
1411
+ GEN_E(41, 19, 12, message_sbas_t, ddz_km_s2),
1412
+ GEN_E2(60, 19, 12, message_sbas_t, iodn, unsigned int),
1413
+ };
1414
+ template <class FloatT>
1415
+ const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::eph3_sbas_v3[] = {
1416
+ GEN_E( 4, 19, 12, message_sbas_t, z_km),
1417
+ GEN_E(23, 19, 12, message_sbas_t, dz_km_s),
1418
+ GEN_E(42, 19, 12, message_sbas_t, ddz_km_s2),
1419
+ GEN_E2(61, 19, 12, message_sbas_t, iodn, unsigned int),
1420
+ };
1421
+
1422
+
1102
1423
  template <class FloatT>
1103
1424
  const typename RINEX_NAV_Reader<FloatT>::convert_item_t RINEX_NAV_Reader<FloatT>::iono_alpha_v2[] = {
1104
1425
  GEN_E( 2, 12, 4, iono_utc_t, alpha[0]),
@@ -1224,7 +1545,7 @@ class RINEX_Writer {
1224
1545
  for(typename super_t::reverse_iterator it(header.rbegin()), it_end(header.rend());
1225
1546
  it != it_end; ++it){
1226
1547
  if(it->first != key){continue;}
1227
- it_tail = it.base() - 1;
1548
+ it_tail = it.base(); // it_tail points to the next element of an element having the smae key
1228
1549
  break;
1229
1550
  }
1230
1551
  }
@@ -1235,14 +1556,16 @@ class RINEX_Writer {
1235
1556
  const typename super_t::value_type::second_type &value){
1236
1557
  if(it_head == header.end()){
1237
1558
  header.push_back(typename super_t::value_type(key, value));
1238
- it_head = it_tail = header.rbegin().base();
1559
+ it_tail = header.end(); // in case of invalidation
1560
+ it_head = it_tail - 1;
1239
1561
  return *this;
1240
1562
  }
1241
1563
  it_head->second = value;
1242
- for(; it_tail != it_head; --it_tail){
1243
- if(it_tail->first == key){continue;}
1564
+ for(--it_tail; it_tail != it_head; --it_tail){
1565
+ if(it_tail->first != key){continue;}
1244
1566
  header.erase(it_tail);
1245
1567
  }
1568
+ it_tail = it_head + 1;
1246
1569
  return *this;
1247
1570
  }
1248
1571
  /**
@@ -1250,14 +1573,24 @@ class RINEX_Writer {
1250
1573
  */
1251
1574
  bracket_accessor_t &operator<<(
1252
1575
  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));
1576
+ super_t::size_type i_head(it_head - header.begin()), i_tail(it_tail - header.begin());
1577
+ header.insert(it_tail, typename super_t::value_type(key, value));
1578
+ it_head = header.begin() + i_head; // in case of invalidation
1579
+ it_tail = header.begin() + i_tail + 1;
1259
1580
  return *this;
1260
1581
  }
1582
+ unsigned int entries() const {
1583
+ return it_tail - it_head;
1584
+ }
1585
+ typename super_t::iterator find(
1586
+ const typename super_t::value_type::second_type &value) const {
1587
+ for(typename super_t::iterator it(it_head); it != it_tail; ++it){
1588
+ if(it->second.find(value) != super_t::value_type::second_type::npos){
1589
+ return it;
1590
+ }
1591
+ }
1592
+ return header.end();
1593
+ }
1261
1594
  };
1262
1595
  bracket_accessor_t operator[]( // mimic of std::map::operator[]=
1263
1596
  const typename super_t::value_type::first_type &key){
@@ -1336,20 +1669,25 @@ class RINEX_Writer {
1336
1669
  return s;
1337
1670
  }
1338
1671
 
1339
- static void convert(
1672
+ /**
1673
+ * @return If all conversion are successfully performed, then true; otherwise false;
1674
+ */
1675
+ static bool convert(
1340
1676
  const typename RINEX_Reader<U>::convert_item_t *items, const int &size,
1341
1677
  std::string &buf, const void *values){
1342
1678
  // value => string
1679
+ bool res(true);
1343
1680
  for(int i(0); i < size; ++i){
1344
- (*items[i].func)(
1681
+ res &= (*items[i].func)(
1345
1682
  buf, items[i].offset, items[i].length, (char *)(const_cast<void *>(values)) + items[i].value_offset,
1346
1683
  items[i].opt, false);
1347
1684
  }
1685
+ return res;
1348
1686
  }
1349
1687
  template <int N>
1350
- static inline void convert(
1688
+ static inline bool convert(
1351
1689
  const typename RINEX_Reader<U>::convert_item_t (&items)[N], std::string &buf, const void *values){
1352
- convert(items, N, buf, values);
1690
+ return convert(items, N, buf, values);
1353
1691
  }
1354
1692
 
1355
1693
  void pgm_runby_date(
@@ -1380,6 +1718,7 @@ class RINEX_NAV_Writer : public RINEX_Writer<> {
1380
1718
  public:
1381
1719
  typedef typename RINEX_NAV<FloatT>::space_node_t space_node_t;
1382
1720
  typedef typename RINEX_NAV<FloatT>::message_t message_t;
1721
+ typedef typename RINEX_NAV<FloatT>::message_sbas_t message_sbas_t;
1383
1722
 
1384
1723
  static const typename super_t::header_item_t default_header[];
1385
1724
  static const int default_header_size;
@@ -1426,6 +1765,9 @@ class RINEX_NAV_Writer : public RINEX_Writer<> {
1426
1765
  std::string s(60, ' ');
1427
1766
  if(super_t::_version_type.version >= 301){
1428
1767
  super_t::convert(reader_t::utc_leap_v301, s, &space_node.iono_utc());
1768
+ if(space_node.iono_utc().WN_LSF == 0){
1769
+ s.replace(6, 18, 18, ' ');
1770
+ }
1429
1771
  }else{
1430
1772
  super_t::convert(reader_t::utc_leap_v2, s, &space_node.iono_utc());
1431
1773
  }
@@ -1435,7 +1777,7 @@ class RINEX_NAV_Writer : public RINEX_Writer<> {
1435
1777
  : super_t(out, default_header, default_header_size) {}
1436
1778
  ~RINEX_NAV_Writer(){}
1437
1779
 
1438
- self_t &operator<<(const message_t &msg){
1780
+ self_t &dump(const message_t &msg, const bool &is_qzss = false){
1439
1781
  std::stringstream buf;
1440
1782
  switch(super_t::_version_type.version / 100){
1441
1783
  case 2:
@@ -1458,7 +1800,8 @@ class RINEX_NAV_Writer : public RINEX_Writer<> {
1458
1800
  for(int i(0); i < 8; ++i){
1459
1801
  std::string s(80, ' ');
1460
1802
  switch(i){
1461
- case 0: super_t::convert(reader_t::eph0_v3, s, &msg); s[0] = 'G'; break;
1803
+ case 0: super_t::convert(reader_t::eph0_v3, s, &msg);
1804
+ s[0] = is_qzss ? 'J' : 'G'; break;
1462
1805
  case 1: super_t::convert(reader_t::eph1_v3, s, &msg); break;
1463
1806
  case 2: super_t::convert(reader_t::eph2_v3, s, &msg); break;
1464
1807
  case 3: super_t::convert(reader_t::eph3_v3, s, &msg); break;
@@ -1474,16 +1817,40 @@ class RINEX_NAV_Writer : public RINEX_Writer<> {
1474
1817
  dist << buf.str();
1475
1818
  return *this;
1476
1819
  }
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++;
1820
+ self_t &operator<<(const message_t &msg){
1821
+ return dump(msg);
1822
+ }
1823
+ self_t &operator<<(const message_sbas_t &msg){
1824
+ std::stringstream buf;
1825
+ switch(super_t::_version_type.version / 100){
1826
+ case 2:
1827
+ for(int i(0); i < 8; ++i){
1828
+ std::string s(80, ' ');
1829
+ switch(i){
1830
+ case 0: super_t::convert(reader_t::eph0_sbas_v2, s, &msg); break;
1831
+ case 1: super_t::convert(reader_t::eph1_sbas_v2, s, &msg); break;
1832
+ case 2: super_t::convert(reader_t::eph2_sbas_v2, s, &msg); break;
1833
+ case 3: super_t::convert(reader_t::eph3_sbas_v2, s, &msg); break;
1834
+ }
1835
+ buf << s << std::endl;
1836
+ }
1837
+ break;
1838
+ case 3:
1839
+ for(int i(0); i < 8; ++i){
1840
+ std::string s(80, ' ');
1841
+ switch(i){
1842
+ case 0: super_t::convert(reader_t::eph0_sbas_v3, s, &msg); s[0] = 'S'; break;
1843
+ case 1: super_t::convert(reader_t::eph1_sbas_v3, s, &msg); break;
1844
+ case 2: super_t::convert(reader_t::eph2_sbas_v3, s, &msg); break;
1845
+ case 3: super_t::convert(reader_t::eph3_sbas_v3, s, &msg); break;
1846
+ }
1847
+ buf << s << std::endl;
1848
+ }
1849
+ break;
1485
1850
  }
1486
- };
1851
+ dist << buf.str();
1852
+ return *this;
1853
+ }
1487
1854
 
1488
1855
  public:
1489
1856
  void set_version(
@@ -1493,31 +1860,122 @@ class RINEX_NAV_Writer : public RINEX_Writer<> {
1493
1860
  version, super_t::version_type_t::FTYPE_NAVIGATION, sys));
1494
1861
  }
1495
1862
 
1496
- int write_all(const space_node_t &space_node, const int &version = 304){
1863
+ int write_all(
1864
+ const typename reader_t::space_node_list_t &space_nodes,
1865
+ const int &version = 304){
1497
1866
  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);
1867
+ int systems(0);
1868
+ set_version(version, super_t::version_type_t::SYS_UNKNOWN);
1869
+ do{
1870
+ if(!space_nodes.gps){break;}
1871
+ ++systems;
1872
+ set_version(version, super_t::version_type_t::SYS_GPS);
1873
+ if(!space_nodes.gps->is_valid_iono_utc()){break;}
1874
+ switch(version / 100){
1875
+ case 2:
1876
+ if(_header["ION ALPHA"].entries() == 0){iono_alpha(*space_nodes.gps);}
1877
+ if(_header["ION BETA"].entries() == 0){iono_beta(*space_nodes.gps);}
1878
+ if(_header["DELTA-UTC: A0,A1,T,W"].entries() == 0){utc_params(*space_nodes.gps);}
1879
+ if(_header["LEAP SECONDS"].entries() == 0){leap_seconds(*space_nodes.gps);}
1880
+ break;
1881
+ case 3:
1882
+ if(_header["IONOSPHERIC CORR"].find("GPSA") == _header.end()){iono_alpha(*space_nodes.gps);}
1883
+ if(_header["IONOSPHERIC CORR"].find("GPSB") == _header.end()){iono_beta(*space_nodes.gps);}
1884
+ if(_header["TIME SYSTEM CORR"].find("GPUT") == _header.end()){utc_params(*space_nodes.gps);}
1885
+ if(_header["LEAP SECONDS"].entries() == 0){leap_seconds(*space_nodes.gps);}
1886
+ break;
1887
+ }
1888
+ }while(false);
1889
+ do{
1890
+ if(!space_nodes.sbas){break;}
1891
+ ++systems;
1892
+ set_version(version, super_t::version_type_t::SYS_SBAS);
1893
+ }while(false);
1894
+ do{
1895
+ if((version < 302) || (!space_nodes.qzss)){break;}
1896
+ ++systems;
1897
+ set_version(version, super_t::version_type_t::SYS_QZSS);
1898
+ if(!space_nodes.qzss->is_valid_iono_utc()){break;}
1899
+ switch(version / 100){
1900
+ case 3:
1901
+ if(_header["IONOSPHERIC CORR"].find("GPSA") == _header.end()){iono_alpha(*space_nodes.qzss);}
1902
+ if(_header["IONOSPHERIC CORR"].find("GPSB") == _header.end()){iono_beta(*space_nodes.qzss);}
1903
+ if(_header["TIME SYSTEM CORR"].find("QZUT") == _header.end()){utc_params(*space_nodes.qzss);}
1904
+ if(_header["LEAP SECONDS"].entries() == 0){leap_seconds(*space_nodes.qzss);}
1905
+ break;
1906
+ }
1907
+ }while(false);
1908
+ if(systems > 1){
1909
+ set_version(version, super_t::version_type_t::SYS_MIXED);
1504
1910
  }
1505
1911
  super_t::dist << header();
1506
1912
  res++;
1507
1913
 
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);
1914
+ struct {
1915
+ RINEX_NAV_Writer &w;
1916
+ int &counter;
1917
+ bool gps, qzss;
1918
+ void operator()(const typename space_node_t::Satellite::Ephemeris &eph) {
1919
+ if(gps && (eph.svid <= 32)){
1920
+ w << message_t(eph);
1921
+ }else if(qzss && (eph.svid >= 193) && (eph.svid < 202)){
1922
+ w.dump(message_t::from_qzss(eph), true);
1923
+ }else{
1924
+ return;
1925
+ }
1926
+ counter++;
1927
+ }
1928
+ void operator()(const typename message_sbas_t::eph_t &eph) {
1929
+ w << message_sbas_t(eph);
1930
+ counter++;
1931
+ }
1932
+ } functor = {*this, res, false, false};
1933
+ if(space_nodes.gps){
1934
+ functor.gps = true;
1935
+ if(space_nodes.gps == space_nodes.qzss){functor.qzss = true;}
1936
+ for(typename space_node_t::satellites_t::const_iterator
1937
+ it(space_nodes.gps->satellites().begin()), it_end(space_nodes.gps->satellites().end());
1938
+ it != it_end; ++it){
1939
+ it->second.each_ephemeris(
1940
+ functor,
1941
+ space_node_t::Satellite::eph_list_t::EACH_ALL_INVERTED);
1942
+ }
1943
+ }
1944
+ if(space_nodes.sbas){
1945
+ for(typename SBAS_SpaceNode<FloatT>::satellites_t::const_iterator
1946
+ it(space_nodes.sbas->satellites().begin()),
1947
+ it_end(space_nodes.sbas->satellites().end());
1948
+ it != it_end; ++it){
1949
+ it->second.each_ephemeris(
1950
+ functor,
1951
+ SBAS_SpaceNode<FloatT>::Satellite::eph_list_t::EACH_ALL_INVERTED);
1952
+ }
1953
+ }
1954
+ if((version >= 302) && (!functor.qzss) && (space_nodes.qzss)){
1955
+ functor.qzss = true;
1956
+ functor.gps = false;
1957
+ for(typename space_node_t::satellites_t::const_iterator
1958
+ it(space_nodes.qzss->satellites().begin()), it_end(space_nodes.qzss->satellites().end());
1959
+ it != it_end; ++it){
1960
+ it->second.each_ephemeris(
1961
+ functor,
1962
+ space_node_t::Satellite::eph_list_t::EACH_ALL_INVERTED);
1963
+ }
1515
1964
  }
1516
1965
  return res;
1517
1966
  }
1967
+ static int write_all(
1968
+ std::ostream &out,
1969
+ const typename reader_t::space_node_list_t &space_nodes,
1970
+ const int &version = 304){
1971
+ return RINEX_NAV_Writer(out).write_all(space_nodes, version);
1972
+ }
1973
+ int write_all(const space_node_t &space_node, const int &version = 304){
1974
+ const typename reader_t::space_node_list_t list = {&const_cast<space_node_t &>(space_node)};
1975
+ return write_all(list, version);
1976
+ }
1518
1977
  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);
1978
+ return RINEX_NAV_Writer(out).write_all(space_node, version);
1521
1979
  }
1522
1980
  };
1523
1981
  template <class FloatT>