gps_pvt 0.6.2 → 0.7.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: 8a67291f7ea2d3146cace6c9e5f9c3262d89c1bd22534d6c147265c6189089c8
4
- data.tar.gz: 211daa142bb6282341367f0ccd375d66a0083e6de01ec7841ac4833795c3a6cc
3
+ metadata.gz: 5d2ab5f33d6ba6233e7a52b05ac2f89306e181240bb2510d6ffe697467278178
4
+ data.tar.gz: d592b929d56554cb3a1e82e734d90366e32ac083eeacfc8535457a5518952075
5
5
  SHA512:
6
- metadata.gz: 80a279b8018856c9d0d73b311c44efd97ce2794dc12353f10462a1b1b65aedc177ae6284fc324feb1980a02da2c2127ab8649058f840fc8279340f1152af3f62
7
- data.tar.gz: ce708fe585b811a99a8e0e42862df7bcac023d44859b17ea08b9e6816425845b5ab0a31b207b79a870ca6d52dc43313b00eb67a5b38746ace843c54264ceca1e
6
+ metadata.gz: 826e7a745be07aad5c86b075e5285d0e31212b6fe83cce8c7af67b500645a698e2c60bd67e6f0ecc6ccd114db2754286941c9e90a72deab7b3219132028cf242
7
+ data.tar.gz: f11f9c72d8bd30f72e77969eb694ce5a5b7d25db5b251e275b2840511d1836275ba5d7adf1829cbeef691f423c7ddf3a5defbb8919f8bd93bc6cd532649bbd4b
data/README.md CHANGED
@@ -41,6 +41,7 @@ The format of file is automatically determined with its extension, such as .ubx
41
41
  | --ubx=file_or_URI | [U-blox](https://www.u-blox.com/) dedicated format |
42
42
  | --sp3=file_or_URI | [Standard Product 3 Orbit Format](https://files.igs.org/pub/data/format/sp3c.txt) (supported gps_pvt version >= 0.6.0) |
43
43
  | --antex=file_or_URI | [Antenna Exchange Format](https://igs.org/wg/antenna#files) (supported gps_pvt version >= 0.6.0) |
44
+ | --rinex_clk=file_or_URI | [RINEX clock](https://files.igs.org/pub/data/format/rinex_clock304.txt) file (supported gps_pvt version >= 0.7.0) |
44
45
 
45
46
  Since version 0.2.0, SBAS and QZSS are supported in addition to GPS. Since version 0.4.0, GLONASS is also available. QZSS ranging is activated in default, however, SBAS is just utilized for ionospheric correction. GLONASS is also turned off by default. If you want to activate SBAS or GLONASS ranging, "--with=(system or PRN)" options are used with gps_pvt executable like
46
47
 
data/Rakefile CHANGED
@@ -56,6 +56,7 @@ namespace :git do
56
56
  tool/navigation/MagneticField.h
57
57
  tool/navigation/NTCM.h
58
58
  tool/navigation/RINEX.h
59
+ tool/navigation/RINEX_Clock.h
59
60
  tool/navigation/WGS84.h
60
61
  tool/navigation/SP3.h
61
62
  tool/navigation/ANTEX.h
data/exe/gps_pvt CHANGED
@@ -24,7 +24,7 @@ misc_options = {}
24
24
  files = ARGV.collect{|arg|
25
25
  next [arg, nil] unless arg =~ /^--([^=]+)=?/
26
26
  k, v = [$1.downcase.to_sym, $']
27
- next [v, k] if [:rinex_nav, :rinex_obs, :ubx, :sp3, :antex].include?(k) # file type
27
+ next [v, k] if [:rinex_nav, :rinex_obs, :ubx, :sp3, :antex, :rinex_clk].include?(k) # file type
28
28
  options << [$1.to_sym, $']
29
29
  nil
30
30
  }.compact
@@ -74,6 +74,7 @@ files.collect!{|fname, ftype|
74
74
  when /\.ubx$/; :ubx
75
75
  when /\.sp3(?:\.Z)?$/; :sp3
76
76
  when /\.atx(?:\.Z)?$/; :antex
77
+ when /\.clk$/; :rinex_clk
77
78
  else
78
79
  raise "Format cannot be guessed, use --(format, ex. rinex_nav)=#{fname}"
79
80
  end
@@ -145,6 +146,7 @@ files.each{|fname, ftype|
145
146
  when :rinex_nav; rcv.parse_rinex_nav(fname)
146
147
  when :sp3; rcv.attach_sp3(fname)
147
148
  when :antex; rcv.attach_antex(fname)
149
+ when :rinex_clk; rcv.attach_rinex_clk(fname)
148
150
  end
149
151
  }
150
152
 
data/exe/to_ubx ADDED
@@ -0,0 +1,214 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'gps_pvt'
4
+ require 'uri'
5
+ require 'gps_pvt/ubx'
6
+
7
+ # Convert file(s) to ubx format
8
+ # TODO currently only RINEX observation file is supported.
9
+
10
+ $stderr.puts <<__STRING__
11
+ Usage: #{__FILE__} GPS_file ... > as_you_like.ubx
12
+ As GPS_file, only rinex_obs(*.YYo) is currently supported.
13
+ (YY = last two digit of year)
14
+ File format is automatically determined based on its extention described in above parentheses.
15
+ If you want to specify its format manually, command options like --rinex_obs=file_name are available.
16
+ Supported RINEX versions are 2 and 3.
17
+ RXM-RAWX and RXM-SFRBX are included in output UBX if corresponding file(s) is given.
18
+ A file having additional ".gz" or ".Z" extension is recognized as a compressed file.
19
+ Major URL such as http(s)://... or ftp://... is acceptable as an input file name.
20
+ __STRING__
21
+
22
+ options = []
23
+ misc_options = {
24
+ :ubx_rawx => false
25
+ }
26
+
27
+ # check options and file format
28
+ files = ARGV.collect{|arg|
29
+ next [arg, nil] unless arg =~ /^--([^=]+)=?/
30
+ k, v = [$1.downcase.to_sym, $']
31
+ next [v, k] if [:rinex_nav, :rinex_obs].include?(k) # file type
32
+ options << [$1.to_sym, $']
33
+ nil
34
+ }.compact
35
+
36
+ # Check file existence and extension
37
+ files.collect!{|fname, ftype|
38
+ ftype ||= case fname
39
+ when /\.\d{2}[nhqg](?:\.gz)?$/; :rinex_nav
40
+ when /\.\d{2}o(?:\.gz)?$/; :rinex_obs
41
+ else
42
+ raise "Format cannot be guessed, use --(format, ex. rinex_obs)=#{fname}"
43
+ end
44
+ fname = proc{
45
+ next fname if File::exist?(fname)
46
+ if uri = URI::parse(fname) and !uri.instance_of?(URI::Generic) then
47
+ next uri
48
+ end
49
+ raise "File not found: #{fname}"
50
+ }.call
51
+ [fname, ftype]
52
+ }
53
+
54
+ options.reject!{|opt|
55
+ case opt[0]
56
+ when :ubx_rawx
57
+ misc_options[opt[0]] = opt[1]
58
+ true
59
+ else
60
+ false
61
+ end
62
+ }
63
+
64
+ rcv = GPS_PVT::Receiver::new(options)
65
+
66
+ obs = []
67
+ rcv.define_singleton_method(:run){|meas, t_meas, *args|
68
+ obs << [t_meas, meas]
69
+ }
70
+
71
+ # parse RINEX NAV
72
+ files.each{|fname, ftype|
73
+ case ftype
74
+ when :rinex_nav; rcv.parse_rinex_nav(fname)
75
+ end
76
+ }
77
+
78
+ # other files
79
+ files.each{|fname, ftype|
80
+ case ftype
81
+ when :rinex_obs; rcv.parse_rinex_obs(fname){}
82
+ end
83
+ }
84
+
85
+ obs.sort!{|a, b| a[0] <=> b[0]} # Sort by measurement time
86
+
87
+ glonass_freq_ch = proc{
88
+ freq0, delta = [:L1_frequency_base, :L1_frequency_gap].collect{|k|
89
+ GPS_PVT::GPS::SpaceNode_GLONASS.send(k)
90
+ }
91
+ proc{|freq| ((freq - freq0) / delta).to_i}
92
+ }.call
93
+
94
+ gen_raw = proc{|t_meas, meas| # Convert to RXM-RAW(0x10)
95
+ meas = meas.to_hash
96
+ ubx = [0xB5, 0x62, 0x02, 0x10, 0, 0]
97
+ ubx += [(t_meas.seconds * 1E3).to_i, t_meas.week].pack("Vv").unpack("C*")
98
+ ubx += [0] * 2
99
+ meas_ubx = meas.collect{|sat, items|
100
+ res = [0] * 24
101
+ setter = proc{|value, offset, len, str, pre_proc|
102
+ array = case value
103
+ when Array; value
104
+ when Symbol
105
+ [items[GPS_PVT::GPS::Measurement.const_get(value)]]
106
+ else
107
+ next nil
108
+ end
109
+ pre_proc.call(array) if pre_proc
110
+ next if array.empty?
111
+ array = array.pack(str).unpack("C*") if str
112
+ res[offset - 8, len] = array
113
+ }
114
+ svid = case sat
115
+ when 1..32, 120..158, 193..202 # GPS, SBAS, QZSS
116
+ sat
117
+ when (0x100 + 1)..(0x100 + 32) # GLONASS
118
+ sat - 0x100 + 64 # => 65..96
119
+ else
120
+ next nil # TODO Galileo, Beidou, ...
121
+ end
122
+
123
+ qi = 6
124
+ setter.call(:L1_CARRIER_PHASE,
125
+ 8, 8, "E", proc{|v| next if v[0]; qi = 4; v.clear})
126
+ setter.call(:L1_PSEUDORANGE,
127
+ 16, 8, "E", proc{|v| next if v[0]; qi = 0; v.clear})
128
+ setter.call(:L1_DOPPLER,
129
+ 24, 4, "e", proc{|v| next if v[0]; qi = 0; v.clear})
130
+ setter.call([svid, qi], 28, 2)
131
+ setter.call(:L1_SIGNAL_STRENGTH_dBHz,
132
+ 30, 1, nil, proc{|v| v.replace(v[0] ? [v[0].to_i] : [])})
133
+ setter.call(:L1_LOCK_SEC,
134
+ 31, 1, nil, proc{|v| v.replace(v[0] ? [(v[0] < 0) ? 1 : 0] : [0])})
135
+
136
+ res
137
+ }.compact
138
+ ubx[6 + 6] = meas_ubx.size
139
+ ubx += meas_ubx.flatten(1)
140
+ ubx += [0, 0]
141
+ GPS_PVT::UBX::update(ubx).pack("C*")
142
+ }
143
+
144
+ gen_rawx = proc{|t_meas, meas| # Convert to RXM-RAWX(0x15)
145
+ meas = meas.to_hash
146
+ ubx = [0xB5, 0x62, 0x02, 0x15, 0, 0]
147
+ ubx += [t_meas.seconds, t_meas.week].pack("Ev").unpack("C*")
148
+ ubx += [0] * 6
149
+ meas_ubx = meas.collect{|sat, items|
150
+ res = [0] * 32
151
+ setter = proc{|value, offset, len, str, pre_proc|
152
+ array = case value
153
+ when Array; value
154
+ when Symbol
155
+ [items[GPS_PVT::GPS::Measurement.const_get(value)]]
156
+ else
157
+ next nil
158
+ end
159
+ pre_proc.call(array) if pre_proc
160
+ next if array.empty?
161
+ array = array.pack(str).unpack("C*") if str
162
+ res[offset - 16, len] = array
163
+ }
164
+ sys, svid = case sat
165
+ when 1..32 # GPS
166
+ [0, sat]
167
+ when 120..158 # SBAS
168
+ [1, sat]
169
+ when 193..202 # QZSS
170
+ [5, sat]
171
+ when (0x100 + 1)..(0x100 + 32) # GLONASS
172
+ setter.call(:L1_FREQUENCY,
173
+ 39, 1, nil, proc{|v| v.replace(v[0] ? glonass_freq_ch.call(v[0]) : [7])})
174
+ [6, sat - 0x100]
175
+ else
176
+ next nil # TODO Galileo, Beidou, ...
177
+ end
178
+ setter.call([sys, svid], 36, 2)
179
+
180
+ trk_stat = 0
181
+ setter.call(:L1_PSEUDORANGE,
182
+ 16, 8, "E", proc{|v| v[0] ? (trk_stat |= 0x1) : v.clear})
183
+ setter.call(:L1_PSEUDORANGE_SIGMA,
184
+ 43, 1, nil, proc{|v|
185
+ b = (Math::log2(v[0] / 1E-2).to_i & 0xF) rescue 0x8
186
+ v.replace((trk_stat & 0x1 == 0x1) ? [b] : [])
187
+ })
188
+ setter.call(:L1_DOPPLER, 32, 4, "e")
189
+ setter.call(:L1_DOPPLER_SIGMA,
190
+ 45, 1, nil, proc{|v| v.replace(v[0] ? [Math::log2(v[0] / 2E-3).to_i & 0xF] : [0x8])})
191
+ setter.call(:L1_CARRIER_PHASE,
192
+ 24, 8, "E", proc{|v| v[0] ? (trk_stat |= 0x2) : v.clear})
193
+ setter.call(:L1_CARRIER_PHASE_SIGMA,
194
+ 44, 1, nil, proc{|v|
195
+ b = ((v[0] / 0.004).to_i & 0xF) rescue 0x8
196
+ v.replace((trk_stat & 0x2 == 0x2) ? [b] : [])
197
+ })
198
+ setter.call(:L1_SIGNAL_STRENGTH_dBHz,
199
+ 42, 1, nil, proc{|v| v.replace(v[0] ? [v[0].to_i] : [])})
200
+ setter.call(:L1_LOCK_SEC,
201
+ 40, 2, "v", proc{|v| v.replace(v[0] ? [(v[0] / 1E-3).to_i] : [])})
202
+ setter.call([trk_stat], 46, 1)
203
+
204
+ res
205
+ }.compact
206
+ ubx[6 + 11] = meas_ubx.size
207
+ ubx += meas_ubx.flatten(1)
208
+ ubx += [0, 0]
209
+ GPS_PVT::UBX::update(ubx).pack("C*")
210
+ }
211
+
212
+ gen = misc_options[:ubx_rawx] ? gen_rawx : gen_raw
213
+ STDOUT.binmode
214
+ obs.each{|*item| print gen.call(*item)}