gps_pvt 0.1.5 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +16 -4
- data/Rakefile +9 -4
- data/exe/gps_pvt +32 -23
- data/ext/gps_pvt/Coordinate/Coordinate_wrap.cxx +5 -3
- data/ext/gps_pvt/GPS/GPS_wrap.cxx +4302 -529
- 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 +33 -25
- data/ext/ninja-scan-light/tool/navigation/QZSS.h +62 -0
- data/ext/ninja-scan-light/tool/navigation/RINEX.h +583 -115
- 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 +284 -99
- data/ext/ninja-scan-light/tool/swig/spec/GPS_spec.rb +18 -1
- data/lib/gps_pvt/receiver.rb +323 -141
- 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;
|
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
|
-
|
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
|
-
|
639
|
-
|
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.
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
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
|
968
|
-
{super_t::template conv_t<
|
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
|
971
|
-
{super_t::template conv_t<
|
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
|
-
|
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
|
-
|
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
|
-
|
1080
|
-
GEN_E(41, 19, 12, message_t, eph.t_GD),
|
1081
|
-
|
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
|
-
|
1087
|
-
GEN_E(42, 19, 12, message_t, eph.t_GD),
|
1088
|
-
|
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()
|
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
|
-
|
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
|
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
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
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
|
-
|
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
|
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 &
|
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);
|
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
|
-
|
1479
|
-
|
1480
|
-
|
1481
|
-
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
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
|
-
|
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
|
-
|
1499
|
-
|
1500
|
-
|
1501
|
-
|
1502
|
-
|
1503
|
-
|
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
|
-
|
1509
|
-
|
1510
|
-
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1514
|
-
|
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
|
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>
|