gps_pvt 0.9.0 → 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/exe/gps2ubx +35 -20
- data/exe/gps_get +15 -24
- data/exe/gps_pvt +10 -14
- data/ext/gps_pvt/GPS/GPS_wrap.cxx +74 -74
- data/ext/ninja-scan-light/tool/swig/GPS.i +5 -5
- data/lib/gps_pvt/receiver/rtcm3.rb +132 -35
- data/lib/gps_pvt/receiver.rb +1 -1
- data/lib/gps_pvt/rtcm3.rb +219 -32
- data/lib/gps_pvt/util.rb +20 -10
- data/lib/gps_pvt/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 27cf7edda7d1df217cef7291fffdd3ab5837c8c09854dc8bb169b2bbe2880339
|
4
|
+
data.tar.gz: 2d818aa2d59114445a03417a5382fbc19994bca67cd62c48c9d5a86cbcb05dac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f7f9a5ae7a47195eebf77d8c403cc6ec96596a9389b388aae1f8ec3f0d97c8086505e4c851c09db5aa2469a97b24325d8a644456fc602d931aa234dfaf7f4739
|
7
|
+
data.tar.gz: 191293262a0b1990292416be5c53f65699bd8d8e152534e3ca4b5dd155be665bc73fd6de94a72bcb18fd8f4e24185a612e8a1a6fdbf7899c65cb879923f59bc7
|
data/README.md
CHANGED
@@ -42,7 +42,7 @@ The format of file is automatically determined with its extension, such as .ubx
|
|
42
42
|
| --sp3=file_or_URI | [Standard Product 3 Orbit Format](https://files.igs.org/pub/data/format/sp3c.txt) (supported gps_pvt version >= 0.6.0) |
|
43
43
|
| --antex=file_or_URI | [Antenna Exchange Format](https://igs.org/wg/antenna#files) (supported gps_pvt version >= 0.6.0) |
|
44
44
|
| --rinex_clk=file_or_URI | [RINEX clock](https://files.igs.org/pub/data/format/rinex_clock304.txt) file (supported gps_pvt version >= 0.7.0) |
|
45
|
-
| <a name=opt_rtcm3>--rtcm3=file_or_URI</a> | [RTCM 10403.x](https://rtcm.myshopify.com/collections/differential-global-navigation-satellite-dgnss-standards)
|
45
|
+
| <a name=opt_rtcm3>--rtcm3=file_or_URI</a> | [RTCM 10403.x](https://rtcm.myshopify.com/collections/differential-global-navigation-satellite-dgnss-standards). (supported gps_pvt version >= 0.9.0) The latest version uses message type Observation(GPS: 1002, 1004; GLONASS: 1010, 1012), Epehemris(GPS: 1019; GLOANSS: 1020; SBAS: 1043; QZSS: 1044), MSM(GPS: 1074..1077; GLONASS: 1084..1087; SBAS: 1104..1107; QZSS: 1114..1117) |
|
46
46
|
|
47
47
|
Since version 0.2.0, SBAS and QZSS are supported in addition to GPS. Since version 0.4.0, GLONASS is also available. QZSS ranging is activated in default, however, SBAS is just utilized for ionospheric correction. GLONASS is also turned off by default. If you want to activate SBAS or GLONASS ranging, "--with=(system or PRN)" options are used with gps_pvt executable like
|
48
48
|
|
data/exe/gps2ubx
CHANGED
@@ -31,7 +31,7 @@ misc_options = {
|
|
31
31
|
files = ARGV.collect{|arg|
|
32
32
|
next [arg, nil] unless arg =~ /^--([^=]+)=?/
|
33
33
|
k, v = [$1.downcase.to_sym, $']
|
34
|
-
next [v, k] if [:rinex_nav, :rinex_obs].include?(k) # file type
|
34
|
+
next [v, k] if [:rinex_nav, :rinex_obs, :ubx, :rtcm3].include?(k) # file type
|
35
35
|
options << [$1.to_sym, $']
|
36
36
|
nil
|
37
37
|
}.compact
|
@@ -43,14 +43,10 @@ files.collect!{|fname, ftype|
|
|
43
43
|
when /\.\d{2}o(?:\.gz)?$/; :rinex_obs
|
44
44
|
when /\.ubx$/; :ubx
|
45
45
|
end
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
next uri
|
51
|
-
end
|
52
|
-
raise "File not found: #{fname}"
|
53
|
-
}.call
|
46
|
+
if (!(uri = URI::parse(fname)).instance_of?(URI::Generic) rescue false) then
|
47
|
+
ftype ||= uri.read_format if uri.instance_of?(URI::Ntrip)
|
48
|
+
fname = uri
|
49
|
+
end
|
54
50
|
raise "Format cannot be guessed, use --(format, ex. rinex_obs)=#{fname}" unless ftype
|
55
51
|
[fname, ftype]
|
56
52
|
}
|
@@ -70,7 +66,7 @@ options.reject!{|opt|
|
|
70
66
|
|
71
67
|
rcv = GPS_PVT::Receiver::new(options)
|
72
68
|
|
73
|
-
obs =
|
69
|
+
obs = Queue::new
|
74
70
|
rcv.define_singleton_method(:run){|meas, t_meas, *args|
|
75
71
|
obs << [t_meas, meas]
|
76
72
|
}
|
@@ -98,15 +94,23 @@ files.each{|fname, ftype|
|
|
98
94
|
}
|
99
95
|
|
100
96
|
# other files
|
101
|
-
files.
|
102
|
-
case ftype
|
103
|
-
when :ubx; rcv.parse_ubx(fname){}
|
104
|
-
when :rinex_obs; rcv.parse_rinex_obs(fname){}
|
105
|
-
when :rtcm3; rcv.parse_rtcm3(fname){}
|
97
|
+
threads = files.collect{|fname, ftype|
|
98
|
+
task = case ftype
|
99
|
+
when :ubx; proc{rcv.parse_ubx(fname){}}
|
100
|
+
when :rinex_obs; proc{rcv.parse_rinex_obs(fname){}}
|
101
|
+
when :rtcm3; proc{rcv.parse_rtcm3(fname){}}
|
106
102
|
end
|
107
|
-
|
103
|
+
case fname
|
104
|
+
when URI::Ntrip; Thread::new(&task)
|
105
|
+
else; task.call; nil
|
106
|
+
end
|
107
|
+
}.compact
|
108
108
|
|
109
|
-
obs
|
109
|
+
obs = proc{
|
110
|
+
tmp = []
|
111
|
+
tmp << obs.pop until obs.empty?
|
112
|
+
tmp
|
113
|
+
}.call.sort!{|a, b| b[0] <=> a[0]} if threads.empty? # Sort by measurement time
|
110
114
|
|
111
115
|
# Time packet for solution of leap seconds
|
112
116
|
gen_gpstime = proc{
|
@@ -368,7 +372,18 @@ gen_list << gen_gpstime unless misc_options[:ubx_rawx]
|
|
368
372
|
gen_list << (misc_options[:ubx_rawx] ? gen_sfrbx : gen_sfrb) if misc_options[:broadcast_data]
|
369
373
|
gen_list << (misc_options[:ubx_rawx] ? gen_rawx : gen_raw)
|
370
374
|
STDOUT.binmode
|
371
|
-
|
372
|
-
|
373
|
-
|
375
|
+
|
376
|
+
task_dump = proc{
|
377
|
+
until obs.empty? do
|
378
|
+
t_meas, meas = obs.pop
|
379
|
+
meas2 = meas.to_hash
|
380
|
+
gen_list.each{|gen| print gen.call(t_meas, meas2)}
|
381
|
+
end
|
374
382
|
}
|
383
|
+
if threads.empty? then
|
384
|
+
task_dump.call
|
385
|
+
else
|
386
|
+
(threads << Thread::new{loop{
|
387
|
+
task_dump.call
|
388
|
+
}}).each{|th| th.join}
|
389
|
+
end
|
data/exe/gps_get
CHANGED
@@ -20,30 +20,21 @@ files = ARGV.collect{|arg|
|
|
20
20
|
nil
|
21
21
|
}.compact
|
22
22
|
|
23
|
-
spec2io = proc{
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
next STDIN if spec == '-'
|
39
|
-
next open(GPS_PVT::Util::get_txt(spec), 'r') if File::exist?(spec)
|
40
|
-
raise "File not found: #{spec}"
|
41
|
-
else
|
42
|
-
next STDOUT if spec == '-'
|
43
|
-
open(spec, 'a+')
|
44
|
-
end
|
45
|
-
}
|
46
|
-
}.call
|
23
|
+
spec2io = proc{|spec, mode_r|
|
24
|
+
mode_r = ((nil == mode_r) || mode_r)
|
25
|
+
is_stream = false
|
26
|
+
if (!(uri = URI::parse(spec)).instance_of?(URI::Generic) rescue false) then
|
27
|
+
spec = uri
|
28
|
+
is_stream = true if uri.kind_of?(URI::Ntrip)
|
29
|
+
else
|
30
|
+
is_stream = GPS_PVT::Util::special_stream?(spec)
|
31
|
+
end
|
32
|
+
if is_stream || (!mode_r) then
|
33
|
+
GPS_PVT::Util::open(spec, mode_r ? 'r' : 'a+')
|
34
|
+
else
|
35
|
+
open(GPS_PVT::Util::get_txt(spec), 'r')
|
36
|
+
end
|
37
|
+
}
|
47
38
|
|
48
39
|
STDIN.binmode
|
49
40
|
STDOUT.binmode
|
data/exe/gps_pvt
CHANGED
@@ -77,15 +77,10 @@ files.collect!{|fname, ftype|
|
|
77
77
|
when /\.atx(?:\.Z)?$/; :antex
|
78
78
|
when /\.clk$/; :rinex_clk
|
79
79
|
end
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
ftype ||= uri.read_format if uri.instance_of?(URI::Ntrip)
|
85
|
-
next uri
|
86
|
-
end
|
87
|
-
raise "File not found: #{fname}"
|
88
|
-
}.call
|
80
|
+
if (!(uri = URI::parse(fname)).instance_of?(URI::Generic) rescue false) then
|
81
|
+
ftype ||= uri.read_format if uri.instance_of?(URI::Ntrip)
|
82
|
+
fname = uri
|
83
|
+
end
|
89
84
|
raise "Format cannot be guessed, use --(format, ex. rinex_nav)=#{fname}" unless ftype
|
90
85
|
[fname, ftype]
|
91
86
|
}
|
@@ -137,10 +132,11 @@ files.each{|fname, ftype|
|
|
137
132
|
}
|
138
133
|
|
139
134
|
# other files
|
140
|
-
files.
|
135
|
+
files.collect{|fname, ftype|
|
141
136
|
case ftype
|
142
|
-
when :ubx; rcv.parse_ubx(fname)
|
143
|
-
when :rinex_obs; rcv.parse_rinex_obs(fname)
|
144
|
-
when :rtcm3; rcv.parse_rtcm3(fname)
|
137
|
+
when :ubx; Thread::new{rcv.parse_ubx(fname)}
|
138
|
+
when :rinex_obs; Thread::new{rcv.parse_rinex_obs(fname)}
|
139
|
+
when :rtcm3; Thread::new{rcv.parse_rtcm3(fname)}
|
140
|
+
else; nil
|
145
141
|
end
|
146
|
-
}
|
142
|
+
}.compact.each{|th| th.join}
|
@@ -2406,6 +2406,10 @@ struct GLONASS_Ephemeris
|
|
2406
2406
|
bool is_consistent() const {
|
2407
2407
|
return has_string == 0x1F;
|
2408
2408
|
}
|
2409
|
+
bool is_in_range(const GPS_Time<FloatT> &t) const {
|
2410
|
+
// "invalidate()" is used to make raw and converted data inconsistent.
|
2411
|
+
return eph_t::is_valid(t);
|
2412
|
+
}
|
2409
2413
|
bool is_valid(const GPS_Time<FloatT> &t) const {
|
2410
2414
|
return is_consistent() && eph_t::is_valid(t);
|
2411
2415
|
}
|
@@ -4375,10 +4379,10 @@ SWIGINTERN double SBAS_Ephemeris_Sl_double_Sg__set_t_0(SBAS_Ephemeris< double >
|
|
4375
4379
|
SWIGINTERN double const &SBAS_Ephemeris_Sl_double_Sg__get_t_0(SBAS_Ephemeris< double > const *self){
|
4376
4380
|
return self->t_0;
|
4377
4381
|
}
|
4378
|
-
SWIGINTERN
|
4382
|
+
SWIGINTERN double SBAS_Ephemeris_Sl_double_Sg__set_URA(SBAS_Ephemeris< double > *self,double const &v){
|
4379
4383
|
return self->URA= v;
|
4380
4384
|
}
|
4381
|
-
SWIGINTERN
|
4385
|
+
SWIGINTERN double const &SBAS_Ephemeris_Sl_double_Sg__get_URA(SBAS_Ephemeris< double > const *self){
|
4382
4386
|
return self->URA;
|
4383
4387
|
}
|
4384
4388
|
SWIGINTERN double SBAS_Ephemeris_Sl_double_Sg__set_x(SBAS_Ephemeris< double > *self,double const &v){
|
@@ -4750,10 +4754,6 @@ SWIGINTERN GPS_Ephemeris< double >::constellation_res_t GLONASS_Ephemeris_Sl_dou
|
|
4750
4754
|
pv.position, pv.velocity, self->clock_error(t_tx), self->clock_error_dot()};
|
4751
4755
|
return res;
|
4752
4756
|
}
|
4753
|
-
SWIGINTERN bool GLONASS_Ephemeris_Sl_double_Sg__is_in_range(GLONASS_Ephemeris< double > const *self,GPS_Time< double > const &t){
|
4754
|
-
// "invalidate()" is used to make raw and converted data inconsistent.
|
4755
|
-
return self->is_valid(t);
|
4756
|
-
}
|
4757
4757
|
SWIGINTERN void RINEX_Observation_Sl_double_Sg__read(char const *fname){
|
4758
4758
|
std::fstream fin(fname, std::ios::in | std::ios::binary);
|
4759
4759
|
struct reader_t : public RINEX_OBS_Reader<double> {
|
@@ -18732,7 +18732,7 @@ fail:
|
|
18732
18732
|
Document-method: GPS_PVT::GPS::Ephemeris_SBAS.URA=
|
18733
18733
|
|
18734
18734
|
call-seq:
|
18735
|
-
URA=(
|
18735
|
+
URA=(double const & v) -> double
|
18736
18736
|
|
18737
18737
|
An instance method.
|
18738
18738
|
|
@@ -18740,13 +18740,13 @@ An instance method.
|
|
18740
18740
|
SWIGINTERN VALUE
|
18741
18741
|
_wrap_Ephemeris_SBAS_URAe___(int argc, VALUE *argv, VALUE self) {
|
18742
18742
|
SBAS_Ephemeris< double > *arg1 = (SBAS_Ephemeris< double > *) 0 ;
|
18743
|
-
|
18743
|
+
double *arg2 = 0 ;
|
18744
18744
|
void *argp1 = 0 ;
|
18745
18745
|
int res1 = 0 ;
|
18746
|
-
|
18747
|
-
|
18746
|
+
double temp2 ;
|
18747
|
+
double val2 ;
|
18748
18748
|
int ecode2 = 0 ;
|
18749
|
-
|
18749
|
+
double result;
|
18750
18750
|
VALUE vresult = Qnil;
|
18751
18751
|
|
18752
18752
|
if ((argc < 1) || (argc > 1)) {
|
@@ -18757,15 +18757,15 @@ _wrap_Ephemeris_SBAS_URAe___(int argc, VALUE *argv, VALUE self) {
|
|
18757
18757
|
SWIG_exception_fail(SWIG_ArgError(res1), Ruby_Format_TypeError( "", "SBAS_Ephemeris< double > *","set_URA", 1, self ));
|
18758
18758
|
}
|
18759
18759
|
arg1 = reinterpret_cast< SBAS_Ephemeris< double > * >(argp1);
|
18760
|
-
ecode2 =
|
18760
|
+
ecode2 = SWIG_AsVal_double(argv[0], &val2);
|
18761
18761
|
if (!SWIG_IsOK(ecode2)) {
|
18762
|
-
SWIG_exception_fail(SWIG_ArgError(ecode2), Ruby_Format_TypeError( "", "
|
18762
|
+
SWIG_exception_fail(SWIG_ArgError(ecode2), Ruby_Format_TypeError( "", "double","set_URA", 2, argv[0] ));
|
18763
18763
|
}
|
18764
|
-
temp2 = static_cast<
|
18764
|
+
temp2 = static_cast< double >(val2);
|
18765
18765
|
arg2 = &temp2;
|
18766
18766
|
{
|
18767
18767
|
try {
|
18768
|
-
result = (
|
18768
|
+
result = (double)SBAS_Ephemeris_Sl_double_Sg__set_URA(arg1,(double const &)*arg2);
|
18769
18769
|
} catch (const native_exception &e) {
|
18770
18770
|
e.regenerate();
|
18771
18771
|
SWIG_fail;
|
@@ -18773,7 +18773,7 @@ _wrap_Ephemeris_SBAS_URAe___(int argc, VALUE *argv, VALUE self) {
|
|
18773
18773
|
SWIG_exception_fail(SWIG_RuntimeError, e.what());
|
18774
18774
|
}
|
18775
18775
|
}
|
18776
|
-
vresult =
|
18776
|
+
vresult = SWIG_From_double(static_cast< double >(result));
|
18777
18777
|
return vresult;
|
18778
18778
|
fail:
|
18779
18779
|
return Qnil;
|
@@ -18784,7 +18784,7 @@ fail:
|
|
18784
18784
|
Document-method: GPS_PVT::GPS::Ephemeris_SBAS.URA
|
18785
18785
|
|
18786
18786
|
call-seq:
|
18787
|
-
URA ->
|
18787
|
+
URA -> double const &
|
18788
18788
|
|
18789
18789
|
An instance method.
|
18790
18790
|
|
@@ -18794,7 +18794,7 @@ _wrap_Ephemeris_SBAS_URA(int argc, VALUE *argv, VALUE self) {
|
|
18794
18794
|
SBAS_Ephemeris< double > *arg1 = (SBAS_Ephemeris< double > *) 0 ;
|
18795
18795
|
void *argp1 = 0 ;
|
18796
18796
|
int res1 = 0 ;
|
18797
|
-
|
18797
|
+
double *result = 0 ;
|
18798
18798
|
VALUE vresult = Qnil;
|
18799
18799
|
|
18800
18800
|
if ((argc < 0) || (argc > 0)) {
|
@@ -18807,7 +18807,7 @@ _wrap_Ephemeris_SBAS_URA(int argc, VALUE *argv, VALUE self) {
|
|
18807
18807
|
arg1 = reinterpret_cast< SBAS_Ephemeris< double > * >(argp1);
|
18808
18808
|
{
|
18809
18809
|
try {
|
18810
|
-
result = (
|
18810
|
+
result = (double *) &SBAS_Ephemeris_Sl_double_Sg__get_URA((SBAS_Ephemeris< double > const *)arg1);
|
18811
18811
|
} catch (const native_exception &e) {
|
18812
18812
|
e.regenerate();
|
18813
18813
|
SWIG_fail;
|
@@ -18815,7 +18815,7 @@ _wrap_Ephemeris_SBAS_URA(int argc, VALUE *argv, VALUE self) {
|
|
18815
18815
|
SWIG_exception_fail(SWIG_RuntimeError, e.what());
|
18816
18816
|
}
|
18817
18817
|
}
|
18818
|
-
vresult =
|
18818
|
+
vresult = SWIG_From_double(static_cast< double >(*result));
|
18819
18819
|
return vresult;
|
18820
18820
|
fail:
|
18821
18821
|
return Qnil;
|
@@ -22603,6 +22603,59 @@ fail:
|
|
22603
22603
|
}
|
22604
22604
|
|
22605
22605
|
|
22606
|
+
/*
|
22607
|
+
Document-method: GPS_PVT::GPS::Ephemeris_GLONASS.in_range?
|
22608
|
+
|
22609
|
+
call-seq:
|
22610
|
+
in_range?(Time t) -> bool
|
22611
|
+
|
22612
|
+
An instance method.
|
22613
|
+
|
22614
|
+
*/
|
22615
|
+
SWIGINTERN VALUE
|
22616
|
+
_wrap_Ephemeris_GLONASS_in_rangeq___(int argc, VALUE *argv, VALUE self) {
|
22617
|
+
GLONASS_Ephemeris< double > *arg1 = (GLONASS_Ephemeris< double > *) 0 ;
|
22618
|
+
GPS_Time< double > *arg2 = 0 ;
|
22619
|
+
void *argp1 = 0 ;
|
22620
|
+
int res1 = 0 ;
|
22621
|
+
void *argp2 ;
|
22622
|
+
int res2 = 0 ;
|
22623
|
+
bool result;
|
22624
|
+
VALUE vresult = Qnil;
|
22625
|
+
|
22626
|
+
if ((argc < 1) || (argc > 1)) {
|
22627
|
+
rb_raise(rb_eArgError, "wrong # of arguments(%d for 1)",argc); SWIG_fail;
|
22628
|
+
}
|
22629
|
+
res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_GLONASS_EphemerisT_double_t, 0 | 0 );
|
22630
|
+
if (!SWIG_IsOK(res1)) {
|
22631
|
+
SWIG_exception_fail(SWIG_ArgError(res1), Ruby_Format_TypeError( "", "GLONASS_Ephemeris< double > const *","is_in_range", 1, self ));
|
22632
|
+
}
|
22633
|
+
arg1 = reinterpret_cast< GLONASS_Ephemeris< double > * >(argp1);
|
22634
|
+
res2 = SWIG_ConvertPtr(argv[0], &argp2, SWIGTYPE_p_GPS_TimeT_double_t, 0 );
|
22635
|
+
if (!SWIG_IsOK(res2)) {
|
22636
|
+
SWIG_exception_fail(SWIG_ArgError(res2), Ruby_Format_TypeError( "", "GPS_Time< double > const &","is_in_range", 2, argv[0] ));
|
22637
|
+
}
|
22638
|
+
if (!argp2) {
|
22639
|
+
SWIG_exception_fail(SWIG_ValueError, Ruby_Format_TypeError("invalid null reference ", "GPS_Time< double > const &","is_in_range", 2, argv[0]));
|
22640
|
+
}
|
22641
|
+
arg2 = reinterpret_cast< GPS_Time< double > * >(argp2);
|
22642
|
+
{
|
22643
|
+
try {
|
22644
|
+
result = (bool)((GLONASS_Ephemeris< double > const *)arg1)->is_in_range((GPS_Time< double > const &)*arg2);
|
22645
|
+
} catch (const native_exception &e) {
|
22646
|
+
e.regenerate();
|
22647
|
+
SWIG_fail;
|
22648
|
+
} catch (const std::exception& e) {
|
22649
|
+
SWIG_exception_fail(SWIG_RuntimeError, e.what());
|
22650
|
+
}
|
22651
|
+
}
|
22652
|
+
vresult = SWIG_From_bool(static_cast< bool >(result));
|
22653
|
+
return vresult;
|
22654
|
+
fail:
|
22655
|
+
return Qnil;
|
22656
|
+
}
|
22657
|
+
|
22658
|
+
|
22606
22659
|
/*
|
22607
22660
|
Document-method: GPS_PVT::GPS::Ephemeris_GLONASS.valid?
|
22608
22661
|
|
@@ -26483,59 +26536,6 @@ fail:
|
|
26483
26536
|
}
|
26484
26537
|
|
26485
26538
|
|
26486
|
-
/*
|
26487
|
-
Document-method: GPS_PVT::GPS::Ephemeris_GLONASS.in_range?
|
26488
|
-
|
26489
|
-
call-seq:
|
26490
|
-
in_range?(Time t) -> bool
|
26491
|
-
|
26492
|
-
An instance method.
|
26493
|
-
|
26494
|
-
*/
|
26495
|
-
SWIGINTERN VALUE
|
26496
|
-
_wrap_Ephemeris_GLONASS_in_rangeq___(int argc, VALUE *argv, VALUE self) {
|
26497
|
-
GLONASS_Ephemeris< double > *arg1 = (GLONASS_Ephemeris< double > *) 0 ;
|
26498
|
-
GPS_Time< double > *arg2 = 0 ;
|
26499
|
-
void *argp1 = 0 ;
|
26500
|
-
int res1 = 0 ;
|
26501
|
-
void *argp2 ;
|
26502
|
-
int res2 = 0 ;
|
26503
|
-
bool result;
|
26504
|
-
VALUE vresult = Qnil;
|
26505
|
-
|
26506
|
-
if ((argc < 1) || (argc > 1)) {
|
26507
|
-
rb_raise(rb_eArgError, "wrong # of arguments(%d for 1)",argc); SWIG_fail;
|
26508
|
-
}
|
26509
|
-
res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_GLONASS_EphemerisT_double_t, 0 | 0 );
|
26510
|
-
if (!SWIG_IsOK(res1)) {
|
26511
|
-
SWIG_exception_fail(SWIG_ArgError(res1), Ruby_Format_TypeError( "", "GLONASS_Ephemeris< double > const *","is_in_range", 1, self ));
|
26512
|
-
}
|
26513
|
-
arg1 = reinterpret_cast< GLONASS_Ephemeris< double > * >(argp1);
|
26514
|
-
res2 = SWIG_ConvertPtr(argv[0], &argp2, SWIGTYPE_p_GPS_TimeT_double_t, 0 );
|
26515
|
-
if (!SWIG_IsOK(res2)) {
|
26516
|
-
SWIG_exception_fail(SWIG_ArgError(res2), Ruby_Format_TypeError( "", "GPS_Time< double > const &","is_in_range", 2, argv[0] ));
|
26517
|
-
}
|
26518
|
-
if (!argp2) {
|
26519
|
-
SWIG_exception_fail(SWIG_ValueError, Ruby_Format_TypeError("invalid null reference ", "GPS_Time< double > const &","is_in_range", 2, argv[0]));
|
26520
|
-
}
|
26521
|
-
arg2 = reinterpret_cast< GPS_Time< double > * >(argp2);
|
26522
|
-
{
|
26523
|
-
try {
|
26524
|
-
result = (bool)GLONASS_Ephemeris_Sl_double_Sg__is_in_range((GLONASS_Ephemeris< double > const *)arg1,(GPS_Time< double > const &)*arg2);
|
26525
|
-
} catch (const native_exception &e) {
|
26526
|
-
e.regenerate();
|
26527
|
-
SWIG_fail;
|
26528
|
-
} catch (const std::exception& e) {
|
26529
|
-
SWIG_exception_fail(SWIG_RuntimeError, e.what());
|
26530
|
-
}
|
26531
|
-
}
|
26532
|
-
vresult = SWIG_From_bool(static_cast< bool >(result));
|
26533
|
-
return vresult;
|
26534
|
-
fail:
|
26535
|
-
return Qnil;
|
26536
|
-
}
|
26537
|
-
|
26538
|
-
|
26539
26539
|
SWIGINTERN void
|
26540
26540
|
free_GLONASS_Ephemeris_Sl_double_Sg_(void *self) {
|
26541
26541
|
GLONASS_Ephemeris< double > *arg1 = (GLONASS_Ephemeris< double > *)self;
|
@@ -28978,6 +28978,7 @@ SWIGEXPORT void Init_GPS(void) {
|
|
28978
28978
|
rb_define_method(SwigClassEphemeris_GLONASS.klass, "raw", VALUEFUNC(_wrap_Ephemeris_GLONASS_raw_get), -1);
|
28979
28979
|
rb_define_method(SwigClassEphemeris_GLONASS.klass, "invalidate", VALUEFUNC(_wrap_Ephemeris_GLONASS_invalidate), -1);
|
28980
28980
|
rb_define_method(SwigClassEphemeris_GLONASS.klass, "consistent?", VALUEFUNC(_wrap_Ephemeris_GLONASS_consistentq___), -1);
|
28981
|
+
rb_define_method(SwigClassEphemeris_GLONASS.klass, "in_range?", VALUEFUNC(_wrap_Ephemeris_GLONASS_in_rangeq___), -1);
|
28981
28982
|
rb_define_method(SwigClassEphemeris_GLONASS.klass, "valid?", VALUEFUNC(_wrap_Ephemeris_GLONASS_validq___), -1);
|
28982
28983
|
rb_define_method(SwigClassEphemeris_GLONASS.klass, "rehash", VALUEFUNC(_wrap_Ephemeris_GLONASS_rehash), -1);
|
28983
28984
|
rb_define_method(SwigClassEphemeris_GLONASS.klass, "svid=", VALUEFUNC(_wrap_Ephemeris_GLONASS_svide___), -1);
|
@@ -29047,7 +29048,6 @@ SWIGEXPORT void Init_GPS(void) {
|
|
29047
29048
|
rb_define_method(SwigClassEphemeris_GLONASS.klass, "parse", VALUEFUNC(_wrap_Ephemeris_GLONASS_parse), -1);
|
29048
29049
|
rb_define_method(SwigClassEphemeris_GLONASS.klass, "dump", VALUEFUNC(_wrap_Ephemeris_GLONASS_dump), -1);
|
29049
29050
|
rb_define_method(SwigClassEphemeris_GLONASS.klass, "constellation", VALUEFUNC(_wrap_Ephemeris_GLONASS_constellation), -1);
|
29050
|
-
rb_define_method(SwigClassEphemeris_GLONASS.klass, "in_range?", VALUEFUNC(_wrap_Ephemeris_GLONASS_in_rangeq___), -1);
|
29051
29051
|
SwigClassEphemeris_GLONASS.mark = 0;
|
29052
29052
|
SwigClassEphemeris_GLONASS.destroy = (void (*)(void *)) free_GLONASS_Ephemeris_Sl_double_Sg_;
|
29053
29053
|
SwigClassEphemeris_GLONASS.trackObjects = 0;
|
@@ -571,7 +571,7 @@ struct SBAS_Ephemeris : public SBAS_SpaceNode<FloatT>::SatelliteProperties::Ephe
|
|
571
571
|
|
572
572
|
MAKE_ACCESSOR(WN, unsigned int);
|
573
573
|
MAKE_ACCESSOR(t_0, FloatT);
|
574
|
-
MAKE_ACCESSOR(URA,
|
574
|
+
MAKE_ACCESSOR(URA, FloatT);
|
575
575
|
MAKE_ACCESSOR( x, FloatT); MAKE_ACCESSOR( y, FloatT); MAKE_ACCESSOR( z, FloatT);
|
576
576
|
MAKE_ACCESSOR( dx, FloatT); MAKE_ACCESSOR( dy, FloatT); MAKE_ACCESSOR( dz, FloatT);
|
577
577
|
MAKE_ACCESSOR(ddx, FloatT); MAKE_ACCESSOR(ddy, FloatT); MAKE_ACCESSOR(ddz, FloatT);
|
@@ -654,6 +654,10 @@ struct GLONASS_Ephemeris
|
|
654
654
|
bool is_consistent() const {
|
655
655
|
return has_string == 0x1F;
|
656
656
|
}
|
657
|
+
bool is_in_range(const GPS_Time<FloatT> &t) const {
|
658
|
+
// "invalidate()" is used to make raw and converted data inconsistent.
|
659
|
+
return eph_t::is_valid(t);
|
660
|
+
}
|
657
661
|
bool is_valid(const GPS_Time<FloatT> &t) const {
|
658
662
|
return is_consistent() && eph_t::is_valid(t);
|
659
663
|
}
|
@@ -800,10 +804,6 @@ struct GLONASS_Ephemeris
|
|
800
804
|
%rename("valid?") is_valid;
|
801
805
|
%rename("in_range?") is_in_range;
|
802
806
|
#endif
|
803
|
-
bool is_in_range(const GPS_Time<FloatT> &t) const {
|
804
|
-
// "invalidate()" is used to make raw and converted data inconsistent.
|
805
|
-
return self->is_valid(t);
|
806
|
-
}
|
807
807
|
}
|
808
808
|
|
809
809
|
%extend GLONASS_SpaceNode {
|
@@ -7,7 +7,7 @@ class Receiver
|
|
7
7
|
def parse_rtcm3(src, opt = {}, &b)
|
8
8
|
$stderr.print "Reading RTCM3 stream (%s) "%[src]
|
9
9
|
require_relative '../rtcm3'
|
10
|
-
src_io = open(src)
|
10
|
+
src_io = Util::open(src)
|
11
11
|
rtcm3 = GPS_PVT::RTCM3::new(src_io)
|
12
12
|
ref_time = case (ref_time = opt[:ref_time])
|
13
13
|
when GPS::Time;
|
@@ -19,13 +19,88 @@ class Receiver
|
|
19
19
|
end
|
20
20
|
leap_sec = ref_time.leap_seconds
|
21
21
|
after_run = b || proc{|pvt| puts pvt.to_s if pvt}
|
22
|
-
t_meas, meas = [nil,
|
22
|
+
t_meas, meas = [nil, {}]
|
23
|
+
# meas := {msg_num => [[], ...]} due to duplicated observation such as 1074 and 1077
|
24
|
+
run_proc = proc{
|
25
|
+
meas_ = GPS::Measurement::new
|
26
|
+
meas.sort.each{|k, values| # larger msg_num entries have higher priority
|
27
|
+
values.each{|prn_k_v| meas_.add(*prn_k_v)}
|
28
|
+
}
|
29
|
+
after_run.call(run(meas_, t_meas), [meas_, ref_time = t_meas]) if t_meas
|
30
|
+
t_meas, meas = [nil, {}]
|
31
|
+
}
|
23
32
|
dt_threshold = GPS::Time::Seconds_week / 2
|
33
|
+
tow2t = proc{|tow_sec|
|
34
|
+
dt = tow_sec - ref_time.seconds
|
35
|
+
GPS::Time::new(ref_time.week + if dt <= -dt_threshold then; 1
|
36
|
+
elsif dt >= dt_threshold then; -1
|
37
|
+
else; 0; end, tow_sec)
|
38
|
+
}
|
39
|
+
utc2t = proc{|utc_tod|
|
40
|
+
if t_meas then
|
41
|
+
delta = (t_meas.seconds - utc_tod).to_i % (60 * 60 * 24)
|
42
|
+
leap_sec = (delta >= (60 * 60 * 12)) ? delta - (60 * 60 * 12) : delta
|
43
|
+
t_meas
|
44
|
+
else
|
45
|
+
ref_dow, ref_tod = ref_time.seconds.divmod(60 * 60 * 24)
|
46
|
+
tod = utc_tod + leap_sec
|
47
|
+
tod_delta = ref_tod - tod
|
48
|
+
if tod_delta > 12 * 60 * 60 then
|
49
|
+
ref_dow -= 1
|
50
|
+
elsif tod_delta < -12 * 60 * 60 then
|
51
|
+
ref_dow += 1
|
52
|
+
end
|
53
|
+
GPS::Time::new(ref_time.week, 0) + tod + 60 * 60 * 24 * ref_dow
|
54
|
+
end
|
55
|
+
}
|
24
56
|
|
25
57
|
while packet = rtcm3.read_packet
|
26
58
|
msg_num = packet.message_number
|
27
59
|
parsed = packet.parse
|
60
|
+
t_meas2, meas2 = [nil, []] # per_packet
|
61
|
+
add_proc = proc{
|
62
|
+
t_meas ||= t_meas2
|
63
|
+
meas[msg_num] = meas2 unless meas2.empty?
|
64
|
+
}
|
28
65
|
case msg_num
|
66
|
+
when 1001..1004
|
67
|
+
t_meas2 = tow2t.call(parsed[2][0]) # DF004
|
68
|
+
ranges = parsed.ranges
|
69
|
+
item_size = ranges[:sat].size
|
70
|
+
[:sat, :pseudo_range, :phase_range, :cn].collect{|k|
|
71
|
+
ranges[k] || ([nil] * item_size)
|
72
|
+
}.transpose.each{|svid, pr, cpr, cn|
|
73
|
+
case svid
|
74
|
+
when 1..32; # GPS
|
75
|
+
when 40..58; svid += 80 # SBAS
|
76
|
+
else; next
|
77
|
+
end
|
78
|
+
meas2 << [svid, :L1_PSEUDORANGE, pr] if pr
|
79
|
+
meas2 << [svid, :L1_CARRIER_PHASE, cpr / GPS::SpaceNode.L1_WaveLength] if cpr
|
80
|
+
meas2 << [svid, :L1_SIGNAL_STRENGTH_dBHz, cn] if cn
|
81
|
+
}
|
82
|
+
when 1009..1012
|
83
|
+
t_meas2 = utc2t.call(parsed[2][0] - 60 * 60 * 3) # DF034 UTC(SU)+3hr, time of day[sec]
|
84
|
+
ranges = parsed.ranges
|
85
|
+
item_size = ranges[:sat].size
|
86
|
+
[:sat, :freq_ch, :pseudo_range, :phase_range, :cn].collect{|k|
|
87
|
+
ranges[k] || ([nil] * item_size)
|
88
|
+
}.transpose.each{|svid, freq_ch, pr, cpr, cn|
|
89
|
+
case svid
|
90
|
+
when 1..24 # GLONASS
|
91
|
+
svid += 0x100
|
92
|
+
freq = GPS::SpaceNode_GLONASS::L1_frequency(freq_ch)
|
93
|
+
len = GPS::SpaceNode_GLONASS.light_speed / freq
|
94
|
+
meas2 << [svid, :L1_FREQUENCY, freq]
|
95
|
+
meas2 << [svid, :L1_CARRIER_PHASE, cpr / len] if cpr
|
96
|
+
when 40..58
|
97
|
+
svid += 80 # SBAS
|
98
|
+
meas2 << [svid, :L1_CARRIER_PHASE, cpr / GPS::SpaceNode.L1_WaveLength] if cpr
|
99
|
+
else; next
|
100
|
+
end
|
101
|
+
meas2 << [svid, :L1_PSEUDORANGE, pr] if pr
|
102
|
+
meas2 << [svid, :L1_SIGNAL_STRENGTH_dBHz, cn] if cn
|
103
|
+
}
|
29
104
|
when 1019, 1044
|
30
105
|
params = parsed.params
|
31
106
|
if msg_num == 1044
|
@@ -55,55 +130,77 @@ class Receiver
|
|
55
130
|
critical{
|
56
131
|
@solver.glonass_space_node.register_ephemeris(eph.svid, eph)
|
57
132
|
}
|
58
|
-
when
|
133
|
+
when 1043
|
134
|
+
params = parsed.params
|
135
|
+
eph = GPS::Ephemeris_SBAS::new
|
136
|
+
tod_delta = params[:tod] - (ref_time.seconds % (24 * 60 * 60))
|
137
|
+
if tod_delta > (12 * 60 * 60) then
|
138
|
+
tod_delta -= (24 * 60 * 60)
|
139
|
+
elsif tod_delta < -(12 * 60 * 60) then
|
140
|
+
tod_delta += (24 * 60 * 60)
|
141
|
+
end
|
142
|
+
toe = ref_time + tod_delta
|
143
|
+
eph.WN, eph.t_0 = [:week, :seconds].collect{|k| toe.send(k)}
|
144
|
+
params.each{|k, v| eph.send("#{k}=".to_sym, v) unless [:iodn, :tod].include?(k)}
|
145
|
+
critical{
|
146
|
+
@solver.sbas_space_node.register_ephemeris(eph.svid, eph)
|
147
|
+
}
|
148
|
+
when 1071..1077, 1081..1087, 1101..1107, 1111..1117
|
59
149
|
ranges = parsed.ranges
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
}.
|
150
|
+
glonass_freq = nil
|
151
|
+
case msg_num / 10 # check time of measurement
|
152
|
+
when 107, 110, 111 # GPS, SBAS, QZSS
|
153
|
+
t_meas2 = tow2t.call(parsed[2][0]) # DF004
|
154
|
+
when 108 # GLONASS
|
155
|
+
t_meas2 = utc2t.call(parsed[3][0] - 60 * 60 * 3) # DF034 UTC(SU)+3hr, time of day[sec]
|
156
|
+
glonass_freq = critical{
|
157
|
+
@solver.glonass_space_node.update_all_ephemeris(t_meas2)
|
158
|
+
Hash[*(ranges[:sat_sig].collect{|svid, sig| svid}.uniq.collect{|svid|
|
159
|
+
eph = @solver.glonass_space_node.ephemeris(svid)
|
160
|
+
next nil unless eph.in_range?(t_meas2)
|
161
|
+
[svid, {:L1 => eph.frequency_L1}]
|
162
|
+
}.compact.flatten(1))]
|
163
|
+
}
|
164
|
+
end
|
165
|
+
sig_list, svid_offset = case msg_num / 10
|
166
|
+
when 107 # GPS
|
69
167
|
[{2 => [:L1, GPS::SpaceNode.L1_WaveLength],
|
70
168
|
15 => [:L2CM, GPS::SpaceNode.L2_WaveLength],
|
71
169
|
16 => [:L2CL, GPS::SpaceNode.L2_WaveLength]}, 0]
|
72
|
-
when
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
}.call if t_meas
|
78
|
-
[{2 => [:L1, GPS::SpaceNode_GLONASS.light_speed / GPS::SpaceNode_GLONASS.L1_frequency_base]}, 0x100]
|
79
|
-
when 1117 # QZSS
|
170
|
+
when 108 # GLONASS
|
171
|
+
[{2 => [:L1, nil]}, 0x100]
|
172
|
+
when 110 # SBAS
|
173
|
+
[{2 => [:L1, GPS::SpaceNode.L1_WaveLength]}, 120]
|
174
|
+
when 111 # QZSS
|
80
175
|
[{2 => [:L1, GPS::SpaceNode.L1_WaveLength],
|
81
176
|
15 => [:L2CM, GPS::SpaceNode.L2_WaveLength],
|
82
177
|
16 => [:L2CL, GPS::SpaceNode.L2_WaveLength]}, 192]
|
83
178
|
else; [{}, 0]
|
84
179
|
end
|
85
|
-
[:sat_sig
|
86
|
-
|
87
|
-
|
180
|
+
item_size = ranges[:sat_sig].size
|
181
|
+
[:sat_sig, :pseudo_range, :phase_range, :phase_range_rate, :cn].collect{|k|
|
182
|
+
ranges[k] || ([nil] * item_size)
|
183
|
+
}.transpose.each{|(svid, sig), pr, cpr, dr, cn|
|
88
184
|
prefix, len = sig_list[sig]
|
89
185
|
next unless prefix
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
186
|
+
proc{
|
187
|
+
next unless freq = (glonass_freq[svid] || {})[prefix]
|
188
|
+
meas2 << [svid, "#{prefix}_FREQUENCY".to_sym, freq]
|
189
|
+
len = GPS::SpaceNode_GLONASS.light_speed / freq
|
190
|
+
}.call if glonass_freq
|
94
191
|
svid += svid_offset
|
95
|
-
|
96
|
-
|
97
|
-
|
192
|
+
meas2 << [svid, "#{prefix}_PSEUDORANGE".to_sym, pr] if pr
|
193
|
+
meas2 << [svid, "#{prefix}_RANGE_RATE".to_sym, dr] if dr
|
194
|
+
meas2 << [svid, "#{prefix}_CARRIER_PHASE".to_sym, cpr / len] if cpr && len
|
195
|
+
meas2 << [svid, "#{prefix}_SIGNAL_STRENGTH_dBHz".to_sym, cn] if cn
|
98
196
|
}
|
99
197
|
else
|
100
198
|
#p({msg_num => parsed})
|
101
199
|
end
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
end
|
200
|
+
|
201
|
+
run_proc.call if t_meas && t_meas2 && ((t_meas - t_meas2).abs > 1E-3) # fallback for incorrect more_data flag
|
202
|
+
add_proc.call
|
203
|
+
run_proc.call if (1070..1229).include?(msg_num) && (!parsed.more_data?)
|
107
204
|
end
|
108
205
|
end
|
109
206
|
end
|
data/lib/gps_pvt/receiver.rb
CHANGED
@@ -460,7 +460,7 @@ class Receiver
|
|
460
460
|
$stderr.print "Reading UBX file (%s) "%[ubx_fname]
|
461
461
|
require_relative 'ubx'
|
462
462
|
|
463
|
-
ubx = UBX::new(open(ubx_fname))
|
463
|
+
ubx = UBX::new(Util::open(ubx_fname))
|
464
464
|
ubx_kind = Hash::new(0)
|
465
465
|
|
466
466
|
after_run = b || proc{|pvt| puts pvt.to_s if pvt}
|
data/lib/gps_pvt/rtcm3.rb
CHANGED
@@ -13,6 +13,7 @@ class RTCM3
|
|
13
13
|
end
|
14
14
|
module Packet
|
15
15
|
def decode(bits_list, offset = nil)
|
16
|
+
# 24 is offset of header in transport layer
|
16
17
|
Util::BitOp::extract(self, bits_list, offset || 24)
|
17
18
|
end
|
18
19
|
def message_number
|
@@ -56,15 +57,44 @@ class RTCM3
|
|
56
57
|
2 => 12,
|
57
58
|
3 => 12,
|
58
59
|
4 => unum_gen.call(30, Rational(1, 1000)), # [sec]
|
60
|
+
5 => 1,
|
61
|
+
6 => 5,
|
62
|
+
7 => 1,
|
63
|
+
8 => 3,
|
59
64
|
9 => 6,
|
65
|
+
10 => 1,
|
66
|
+
11 => invalidate.call(unum_gen.call(24, Rational(2, 100)), 0x800000), # [m]
|
67
|
+
12 => invalidate.call(num_gen.call(20, Rational(5, 10000)), 0x80000), # [m]
|
68
|
+
13 => 7,
|
69
|
+
14 => unum_gen.call(8, 299_792.458), # [m]
|
70
|
+
15 => invalidate.call(unum_gen.call(8, Rational(1, 4)), 0), # [db-Hz],
|
71
|
+
16 => 2,
|
72
|
+
17 => invalidate.call(num_gen.call(14, Rational(2, 100)), 0x2000), # [m]
|
73
|
+
18 => num_gen.call(20, Rational(5, 10000)), # [m]
|
74
|
+
19 => 7,
|
75
|
+
20 => invalidate.call(unum_gen.call(8, Rational(1, 4)), 0), # [db-Hz]
|
60
76
|
21 => 6,
|
61
77
|
22 => 1,
|
62
78
|
23 => 1,
|
63
79
|
24 => 1,
|
64
80
|
25 => num_gen.call(38, Rational(1, 10000)), # [m]
|
65
81
|
34 => unum_gen.call(27, Rational(1, 1000)), # [sec]
|
82
|
+
35 => 5,
|
83
|
+
36 => 1,
|
84
|
+
37 => 3,
|
66
85
|
38 => 6,
|
67
|
-
|
86
|
+
39 => 1,
|
87
|
+
40 => [5, proc{|v| v - 7}],
|
88
|
+
41 => invalidate.call(unum_gen.call(25, Rational(2, 100)), 0x1000000), # [m]
|
89
|
+
42 => invalidate.call(num_gen.call(20, Rational(5, 10000)), 0x80000), # [m]
|
90
|
+
43 => 7,
|
91
|
+
44 => unum_gen.call(7, 599_584.916), # [m]
|
92
|
+
45 => invalidate.call(unum_gen.call(8, Rational(1, 4)), 0), # [db-Hz],
|
93
|
+
46 => 2,
|
94
|
+
47 => invalidate.call(num_gen.call(14, Rational(2, 100)), 0x2000), # [m]
|
95
|
+
48 => invalidate.call(num_gen.call(20, Rational(5, 10000)), 0x80000), # [m]
|
96
|
+
49 => 7,
|
97
|
+
50 => invalidate.call(unum_gen.call(8, Rational(1, 4)), 0), # [db-Hz]
|
68
98
|
71 => 8,
|
69
99
|
76 => 10,
|
70
100
|
77 => proc{
|
@@ -146,11 +176,15 @@ class RTCM3
|
|
146
176
|
397 => invalidate.call(unum_gen.call(8, Rational(1, 1000)), 0xFF), # [sec]
|
147
177
|
398 => unum_gen.call(10, Rational(1, 1000 << 10)), # [sec]
|
148
178
|
399 => invalidate.call(num_gen.call(14), 0x2000), # [m/s]
|
179
|
+
400 => invalidate.call(num_gen.call(15, Rational(1, 1000 << 24)), 0x4000), # [sec],
|
180
|
+
401 => invalidate.call(num_gen.call(22, Rational(1, 1000 << 29)), 0x200000), # [sec],
|
181
|
+
402 => 4,
|
182
|
+
403 => invalidate.call(unum_gen.call(6), 0), # [dB-Hz],
|
149
183
|
404 => invalidate.call(num_gen.call(15, Rational(1, 10000)), 0x4000), # [m/s]
|
150
184
|
405 => invalidate.call(num_gen.call(20, Rational(1, 1000 << 29)), 0x80000), # [sec]
|
151
185
|
406 => invalidate.call(num_gen.call(24, Rational(1, 1000 << 31)), 0x800000), # [sec]
|
152
186
|
407 => 10,
|
153
|
-
408 => unum_gen.call(10, Rational(1, 1 << 4)), # [dB-Hz]
|
187
|
+
408 => invalidate.call(unum_gen.call(10, Rational(1, 1 << 4)), 0), # [dB-Hz]
|
154
188
|
409 => 3,
|
155
189
|
411 => 2,
|
156
190
|
412 => 2,
|
@@ -171,6 +205,20 @@ class RTCM3
|
|
171
205
|
src = (src.to_a rescue [src]).flatten
|
172
206
|
(dst.to_a rescue ([dst] * src.size)).flatten.zip(src).each{|i, j| df[i] = df[j]}
|
173
207
|
}
|
208
|
+
df.merge!({
|
209
|
+
:SBAS_prn => [6, proc{|v| v + 120}],
|
210
|
+
:SBAS_iodn => 8,
|
211
|
+
:SBAS_tod => num_gen.call(13, 1 << 4),
|
212
|
+
:SBAS_ura => df[77],
|
213
|
+
:SBAS_xy => num_gen.call(30, Rational(8, 100)),
|
214
|
+
:SBAS_z => num_gen.call(25, Rational(4, 10)),
|
215
|
+
:SBAS_dxy => num_gen.call(17, Rational(1, 1600)),
|
216
|
+
:SBAS_dz => num_gen.call(18, Rational(1, 250)),
|
217
|
+
:SBAS_ddxy => num_gen.call(10, Rational(1, 80000)),
|
218
|
+
:SBAS_ddz => num_gen.call(10, Rational(1, 16000)),
|
219
|
+
:SBAS_agf0 => num_gen.call(12, Rational(1, 1 << 31)),
|
220
|
+
:SBAS_agf1 => num_gen.call(8, Rational(1, 1 << 40)),
|
221
|
+
})
|
174
222
|
df.define_singleton_method(:generate_prop){|idx_list|
|
175
223
|
hash = Hash[*([:bits, :op].collect.with_index{|k, i|
|
176
224
|
[k, idx_list.collect{|idx, *args|
|
@@ -180,21 +228,79 @@ class RTCM3
|
|
180
228
|
[prop].flatten(1)[i]
|
181
229
|
}]
|
182
230
|
}.flatten(1))].merge({:df => idx_list})
|
183
|
-
hash[:bits_total] = hash[:bits].inject{|a, b| a + b}
|
231
|
+
hash[:bits_total] = hash[:bits].inject{|a, b| a + b} || 0
|
184
232
|
hash
|
185
233
|
}
|
186
234
|
df
|
187
235
|
}.call
|
188
236
|
MessageType = Hash[*({
|
237
|
+
1001..1004 => (2..8).to_a,
|
189
238
|
1005 => [2, 3, 21, 22, 23, 24, 141, 25, 142, [1, 1], 26, 364, 27],
|
239
|
+
1009..1012 => [2, 3, 34, 5, 35, 36, 37],
|
190
240
|
1019 => [2, 9, (76..79).to_a, 71, (81..103).to_a, 137].flatten, # 488 bits @see Table 3.5-21
|
191
241
|
1020 => [2, 38, 40, (104..136).to_a].flatten, # 360 bits @see Table 3.5-21
|
242
|
+
1043 => [2] + [:prn, :iodn, :tod, :ura,
|
243
|
+
[:xy] * 2, :z, [:dxy] * 2, :dz, [:ddxy] * 2, :ddz,
|
244
|
+
:agf0, :agf1].flatten.collect{|k| "SBAS_#{k}".to_sym}, # @see BNC Ntrip client RTCM3Decorder.cpp
|
192
245
|
1044 => [2, (429..457).to_a].flatten, # 485 bits
|
193
|
-
1077 => [2, 3, 4, 393, 409, [1, 7], 411, 412, 417, 418, 394, 395], # 169 bits @see Table 3.5-78
|
194
|
-
1087 => [2, 3, 416, 34, 393, 409, [1, 7], 411, 412, 417, 418, 394, 395], # 169 bits @see Table 3.5-93
|
195
|
-
1097 => [2, 3, 248, 393, 409, [1, 7], 411, 412, 417, 418, 394, 395], # 169 bits @see Table 3.5-98
|
196
|
-
|
197
|
-
|
246
|
+
1071..1077 => [2, 3, 4, 393, 409, [1, 7], 411, 412, 417, 418, 394, 395], # 169 bits @see Table 3.5-78
|
247
|
+
1081..1087 => [2, 3, 416, 34, 393, 409, [1, 7], 411, 412, 417, 418, 394, 395], # 169 bits @see Table 3.5-93
|
248
|
+
1091..1097 => [2, 3, 248, 393, 409, [1, 7], 411, 412, 417, 418, 394, 395], # 169 bits @see Table 3.5-98
|
249
|
+
1101..1107 => [2, 3, 4, 393, 409, [1, 7], 411, 412, 417, 418, 394, 395], # 169 bits
|
250
|
+
1111..1117 => [2, 3, 4, 393, 409, [1, 7], 411, 412, 417, 418, 394, 395], # 169 bits
|
251
|
+
1121..1127 => [2, 3, 4, 393, 409, [1, 7], 411, 412, 417, 418, 394, 395], # 169 bits
|
252
|
+
}.collect{|mt_list, df_list|
|
253
|
+
(mt_list.to_a rescue [mt_list]).collect{|mt|
|
254
|
+
[mt, DataFrame.generate_prop(df_list)]
|
255
|
+
}
|
256
|
+
}.flatten(2))]
|
257
|
+
module GPS_Observation
|
258
|
+
def ranges
|
259
|
+
res = {
|
260
|
+
:sat => select{|v, df| df == 9}.transpose[0],
|
261
|
+
:pseudo_range_rem => select{|v, df| df == 11}.transpose[0],
|
262
|
+
}
|
263
|
+
add_proc = proc{|k, df, base|
|
264
|
+
values = select{|v, df_| df_ == df}
|
265
|
+
next if values.empty?
|
266
|
+
res[k] = values.transpose[0]
|
267
|
+
res[k] = res[k].zip(res[base]).collect{|a, b| (a + b) rescue nil} if base
|
268
|
+
}
|
269
|
+
add_proc.call(:pseudo_range, 14, :pseudo_range_rem)
|
270
|
+
suffix = res[:pseudo_range] ? "" : "_rem"
|
271
|
+
base = "pseudo_range#{suffix}".to_sym
|
272
|
+
add_proc.call("phase_range#{suffix}".to_sym, 12, base)
|
273
|
+
add_proc.call(:cn, 15)
|
274
|
+
add_proc.call("pseudo_range_L2#{suffix}".to_sym, 17, base)
|
275
|
+
add_proc.call("phase_range_L2#{suffix}".to_sym, 18, base)
|
276
|
+
add_proc.call(:cn_L2, 20)
|
277
|
+
res
|
278
|
+
end
|
279
|
+
end
|
280
|
+
module GLONASS_Observation
|
281
|
+
def ranges
|
282
|
+
res = {
|
283
|
+
:sat => select{|v, df| df == 38}.transpose[0],
|
284
|
+
:freq_ch => select{|v, df| df == 40}.transpose[0],
|
285
|
+
:pseudo_range_rem => select{|v, df| df == 41}.transpose[0],
|
286
|
+
}
|
287
|
+
add_proc = proc{|k, df, base|
|
288
|
+
values = select{|v, df_| df_ == df}
|
289
|
+
next if values.empty?
|
290
|
+
res[k] = values.transpose[0]
|
291
|
+
res[k] = res[k].zip(res[base]).collect{|a, b| (a + b) rescue nil} if base
|
292
|
+
}
|
293
|
+
add_proc.call(:pseudo_range, 44, :pseudo_range_rem)
|
294
|
+
suffix = res[:pseudo_range] ? "" : "_rem"
|
295
|
+
base = "pseudo_range#{suffix}".to_sym
|
296
|
+
add_proc.call("phase_range#{suffix}".to_sym, 42, base)
|
297
|
+
add_proc.call(:cn, 45)
|
298
|
+
add_proc.call("pseudo_range_L2#{suffix}".to_sym, 47, base)
|
299
|
+
add_proc.call("phase_range_L2#{suffix}".to_sym, 48, base)
|
300
|
+
add_proc.call(:cn_L2, 50)
|
301
|
+
res
|
302
|
+
end
|
303
|
+
end
|
198
304
|
module GPS_Ephemeris
|
199
305
|
KEY2IDX = {:svid => 1, :WN => 2, :URA => 3, :dot_i0 => 5, :iode => 6, :t_oc => 7,
|
200
306
|
:a_f2 => 8, :a_f1 => 9, :a_f0 => 10, :iodc => 11, :c_rs => 12, :delta_n => 13,
|
@@ -218,6 +324,17 @@ class RTCM3
|
|
218
324
|
res
|
219
325
|
end
|
220
326
|
end
|
327
|
+
module SBAS_Ephemeris
|
328
|
+
KEY2IDX = {:svid => 1, :iodn => 2, :tod => 3, :URA => 4,
|
329
|
+
:x => 5, :y => 6, :z => 7,
|
330
|
+
:dx => 8, :dy => 9, :dz => 10,
|
331
|
+
:ddx => 11, :ddy => 12, :ddz => 13,
|
332
|
+
:a_Gf0 => 14, :a_Gf1 => 15}
|
333
|
+
def params
|
334
|
+
# TODO WN is required to provide
|
335
|
+
Hash[*(KEY2IDX.collect{|k, i| [k, self[i][0]]}.flatten(1))]
|
336
|
+
end
|
337
|
+
end
|
221
338
|
module GLONASS_Ephemeris
|
222
339
|
def params
|
223
340
|
# TODO insufficient: :n => ?(String4); extra: :P3
|
@@ -259,30 +376,63 @@ class RTCM3
|
|
259
376
|
def more_data?
|
260
377
|
self.find{|v| v[1] == 393}[0] == 1
|
261
378
|
end
|
379
|
+
def property
|
380
|
+
idx_sat = self.find_index{|v| v[1] == 394}
|
381
|
+
{
|
382
|
+
:sats => self[idx_sat][0],
|
383
|
+
:cells => self[idx_sat + 2][0], # DF396
|
384
|
+
:header_items => idx_sat + 3,
|
385
|
+
}
|
386
|
+
end
|
262
387
|
end
|
263
|
-
module
|
388
|
+
module MSM
|
389
|
+
include MSM_Header
|
390
|
+
def ranges
|
391
|
+
{:sat_sig => property[:cells]} # expect to be overriden
|
392
|
+
end
|
264
393
|
SPEED_OF_LIGHT = 299_792_458
|
394
|
+
end
|
395
|
+
module MSM4_6
|
396
|
+
include MSM
|
265
397
|
def ranges
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
398
|
+
sats, cells, offset = property.values_at(:sats, :cells, :header_items)
|
399
|
+
nsat, ncell = [sats.size, cells.size]
|
400
|
+
range_rough = self[offset, nsat] # DF397
|
401
|
+
range_rough2 = self[offset + (nsat * 1), nsat] # DF398
|
402
|
+
range_fine = self[offset + (nsat * 2), ncell] # DF400/405
|
403
|
+
phase_fine = self[offset + (nsat * 2) + (ncell * 1), ncell] # DF401/406
|
404
|
+
cn = self[offset + (nsat * 2) + (ncell * 4), ncell] # DF403/408
|
405
|
+
Hash[*([:sat_sig, :pseudo_range, :phase_range, :cn].zip(
|
406
|
+
[cells] + cells.collect.with_index{|(sat, sig), i|
|
407
|
+
i2 = sats.find_index(sat)
|
408
|
+
rough_ms = (range_rough2[i2][0] + range_rough[i2][0]) rescue nil
|
409
|
+
[(((range_fine[i][0] + rough_ms) * SPEED_OF_LIGHT) rescue nil),
|
410
|
+
(((phase_fine[i][0] + rough_ms) * SPEED_OF_LIGHT) rescue nil),
|
411
|
+
cn[i][0]]
|
412
|
+
}.transpose).flatten(1))]
|
413
|
+
end
|
414
|
+
end
|
415
|
+
module MSM5_7
|
416
|
+
include MSM
|
417
|
+
def ranges
|
418
|
+
sats, cells, offset = property.values_at(:sats, :cells, :header_items)
|
419
|
+
nsat, ncell = [sats.size, cells.size]
|
272
420
|
range_rough = self[offset, nsat] # DF397
|
273
421
|
range_rough2 = self[offset + (nsat * 2), nsat] # DF398
|
274
422
|
delta_rough = self[offset + (nsat * 3), nsat] # DF399
|
275
|
-
range_fine = self[offset + (nsat * 4), ncell] #
|
276
|
-
phase_fine = self[offset + (nsat * 4) + (ncell * 1), ncell] #
|
423
|
+
range_fine = self[offset + (nsat * 4), ncell] # DF400/405
|
424
|
+
phase_fine = self[offset + (nsat * 4) + (ncell * 1), ncell] # DF401/406
|
425
|
+
cn = self[offset + (nsat * 4) + (ncell * 4), ncell] # DF403/408
|
277
426
|
delta_fine = self[offset + (nsat * 4) + (ncell * 5), ncell] # DF404
|
278
|
-
Hash[*([:pseudo_range, :phase_range, :phase_range_rate, :
|
279
|
-
cells.collect.with_index{|(sat, sig), i|
|
427
|
+
Hash[*([:sat_sig, :pseudo_range, :phase_range, :phase_range_rate, :cn].zip(
|
428
|
+
[cells] + cells.collect.with_index{|(sat, sig), i|
|
280
429
|
i2 = sats.find_index(sat)
|
281
|
-
|
430
|
+
rough_ms = (range_rough2[i2][0] + range_rough[i2][0]) rescue nil
|
282
431
|
[(((range_fine[i][0] + rough_ms) * SPEED_OF_LIGHT) rescue nil),
|
283
432
|
(((phase_fine[i][0] + rough_ms) * SPEED_OF_LIGHT) rescue nil),
|
284
|
-
((delta_fine[i][0] + delta_rough[i2][0]) rescue nil)
|
285
|
-
|
433
|
+
((delta_fine[i][0] + delta_rough[i2][0]) rescue nil),
|
434
|
+
cn[i][0]]
|
435
|
+
}.transpose).flatten(1))]
|
286
436
|
end
|
287
437
|
end
|
288
438
|
def parse
|
@@ -298,28 +448,65 @@ class RTCM3
|
|
298
448
|
}
|
299
449
|
add_proc.call(mt)
|
300
450
|
case msg_num
|
451
|
+
when 1001..1004
|
452
|
+
nsat = values[4]
|
453
|
+
offset = 24 + mt[:bits_total]
|
454
|
+
add_proc.call(DataFrame.generate_prop(([{
|
455
|
+
1001 => (9..13).to_a,
|
456
|
+
1002 => (9..15).to_a,
|
457
|
+
1003 => (9..13).to_a + (16..19).to_a,
|
458
|
+
1004 => (9..20).to_a,
|
459
|
+
}[msg_num]] * nsat).flatten), offset)
|
460
|
+
attributes << GPS_Observation
|
461
|
+
when 1009..1012
|
462
|
+
nsat = values[4]
|
463
|
+
offset = 24 + mt[:bits_total]
|
464
|
+
add_proc.call(DataFrame.generate_prop(([{
|
465
|
+
1009 => (38..43).to_a,
|
466
|
+
1010 => (38..45).to_a,
|
467
|
+
1011 => (38..43).to_a + (46..49).to_a,
|
468
|
+
1012 => (38..50).to_a,
|
469
|
+
}[msg_num]] * nsat).flatten), offset)
|
470
|
+
attributes << GLONASS_Observation
|
301
471
|
when 1019
|
302
472
|
attributes << GPS_Ephemeris
|
303
473
|
when 1020
|
304
474
|
attributes << GLONASS_Ephemeris
|
475
|
+
when 1043
|
476
|
+
attributes << SBAS_Ephemeris
|
305
477
|
when 1044
|
306
478
|
attributes << QZSS_Ephemeris
|
307
|
-
when 1077, 1087, 1097, 1117
|
308
|
-
#
|
309
|
-
attributes << MSM7
|
479
|
+
when 1071..1077, 1081..1087, 1091..1097, 1101..1107, 1111..1117, 1121..1127
|
480
|
+
# 107X(GPS), 108X(GLONASS), 109X(GALILEO), 110X(SBAS), 111X(QZSS), 112X(Beidou)
|
310
481
|
nsat, nsig = [-2, -1].collect{|i| values[i].size}
|
311
482
|
offset = 24 + mt[:bits_total]
|
312
483
|
df396 = DataFrame.generate_prop([[396, values[-2], values[-1]]])
|
313
484
|
add_proc.call(df396, offset)
|
314
485
|
ncell = values[-1].size
|
315
486
|
offset += df396[:bits_total]
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
487
|
+
msm_proc = proc{|sat_data, signal_data|
|
488
|
+
msm_sat = DataFrame.generate_prop(([sat_data] * nsat).transpose.flatten(1))
|
489
|
+
add_proc.call(msm_sat, offset)
|
490
|
+
offset += msm_sat[:bits_total]
|
491
|
+
msm_sig = DataFrame.generate_prop(([signal_data] * ncell).transpose.flatten(1))
|
492
|
+
add_proc.call(msm_sig, offset)
|
493
|
+
}
|
494
|
+
case msg_num % 10
|
495
|
+
when 4
|
496
|
+
attributes << MSM4_6
|
497
|
+
msm_proc.call([397, 398], [400, 401, 402, 420, 403])
|
498
|
+
when 5
|
499
|
+
attributes << MSM5_7
|
500
|
+
msm_proc.call([397, [:uint, 4], 398, 399], [400, 401, 402, 420, 403, 404])
|
501
|
+
when 6
|
502
|
+
attributes << MSM4_6
|
503
|
+
msm_proc.call([397, 398], [405, 406, 407, 420, 408])
|
504
|
+
when 7
|
505
|
+
attributes << MSM5_7
|
506
|
+
msm_proc.call([397, [:uint, 4], 398, 399], [405, 406, 407, 420, 408, 404])
|
507
|
+
else
|
508
|
+
attributes << MSM # for #range
|
509
|
+
end
|
323
510
|
end
|
324
511
|
attributes << MSM_Header if (1070..1229).include?(msg_num)
|
325
512
|
res = values.zip(df_list)
|
data/lib/gps_pvt/util.rb
CHANGED
@@ -23,14 +23,6 @@ proc{
|
|
23
23
|
}
|
24
24
|
def eof?; false; end
|
25
25
|
}
|
26
|
-
module Kernel
|
27
|
-
open_orig = instance_method(:open)
|
28
|
-
define_method(:open){|*args, &b|
|
29
|
-
return open_orig.bind(self).call(*args, &b) unless Serial::SPEC =~ args[0]
|
30
|
-
Serial::new($1, $2 ? $2.to_i : 115200)
|
31
|
-
}
|
32
|
-
module_function(:open)
|
33
|
-
end
|
34
26
|
}.call if require 'rubyserial'
|
35
27
|
|
36
28
|
require 'open-uri'
|
@@ -41,7 +33,7 @@ class URI::Ntrip
|
|
41
33
|
pnt_list = self.read_source_table(options).mount_points
|
42
34
|
case pnt_list[self.mount_point][:format]
|
43
35
|
when /u-?b(?:lo)?x/i; :ubx
|
44
|
-
when /RTCM 3/i; :rtcm3
|
36
|
+
when /RTCM ?3/i; :rtcm3
|
45
37
|
else; nil
|
46
38
|
end
|
47
39
|
end
|
@@ -50,6 +42,24 @@ end
|
|
50
42
|
module GPS_PVT
|
51
43
|
module Util
|
52
44
|
class << self
|
45
|
+
def special_stream?(spec)
|
46
|
+
['-', (Serial::SPEC rescue nil)].compact.any?{|v| v === spec}
|
47
|
+
end
|
48
|
+
def open(*args, &b)
|
49
|
+
return args[0].open(*args[1..-1], &b) if args[0].respond_to?(:open)
|
50
|
+
case args[0].to_str
|
51
|
+
when (Serial::SPEC rescue nil)
|
52
|
+
return ((@serial_ports ||= {})[$1] ||= Serial::new($1, $2 ? $2.to_i : 115200))
|
53
|
+
when '-'
|
54
|
+
if (/^[wa]/ === args[1]) \
|
55
|
+
|| (args[1].kind_of?(Integer) && ((File::Constants::WRONLY & args[1]) > 0)) then
|
56
|
+
return STDOUT
|
57
|
+
else
|
58
|
+
return STDIN
|
59
|
+
end
|
60
|
+
end rescue nil
|
61
|
+
super
|
62
|
+
end
|
53
63
|
def inflate(src, type = :gz)
|
54
64
|
case type
|
55
65
|
when :gz
|
@@ -66,7 +76,7 @@ module Util
|
|
66
76
|
end
|
67
77
|
def get_txt(fname_or_uri)
|
68
78
|
is_uri = fname_or_uri.kind_of?(URI)
|
69
|
-
(
|
79
|
+
open(fname_or_uri){|src|
|
70
80
|
compressed = proc{
|
71
81
|
case src.content_type
|
72
82
|
when /gzip/; next :gz
|
data/lib/gps_pvt/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gps_pvt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- fenrir(M.Naruoka)
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubyserial
|