gps_pvt 0.8.0 → 0.8.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|