gps_pvt 0.7.2 → 0.8.1
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/Rakefile +1 -0
- data/exe/gps_pvt +3 -18
- data/exe/to_ubx +103 -8
- data/ext/gps_pvt/GPS/GPS_wrap.cxx +1136 -65
- data/ext/ninja-scan-light/tool/navigation/GLONASS.h +137 -9
- data/ext/ninja-scan-light/tool/navigation/GPS.h +301 -50
- data/ext/ninja-scan-light/tool/navigation/QZSS.h +48 -15
- data/ext/ninja-scan-light/tool/navigation/SBAS.h +106 -4
- data/ext/ninja-scan-light/tool/param/bit_array.h +53 -16
- data/ext/ninja-scan-light/tool/swig/GPS.i +228 -24
- data/ext/ninja-scan-light/tool/swig/spec/GPS_spec.rb +61 -0
- data/ext/ninja-scan-light/tool/util/bit_counter.h +84 -0
- data/gps_pvt.gemspec +1 -0
- data/lib/gps_pvt/receiver/extension.rb +51 -0
- data/lib/gps_pvt/receiver.rb +79 -56
- data/lib/gps_pvt/util.rb +33 -1
- data/lib/gps_pvt/version.rb +1 -1
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fb3abd803cfe1b0b5199c4187fe17c2595eb603ab27e09f71b66fde11eeafce0
|
4
|
+
data.tar.gz: 351d46d74583346750aec426c087c33bc13f9e9e9adff746567e40df7eb1e39e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0fb78d49675fbbcb3fcfeb80debd7ca15f351be478ed5716f94a61b23f26af7ff957ee446a5ab6c4cc2e67abf2f251cf62845a347ea3810282987da04fa9a2e8
|
7
|
+
data.tar.gz: ac74ba61920cad427d6e848f4621227d150bfe9a30a2f1465bd6d87681cfdd935e20e8e141575306b87c770b485f8dad1555766b7281980ba1f412adddff4e7c
|
data/README.md
CHANGED
@@ -32,7 +32,7 @@ An attached executable is useful. After installation, type
|
|
32
32
|
|
33
33
|
$ gps_pvt file_or_URI(s)
|
34
34
|
|
35
|
-
The format of file is automatically determined with its extension, such as .ubx will be treated as UBX format. A compressed file of .gz or .Z can be specified directly (decompression is internally performed)
|
35
|
+
The format of file is automatically determined with its extension, such as .ubx will be treated as UBX format. A compressed file of .gz or .Z can be specified directly (decompression is internally performed). URI such as http(s)://... and ftp://, and serial port (COMn for Windows and /dev/tty* for *NIX, version >= 0.8.0) are also acceptable. If you want to specify the file format, instead of file_or_URI(s), use the following arguments:
|
36
36
|
|
37
37
|
| specification | recoginized as |
|
38
38
|
----|----
|
data/Rakefile
CHANGED
data/exe/gps_pvt
CHANGED
@@ -14,7 +14,7 @@ If you want to specify its format manually, command options like --rinex_nav=fil
|
|
14
14
|
Other than --rinex_nav, --rinex_obs, -rinex_clk, --ubx, --sp3 or --antex are supported.
|
15
15
|
Supported RINEX versions are 2 and 3.
|
16
16
|
A file having additional ".gz" or ".Z" extension is recognized as a compressed file.
|
17
|
-
Major URL such as http(s)://... or ftp
|
17
|
+
Major URL such as http(s)://... or ftp://..., and serial port (COMn for Windows, /dev/tty* for *NIX) is acceptable as an input file name.
|
18
18
|
__STRING__
|
19
19
|
|
20
20
|
options = []
|
@@ -80,6 +80,7 @@ files.collect!{|fname, ftype|
|
|
80
80
|
end
|
81
81
|
fname = proc{
|
82
82
|
next fname if File::exist?(fname)
|
83
|
+
next fname if ((fname =~ Serial::SPEC) rescue false)
|
83
84
|
if uri = URI::parse(fname) and !uri.instance_of?(URI::Generic) then
|
84
85
|
next uri
|
85
86
|
end
|
@@ -91,23 +92,7 @@ files.collect!{|fname, ftype|
|
|
91
92
|
rcv = GPS_PVT::Receiver::new(options)
|
92
93
|
|
93
94
|
proc{|src|
|
94
|
-
|
95
|
-
loader = proc{|t_meas|
|
96
|
-
utc = Time::utc(*t_meas.c_tm)
|
97
|
-
y, yday = [:year, :yday].collect{|f| utc.send(f)}
|
98
|
-
uri = URI::parse(
|
99
|
-
"ftp://gssc.esa.int/gnss/data/daily/" +
|
100
|
-
"%04d/brdc/BRDC00IGS_R_%04d%03d0000_01D_MN.rnx.gz"%[y, y, yday])
|
101
|
-
rcv.parse_rinex_nav(uri)
|
102
|
-
uri
|
103
|
-
}
|
104
|
-
run_orig = rcv.method(:run)
|
105
|
-
eph_list = {}
|
106
|
-
rcv.define_singleton_method(:run){|meas, t_meas, *args|
|
107
|
-
w_d = [t_meas.week, (t_meas.seconds.to_i / 86400)]
|
108
|
-
eph_list[w_d] ||= loader.call(t_meas)
|
109
|
-
run_orig.call(meas, t_meas, *args)
|
110
|
-
}
|
95
|
+
rcv.attach_online_ephemeris(src) if src
|
111
96
|
}.call(misc_options[:online_ephemeris])
|
112
97
|
|
113
98
|
proc{
|
data/exe/to_ubx
CHANGED
@@ -21,7 +21,9 @@ __STRING__
|
|
21
21
|
|
22
22
|
options = []
|
23
23
|
misc_options = {
|
24
|
-
:
|
24
|
+
:broadcast_data => false,
|
25
|
+
:ubx_rawx => false,
|
26
|
+
:eph_interval => 60 * 5,
|
25
27
|
}
|
26
28
|
|
27
29
|
# check options and file format
|
@@ -53,7 +55,7 @@ files.collect!{|fname, ftype|
|
|
53
55
|
|
54
56
|
options.reject!{|opt|
|
55
57
|
case opt[0]
|
56
|
-
when :ubx_rawx
|
58
|
+
when :ubx_rawx, :online_ephemeris, :broadcast_data, :eph_interval
|
57
59
|
misc_options[opt[0]] = opt[1]
|
58
60
|
true
|
59
61
|
else
|
@@ -68,6 +70,10 @@ rcv.define_singleton_method(:run){|meas, t_meas, *args|
|
|
68
70
|
obs << [t_meas, meas]
|
69
71
|
}
|
70
72
|
|
73
|
+
proc{|src|
|
74
|
+
rcv.attach_online_ephemeris(src) if src
|
75
|
+
}.call(misc_options[:online_ephemeris])
|
76
|
+
|
71
77
|
# parse RINEX NAV
|
72
78
|
files.each{|fname, ftype|
|
73
79
|
case ftype
|
@@ -84,6 +90,92 @@ files.each{|fname, ftype|
|
|
84
90
|
|
85
91
|
obs.sort!{|a, b| a[0] <=> b[0]} # Sort by measurement time
|
86
92
|
|
93
|
+
# Add dummy before actual first observation in order to notify time to solver
|
94
|
+
obs.unshift([obs[0][0] - 1, GPS_PVT::GPS::Measurement::new])
|
95
|
+
|
96
|
+
gen_sfrb, gen_sfrbx = proc{
|
97
|
+
cache = {}
|
98
|
+
sfrb_tmpl = [0xB5, 0x62, 0x02, 0x11, 0, 0]
|
99
|
+
sfrb_tmpl += [0, 0] # ch, id
|
100
|
+
sfrbx_tmpl = [0xB5, 0x62, 0x02, 0x13, 0, 0]
|
101
|
+
sfrbx_tmpl += [0, 0, 0, 0, 0, 0, 2, 0] # version = 2
|
102
|
+
iono_utc = rcv.solver.gps_space_node.iono_utc.instance_eval{
|
103
|
+
f_orig = method(:dump)
|
104
|
+
define_singleton_method(:dump){|t_meas|
|
105
|
+
rcv.solver.gps_space_node.is_valid_iono_utc ? f_orig.call(t_meas) : []
|
106
|
+
}
|
107
|
+
self
|
108
|
+
}
|
109
|
+
[proc{|t_meas, meas| # Convert to RXM-SFRB(0x11)
|
110
|
+
meas.collect{|sat, items|
|
111
|
+
t_prv, eph, ch = cache.include?(sat) ? cache[sat] : []
|
112
|
+
next nil if t_prv && (t_meas - t_prv < misc_options[:eph_interval])
|
113
|
+
sfrb = sfrb_tmpl.clone
|
114
|
+
sfrb[6] = (ch ||= (cache.size % 0x100))
|
115
|
+
sfrb[7] = sat
|
116
|
+
res = case sat
|
117
|
+
when 1..32 # GPS
|
118
|
+
next nil unless (eph = rcv.ephemeris(t_meas, :GPS, sat))
|
119
|
+
(eph.dump(t_meas) + iono_utc.dump(t_meas)).each_slice(10).collect{|subframe|
|
120
|
+
ubx = sfrb + subframe.collect{|word|
|
121
|
+
word >> 6
|
122
|
+
}.pack("V*").unpack("C*") + [0, 0]
|
123
|
+
GPS_PVT::UBX::update(ubx)
|
124
|
+
}
|
125
|
+
when 120..158 # SBAS
|
126
|
+
next nil unless (eph = rcv.ephemeris(t_meas, :SBAS, sat))
|
127
|
+
ubx = sfrb + proc{|msg|
|
128
|
+
msg[7] >>= 6
|
129
|
+
msg
|
130
|
+
}.call(eph.dump + [0, 0]).pack("V*").unpack("C*") + [0, 0]
|
131
|
+
GPS_PVT::UBX::update(ubx)
|
132
|
+
else
|
133
|
+
next nil
|
134
|
+
end
|
135
|
+
cache[sat] = [t_meas, eph, ch]
|
136
|
+
res
|
137
|
+
}.compact.flatten.pack("C*")
|
138
|
+
},
|
139
|
+
proc{|t_meas, meas| # Convert to RXM-SFRBX(0x13)
|
140
|
+
meas.collect{|sat, items|
|
141
|
+
t_prv, eph, ch = cache.include?(sat) ? cache[sat] : []
|
142
|
+
next nil if t_prv && (t_meas - t_prv < misc_options[:eph_interval])
|
143
|
+
sfrbx = sfrbx_tmpl.clone
|
144
|
+
|
145
|
+
res = case sat
|
146
|
+
when 1..32, 193..202 # GPS, QZSS
|
147
|
+
sys = sat <= 32 ? :GPS : :QZSS
|
148
|
+
next nil unless (eph = rcv.ephemeris(t_meas, sys, sat))
|
149
|
+
sfrbx[6..7] = [GPS_PVT::UBX::GNSS_ID[sys], sys == :QZSS ? (sat - 192) : sat] # sys, id
|
150
|
+
sfrbx[10] = 10 # words
|
151
|
+
sfrbx[11] = (ch ||= (cache.size % 0x100)) # ch
|
152
|
+
(eph.dump(t_meas) + iono_utc.dump(t_meas)).each_slice(10).collect{|subframe|
|
153
|
+
GPS_PVT::UBX::update(sfrbx + subframe.pack("V*").unpack("C*") + [0, 0])
|
154
|
+
}
|
155
|
+
when 120..158 # SBAS
|
156
|
+
next nil unless (eph = rcv.ephemeris(t_meas, :SBAS, sat))
|
157
|
+
sfrbx[6..7] = [GPS_PVT::UBX::GNSS_ID[:SBAS], sat] # sys, id
|
158
|
+
sfrbx[10] = 8 # words
|
159
|
+
sfrbx[11] = (ch ||= (cache.size % 0x100)) # ch
|
160
|
+
GPS_PVT::UBX::update(sfrbx + eph.dump.pack("V*").unpack("C*") + [0, 0])
|
161
|
+
when (0x100 + 1)..(0x100 + 32) # GLONASS
|
162
|
+
svid = sat - 0x100
|
163
|
+
next nil unless (eph = rcv.ephemeris(t_meas, :GLONASS, svid))
|
164
|
+
sfrbx[6..7] = [GPS_PVT::UBX::GNSS_ID[:GLONASS], svid] # sys, id
|
165
|
+
sfrbx[10] = 4 # words
|
166
|
+
sfrbx[11] = (ch ||= (cache.size % 0x100)) # ch
|
167
|
+
eph.dump(t_meas).each_slice(3).collect{|str|
|
168
|
+
GPS_PVT::UBX::update(sfrbx + (str + [0]).pack("V*").unpack("C*") + [0, 0])
|
169
|
+
}
|
170
|
+
else
|
171
|
+
next nil
|
172
|
+
end
|
173
|
+
cache[sat] = [t_meas, eph, ch]
|
174
|
+
res
|
175
|
+
}.compact.flatten.pack("C*")
|
176
|
+
}]
|
177
|
+
}.call
|
178
|
+
|
87
179
|
glonass_freq_ch = proc{
|
88
180
|
freq0, delta = [:L1_frequency_base, :L1_frequency_gap].collect{|k|
|
89
181
|
GPS_PVT::GPS::SpaceNode_GLONASS.send(k)
|
@@ -92,7 +184,6 @@ glonass_freq_ch = proc{
|
|
92
184
|
}.call
|
93
185
|
|
94
186
|
gen_raw = proc{|t_meas, meas| # Convert to RXM-RAW(0x10)
|
95
|
-
meas = meas.to_hash
|
96
187
|
ubx = [0xB5, 0x62, 0x02, 0x10, 0, 0]
|
97
188
|
ubx += [(t_meas.seconds * 1E3).to_i, t_meas.week].pack("Vv").unpack("C*")
|
98
189
|
ubx += [0] * 2
|
@@ -142,7 +233,6 @@ gen_raw = proc{|t_meas, meas| # Convert to RXM-RAW(0x10)
|
|
142
233
|
}
|
143
234
|
|
144
235
|
gen_rawx = proc{|t_meas, meas| # Convert to RXM-RAWX(0x15)
|
145
|
-
meas = meas.to_hash
|
146
236
|
ubx = [0xB5, 0x62, 0x02, 0x15, 0, 0]
|
147
237
|
ubx += [t_meas.seconds, t_meas.week].pack("Ev").unpack("C*")
|
148
238
|
ubx += [0] * 6
|
@@ -170,7 +260,7 @@ gen_rawx = proc{|t_meas, meas| # Convert to RXM-RAWX(0x15)
|
|
170
260
|
[5, sat]
|
171
261
|
when (0x100 + 1)..(0x100 + 32) # GLONASS
|
172
262
|
setter.call(:L1_FREQUENCY,
|
173
|
-
39, 1, nil, proc{|v| v.replace(v[0] ? glonass_freq_ch.call(v[0]) :
|
263
|
+
39, 1, nil, proc{|v| v.replace([(v[0] ? glonass_freq_ch.call(v[0]) : 0) + 7])} )
|
174
264
|
[6, sat - 0x100]
|
175
265
|
else
|
176
266
|
next nil # TODO Galileo, Beidou, ...
|
@@ -185,7 +275,7 @@ gen_rawx = proc{|t_meas, meas| # Convert to RXM-RAWX(0x15)
|
|
185
275
|
b = (Math::log2(v[0] / 1E-2).to_i & 0xF) rescue 0x8
|
186
276
|
v.replace((trk_stat & 0x1 == 0x1) ? [b] : [])
|
187
277
|
})
|
188
|
-
setter.call(:L1_DOPPLER, 32, 4, "e")
|
278
|
+
setter.call(:L1_DOPPLER, 32, 4, "e") rescue next nil
|
189
279
|
setter.call(:L1_DOPPLER_SIGMA,
|
190
280
|
45, 1, nil, proc{|v| v.replace(v[0] ? [Math::log2(v[0] / 2E-3).to_i & 0xF] : [0x8])})
|
191
281
|
setter.call(:L1_CARRIER_PHASE,
|
@@ -209,6 +299,11 @@ gen_rawx = proc{|t_meas, meas| # Convert to RXM-RAWX(0x15)
|
|
209
299
|
GPS_PVT::UBX::update(ubx).pack("C*")
|
210
300
|
}
|
211
301
|
|
212
|
-
|
302
|
+
gen_list = []
|
303
|
+
gen_list << (misc_options[:ubx_rawx] ? gen_sfrbx : gen_sfrb) if misc_options[:broadcast_data]
|
304
|
+
gen_list << (misc_options[:ubx_rawx] ? gen_rawx : gen_raw)
|
213
305
|
STDOUT.binmode
|
214
|
-
obs.each{
|
306
|
+
obs.each{|t_meas, meas|
|
307
|
+
meas2 = meas.to_hash
|
308
|
+
gen_list.each{|gen| print gen.call(t_meas, meas2)}
|
309
|
+
}
|