gps_pvt 0.7.2 → 0.8.0

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: 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