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.
- checksums.yaml +4 -4
- data/README.md +3 -2
- data/Rakefile +9 -4
- data/exe/gps_pvt +4 -4
- data/ext/gps_pvt/Coordinate/Coordinate_wrap.cxx +5 -3
- data/ext/gps_pvt/GPS/GPS_wrap.cxx +4229 -508
- data/ext/gps_pvt/SylphideMath/SylphideMath_wrap.cxx +7 -5
- data/ext/ninja-scan-light/tool/navigation/GPS.h +5 -4
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver.h +62 -15
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver_Base.h +6 -5
- data/ext/ninja-scan-light/tool/navigation/QZSS.h +62 -0
- data/ext/ninja-scan-light/tool/navigation/RINEX.h +571 -113
- data/ext/ninja-scan-light/tool/navigation/SBAS.h +2330 -0
- data/ext/ninja-scan-light/tool/navigation/SBAS_Solver.h +329 -0
- data/ext/ninja-scan-light/tool/swig/GPS.i +197 -65
- data/lib/gps_pvt/receiver.rb +311 -132
- data/lib/gps_pvt/version.rb +1 -1
- metadata +9 -7
- data/gps_pvt.gemspec +0 -57
@@ -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
|
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))
|
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
|
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))
|
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
|
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)
|
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
|
-
|
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
|
-
|
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
|
274
|
-
|
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
|
583
|
+
void seek_next_v2_gps() {
|
484
584
|
char buf[256];
|
485
585
|
|
486
|
-
for(int i
|
487
|
-
if(super_t::src.
|
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
|
613
|
+
void seek_next_v2_glonass() {
|
512
614
|
char buf[256];
|
513
615
|
|
514
|
-
for(int i
|
515
|
-
if(super_t::src.
|
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
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
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
|
-
|
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
|
-
|
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
|
-
(
|
642
|
-
|
643
|
-
|
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();
|
646
|
-
|
647
|
-
|
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
|
968
|
-
{super_t::template conv_t<
|
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
|
971
|
-
{super_t::template conv_t<
|
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
|
-
|
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
|
-
|
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
|
-
|
1080
|
-
GEN_E(41, 19, 12, message_t, eph.t_GD),
|
1081
|
-
|
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
|
-
|
1087
|
-
GEN_E(42, 19, 12, message_t, eph.t_GD),
|
1088
|
-
|
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()
|
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
|
-
|
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
|
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
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
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
|
-
|
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
|
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 &
|
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);
|
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
|
-
|
1479
|
-
|
1480
|
-
|
1481
|
-
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
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(
|
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
|
-
|
1499
|
-
|
1500
|
-
|
1501
|
-
|
1502
|
-
|
1503
|
-
|
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
|
-
|
1509
|
-
|
1510
|
-
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1514
|
-
|
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
|
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>
|