gps_pvt 0.1.5 → 0.2.1

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;
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>