gps_pvt 0.8.0 → 0.8.2
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/Rakefile +1 -0
- data/exe/gps_pvt +1 -17
- data/exe/to_ubx +162 -32
- data/ext/gps_pvt/GPS/GPS_wrap.cxx +1677 -399
- data/ext/ninja-scan-light/tool/navigation/GLONASS.h +137 -9
- data/ext/ninja-scan-light/tool/navigation/GLONASS_Solver.h +5 -3
- data/ext/ninja-scan-light/tool/navigation/GPS.h +301 -50
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver.h +5 -3
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver_MultiFrequency.h +1 -0
- 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/navigation/SBAS_Solver.h +5 -3
- data/ext/ninja-scan-light/tool/param/bit_array.h +53 -16
- data/ext/ninja-scan-light/tool/swig/GPS.i +265 -25
- data/ext/ninja-scan-light/tool/swig/spec/GPS_spec.rb +64 -0
- data/ext/ninja-scan-light/tool/util/bit_counter.h +84 -0
- data/lib/gps_pvt/receiver/extension.rb +51 -0
- data/lib/gps_pvt/receiver.rb +49 -32
- data/lib/gps_pvt/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b87c77fbb3844eb0fd835ef079b8a379708a6fe24e3de4ceeb6934206573f489
|
4
|
+
data.tar.gz: a280c1aa82bed41319e13069907940a062a073a0b01c95eefa3d3d8c1b32c517
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 761d7e99868e04d93adb48fac0345ff71467068657c544efe857ed4f6206ed8d11698871ad7dc73c232f4bd51094cf13c6752d96fc17307caccb4a2eab8dbe03
|
7
|
+
data.tar.gz: fd70c1d59dbf3885e7a2286726a9c16e0cfbec3097a105bbffde59e3a65ee22eb09f1d0b4032b371faf2d1695b074b0752f37763ef6b5716dd4214fed4566755
|
data/Rakefile
CHANGED
data/exe/gps_pvt
CHANGED
@@ -92,23 +92,7 @@ files.collect!{|fname, ftype|
|
|
92
92
|
rcv = GPS_PVT::Receiver::new(options)
|
93
93
|
|
94
94
|
proc{|src|
|
95
|
-
|
96
|
-
loader = proc{|t_meas|
|
97
|
-
utc = Time::utc(*t_meas.c_tm)
|
98
|
-
y, yday = [:year, :yday].collect{|f| utc.send(f)}
|
99
|
-
uri = URI::parse(
|
100
|
-
"ftp://gssc.esa.int/gnss/data/daily/" +
|
101
|
-
"%04d/brdc/BRDC00IGS_R_%04d%03d0000_01D_MN.rnx.gz"%[y, y, yday])
|
102
|
-
rcv.parse_rinex_nav(uri)
|
103
|
-
uri
|
104
|
-
}
|
105
|
-
run_orig = rcv.method(:run)
|
106
|
-
eph_list = {}
|
107
|
-
rcv.define_singleton_method(:run){|meas, t_meas, *args|
|
108
|
-
w_d = [t_meas.week, (t_meas.seconds.to_i / 86400)]
|
109
|
-
eph_list[w_d] ||= loader.call(t_meas)
|
110
|
-
run_orig.call(meas, t_meas, *args)
|
111
|
-
}
|
95
|
+
rcv.attach_online_ephemeris(src) if src
|
112
96
|
}.call(misc_options[:online_ephemeris])
|
113
97
|
|
114
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,21 @@ 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
|
+
|
77
|
+
proc{
|
78
|
+
cache = nil
|
79
|
+
rcv.define_singleton_method(:leap_seconds){|t_meas|
|
80
|
+
cache ||= if self.solver.gps_space_node.is_valid_utc then
|
81
|
+
self.solver.gps_space_node.iono_utc.delta_t_LS
|
82
|
+
else
|
83
|
+
t_meas.leap_seconds
|
84
|
+
end
|
85
|
+
}
|
86
|
+
}.call
|
87
|
+
|
71
88
|
# parse RINEX NAV
|
72
89
|
files.each{|fname, ftype|
|
73
90
|
case ftype
|
@@ -84,6 +101,92 @@ files.each{|fname, ftype|
|
|
84
101
|
|
85
102
|
obs.sort!{|a, b| a[0] <=> b[0]} # Sort by measurement time
|
86
103
|
|
104
|
+
# Add dummy before actual first observation in order to notify time to solver
|
105
|
+
obs.unshift([obs[0][0] - 1, GPS_PVT::GPS::Measurement::new])
|
106
|
+
|
107
|
+
gen_sfrb, gen_sfrbx = proc{
|
108
|
+
cache = {}
|
109
|
+
sfrb_tmpl = [0xB5, 0x62, 0x02, 0x11, 0, 0]
|
110
|
+
sfrb_tmpl += [0, 0] # ch, id
|
111
|
+
sfrbx_tmpl = [0xB5, 0x62, 0x02, 0x13, 0, 0]
|
112
|
+
sfrbx_tmpl += [0, 0, 0, 0, 0, 0, 2, 0] # version = 2
|
113
|
+
iono_utc = rcv.solver.gps_space_node.iono_utc.instance_eval{
|
114
|
+
f_orig = method(:dump)
|
115
|
+
define_singleton_method(:dump){|t_meas|
|
116
|
+
rcv.solver.gps_space_node.is_valid_iono_utc ? f_orig.call(t_meas) : []
|
117
|
+
}
|
118
|
+
self
|
119
|
+
}
|
120
|
+
[proc{|t_meas, meas| # Convert to RXM-SFRB(0x11)
|
121
|
+
meas.collect{|sat, items|
|
122
|
+
t_prv, eph, ch = cache.include?(sat) ? cache[sat] : []
|
123
|
+
next nil if t_prv && (t_meas - t_prv < misc_options[:eph_interval])
|
124
|
+
sfrb = sfrb_tmpl.clone
|
125
|
+
sfrb[6] = (ch ||= (cache.size % 0x100))
|
126
|
+
sfrb[7] = sat
|
127
|
+
res = case sat
|
128
|
+
when 1..32 # GPS
|
129
|
+
next nil unless (eph = rcv.ephemeris(t_meas, :GPS, sat))
|
130
|
+
(eph.dump(t_meas) + iono_utc.dump(t_meas)).each_slice(10).collect{|subframe|
|
131
|
+
ubx = sfrb + subframe.collect{|word|
|
132
|
+
word >> 6
|
133
|
+
}.pack("V*").unpack("C*") + [0, 0]
|
134
|
+
GPS_PVT::UBX::update(ubx)
|
135
|
+
}
|
136
|
+
when 120..158 # SBAS
|
137
|
+
next nil unless (eph = rcv.ephemeris(t_meas, :SBAS, sat))
|
138
|
+
ubx = sfrb + proc{|msg|
|
139
|
+
msg[7] >>= 6
|
140
|
+
msg
|
141
|
+
}.call(eph.dump + [0, 0]).pack("V*").unpack("C*") + [0, 0]
|
142
|
+
GPS_PVT::UBX::update(ubx)
|
143
|
+
else
|
144
|
+
next nil
|
145
|
+
end
|
146
|
+
cache[sat] = [t_meas, eph, ch]
|
147
|
+
res
|
148
|
+
}.compact.flatten.pack("C*")
|
149
|
+
},
|
150
|
+
proc{|t_meas, meas| # Convert to RXM-SFRBX(0x13)
|
151
|
+
meas.collect{|sat, items|
|
152
|
+
t_prv, eph, ch = cache.include?(sat) ? cache[sat] : []
|
153
|
+
next nil if t_prv && (t_meas - t_prv < misc_options[:eph_interval])
|
154
|
+
sfrbx = sfrbx_tmpl.clone
|
155
|
+
|
156
|
+
res = case sat
|
157
|
+
when 1..32, 193..202 # GPS, QZSS
|
158
|
+
sys = sat <= 32 ? :GPS : :QZSS
|
159
|
+
next nil unless (eph = rcv.ephemeris(t_meas, sys, sat))
|
160
|
+
sfrbx[6..7] = [GPS_PVT::UBX::GNSS_ID[sys], sys == :QZSS ? (sat - 192) : sat] # sys, id
|
161
|
+
sfrbx[10] = 10 # words
|
162
|
+
sfrbx[11] = (ch ||= (cache.size % 0x100)) # ch
|
163
|
+
(eph.dump(t_meas) + iono_utc.dump(t_meas)).each_slice(10).collect{|subframe|
|
164
|
+
GPS_PVT::UBX::update(sfrbx + subframe.pack("V*").unpack("C*") + [0, 0])
|
165
|
+
}
|
166
|
+
when 120..158 # SBAS
|
167
|
+
next nil unless (eph = rcv.ephemeris(t_meas, :SBAS, sat))
|
168
|
+
sfrbx[6..7] = [GPS_PVT::UBX::GNSS_ID[:SBAS], sat] # sys, id
|
169
|
+
sfrbx[10] = 8 # words
|
170
|
+
sfrbx[11] = (ch ||= (cache.size % 0x100)) # ch
|
171
|
+
GPS_PVT::UBX::update(sfrbx + eph.dump.pack("V*").unpack("C*") + [0, 0])
|
172
|
+
when (0x100 + 1)..(0x100 + 32) # GLONASS
|
173
|
+
svid = sat - 0x100
|
174
|
+
next nil unless (eph = rcv.ephemeris(t_meas, :GLONASS, svid))
|
175
|
+
sfrbx[6..7] = [GPS_PVT::UBX::GNSS_ID[:GLONASS], svid] # sys, id
|
176
|
+
sfrbx[10] = 4 # words
|
177
|
+
sfrbx[11] = (ch ||= (cache.size % 0x100)) # ch
|
178
|
+
eph.dump(t_meas).each_slice(3).collect{|str|
|
179
|
+
GPS_PVT::UBX::update(sfrbx + (str + [0]).pack("V*").unpack("C*") + [0, 0])
|
180
|
+
}
|
181
|
+
else
|
182
|
+
next nil
|
183
|
+
end
|
184
|
+
cache[sat] = [t_meas, eph, ch]
|
185
|
+
res
|
186
|
+
}.compact.flatten.pack("C*")
|
187
|
+
}]
|
188
|
+
}.call
|
189
|
+
|
87
190
|
glonass_freq_ch = proc{
|
88
191
|
freq0, delta = [:L1_frequency_base, :L1_frequency_gap].collect{|k|
|
89
192
|
GPS_PVT::GPS::SpaceNode_GLONASS.send(k)
|
@@ -92,7 +195,6 @@ glonass_freq_ch = proc{
|
|
92
195
|
}.call
|
93
196
|
|
94
197
|
gen_raw = proc{|t_meas, meas| # Convert to RXM-RAW(0x10)
|
95
|
-
meas = meas.to_hash
|
96
198
|
ubx = [0xB5, 0x62, 0x02, 0x10, 0, 0]
|
97
199
|
ubx += [(t_meas.seconds * 1E3).to_i, t_meas.week].pack("Vv").unpack("C*")
|
98
200
|
ubx += [0] * 2
|
@@ -142,17 +244,17 @@ gen_raw = proc{|t_meas, meas| # Convert to RXM-RAW(0x10)
|
|
142
244
|
}
|
143
245
|
|
144
246
|
gen_rawx = proc{|t_meas, meas| # Convert to RXM-RAWX(0x15)
|
145
|
-
meas = meas.to_hash
|
146
247
|
ubx = [0xB5, 0x62, 0x02, 0x15, 0, 0]
|
147
248
|
ubx += [t_meas.seconds, t_meas.week].pack("Ev").unpack("C*")
|
148
249
|
ubx += [0] * 6
|
149
|
-
|
250
|
+
gen_packet = proc{|sys, svid, sig, items|
|
150
251
|
res = [0] * 32
|
151
252
|
setter = proc{|value, offset, len, str, pre_proc|
|
152
253
|
array = case value
|
153
254
|
when Array; value
|
154
255
|
when Symbol
|
155
|
-
[
|
256
|
+
k = [sig, value].join('_').to_sym
|
257
|
+
[items[GPS_PVT::GPS::Measurement.const_get(k)]]
|
156
258
|
else
|
157
259
|
next nil
|
158
260
|
end
|
@@ -161,54 +263,82 @@ gen_rawx = proc{|t_meas, meas| # Convert to RXM-RAWX(0x15)
|
|
161
263
|
array = array.pack(str).unpack("C*") if str
|
162
264
|
res[offset - 16, len] = array
|
163
265
|
}
|
164
|
-
sys, svid = case sat
|
165
|
-
when 1..32 # GPS
|
166
|
-
[0, sat]
|
167
|
-
when 120..158 # SBAS
|
168
|
-
[1, sat]
|
169
|
-
when 193..202 # QZSS
|
170
|
-
[5, sat]
|
171
|
-
when (0x100 + 1)..(0x100 + 32) # GLONASS
|
172
|
-
setter.call(:L1_FREQUENCY,
|
173
|
-
39, 1, nil, proc{|v| v.replace(v[0] ? glonass_freq_ch.call(v[0]) : [7])})
|
174
|
-
[6, sat - 0x100]
|
175
|
-
else
|
176
|
-
next nil # TODO Galileo, Beidou, ...
|
177
|
-
end
|
178
|
-
setter.call([sys, svid], 36, 2)
|
179
266
|
|
267
|
+
setter.call([sys, svid], 36, 2)
|
268
|
+
|
180
269
|
trk_stat = 0
|
181
|
-
setter.call(:
|
270
|
+
setter.call(:PSEUDORANGE,
|
182
271
|
16, 8, "E", proc{|v| v[0] ? (trk_stat |= 0x1) : v.clear})
|
183
|
-
setter.call(:
|
272
|
+
setter.call(:PSEUDORANGE_SIGMA,
|
184
273
|
43, 1, nil, proc{|v|
|
185
274
|
b = (Math::log2(v[0] / 1E-2).to_i & 0xF) rescue 0x8
|
186
275
|
v.replace((trk_stat & 0x1 == 0x1) ? [b] : [])
|
187
276
|
})
|
188
|
-
setter.call(:
|
189
|
-
setter.call(:
|
277
|
+
setter.call(:DOPPLER, 32, 4, "e") rescue next nil
|
278
|
+
setter.call(:DOPPLER_SIGMA,
|
190
279
|
45, 1, nil, proc{|v| v.replace(v[0] ? [Math::log2(v[0] / 2E-3).to_i & 0xF] : [0x8])})
|
191
|
-
setter.call(:
|
280
|
+
setter.call(:CARRIER_PHASE,
|
192
281
|
24, 8, "E", proc{|v| v[0] ? (trk_stat |= 0x2) : v.clear})
|
193
|
-
setter.call(:
|
282
|
+
setter.call(:CARRIER_PHASE_SIGMA,
|
194
283
|
44, 1, nil, proc{|v|
|
195
284
|
b = ((v[0] / 0.004).to_i & 0xF) rescue 0x8
|
196
285
|
v.replace((trk_stat & 0x2 == 0x2) ? [b] : [])
|
197
286
|
})
|
198
|
-
setter.call(:
|
287
|
+
setter.call(:SIGNAL_STRENGTH_dBHz,
|
199
288
|
42, 1, nil, proc{|v| v.replace(v[0] ? [v[0].to_i] : [])})
|
200
|
-
setter.call(:
|
289
|
+
setter.call(:LOCK_SEC,
|
201
290
|
40, 2, "v", proc{|v| v.replace(v[0] ? [(v[0] / 1E-3).to_i] : [])})
|
202
291
|
setter.call([trk_stat], 46, 1)
|
292
|
+
res.define_singleton_method(:set, &setter)
|
203
293
|
|
204
294
|
res
|
295
|
+
}
|
296
|
+
meas_ubx = meas.inject([]){|packets, (sat, items)|
|
297
|
+
case sat
|
298
|
+
when 1..32 # GPS
|
299
|
+
packets << gen_packet.call(0, sat, :L1, items)
|
300
|
+
packets += {:L2CL => 3, :L2CM => 4}.collect{|sig, sigid|
|
301
|
+
next nil unless packet = gen_packet.call(0, sat, sig, items)
|
302
|
+
packet[38 - 16] = sigid
|
303
|
+
packet
|
304
|
+
}
|
305
|
+
when 120..158 # SBAS
|
306
|
+
packets << gen_packet.call(1, sat, :L1, items)
|
307
|
+
when 193..202 # QZSS
|
308
|
+
packets << gen_packet.call(5, sat, :L1, items)
|
309
|
+
packets += {:L2CL => 5, :L2CM => 4}.collect{|sig, sigid|
|
310
|
+
next nil unless packet = gen_packet.call(5, sat, sig, items)
|
311
|
+
packet[38 - 16] = sigid
|
312
|
+
packet
|
313
|
+
}
|
314
|
+
when (0x100 + 1)..(0x100 + 32) # GLONASS
|
315
|
+
packet = gen_packet.call(6, sat - 0x100, :L1, items)
|
316
|
+
packet.set(:FREQUENCY,
|
317
|
+
39, 1, nil,
|
318
|
+
proc{|v| v.replace([(v[0] ? glonass_freq_ch.call(v[0]) : 0) + 7])} ) if packet
|
319
|
+
packets << packet
|
320
|
+
else
|
321
|
+
# TODO Galileo, Beidou, ...
|
322
|
+
end
|
205
323
|
}.compact
|
324
|
+
|
325
|
+
proc{|ls| # leap seconds
|
326
|
+
next unless ls
|
327
|
+
ubx[6 + 10] = ls
|
328
|
+
ubx[6 + 12] |= 0x01
|
329
|
+
}.call(rcv.leap_seconds(t_meas))
|
206
330
|
ubx[6 + 11] = meas_ubx.size
|
207
|
-
ubx
|
331
|
+
ubx[6 + 13] = 1 # version
|
332
|
+
ubx += meas_ubx.flatten
|
208
333
|
ubx += [0, 0]
|
209
334
|
GPS_PVT::UBX::update(ubx).pack("C*")
|
210
335
|
}
|
211
336
|
|
212
|
-
|
337
|
+
gen_list = []
|
338
|
+
gen_list << (misc_options[:ubx_rawx] ? gen_sfrbx : gen_sfrb) if misc_options[:broadcast_data]
|
339
|
+
gen_list << (misc_options[:ubx_rawx] ? gen_rawx : gen_raw)
|
213
340
|
STDOUT.binmode
|
214
|
-
obs.each{
|
341
|
+
obs.each{|t_meas, meas|
|
342
|
+
meas2 = meas.to_hash
|
343
|
+
gen_list.each{|gen| print gen.call(t_meas, meas2)}
|
344
|
+
}
|