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 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
+ }