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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5bccc645ba148e24c0d8b43c1663ed245a6306eedfd376bdccf0f817977d5964
4
- data.tar.gz: 13b461cf2ce59b7064f4c69f13969f3e758974ae6dd331bf3628a901f76b3762
3
+ metadata.gz: b87c77fbb3844eb0fd835ef079b8a379708a6fe24e3de4ceeb6934206573f489
4
+ data.tar.gz: a280c1aa82bed41319e13069907940a062a073a0b01c95eefa3d3d8c1b32c517
5
5
  SHA512:
6
- metadata.gz: cebbb365561e4a2a56cadde92d69f03490313d56baa33ed5e14749220385a85813ee91cbdb93cb3980f66d69d95e1a63fb2852fb8441992767b64e7a80558ec5
7
- data.tar.gz: 251feae90231587a9e1c720ab20675084573b6ef1fc50429ad04223a1ad269eccc16d0e79cb7f4ffa547be95c1129a83e12e3edb5dc1495d20245cb1afc39693
6
+ metadata.gz: 761d7e99868e04d93adb48fac0345ff71467068657c544efe857ed4f6206ed8d11698871ad7dc73c232f4bd51094cf13c6752d96fc17307caccb4a2eab8dbe03
7
+ data.tar.gz: fd70c1d59dbf3885e7a2286726a9c16e0cfbec3097a105bbffde59e3a65ee22eb09f1d0b4032b371faf2d1695b074b0752f37763ef6b5716dd4214fed4566755
data/Rakefile CHANGED
@@ -45,6 +45,7 @@ namespace :git do
45
45
  + (<<-__SPARSE_PATTERNS__).lines.collect{|str| str.chomp.gsub(/^ */, ' ')}.join,
46
46
  tool/param/
47
47
  tool/util/text_helper.h
48
+ tool/util/bit_counter.h
48
49
  tool/algorithm/integral.h
49
50
  tool/algorithm/interpolate.h
50
51
  tool/navigation/GPS*
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
- next unless src
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
- :ubx_rawx => false
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
- meas_ubx = meas.collect{|sat, items|
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
- [items[GPS_PVT::GPS::Measurement.const_get(value)]]
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(:L1_PSEUDORANGE,
270
+ setter.call(:PSEUDORANGE,
182
271
  16, 8, "E", proc{|v| v[0] ? (trk_stat |= 0x1) : v.clear})
183
- setter.call(:L1_PSEUDORANGE_SIGMA,
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(:L1_DOPPLER, 32, 4, "e")
189
- setter.call(:L1_DOPPLER_SIGMA,
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(:L1_CARRIER_PHASE,
280
+ setter.call(:CARRIER_PHASE,
192
281
  24, 8, "E", proc{|v| v[0] ? (trk_stat |= 0x2) : v.clear})
193
- setter.call(:L1_CARRIER_PHASE_SIGMA,
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(:L1_SIGNAL_STRENGTH_dBHz,
287
+ setter.call(:SIGNAL_STRENGTH_dBHz,
199
288
  42, 1, nil, proc{|v| v.replace(v[0] ? [v[0].to_i] : [])})
200
- setter.call(:L1_LOCK_SEC,
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 += meas_ubx.flatten(1)
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
- gen = misc_options[:ubx_rawx] ? gen_rawx : gen_raw
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{|*item| print gen.call(*item)}
341
+ obs.each{|t_meas, meas|
342
+ meas2 = meas.to_hash
343
+ gen_list.each{|gen| print gen.call(t_meas, meas2)}
344
+ }