gps_pvt 0.8.3 → 0.8.4

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: e2f23806309c4244499a91877edba1a5dfacb1a9108596527dffad650c9cd9ee
4
- data.tar.gz: dc33e31c739a79dc7e7c28ad0d6f404b65788499dfa2f53f9b93edae7b589e7e
3
+ metadata.gz: 39089e2daa55491ccf086809797c2fef68d1e0268e75e6217ed793f091e748de
4
+ data.tar.gz: cca39a3dbcca26921606019be603526f62766c841a92191ee0a99174f00b54c7
5
5
  SHA512:
6
- metadata.gz: 2a3ec484712ccbd06b99a08a672ef20980d68e5f1670b07b093f1d6e4d0480dce974cbe8a181ecb0e8d6074cc60c1c122778113e962625f57b41a7a85b61fc4a
7
- data.tar.gz: 5368619df05a35b6295702e3ad64958aab84e92652b01747f31b5bb98974243ac56a5b4fc25bde1075109bd4d586eac14bf64e1c2ac6b5a31d9bc990ece92fd7
6
+ metadata.gz: becc6540b82ff9d3a97b4b6c5e58f2a7b0872f63584abdee2c425860e1c47b07700f778550ab95bccb3fc7b6462f9fb2f6249ca7846d1a9a9319471e96577c55
7
+ data.tar.gz: 67b2b12b88df52a19e84ef68a7773f2ec989dec3858b5d64e0e60961f8f9f4154eda3e36ef1548b61004c8af4cc6b6850ba73c145f15da41832944857c904889
data/Gemfile CHANGED
@@ -4,7 +4,3 @@ source "https://rubygems.org"
4
4
 
5
5
  # Specify your gem's dependencies in gps_pvt.gemspec
6
6
  gemspec
7
-
8
- gem "rake", "~> 13.0"
9
-
10
- gem "rspec", "~> 3.0"
data/LICENSE ADDED
@@ -0,0 +1,30 @@
1
+ (The following license is applied to each file in which there is no license statement.)
2
+
3
+ BSD 3-Clause License
4
+
5
+ Copyright (c) 2022, M.Naruoka (fenrir)
6
+
7
+ Redistribution and use in source and binary forms, with or without
8
+ modification, are permitted provided that the following conditions are met:
9
+
10
+ 1. Redistributions of source code must retain the above copyright notice, this
11
+ list of conditions and the following disclaimer.
12
+
13
+ 2. Redistributions in binary form must reproduce the above copyright notice,
14
+ this list of conditions and the following disclaimer in the documentation
15
+ and/or other materials provided with the distribution.
16
+
17
+ 3. Neither the name of the copyright holder nor the names of its
18
+ contributors may be used to endorse or promote products derived from
19
+ this software without specific prior written permission.
20
+
21
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md CHANGED
@@ -2,14 +2,18 @@
2
2
 
3
3
  GPS_PVT is a Ruby GPS (Global positioning system) PVT (position, velocity and time) solver. It accepts RINEX NAV and OBS files in addition to u-blox ubx format. Its significant features are easy to use with highly flexibility to customize internal solver behavior such as weight for each available satellite.
4
4
 
5
- The PVT solution is obtained with a stand alone positioning (i.e. neither differential nor kinematic) with application of least square to each snapshot. Its main internal codes are derived from ones of [ninja-scan-light](https://github.com/fenrir-naru/ninja-scan-light) having capability to calculate tightly-coupled GNSS/INS integrated solution. These codes are written by C++, and wrapped by [SWIG](http://www.swig.org/).
5
+ The PVT solution is obtained with a stand alone positioning (i.e. neither differential nor kinematic) with application of least square to each snapshot. Its main internal codes are derived from ones of [ninja-scan-light](https://github.com/fenrir-naru/ninja-scan-light) having capability to calculate tightly-coupled GNSS/INS integrated solution. These codes are written in C++, and wrapped by [SWIG](http://www.swig.org/).
6
6
 
7
7
  [![Gem Version](https://badge.fury.io/rb/gps_pvt.svg)](https://badge.fury.io/rb/gps_pvt)
8
8
  [![Ruby](https://github.com/fenrir-naru/gps_pvt/actions/workflows/main.yml/badge.svg)](https://github.com/fenrir-naru/gps_pvt/actions/workflows/main.yml)
9
9
 
10
10
  ## Installation
11
11
 
12
- Add this line to your application's Gemfile:
12
+ Install it yourself as:
13
+
14
+ $ gem install gps_pvt
15
+
16
+ Or add this line to your Ruby application's Gemfile:
13
17
 
14
18
  ```ruby
15
19
  gem 'gps_pvt'
@@ -19,11 +23,7 @@ And then execute:
19
23
 
20
24
  $ bundle install
21
25
 
22
- Or install it yourself as:
23
-
24
- $ gem install gps_pvt
25
-
26
- For Windows users, this gem requires Devkit because of native compilation.
26
+ For Windows users, this gem requires Devkit because of compilation of native shared library.
27
27
 
28
28
  ## Usage
29
29
 
@@ -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). 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:
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. Moreover, Ntrip URI of ntrip://(username):(password)@(caster_host):(port)/(mount_point), for exmaple, ```ntrip://test%40example.com:none@rtk2go.com:2101/NAIST-UBX``` (%40 is recognized as '@') is supported (version >= 0.8.4). 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
  ----|----
@@ -57,7 +57,7 @@ Additionally, the following command options *--key=value* are available.
57
57
  | end_time | time string | end time to perform solution. Its format is the same as start_time. | v0.3.3 |
58
58
  | <a name=opt_online_ephemeris>online_ephemeris</a> | URL string | based on observation, ephemeris which is previously broadcasted from satellite and currently published online will automatically be loaded. If value is not given, the default source "ftp://gssc.esa.int/gnss/data/daily/%Y/brdc/BRDC00IGS_R_%Y%j0000_01D_MN.rnx.gz" is used. The value string is converted with [strftime](https://docs.ruby-lang.org/en/master/strftime_formatting_rdoc.html) before actual use. | v0.8.1 |
59
59
 
60
- ### For developer
60
+ ### For advanced user
61
61
 
62
62
  This library will be used like:
63
63
 
@@ -136,14 +136,14 @@ receiver.solver.correction = { # provide by using a Hash
136
136
 
137
137
  # Dynamic customization of weight for each epoch
138
138
  (class << receiver; self; end).instance_eval{ # do before parse_XXX
139
- alias_method(:run_orig, :run)
139
+ run_orig = instance_method(:run)
140
140
  define_method(:run){|meas, t_meas, &b|
141
141
  meas # observation, same as the 2nd argument of parse_XXX
142
142
  receiver.solver.hooks[:relative_property] = proc{|prn, rel_prop, meas, rcv_e, t_arv, usr_pos, usr_vel|
143
143
  # Do something based on meas, t_meas.
144
144
  rel_prop
145
145
  }
146
- run_orig(meas, t_meas, &b)
146
+ run_orig.bind(self).call(meas, t_meas, &b)
147
147
  }
148
148
  }
149
149
  ```
data/gps_pvt.gemspec CHANGED
@@ -59,8 +59,10 @@ Gem::Specification.new do |spec|
59
59
  # Uncomment to register a new dependency of your gem
60
60
  # spec.add_dependency "example-gem", "~> 1.0"
61
61
  spec.add_dependency "rubyserial"
62
- spec.add_development_dependency "rake"
62
+ spec.add_development_dependency "rake", "~> 13.0"
63
63
  spec.add_development_dependency "rake-compiler"
64
+ spec.add_development_dependency "rspec", "~> 3.0"
65
+ spec.add_development_dependency "matrix" if GPS_PVT::version_compare(RUBY_VERSION, "3.1") >= 0
64
66
 
65
67
  # For more information and examples about making a new gem, checkout our
66
68
  # guide at: https://bundler.io/guides/creating_gem.html
@@ -0,0 +1,153 @@
1
+ # Ntrip (Networked Transport of RTCM via Internet Protocol)
2
+
3
+ require 'net/http'
4
+ require 'uri'
5
+ require_relative 'version'
6
+
7
+ module GPS_PVT
8
+ class Ntrip < Net::HTTP
9
+ Net::HTTPResponse.class_eval{
10
+ orig = singleton_method(:read_new)
11
+ define_singleton_method(:read_new){|sock|
12
+ # handle Ntrip(rev1), which does not comply with HTTP
13
+ unless sock.respond_to?(:ntrip) then
14
+ orig.call(sock)
15
+ else
16
+ str = sock.readline
17
+ case str
18
+ when /\A(?:(?:HTTP(?:\/(\d+\.\d+))?|([^\d\s]+))\s+)?(\d\d\d)(?:\s+(.*))?\z/in
19
+ res = response_class($3).new($1 || '1.1', $3, $2 || $4)
20
+ each_response_header(sock){|k,v|
21
+ res.add_field k, v
22
+ } unless res.message == 'ICY' # or 'SOURCETABLE' for Ntrip(rev1)
23
+ res
24
+ else
25
+ raise Net::HTTPBadResponse, "wrong status line: #{str.dump}"
26
+ end
27
+ end
28
+ }
29
+ }
30
+ def on_connect
31
+ super
32
+ @socket.define_singleton_method(:ntrip){true}
33
+ end
34
+
35
+ SOURCE_TBL_ITEMS = {
36
+ :STR => [
37
+ :type, :mountpoint, :identifier, :format, :format_details,
38
+ :carrier, :nav_system, :network, :country, :latitude, :longitude,
39
+ :nmea, :solution, :generator, :compression, :authentication, :fee, :bitrate],
40
+ :CAS => [
41
+ :type, :host, :port, :identifier, :operator,
42
+ :nmea, :country, :latitude, :longitude, :fallback_host, :fallback_ip],
43
+ :NET => [
44
+ :type, :identifier, :operator, :authentication, :fee,
45
+ :web_net, :web_str, :web_reg],
46
+ }
47
+ def Ntrip.parse_source_table(str)
48
+ res = {}
49
+ str.lines.each{|line|
50
+ values = line.chomp.split(/\s*;\s*/)
51
+ type = values[0].to_sym
52
+ next unless keys = SOURCE_TBL_ITEMS[type]
53
+ next unless (values.size >= keys.size)
54
+ entry = Hash[*(keys.zip(values).flatten(1))]
55
+ entry[:misc] = values[(keys.size)..-1] if values.size > keys.size
56
+ (res[type] ||= []) << entry
57
+ }
58
+ res.define_singleton_method(:mount_points){
59
+ Hash[*((self[:STR] || []).collect{|entry|
60
+ [entry[:mountpoint], entry]
61
+ }.flatten(1))]
62
+ }
63
+ res
64
+ end
65
+ def generate_request(path, header)
66
+ req = Net::HTTP::Get.new(path, {
67
+ 'User-Agent' => "GPS_PVT NTRIP client/#{GPS_PVT::VERSION}",
68
+ 'Accept' => '*/*',
69
+ 'Ntrip-Version' => 'Ntrip/2.0',
70
+ }.merge(header.select{|k, v| k.kind_of?(String)}))
71
+ header.each{|k, v|
72
+ next unless k.kind_of?(Symbol)
73
+ req.send(k, *v)
74
+ }
75
+ req
76
+ end
77
+ def get_source_table(header = {})
78
+ Ntrip.parse_source_table(request(generate_request('/', header)).read_body)
79
+ end
80
+ def get_data(mount_point, header = {}, &b)
81
+ request(generate_request("/#{mount_point}", header)){|res|
82
+ res.read_body(&b)
83
+ }
84
+ end
85
+ end
86
+ end
87
+
88
+ require 'open-uri'
89
+
90
+ OpenURI.class_eval{
91
+ check_options_orig = singleton_method(:check_options)
92
+ define_singleton_method(:check_options){|options|
93
+ uri = options.delete(:uri)
94
+ case uri
95
+ when URI::Ntrip
96
+ options[:basic_auth] ||=
97
+ options.delete(:http_basic_authentication) ||
98
+ ([:user, :password].collect{|k|
99
+ URI::decode_www_form_component(uri.send(k))
100
+ } rescue nil)
101
+ options['Ntrip-Version'] ||= "Ntrip/%3.1f"%[options.delete(:version)] if options[:version]
102
+ options['User-Agent'] ||= options[:user_agent]
103
+ options.select!{|k, v| v} #compact! Ruby >= 2.4.0
104
+ true
105
+ else
106
+ check_options_orig.call(options)
107
+ end
108
+ }
109
+ open_uri_orig = singleton_method(:open_uri)
110
+ define_singleton_method(:open_uri){|name, *rest, &b|
111
+ uri = URI::Generic === name ? name : URI.parse(name)
112
+ (rest[-1].kind_of?(Hash) ? rest : (rest << {}))[-1][:uri] = uri
113
+ open_uri_orig.call(uri, *rest, &b)
114
+ }
115
+ def OpenURI.open_ntrip(buf, target, proxy, options) # :nodoc:
116
+ GPS_PVT::Ntrip.start(target.host, target.port){|ntrip|
117
+ # get source table
118
+ tbl = ntrip.get_source_table(options)
119
+
120
+ # check mount point
121
+ mnt_pt = target.path.sub(%r|^/|, '')
122
+ prop = tbl.mount_points[mnt_pt]
123
+ raise Net::ProtocolError::new("Mount point(#{mnt_pt}) not found") unless prop
124
+
125
+ # set stream
126
+ buf.instance_eval{
127
+ @io, w = IO::pipe
128
+ @io.define_singleton_method(:property){prop}
129
+ Thread::new{
130
+ begin
131
+ ntrip.get_data(mnt_pt, options){|data| w << data}
132
+ rescue Errno::EPIPE;
133
+ rescue; raise
134
+ ensure; w.close
135
+ end
136
+ }
137
+ }
138
+ }
139
+ end
140
+ }
141
+ module URI
142
+ class Ntrip < HTTP
143
+ def buffer_open(buf, proxy, options)
144
+ OpenURI.open_ntrip(buf, self, proxy, options)
145
+ end
146
+ include OpenURI::OpenRead
147
+ end
148
+ if respond_to?(:register_scheme) then
149
+ register_scheme('NTRIP', Ntrip)
150
+ else
151
+ @@schemes['NTRIP'] = Ntrip
152
+ end
153
+ end
data/lib/gps_pvt/util.rb CHANGED
@@ -23,16 +23,18 @@ proc{
23
23
  }
24
24
  def eof?; false; end
25
25
  }
26
- Kernel.instance_eval{
27
- open_orig = method(:open)
26
+ module Kernel
27
+ open_orig = instance_method(:open)
28
28
  define_method(:open){|*args, &b|
29
- return open_orig.call(*args, &b) unless Serial::SPEC =~ args[0]
29
+ return open_orig.bind(self).call(*args, &b) unless Serial::SPEC =~ args[0]
30
30
  Serial::new($1, $2 ? $2.to_i : 115200)
31
31
  }
32
- }
32
+ module_function(:open)
33
+ end
33
34
  }.call if require 'rubyserial'
34
35
 
35
36
  require 'open-uri'
37
+ require_relative 'ntrip'
36
38
 
37
39
  module GPS_PVT
38
40
  module Util
@@ -53,8 +55,7 @@ module Util
53
55
  end
54
56
  def get_txt(fname_or_uri)
55
57
  is_uri = fname_or_uri.kind_of?(URI)
56
- ((is_uri && (RUBY_VERSION >= "2.5.0")) ? URI : Kernel) \
57
- .send(:open, fname_or_uri){|src|
58
+ (is_uri ? URI : Kernel).send(:open, fname_or_uri){|src|
58
59
  compressed = proc{
59
60
  case src.content_type
60
61
  when /gzip/; next :gz
@@ -1,5 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GPS_PVT
4
- VERSION = "0.8.3"
4
+ VERSION = "0.8.4"
5
+
6
+ def GPS_PVT.version_compare(a, b)
7
+ Gem::Version::new(a) <=> Gem::Version::new(b)
8
+ end
5
9
  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.8.3
4
+ version: 0.8.4
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-11-30 00:00:00.000000000 Z
11
+ date: 2022-12-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubyserial
@@ -28,16 +28,16 @@ dependencies:
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '13.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '13.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake-compiler
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
55
69
  description: This module calculate PVT by using raw observation obtained from a GPS
56
70
  receiver
57
71
  email:
@@ -67,6 +81,7 @@ files:
67
81
  - CHANGELOG.md
68
82
  - CODE_OF_CONDUCT.md
69
83
  - Gemfile
84
+ - LICENSE
70
85
  - README.md
71
86
  - Rakefile
72
87
  - bin/console
@@ -117,6 +132,7 @@ files:
117
132
  - gps_pvt.gemspec
118
133
  - gps_pvt.rbs
119
134
  - lib/gps_pvt.rb
135
+ - lib/gps_pvt/ntrip.rb
120
136
  - lib/gps_pvt/receiver.rb
121
137
  - lib/gps_pvt/receiver/extension.rb
122
138
  - lib/gps_pvt/ubx.rb