gps_pvt 0.7.2 → 0.8.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b2eb20de6303a24b0e5b134c7c78cd1edb043ff38d823181e596b4626b6bc536
4
- data.tar.gz: 183ae6e8cfd2577132113bb3684e6e225989ce444d6647820496b13ddd3a4903
3
+ metadata.gz: 5bccc645ba148e24c0d8b43c1663ed245a6306eedfd376bdccf0f817977d5964
4
+ data.tar.gz: 13b461cf2ce59b7064f4c69f13969f3e758974ae6dd331bf3628a901f76b3762
5
5
  SHA512:
6
- metadata.gz: a35228704032066f682e15f5abf6f8a2238d90424e6b50182e07b8fc342a1f4150ba6747ca88a9fcaef163e0ce8149a68edf087e6c0f5525a2c7a09553beb504
7
- data.tar.gz: 10ace25d753123375bf8ad46cbd4d7490b13219522b39ee5774a1df6d3ba1fd3fd9f318364a19253981f24a3b83998e5df9bb82700b37d6d7f17bd1ad27ad14d
6
+ metadata.gz: cebbb365561e4a2a56cadde92d69f03490313d56baa33ed5e14749220385a85813ee91cbdb93cb3980f66d69d95e1a63fb2852fb8441992767b64e7a80558ec5
7
+ data.tar.gz: 251feae90231587a9e1c720ab20675084573b6ef1fc50429ad04223a1ad269eccc16d0e79cb7f4ffa547be95c1129a83e12e3edb5dc1495d20245cb1afc39693
data/README.md CHANGED
@@ -32,7 +32,7 @@ An attached executable is useful. After installation, type
32
32
 
33
33
  $ gps_pvt file_or_URI(s)
34
34
 
35
- The format of file is automatically determined with its extension, such as .ubx will be treated as UBX format. A compressed file of .gz or .Z can be specified directly (decompression is internally performed), and URI such as http(s)://... and ftp:// is also acceptable. If you want to specify the file format, instead of file_or_URI(s), use the following arguments:
35
+ The format of file is automatically determined with its extension, such as .ubx will be treated as UBX format. A compressed file of .gz or .Z can be specified directly (decompression is internally performed). URI such as http(s)://... and ftp://, and serial port (COMn for Windows and /dev/tty* for *NIX, version >= 0.8.0) are also acceptable. If you want to specify the file format, instead of file_or_URI(s), use the following arguments:
36
36
 
37
37
  | specification | recoginized as |
38
38
  ----|----
data/exe/gps_pvt CHANGED
@@ -14,7 +14,7 @@ If you want to specify its format manually, command options like --rinex_nav=fil
14
14
  Other than --rinex_nav, --rinex_obs, -rinex_clk, --ubx, --sp3 or --antex are supported.
15
15
  Supported RINEX versions are 2 and 3.
16
16
  A file having additional ".gz" or ".Z" extension is recognized as a compressed file.
17
- Major URL such as http(s)://... or ftp://... is acceptable as an input file name.
17
+ Major URL such as http(s)://... or ftp://..., and serial port (COMn for Windows, /dev/tty* for *NIX) is acceptable as an input file name.
18
18
  __STRING__
19
19
 
20
20
  options = []
@@ -80,6 +80,7 @@ files.collect!{|fname, ftype|
80
80
  end
81
81
  fname = proc{
82
82
  next fname if File::exist?(fname)
83
+ next fname if ((fname =~ Serial::SPEC) rescue false)
83
84
  if uri = URI::parse(fname) and !uri.instance_of?(URI::Generic) then
84
85
  next uri
85
86
  end
data/gps_pvt.gemspec CHANGED
@@ -58,6 +58,7 @@ Gem::Specification.new do |spec|
58
58
 
59
59
  # Uncomment to register a new dependency of your gem
60
60
  # spec.add_dependency "example-gem", "~> 1.0"
61
+ spec.add_dependency "rubyserial"
61
62
  spec.add_development_dependency "rake"
62
63
  spec.add_development_dependency "rake-compiler"
63
64
 
@@ -154,6 +154,7 @@ class Receiver
154
154
  :skip_exclusion => true, # default is to skip fault exclusion calculation
155
155
  }
156
156
  @debug = {}
157
+ @semaphore = Mutex::new
157
158
  solver_opts = [:gps_options, :sbas_options, :glonass_options].collect{|target|
158
159
  @solver.send(target)
159
160
  }
@@ -298,6 +299,24 @@ class Receiver
298
299
  :meas => Receiver::meas_items(output_options),
299
300
  }
300
301
  end
302
+
303
+ def critical(&b)
304
+ begin
305
+ @semaphore.synchronize{b.call}
306
+ rescue ThreadError # recovery from deadlock
307
+ b.call
308
+ end
309
+ end
310
+
311
+ class << self
312
+ def make_critical(fname)
313
+ f_orig = instance_method(fname)
314
+ define_method(fname){|*args, &b|
315
+ critical{f_orig.bind(self).call(*args, &b)}
316
+ }
317
+ end
318
+ private :make_critical
319
+ end
301
320
 
302
321
  GPS::Measurement.class_eval{
303
322
  proc{
@@ -331,7 +350,7 @@ class Receiver
331
350
  =end
332
351
 
333
352
  #@solver.gps_space_node.update_all_ephemeris(t_meas) # internally called in the following solver.solve
334
- pvt = @solver.solve(meas, t_meas)
353
+ pvt = critical{@solver.solve(meas, t_meas)}
335
354
  pvt.define_singleton_method(:rel_ENU){
336
355
  Coordinate::ENU::relative(xyz, ref_pos)
337
356
  } if (ref_pos && pvt.position_solved?)
@@ -378,60 +397,59 @@ class Receiver
378
397
  }
379
398
  }
380
399
 
381
- proc{
382
- eph_list = Hash[*((1..32).to_a + (193..202).to_a).collect{|prn|
400
+ def register_ephemeris(t_meas, sys, prn, bcast_data, *options)
401
+ @eph_list ||= Hash[*((1..32).to_a + (193..202).to_a).collect{|prn|
383
402
  eph = GPS::Ephemeris::new
384
403
  eph.svid = prn
385
404
  [prn, eph]
386
405
  }.flatten(1)]
387
- eph_glonass_list = Hash[*(1..24).collect{|num|
406
+ @eph_glonass_list ||= Hash[*(1..24).collect{|num|
388
407
  eph = GPS::Ephemeris_GLONASS::new
389
408
  eph.svid = num
390
409
  [num, eph]
391
410
  }.flatten(1)]
392
- define_method(:register_ephemeris){|t_meas, sys, prn, bcast_data, *options|
393
- opt = options[0] || {}
394
- case sys
395
- when :GPS, :QZSS
396
- next unless eph = eph_list[prn]
397
- sn = @solver.gps_space_node
398
- subframe, iodc_or_iode = eph.parse(bcast_data)
399
- if iodc_or_iode < 0 then
400
- begin
401
- sn.update_iono_utc(
402
- GPS::Ionospheric_UTC_Parameters::parse(bcast_data))
403
- [:alpha, :beta].each{|k|
404
- $stderr.puts "Iono #{k}: #{sn.iono_utc.send(k)}"
405
- } if false
406
- rescue
407
- end
408
- next
409
- end
410
- if t_meas and eph.consistent? then
411
- eph.WN = ((t_meas.week / 1024).to_i * 1024) + (eph.WN % 1024)
412
- sn.register_ephemeris(prn, eph)
413
- eph.invalidate
411
+ opt = options[0] || {}
412
+ case sys
413
+ when :GPS, :QZSS
414
+ return unless eph = @eph_list[prn]
415
+ sn = @solver.gps_space_node
416
+ subframe, iodc_or_iode = eph.parse(bcast_data)
417
+ if iodc_or_iode < 0 then
418
+ begin
419
+ sn.update_iono_utc(
420
+ GPS::Ionospheric_UTC_Parameters::parse(bcast_data))
421
+ [:alpha, :beta].each{|k|
422
+ $stderr.puts "Iono #{k}: #{sn.iono_utc.send(k)}"
423
+ } if false
424
+ rescue
414
425
  end
415
- when :SBAS
416
- case @solver.sbas_space_node.decode_message(bcast_data[0..7], prn, t_meas)
417
- when 26
418
- ['', "IGP broadcasted by PRN#{prn} @ #{Time::utc(*t_meas.c_tm)}",
419
- @solver.sbas_space_node.ionospheric_grid_points(prn)].each{|str|
420
- $stderr.puts str
421
- } if @debug[:SBAS_IGP]
422
- end if t_meas
423
- when :GLONASS
424
- next unless eph = eph_glonass_list[prn]
425
- leap_sec = @solver.gps_space_node.is_valid_utc ?
426
- @solver.gps_space_node.iono_utc.delta_t_LS :
427
- GPS::Time::guess_leap_seconds(t_meas)
428
- next unless eph.parse(bcast_data[0..3], leap_sec)
429
- eph.freq_ch = opt[:freq_ch] || 0
430
- @solver.glonass_space_node.register_ephemeris(prn, eph)
426
+ return
427
+ end
428
+ if t_meas and eph.consistent? then
429
+ eph.WN = ((t_meas.week / 1024).to_i * 1024) + (eph.WN % 1024)
430
+ sn.register_ephemeris(prn, eph)
431
431
  eph.invalidate
432
432
  end
433
- }
434
- }.call
433
+ when :SBAS
434
+ case @solver.sbas_space_node.decode_message(bcast_data[0..7], prn, t_meas)
435
+ when 26
436
+ ['', "IGP broadcasted by PRN#{prn} @ #{Time::utc(*t_meas.c_tm)}",
437
+ @solver.sbas_space_node.ionospheric_grid_points(prn)].each{|str|
438
+ $stderr.puts str
439
+ } if @debug[:SBAS_IGP]
440
+ end if t_meas
441
+ when :GLONASS
442
+ return unless eph = @eph_glonass_list[prn]
443
+ leap_sec = @solver.gps_space_node.is_valid_utc ?
444
+ @solver.gps_space_node.iono_utc.delta_t_LS :
445
+ GPS::Time::guess_leap_seconds(t_meas)
446
+ return unless eph.parse(bcast_data[0..3], leap_sec)
447
+ eph.freq_ch = opt[:freq_ch] || 0
448
+ @solver.glonass_space_node.register_ephemeris(prn, eph)
449
+ eph.invalidate
450
+ end
451
+ end
452
+ make_critical :register_ephemeris
435
453
 
436
454
  def parse_ubx(ubx_fname, &b)
437
455
  $stderr.print "Reading UBX file (%s) "%[ubx_fname]
@@ -564,7 +582,7 @@ class Receiver
564
582
  @solver.sbas_space_node,
565
583
  @solver.glonass_space_node,
566
584
  ].inject(0){|res, sn|
567
- loaded_items = sn.send(:read, fname)
585
+ loaded_items = critical{sn.send(:read, fname)}
568
586
  raise "Format error! (Not RINEX) #{src}" if loaded_items < 0
569
587
  res + loaded_items
570
588
  }
@@ -648,7 +666,7 @@ class Receiver
648
666
  next unless /^SYS_(?!SYSTEMS)(.*)/ =~ sys.to_s
649
667
  idx, sys_name = [@sp3.class.const_get(sys), $1]
650
668
  next unless sats[idx] > 0
651
- next unless @sp3.push(@solver, idx)
669
+ next unless critical{@sp3.push(@solver, idx)}
652
670
  $stderr.puts "Change ephemeris source of #{sys_name} to SP3"
653
671
  }
654
672
  end
@@ -656,7 +674,7 @@ class Receiver
656
674
  def attach_antex(src)
657
675
  fname = Util::get_txt(src)
658
676
  raise "Specify SP3 before ANTEX application!" unless @sp3
659
- applied_items = @sp3.apply_antex(fname)
677
+ applied_items = critical{@sp3.apply_antex(fname)}
660
678
  raise "Format error! (Not ANTEX) #{src}" unless applied_items >= 0
661
679
  $stderr.puts "SP3 correction with ANTEX file (%s): %d items have been processed."%[src, applied_items]
662
680
  end
@@ -672,7 +690,7 @@ class Receiver
672
690
  next unless /^SYS_(?!SYSTEMS)(.*)/ =~ sys.to_s
673
691
  idx, sys_name = [@clk.class.const_get(sys), $1]
674
692
  next unless sats[idx] > 0
675
- next unless @clk.push(@solver, idx)
693
+ next unless critical{@clk.push(@solver, idx)}
676
694
  $stderr.puts "Change clock error source of #{sys_name} to RINEX clock"
677
695
  }
678
696
  end
data/lib/gps_pvt/util.rb CHANGED
@@ -1,7 +1,39 @@
1
- require 'open-uri'
2
1
  require 'tempfile'
3
2
  require 'uri'
4
3
 
4
+ proc{
5
+ # port[:baudrate], baudrate default is 115200
6
+ Serial.class_eval{
7
+ const_set(:SPEC,
8
+ if RubySerial::ON_WINDOWS then
9
+ %r{^(?:\\\\.\\)?(COM\d+)(?::(\d+))?$}
10
+ elsif RubySerial::ON_LINUX then
11
+ %r{^(/dev/tty[^:]+)(?::(\d+))?$}
12
+ else
13
+ nil
14
+ end)
15
+ }
16
+ Serial.class_eval{
17
+ read_orig = instance_method(:read)
18
+ define_method(:read){|len|
19
+ buf = ''
20
+ f = read_orig.bind(self)
21
+ buf += f.call(len - buf.size) while buf.size < len
22
+ buf
23
+ }
24
+ def eof?; false; end
25
+ }
26
+ Kernel.instance_eval{
27
+ open_orig = method(:open)
28
+ define_method(:open){|*args, &b|
29
+ return open_orig.call(*args, &b) unless Serial::SPEC =~ args[0]
30
+ Serial::new($1, $2 ? $2.to_i : 115200)
31
+ }
32
+ }
33
+ }.call if require 'rubyserial'
34
+
35
+ require 'open-uri'
36
+
5
37
  module GPS_PVT
6
38
  module Util
7
39
  class << self
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GPS_PVT
4
- VERSION = "0.7.2"
4
+ VERSION = "0.8.0"
5
5
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gps_pvt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.2
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - fenrir(M.Naruoka)
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-09-07 00:00:00.000000000 Z
11
+ date: 2022-09-13 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rubyserial
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: rake
15
29
  requirement: !ruby/object:Gem::Requirement