gps_pvt 0.5.1 → 0.6.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 +11 -7
- data/Rakefile +42 -23
- data/exe/gps_pvt +13 -6
- data/ext/gps_pvt/Coordinate/Coordinate_wrap.cxx +44 -0
- data/ext/gps_pvt/GPS/GPS_wrap.cxx +8975 -7360
- data/ext/ninja-scan-light/tool/algorithm/interpolate.h +121 -0
- data/ext/ninja-scan-light/tool/navigation/ANTEX.h +747 -0
- data/ext/ninja-scan-light/tool/navigation/GPS.h +92 -4
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver_Base.h +9 -1
- data/ext/ninja-scan-light/tool/navigation/RINEX.h +18 -161
- data/ext/ninja-scan-light/tool/navigation/SP3.h +1178 -0
- data/ext/ninja-scan-light/tool/navigation/coordinate.h +81 -1
- data/ext/ninja-scan-light/tool/swig/GPS.i +120 -1
- data/ext/ninja-scan-light/tool/swig/spec/GPS_spec.rb +503 -0
- data/ext/ninja-scan-light/tool/util/text_helper.h +248 -0
- data/lib/gps_pvt/receiver.rb +24 -0
- data/lib/gps_pvt/util.rb +25 -7
- data/lib/gps_pvt/version.rb +1 -1
- metadata +6 -2
@@ -452,7 +452,7 @@ struct GPS_Time {
|
|
452
452
|
struct {
|
453
453
|
int week;
|
454
454
|
float_t seconds;
|
455
|
-
} uncorrected; // to work around of "incomplete type" error within g++
|
455
|
+
} uncorrected, corrected; // to work around of "incomplete type" error within g++
|
456
456
|
leap_second_event_t(
|
457
457
|
const int &year, const int &month, const int &day,
|
458
458
|
const int &leap)
|
@@ -462,9 +462,11 @@ struct GPS_Time {
|
|
462
462
|
t.tm_year = tm_year;
|
463
463
|
t.tm_mon = tm_mon;
|
464
464
|
t.tm_mday = tm_mday;
|
465
|
-
GPS_Time
|
466
|
-
uncorrected.week =
|
467
|
-
uncorrected.seconds =
|
465
|
+
GPS_Time t_gps_uc(t), t_gps(t_gps_uc + leap);
|
466
|
+
uncorrected.week = t_gps_uc.week;
|
467
|
+
uncorrected.seconds = t_gps_uc.seconds;
|
468
|
+
corrected.week = t_gps.week;
|
469
|
+
corrected.seconds = t_gps.seconds;
|
468
470
|
}
|
469
471
|
};
|
470
472
|
static const leap_second_event_t leap_second_events[];
|
@@ -484,6 +486,92 @@ struct GPS_Time {
|
|
484
486
|
}
|
485
487
|
return 0;
|
486
488
|
}
|
489
|
+
|
490
|
+
int leap_seconds() const {
|
491
|
+
// Treat *this as (normal) GPS time, to which leap seconds are added when it is converted from std::tm
|
492
|
+
for(const leap_second_event_t *i(&leap_second_events[0]); i->leap_seconds > 0; ++i){
|
493
|
+
if(*this >= GPS_Time(i->corrected.week, i->corrected.seconds)){return i->leap_seconds;}
|
494
|
+
}
|
495
|
+
return 0;
|
496
|
+
}
|
497
|
+
float_t julian_date() const {
|
498
|
+
struct conv_t {
|
499
|
+
static int ymd2jd(const int &year, const int &month, const int &day){
|
500
|
+
// @see https://en.wikipedia.org/wiki/Julian_day#Converting_Gregorian_calendar_date_to_Julian_Day_Number
|
501
|
+
return std::div(1461 * (year + 4800 + std::div(month - 14, 12).quot), 4).quot
|
502
|
+
+ std::div(367 * (month - 2 - 12 * std::div((month - 14), 12).quot), 12).quot
|
503
|
+
- std::div(3 * std::div((year + 4900 + std::div(month - 14, 12).quot), 100).quot, 4).quot
|
504
|
+
+ day - 32075;
|
505
|
+
}
|
506
|
+
};
|
507
|
+
// origin of Julian day is "noon (not midnight)" BC4713/1/1
|
508
|
+
static const float_t t0(conv_t::ymd2jd(1980, 1, 6) - 0.5);
|
509
|
+
// GPS Time is advanced by leap seconds compared with UTC.
|
510
|
+
// The following calculation is incorrect for a day in which a leap second is inserted or truncated.
|
511
|
+
// @see https://en.wikipedia.org/wiki/Julian_day#Julian_date_calculation
|
512
|
+
return t0 + week * 7 + (seconds - leap_seconds()) / seconds_day;
|
513
|
+
}
|
514
|
+
float_t julian_date_2000() const {
|
515
|
+
static const std::tm tm_2000 = {0, 0, 12, 1, 0, 2000 - 1900};
|
516
|
+
static const float_t jd2000(GPS_Time(tm_2000, 13).julian_date());
|
517
|
+
return julian_date() - jd2000;
|
518
|
+
}
|
519
|
+
std::tm utc() const {return c_tm(leap_seconds());}
|
520
|
+
|
521
|
+
float_t greenwich_mean_sidereal_time_sec_ires1996(const float_t &delta_ut1 = float_t(0)) const {
|
522
|
+
float_t jd2000(julian_date_2000() + delta_ut1 / seconds_day);
|
523
|
+
float_t jd2000_day(float_t(0.5) + std::floor(jd2000 - 0.5)); // +/-0.5, +/-1.5, ...
|
524
|
+
|
525
|
+
// @see Chapter 2 of Orbits(978-3540785217) by Xu Guochang
|
526
|
+
// @see Chapter 5 of IERS Conventions (1996) https://www.iers.org/IERS/EN/Publications/TechnicalNotes/tn21.html
|
527
|
+
float_t jc(jd2000_day / 36525), // Julian century
|
528
|
+
jc2(std::pow(jc, 2)), jc3(std::pow(jc, 3));
|
529
|
+
float_t gmst0(24110.54841 // = 6h 41m 50.54841s
|
530
|
+
+ jc * 8640184.812866
|
531
|
+
+ jc2 * 0.093104
|
532
|
+
- jc3 * 6.2E-6);
|
533
|
+
// ratio of universal to sidereal time as given by Aoki et al. (1982)
|
534
|
+
float_t r(1.002737909350795 // 7.2921158553E-5 = 1.002737909350795 / 86400 * 2pi
|
535
|
+
+ jc * 5.9006E-11 // 4.3E-15 = 5.9E-11 / 86400 * 2pi
|
536
|
+
- jc2 * 5.9E-15); // in seconds
|
537
|
+
return gmst0 + r * (jd2000 - jd2000_day) * seconds_day;
|
538
|
+
}
|
539
|
+
|
540
|
+
/**
|
541
|
+
* ERA (Earth rotation rate) defined in Sec. 5.5.3 in IERS 2010(Technical Note No.36)
|
542
|
+
*/
|
543
|
+
float_t earth_rotation_angle(const float_t &delta_ut1 = float_t(0),
|
544
|
+
const float_t &scale_factor = float_t(M_PI * 2)) const {
|
545
|
+
float_t jd2000(julian_date_2000() + delta_ut1 / seconds_day);
|
546
|
+
return (jd2000 * 1.00273781191135448 + 0.7790572732640) * scale_factor; // Eq.(5.14)
|
547
|
+
}
|
548
|
+
|
549
|
+
float_t greenwich_mean_sidereal_time_sec_ires2010(const float_t &delta_ut1 = float_t(0)) const {
|
550
|
+
float_t era(earth_rotation_angle(delta_ut1, seconds_day));
|
551
|
+
|
552
|
+
float_t t(julian_date_2000() / 36525);
|
553
|
+
// @see Eq.(5.32) Chapter 5 of IERS Conventions (2010)
|
554
|
+
#define AS2SEC(as) (((float_t)seconds_day / (360 * 3600)) * (as))
|
555
|
+
return era
|
556
|
+
+ AS2SEC(0.014506)
|
557
|
+
+ t * AS2SEC(4612.156534)
|
558
|
+
+ std::pow(t, 2) * AS2SEC(1.3915817)
|
559
|
+
- std::pow(t, 3) * AS2SEC(0.00000044)
|
560
|
+
- std::pow(t, 4) * AS2SEC(0.000029956)
|
561
|
+
- std::pow(t, 5) * AS2SEC(0.0000000368);
|
562
|
+
#undef AS2SEC
|
563
|
+
}
|
564
|
+
|
565
|
+
/**
|
566
|
+
* Calculate Greenwich mean sidereal time (GMST) in seconds
|
567
|
+
* Internally, greenwich_mean_sidereal_time_sec_ired2010() is called.
|
568
|
+
* @param delta_ut1 time difference of UTC and UT1; UT1 = UTC + delta_UT1,
|
569
|
+
* @return GMST in seconds. 86400 seconds correspond to one rotation
|
570
|
+
* @see greenwich_mean_sidereal_time_sec_ires2010()
|
571
|
+
*/
|
572
|
+
float_t greenwich_mean_sidereal_time_sec(const float_t &delta_ut1 = float_t(0)) const {
|
573
|
+
return greenwich_mean_sidereal_time_sec_ires2010(delta_ut1);
|
574
|
+
}
|
487
575
|
};
|
488
576
|
|
489
577
|
template <class FloatT>
|
@@ -248,7 +248,15 @@ struct GPS_Solver_Base {
|
|
248
248
|
return impl_clock_error_dot(impl, t, pseudo_range);
|
249
249
|
}
|
250
250
|
static const satellite_t &unavailable() {
|
251
|
-
|
251
|
+
struct impl_t {
|
252
|
+
static xyz_t v3(const void *, const gps_time_t &, const float_t &){
|
253
|
+
return xyz_t(0, 0, 0);
|
254
|
+
}
|
255
|
+
static float_t v(const void *, const gps_time_t &, const float_t &){
|
256
|
+
return float_t(0);
|
257
|
+
}
|
258
|
+
};
|
259
|
+
static const satellite_t res = {NULL, impl_t::v3, impl_t::v3, impl_t::v, impl_t::v};
|
252
260
|
return res;
|
253
261
|
}
|
254
262
|
};
|
@@ -52,6 +52,7 @@
|
|
52
52
|
#include <cstring>
|
53
53
|
#include <limits>
|
54
54
|
|
55
|
+
#include "util/text_helper.h"
|
55
56
|
#include "GPS.h"
|
56
57
|
#include "SBAS.h"
|
57
58
|
#include "GLONASS.h"
|
@@ -61,56 +62,12 @@ class RINEX_Reader {
|
|
61
62
|
public:
|
62
63
|
typedef RINEX_Reader<U> self_t;
|
63
64
|
typedef std::map<std::string, std::vector<std::string> > header_t;
|
64
|
-
|
65
|
-
struct src_stream_t : public std::istream {
|
66
|
-
src_stream_t(std::istream &is) : std::istream(is.rdbuf()) {}
|
67
|
-
/**
|
68
|
-
* getline() for multi-platform (in addition to \n, \r\n and \r are supported)
|
69
|
-
*
|
70
|
-
* @see https://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf
|
71
|
-
* @see https://en.cppreference.com/w/cpp/io/basic_istream/getline
|
72
|
-
* TODO gcount() mismatch
|
73
|
-
*/
|
74
|
-
std::istream& getline(
|
75
|
-
typename std::istream::char_type* s,
|
76
|
-
std::streamsize n){
|
77
|
-
std::streamsize i(1), consumed(0);
|
78
|
-
typename std::istream::sentry se(*this, true);
|
79
|
-
if((bool)se){
|
80
|
-
std::streambuf* sb(this->rdbuf());
|
81
|
-
for(; i < n; ++i){
|
82
|
-
int c(sb->sbumpc());
|
83
|
-
if(c == std::streambuf::traits_type::eof()){
|
84
|
-
this->setstate(std::ios::eofbit);
|
85
|
-
break;
|
86
|
-
}
|
87
|
-
++consumed;
|
88
|
-
if(c == '\n'){
|
89
|
-
break;
|
90
|
-
}else if(c == '\r'){
|
91
|
-
if(sb->sgetc() == '\n'){
|
92
|
-
sb->sbumpc();
|
93
|
-
++consumed;
|
94
|
-
}
|
95
|
-
break;
|
96
|
-
}
|
97
|
-
*(s++) = (typename std::istream::char_type)c;
|
98
|
-
}
|
99
|
-
}
|
100
|
-
if(((i == 1) && (consumed == 0)) || (i == n)){
|
101
|
-
this->setstate(std::ios::failbit);
|
102
|
-
}else{
|
103
|
-
*s = '\0';
|
104
|
-
}
|
105
|
-
return *this;
|
106
|
-
}
|
107
|
-
};
|
108
65
|
|
109
66
|
protected:
|
110
67
|
header_t _header;
|
111
|
-
|
68
|
+
typename TextHelper<>::crlf_stream_t src;
|
112
69
|
bool _has_next;
|
113
|
-
|
70
|
+
|
114
71
|
public:
|
115
72
|
struct version_type_t {
|
116
73
|
int version;
|
@@ -186,57 +143,8 @@ class RINEX_Reader {
|
|
186
143
|
bool has_next() const {return _has_next;}
|
187
144
|
|
188
145
|
template <class T, bool is_integer = std::numeric_limits<T>::is_integer>
|
189
|
-
struct conv_t {
|
190
|
-
static bool
|
191
|
-
std::string &buf, const int &offset, const int &length, void *value, const int &opt = 0, const bool &str2val = true){
|
192
|
-
if(str2val){
|
193
|
-
std::stringstream ss(buf.substr(offset, length));
|
194
|
-
ss >> *(T *)value;
|
195
|
-
return (ss.rdstate() & std::ios_base::failbit) == 0;
|
196
|
-
}else{
|
197
|
-
std::stringstream ss;
|
198
|
-
ss << std::setfill(opt == 1 ? '0' : ' ') << std::right << std::setw(length) << *(T *)value;
|
199
|
-
buf.replace(offset, length, ss.str());
|
200
|
-
return true;
|
201
|
-
}
|
202
|
-
}
|
203
|
-
static bool f_pure(
|
204
|
-
std::string &buf, const int &offset, const int &length, void *value, const int &precision = 0, const bool &str2val = true){
|
205
|
-
if(str2val){
|
206
|
-
std::stringstream ss(buf.substr(offset, length));
|
207
|
-
ss >> *(T *)value;
|
208
|
-
return (ss.rdstate() & std::ios_base::failbit) == 0;
|
209
|
-
}else{
|
210
|
-
std::stringstream ss;
|
211
|
-
ss << std::setfill(' ') << std::right << std::setw(length)
|
212
|
-
<< std::setprecision(precision) << std::fixed
|
213
|
-
<< *(T *)value;
|
214
|
-
buf.replace(offset, length, ss.str());
|
215
|
-
return true;
|
216
|
-
}
|
217
|
-
}
|
218
|
-
static bool f(
|
219
|
-
std::string &buf, const int &offset, const int &length, void *value, const int &precision = 0, const bool &str2val = true){
|
220
|
-
bool res(f_pure(buf, offset, length, value, precision, str2val));
|
221
|
-
if((!str2val) && res){
|
222
|
-
if((*(T *)value) >= 0){
|
223
|
-
if((*(T *)value) < 1){
|
224
|
-
int i(length - precision - 2);
|
225
|
-
// 0.12345 => .12345
|
226
|
-
if(i >= 0){buf[i + offset] = ' ';}
|
227
|
-
}
|
228
|
-
}else{
|
229
|
-
if((*(T *)value) > -1){
|
230
|
-
int i(length - precision - 2);
|
231
|
-
// -0.12345 => -.12345
|
232
|
-
if(i >= 0){buf[i + offset] = '-';}
|
233
|
-
if(--i >= 0){buf[i + offset] = ' ';}
|
234
|
-
}
|
235
|
-
}
|
236
|
-
}
|
237
|
-
return res;
|
238
|
-
}
|
239
|
-
static bool e(
|
146
|
+
struct conv_t : public TextHelper<>::template format_t<T> {
|
147
|
+
static bool e_dot_head(
|
240
148
|
std::string &buf, const int &offset, const int &length, void *value, const int &precision = 0, const bool &str2val = true){
|
241
149
|
if(str2val){
|
242
150
|
std::string s(buf.substr(offset, length));
|
@@ -272,66 +180,25 @@ class RINEX_Reader {
|
|
272
180
|
}
|
273
181
|
}
|
274
182
|
};
|
183
|
+
|
275
184
|
template <class T>
|
276
|
-
struct conv_t<T, true> {
|
277
|
-
static bool
|
278
|
-
std::string &buf, const int &offset, const int &length, void *value, const int &opt = 0, const bool &str2val = true){
|
279
|
-
return conv_t<T, false>::d(buf, offset, length, value, opt, str2val);
|
280
|
-
}
|
281
|
-
static bool f_pure(
|
282
|
-
std::string &buf, const int &offset, const int &length, void *value, const int &precision = 0, const bool &str2val = true){
|
283
|
-
double v(*(T *)value);
|
284
|
-
bool res(
|
285
|
-
conv_t<double, false>::f_pure(buf, offset, length, &v, precision, str2val));
|
286
|
-
*(T *)value = static_cast<T>(v);
|
287
|
-
return res;
|
288
|
-
}
|
289
|
-
static bool f(
|
290
|
-
std::string &buf, const int &offset, const int &length, void *value, const int &precision = 0, const bool &str2val = true){
|
291
|
-
double v(*(T *)value);
|
292
|
-
bool res(
|
293
|
-
conv_t<double, false>::f(buf, offset, length, &v, precision, str2val));
|
294
|
-
*(T *)value = static_cast<T>(v);
|
295
|
-
return res;
|
296
|
-
}
|
297
|
-
static bool e(
|
185
|
+
struct conv_t<T, true> : public TextHelper<>::template format_t<T> {
|
186
|
+
static bool e_dot_head(
|
298
187
|
std::string &buf, const int &offset, const int &length, void *value, const int &precision = 0, const bool &str2val = true){
|
299
188
|
double v(*(T *)value);
|
300
189
|
bool res(
|
301
|
-
conv_t<double, false>::
|
190
|
+
conv_t<double, false>::e_dot_head(buf, offset, length, &v, precision, str2val));
|
302
191
|
*(T *)value = static_cast<T>(v);
|
303
192
|
return res;
|
304
193
|
}
|
305
194
|
};
|
306
195
|
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
const int &opt, const bool &str2val);
|
311
|
-
int offset;
|
312
|
-
int length;
|
313
|
-
int value_offset;
|
314
|
-
int opt;
|
315
|
-
};
|
316
|
-
|
317
|
-
/**
|
318
|
-
* @param recovery if conversion fails, then this functor is invoked.
|
319
|
-
* If recovery is successfully performed, this functor should return true.
|
320
|
-
* The return value of this function reflects it.
|
321
|
-
* @return (bool) if all conversion are successfully performed, true is returned; otherwise false.
|
322
|
-
*/
|
323
|
-
static bool convert(
|
196
|
+
typedef typename TextHelper<>::convert_item_t convert_item_t;
|
197
|
+
|
198
|
+
static inline bool convert(
|
324
199
|
const convert_item_t *items, const int &size, const std::string &buf, void *values,
|
325
200
|
bool (*recovery)(const int &, const std::string &, void *) = NULL){
|
326
|
-
|
327
|
-
bool res(true);
|
328
|
-
for(int i(0); i < size; ++i){
|
329
|
-
if((*items[i].func)(
|
330
|
-
const_cast<std::string &>(buf), items[i].offset, items[i].length, (char *)values + items[i].value_offset,
|
331
|
-
items[i].opt, true)){continue;}
|
332
|
-
res &= (recovery ? (*recovery)(i, buf, values) : false);
|
333
|
-
}
|
334
|
-
return res;
|
201
|
+
return TextHelper<>::str2val(items, size, buf, values, recovery);
|
335
202
|
}
|
336
203
|
template <int N>
|
337
204
|
static inline bool convert(
|
@@ -1426,10 +1293,10 @@ class RINEX_OBS_Reader : public RINEX_Reader<> {
|
|
1426
1293
|
{super_t::template conv_t<value_type>::d, offset, length, \
|
1427
1294
|
offsetof(container_type, container_member), 1}
|
1428
1295
|
#define GEN_F2(offset, length, precision, container_type, container_member, value_type) \
|
1429
|
-
{super_t::template conv_t<value_type>::
|
1296
|
+
{super_t::template conv_t<value_type>::f_dot_head, offset, length, \
|
1430
1297
|
offsetof(container_type, container_member), precision}
|
1431
1298
|
#define GEN_E2(offset, length, precision, container_type, container_member, value_type) \
|
1432
|
-
{super_t::template conv_t<value_type>::
|
1299
|
+
{super_t::template conv_t<value_type>::e_dot_head, offset, length, \
|
1433
1300
|
offsetof(container_type, container_member), precision}
|
1434
1301
|
#define GEN_F(offset, length, precision, container_type, container_member) \
|
1435
1302
|
GEN_F2(offset, length, precision, container_type, container_member, FloatT)
|
@@ -1958,14 +1825,14 @@ class RINEX_Writer {
|
|
1958
1825
|
static std::string RINEX_Float(
|
1959
1826
|
const FloatT &value, const int width = 19, const int precision = 12){
|
1960
1827
|
std::string s;
|
1961
|
-
RINEX_Reader<U>::template conv_t<FloatT>::
|
1828
|
+
RINEX_Reader<U>::template conv_t<FloatT>::f_dot_head(s, 0, width, &const_cast<FloatT &>(value), precision, false);
|
1962
1829
|
return s;
|
1963
1830
|
}
|
1964
1831
|
template <class FloatT>
|
1965
1832
|
static std::string RINEX_FloatD(
|
1966
1833
|
const FloatT &value, const int width = 19, const int precision = 12){
|
1967
1834
|
std::string s;
|
1968
|
-
RINEX_Reader<U>::template conv_t<FloatT>::
|
1835
|
+
RINEX_Reader<U>::template conv_t<FloatT>::e_dot_head(s, 0, width, &const_cast<FloatT &>(value), precision, false);
|
1969
1836
|
return s;
|
1970
1837
|
}
|
1971
1838
|
template <class T>
|
@@ -1975,20 +1842,10 @@ class RINEX_Writer {
|
|
1975
1842
|
return s;
|
1976
1843
|
}
|
1977
1844
|
|
1978
|
-
/**
|
1979
|
-
* @return If all conversion are successfully performed, then true; otherwise false;
|
1980
|
-
*/
|
1981
1845
|
static bool convert(
|
1982
1846
|
const typename RINEX_Reader<U>::convert_item_t *items, const int &size,
|
1983
1847
|
std::string &buf, const void *values){
|
1984
|
-
|
1985
|
-
bool res(true);
|
1986
|
-
for(int i(0); i < size; ++i){
|
1987
|
-
res &= (*items[i].func)(
|
1988
|
-
buf, items[i].offset, items[i].length, (char *)(const_cast<void *>(values)) + items[i].value_offset,
|
1989
|
-
items[i].opt, false);
|
1990
|
-
}
|
1991
|
-
return res;
|
1848
|
+
return TextHelper<>::val2str(items, size, buf, values);
|
1992
1849
|
}
|
1993
1850
|
template <int N>
|
1994
1851
|
static inline bool convert(
|