gps_pvt 0.1.4 → 0.2.0

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