gps_pvt 0.5.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +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(
|