gps_pvt 0.1.4 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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>
|