gps_pvt 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -221,7 +221,11 @@ __RINEX_OBS_TEXT__
221
221
  f.path
222
222
  },
223
223
  }}
224
- let(:solver){GPS::Solver::new}
224
+ let(:solver){
225
+ res = GPS::Solver::new
226
+ res.correction = {:gps_ionospheric => :klobuchar, :gps_tropospheric => :hopfield}
227
+ res
228
+ }
225
229
 
226
230
  describe 'demo' do
227
231
  it 'calculates position without any error' do
@@ -255,7 +259,6 @@ __RINEX_OBS_TEXT__
255
259
  [:alpha, :beta].each{|k|
256
260
  puts "Iono #{k}: #{sn.iono_utc.send(k)}"
257
261
  }
258
- puts solver.gps_options.ionospheric_models
259
262
 
260
263
  meas.each{|prn, k, v|
261
264
  eph = sn.ephemeris(prn)
@@ -336,11 +339,26 @@ __RINEX_OBS_TEXT__
336
339
 
337
340
  it 'can be modified through hooks' do
338
341
  sn = solver.gps_space_node
342
+ expect(solver.correction[:gps_ionospheric]).to include(:klobuchar)
343
+ expect(solver.correction[:gps_tropospheric]).to include(:hopfield)
344
+ expect{solver.correction = nil}.to raise_error(RuntimeError)
345
+ expect{solver.correction = {
346
+ :gps_ionospheric => [proc{|t, usr_pos, sat_pos|
347
+ expect(t).to be_a_kind_of(GPS::Time)
348
+ expect(usr_pos).to be_a_kind_of(Coordinate::XYZ) unless usr_pos
349
+ expect(sat_pos).to be_a_kind_of(Coordinate::ENU) unless sat_pos
350
+ false
351
+ }, :klobuchar, :no_correction],
352
+ :options => {:f_10_7 => 10},
353
+ }}.not_to raise_error
354
+ expect(solver.correction[:gps_ionospheric]).to include(:no_correction)
355
+ expect(solver.correction[:options][:f_10_7]).to eq(10)
339
356
  sn.read(input[:rinex_nav])
340
357
  t_meas = GPS::Time::new(1849, 172413)
341
358
  sn.update_all_ephemeris(t_meas)
342
- solver.hooks[:relative_property] = proc{|prn, rel_prop, rcv_e, t_arv, usr_pos, usr_vel|
359
+ solver.hooks[:relative_property] = proc{|prn, rel_prop, meas, rcv_e, t_arv, usr_pos, usr_vel|
343
360
  expect(input[:measurement]).to include(prn)
361
+ expect(meas).to be_a_kind_of(Hash)
344
362
  expect(t_arv).to be_a_kind_of(GPS::Time)
345
363
  expect(usr_pos).to be_a_kind_of(Coordinate::XYZ)
346
364
  expect(usr_vel).to be_a_kind_of(Coordinate::XYZ)
@@ -348,12 +366,30 @@ __RINEX_OBS_TEXT__
348
366
  weight = 1
349
367
  [weight, range_c, range_r, rate_rel_neg] + los_neg
350
368
  }
351
- solver.hooks[:update_position_solution] = proc{|*mats|
352
- mats.each{|mat|
369
+ solver.hooks[:update_position_solution] = proc{|mat_G, mat_W, mat_delta_r, temp_pvt|
370
+ expect(temp_pvt).to be_a_kind_of(GPS::PVT)
371
+ [mat_G, mat_W, mat_delta_r].each{|mat|
353
372
  expect(mat).to be_a_kind_of(SylphideMath::MatrixD)
373
+ expect(mat.rows).to be >= temp_pvt.used_satellites
374
+ expect(mat).to respond_to(:resize!)
354
375
  }
355
- mat_G, mat_W, mat_delta_r = mats
356
376
  }
377
+ solver.hooks[:satellite_position] = proc{
378
+ i = 0
379
+ proc{|prn, time, pos|
380
+ expect(input[:measurement]).to include(prn)
381
+ expect(pos).to be_a_kind_of(Coordinate::XYZ).or eq(nil)
382
+ # System_XYZ or [x,y,z] or nil(= unknown position) are acceptable
383
+ case (i += 1) % 5
384
+ when 0
385
+ nil
386
+ when 1
387
+ pos.to_a
388
+ else
389
+ pos
390
+ end
391
+ }
392
+ }.call
357
393
  pvt = solver.solve(
358
394
  input[:measurement].collect{|prn, items|
359
395
  items.collect{|k, v| [prn, k, v]}
@@ -19,6 +19,12 @@ shared_examples 'Matrix' do
19
19
  expect( mat_type::new(*params[:rc]).rows ).to equal(params[:rc][0])
20
20
  expect( mat_type::new(*params[:rc]).columns ).to equal(params[:rc][1])
21
21
  end
22
+ it 'declines negative number argument' do
23
+ [[-1, 1], [1, -1]].each{|sf|
24
+ r, c = params[:rc].zip(sf).collect{|v1, v2| v1 * v2}
25
+ expect{ mat_type::new(r, c) }.to raise_error(ArgumentError)
26
+ }
27
+ end
22
28
  it 'accepts ([[]])' do
23
29
  expect{ mat_type::new(compare_with) }.not_to raise_error
24
30
  expect( mat_type::new(compare_with).rows ).to equal(params[:rc][0])
@@ -44,9 +50,11 @@ shared_examples 'Matrix' do
44
50
  a.define_singleton_method(:[]){|i, j| raise(IndexError) if i != j; 0}
45
51
  expect{ mat_type::new(a) }.to raise_error(IndexError)
46
52
 
47
- a = a_gen.call
48
- a.define_singleton_method(:row_size){-1}
49
- expect{ mat_type::new(a) }.to raise_error(RuntimeError)
53
+ [:row_size, :column_size].each{|f|
54
+ a = a_gen.call
55
+ a.define_singleton_method(f){-1}
56
+ expect{ mat_type::new(a) }.to raise_error(RuntimeError)
57
+ }
50
58
  end
51
59
  it 'is invoked with I, identity, unit' do
52
60
  [:I, :identity, :unit].each{|f|
@@ -132,7 +140,7 @@ shared_examples 'Matrix' do
132
140
  expect(mat[:square].sum).to eq(Matrix[*mat[:square].to_a].sum)
133
141
  expect(mat[:not_square].sum).to eq(Matrix[*mat[:not_square].to_a].sum)
134
142
  end
135
- it 'determinat, det' do
143
+ it 'determinant, det' do
136
144
  [:determinant, :det].each{|f|
137
145
  #expect(mat[:square].send(f)).to eq(Matrix[*mat[:square].to_a].det)
138
146
  expect{mat[:not_square].send(f)}.to raise_error(RuntimeError)
@@ -163,6 +171,15 @@ shared_examples 'Matrix' do
163
171
  }
164
172
  }
165
173
  end
174
+ it 'is inaccessible and unchangeable with negative number arguments' do
175
+ [[-1, 0], [0, -1]].each{|i, j|
176
+ [[:[], i, j], [:[]=, i, j, 0]].each{|args|
177
+ expect{ mat[0].send(*args) }.to raise_error{|err|
178
+ expect(err).to be_a(RangeError).or be_a(ArgumentError)
179
+ }
180
+ }
181
+ }
182
+ end
166
183
  end
167
184
 
168
185
  describe 'elements' do
@@ -394,6 +411,23 @@ shared_examples 'Matrix' do
394
411
  }
395
412
  expect{mat[2] / mat[3]}.to raise_error(RuntimeError)
396
413
  end
414
+ it 'have resize!' do
415
+ [-1, :sym].each{|arg|
416
+ [[arg, nil], [nil, arg]].each{|args|
417
+ expect{mat[0].resize!(*args)}.to raise_error{|err|
418
+ expect(err).to be_a(TypeError).or be_a(ArgumentError)
419
+ }
420
+ }
421
+ }
422
+ mat_orig = mat[0].to_a
423
+ r, c = [:rows, :columns].collect{|f| mat[0].send(f)}
424
+ expect(mat[0].resize!(r, c).to_a).to eq(mat_orig)
425
+ expect(mat[0].resize!(r, nil).to_a).to eq(mat_orig)
426
+ expect(mat[0].resize!(nil, c).to_a).to eq(mat_orig)
427
+ expect(mat[0].resize!(nil, nil).to_a).to eq(mat_orig)
428
+ expect(mat[0].resize!(r * 2, c * 2).to_a).to \
429
+ eq(Matrix::build(r * 2, c * 2){|i, j| (i < r && j < c) ? mat_orig[i][j] : 0}.to_a)
430
+ end
397
431
  end
398
432
 
399
433
  describe 'decomposition' do
data/gps_pvt.gemspec ADDED
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/gps_pvt/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "gps_pvt"
7
+ spec.version = GPS_PVT::VERSION
8
+ spec.authors = ["fenrir(M.Naruoka)"]
9
+ spec.email = ["fenrir.naru@gmail.com"]
10
+
11
+ spec.summary = "GPS position, velocity, and time (PVT) solver"
12
+ spec.description = "This module calculate PVT by using raw observation obtained from a GPS receiver"
13
+ spec.homepage = "https://github.com/fenrir-naru/gps_pvt"
14
+ spec.required_ruby_version = ">= 2.3.0"
15
+
16
+ #spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
17
+
18
+ spec.metadata["homepage_uri"] = spec.homepage
19
+ spec.metadata["source_code_uri"] = spec.homepage
20
+ #spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
21
+
22
+ spec.extensions = ["ext/gps_pvt/extconf.rb"]
23
+
24
+ # Specify which files should be added to the gem when it is released.
25
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
26
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
27
+ `git ls-files -z`.split("\x0").reject do |f|
28
+ (f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
29
+ end
30
+ end
31
+ spec.bindir = "exe"
32
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
33
+ spec.require_paths = ["lib"]
34
+
35
+ spec.files += proc{
36
+ require 'pathname'
37
+ base_dir = Pathname::new(File::absolute_path(File.dirname(__FILE__)))
38
+ # get an array of submodule dirs by executing 'pwd' inside each submodule
39
+ `git submodule --quiet foreach pwd`.split($/).collect{|dir|
40
+ # issue git ls-files in submodule's directory
41
+ `git -C #{dir} ls-files -v`.split($/).collect{|f|
42
+ next nil unless f =~ /^H */ # consider git sparse checkout
43
+ # get relative path
44
+ f = Pathname::new(File::join(dir, $'))
45
+ begin
46
+ (f.relative? ? f : f.relative_path_from(base_dir)).to_s
47
+ rescue
48
+ # Patch for Windows drive letter problem
49
+ base_dir = Pathname::new(base_dir.to_s.sub(/^([^\/])+:\//){"/#{$1}/"})
50
+ f.relative_path_from(base_dir).to_s
51
+ end
52
+ }.compact
53
+ }.flatten
54
+ }.call
55
+
56
+ # Uncomment to register a new dependency of your gem
57
+ # spec.add_dependency "example-gem", "~> 1.0"
58
+ spec.add_development_dependency "rake"
59
+ spec.add_development_dependency "rake-compiler"
60
+
61
+ # For more information and examples about making a new gem, checkout our
62
+ # guide at: https://bundler.io/guides/creating_gem.html
63
+ end
@@ -47,23 +47,31 @@ class Receiver
47
47
  ]] + [
48
48
  [:used_satellites, proc{|pvt| pvt.used_satellites}],
49
49
  ] + opt[:system].collect{|sys, range|
50
- bit_flip = if range.kind_of?(Array) then
51
- proc{|res, i|
50
+ range = range.kind_of?(Array) ? proc{
51
+ # check whether inputs can be converted to Range
52
+ next nil if range.empty?
53
+ a, b = range.minmax
54
+ ((b - a) == (range.length - 1)) ? (a..b) : range
55
+ }.call : range
56
+ next nil unless range
57
+ bit_flip, label = case range
58
+ when Array
59
+ [proc{|res, i|
52
60
  res[i] = "1" if i = range.index(i)
53
61
  res
54
- }
55
- else # expect Range
62
+ }, range.collect{|pen| pen & 0xFF}.reverse.join('+')]
63
+ when Range
56
64
  base_prn = range.min
57
- proc{|res, i|
65
+ [proc{|res, i|
58
66
  res[i - base_prn] = "1" if range.include?(i)
59
67
  res
60
- }
68
+ }, [:max, :min].collect{|f| range.send(f) & 0xFF}.join('..')]
61
69
  end
62
- ["#{sys}_PRN", proc{|pvt|
70
+ ["#{sys}_PRN(#{label})", proc{|pvt|
63
71
  pvt.used_satellite_list.inject("0" * range.size, &bit_flip) \
64
72
  .scan(/.{1,8}/).join('_').reverse
65
73
  }]
66
- } + [[
74
+ }.compact + [[
67
75
  opt[:satellites].collect{|prn, label|
68
76
  [:range_residual, :weight, :azimuth, :elevation, :slopeH, :slopeV].collect{|str|
69
77
  "#{str}(#{label || prn})"
@@ -73,12 +81,12 @@ class Receiver
73
81
  next ([nil] * 6 * opt[:satellites].size) unless pvt.position_solved?
74
82
  sats = pvt.used_satellite_list
75
83
  r, w = [:delta_r, :W].collect{|f| pvt.send(f)}
76
- opt[:satellites].collect{|i|
77
- next ([nil] * 6) unless i2 = sats.index(i)
84
+ opt[:satellites].collect{|prn, label|
85
+ next ([nil] * 6) unless i2 = sats.index(prn)
78
86
  [r[i2, 0], w[i2, i2]] +
79
87
  [:azimuth, :elevation].collect{|f|
80
- pvt.send(f)[i] / Math::PI * 180
81
- } + [pvt.slopeH[i], pvt.slopeV[i]]
88
+ pvt.send(f)[prn] / Math::PI * 180
89
+ } + [pvt.slopeH[prn], pvt.slopeV[prn]]
82
90
  }.flatten
83
91
  },
84
92
  ]] + [[
@@ -106,16 +114,19 @@ class Receiver
106
114
  opt = {
107
115
  :satellites => (1..32).to_a,
108
116
  }.merge(opt)
117
+ keys = [:PSEUDORANGE, :RANGE_RATE, :DOPPLER, :FREQUENCY].collect{|k|
118
+ GPS::Measurement.const_get("L1_#{k}".to_sym)
119
+ }
109
120
  [[
110
121
  opt[:satellites].collect{|prn, label|
111
122
  [:L1_range, :L1_rate].collect{|str| "#{str}(#{label || prn})"}
112
123
  }.flatten,
113
124
  proc{|meas|
114
- meas_hash = Hash[*(meas.collect{|prn, k, v| [[prn, k], v]}.flatten(1))]
115
- opt[:satellites].collect{|prn|
116
- [:L1_PSEUDORANGE, [:L1_DOPPLER, GPS::SpaceNode.L1_WaveLength]].collect{|k, sf|
117
- meas_hash[[prn, GPS::Measurement.const_get(k)]] * (sf || 1) rescue nil
118
- }
125
+ meas_hash = meas.to_hash
126
+ opt[:satellites].collect{|prn, label|
127
+ pr, rate, doppler, freq = keys.collect{|k| meas_hash[prn][k] rescue nil}
128
+ freq ||= GPS::SpaceNode.L1_Frequency
129
+ [pr, rate || ((doppler * GPS::SpaceNode::light_speed / freq) rescue nil)]
119
130
  }
120
131
  }
121
132
  ]]
@@ -130,11 +141,19 @@ class Receiver
130
141
 
131
142
  def initialize(options = {})
132
143
  @solver = GPS::Solver::new
133
- @solver.hooks[:relative_property] = proc{|prn, rel_prop, rcv_e, t_arv, usr_pos, usr_vel|
144
+ @solver.hooks[:relative_property] = proc{|prn, rel_prop, meas, rcv_e, t_arv, usr_pos, usr_vel|
134
145
  rel_prop[0] = 1 if rel_prop[0] > 0 # weight = 1
135
146
  rel_prop
136
147
  }
137
148
  @debug = {}
149
+ solver_opts = [:gps_options, :sbas_options].collect{|target|
150
+ @solver.send(target)
151
+ }
152
+ solver_opts.each{|opt|
153
+ # default solver options
154
+ opt.elevation_mask = 0.0 / 180 * Math::PI # 0 deg (use satellite over horizon)
155
+ opt.residual_mask = 1E4 # 10 km (without residual filter, practically)
156
+ }
138
157
  output_options = {
139
158
  :system => [[:GPS, 1..32], [:QZSS, 193..202]],
140
159
  :satellites => (1..32).to_a + (193..202).to_a, # [idx, ...] or [[idx, label], ...] is acceptable
@@ -148,7 +167,7 @@ class Receiver
148
167
  when :weight
149
168
  case v.to_sym
150
169
  when :elevation # (same as underneath C++ library)
151
- @solver.hooks[:relative_property] = proc{|prn, rel_prop, rcv_e, t_arv, usr_pos, usr_vel|
170
+ @solver.hooks[:relative_property] = proc{|prn, rel_prop, meas, rcv_e, t_arv, usr_pos, usr_vel|
152
171
  if rel_prop[0] > 0 then
153
172
  elv = Coordinate::ENU::relative_rel(
154
173
  Coordinate::XYZ::new(*rel_prop[4..6]), usr_pos).elevation
@@ -160,6 +179,13 @@ class Receiver
160
179
  when :identical # same as default
161
180
  next true
162
181
  end
182
+ when :elevation_mask_deg
183
+ raise "Unknown elevation mask angle: #{v}" unless elv_deg = (Float(v) rescue nil)
184
+ $stderr.puts "Elevation mask: #{elv_deg} deg"
185
+ solver_opts.each{|opt|
186
+ opt.elevation_mask = elv_deg / 180 * Math::PI # 0 deg (use satellite over horizon)
187
+ }
188
+ next true
163
189
  when :base_station
164
190
  crd, sys = v.split(/ *, */).collect.with_index{|item, i|
165
191
  case item
@@ -193,9 +219,9 @@ class Receiver
193
219
  sys, svid = case spec
194
220
  when Integer
195
221
  [nil, spec]
196
- when /([a-zA-Z]+)(?::(-?\d+))?/
197
- [$1.upcase.to_sym, (Integre($2) rescue nil)]
198
- when /-?\d+/
222
+ when /^([a-zA-Z]+)(?::(-?\d+))?$/
223
+ [$1.upcase.to_sym, (Integer($2) rescue nil)]
224
+ when /^-?\d+$/
199
225
  [nil, $&.to_i]
200
226
  else
201
227
  next false
@@ -206,27 +232,37 @@ class Receiver
206
232
  else
207
233
  (k == :with) ? :include : :exclude
208
234
  end
209
- if (sys == :GPS) || (sys == :QZSS) \
210
- || (svid && ((1..32).include?(svid) || (193..202).include?(svid))) then
211
- [svid || ((1..32).to_a + (193..202).to_a)].flatten.each{
212
- @solver.gps_options.send(mode, svid)
213
- }
214
- elsif (sys == :SBAS) || (svid && (120..158).include?(svid)) then
215
- prns = [svid || (120..158).to_a].flatten
216
- unless (i = output_options[:system].index{|sys, range| sys == :SBAS}) then
235
+ update_output = proc{|sys_target, prns, labels|
236
+ unless (i = output_options[:system].index{|sys, range| sys == sys_target}) then
217
237
  i = -1
218
- output_options[:system] << [:SBAS, []]
238
+ output_options[:system] << [sys_target, []]
219
239
  else
220
- output_options[:system][i].reject!{|prn| prns.include?(prn)}
240
+ output_options[:system][i][1].reject!{|prn| prns.include?(prn)}
221
241
  end
222
242
  output_options[:satellites].reject!{|prn, label| prns.include?(prn)}
223
243
  if mode == :include then
224
244
  output_options[:system][i][1] += prns
225
- output_options[:satellites] += prns
245
+ output_options[:system][i][1].sort!
246
+ output_options[:satellites] += (labels ? prns.zip(labels) : prns)
247
+ output_options[:satellites].sort!{|a, b| [a].flatten[0] <=> [b].flatten[0]}
226
248
  end
249
+ }
250
+ check_sys_svid = proc{|sys_target, range_in_sys, offset|
251
+ next range_in_sys.include?(svid - (offset || 0)) unless sys # svid is specified without system
252
+ next false unless sys == sys_target
253
+ next true unless svid # All satellites in a target system (svid == nil)
254
+ range_in_sys.include?(svid)
255
+ }
256
+ if check_sys_svid.call(:GPS, 1..32) then
257
+ [svid || (1..32).to_a].flatten.each{|prn| @solver.gps_options.send(mode, prn)}
258
+ elsif check_sys_svid.call(:SBAS, 120..158) then
259
+ prns = [svid || (120..158).to_a].flatten
260
+ update_output.call(:SBAS, prns)
227
261
  prns.each{|prn| @solver.sbas_options.send(mode, prn)}
262
+ elsif check_sys_svid.call(:QZSS, 193..202) then
263
+ [svid || (193..202).to_a].flatten.each{|prn| @solver.gps_options.send(mode, prn)}
228
264
  else
229
- next false
265
+ raise "Unknown satellite: #{spec}"
230
266
  end
231
267
  $stderr.puts "#{mode.capitalize} satellite: #{[sys, svid].compact.join(':')}"
232
268
  }
@@ -235,10 +271,6 @@ class Receiver
235
271
  false
236
272
  }
237
273
  raise "Unknown receiver options: #{options.inspect}" unless options.empty?
238
- proc{|opt|
239
- opt.elevation_mask = 0.0 / 180 * Math::PI # 0 deg
240
- opt.residual_mask = 1E4 # 10 km
241
- }.call(@solver.gps_options)
242
274
  @output = {
243
275
  :pvt => Receiver::pvt_items(output_options),
244
276
  :meas => Receiver::meas_items(output_options),
@@ -316,6 +348,11 @@ class Receiver
316
348
  [:azimuth, :elevation, :slopeH, :slopeV].each{|k|
317
349
  eval("define_method(:#{k}){@#{k} || self.post_solution(:@#{k})}")
318
350
  }
351
+ define_method(:other_state){
352
+ # If a design matrix G has columns larger than 4,
353
+ # other states excluding position and time are estimated.
354
+ (self.G.rows <= 4) ? [] : (self.S * self.delta_r).transpose.to_a[0][4..-1]
355
+ }
319
356
  }
320
357
 
321
358
  proc{
@@ -477,8 +514,15 @@ class Receiver
477
514
  end
478
515
 
479
516
  def parse_rinex_nav(fname)
480
- $stderr.puts "Read RINEX NAV file (%s): %d items."%[
481
- fname, @solver.gps_space_node.read(fname)]
517
+ items = [
518
+ @solver.gps_space_node,
519
+ @solver.sbas_space_node,
520
+ ].inject(0){|res, sn|
521
+ loaded_items = sn.send(:read, fname)
522
+ raise "Format error! (Not RINEX) #{fname}" if loaded_items < 0
523
+ res + loaded_items
524
+ }
525
+ $stderr.puts "Read RINEX NAV file (%s): %d items."%[fname, items]
482
526
  end
483
527
 
484
528
  def parse_rinex_obs(fname, &b)
@@ -515,7 +559,8 @@ class Receiver
515
559
  when 'J'; prn += 192
516
560
  else; next
517
561
  end
518
- (types[sys] || []).each{|i, type_|
562
+ types[sys] = (types[' '] || []) unless types[sys]
563
+ types[sys].each{|i, type_|
519
564
  meas.add(prn, type_, v[i][0]) if v[i]
520
565
  }
521
566
  }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GPS_PVT
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gps_pvt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - fenrir(M.Naruoka)
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-01-26 00:00:00.000000000 Z
11
+ date: 2022-03-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -89,6 +89,7 @@ files:
89
89
  - ext/ninja-scan-light/tool/swig/makefile
90
90
  - ext/ninja-scan-light/tool/swig/spec/GPS_spec.rb
91
91
  - ext/ninja-scan-light/tool/swig/spec/SylphideMath_spec.rb
92
+ - gps_pvt.gemspec
92
93
  - lib/gps_pvt.rb
93
94
  - lib/gps_pvt/receiver.rb
94
95
  - lib/gps_pvt/ubx.rb
@@ -99,7 +100,7 @@ licenses: []
99
100
  metadata:
100
101
  homepage_uri: https://github.com/fenrir-naru/gps_pvt
101
102
  source_code_uri: https://github.com/fenrir-naru/gps_pvt
102
- post_install_message:
103
+ post_install_message:
103
104
  rdoc_options: []
104
105
  require_paths:
105
106
  - lib
@@ -114,8 +115,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
114
115
  - !ruby/object:Gem::Version
115
116
  version: '0'
116
117
  requirements: []
117
- rubygems_version: 3.0.3
118
- signing_key:
118
+ rubygems_version: 3.1.2
119
+ signing_key:
119
120
  specification_version: 4
120
121
  summary: GPS position, velocity, and time (PVT) solver
121
122
  test_files: []