gps_pvt 0.2.0 → 0.3.0

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.
@@ -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: []