gps_pvt 0.1.7 → 0.2.3
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 +4 -4
- data/README.md +13 -2
- data/Rakefile +2 -0
- data/exe/gps_pvt +32 -23
- data/ext/gps_pvt/Coordinate/Coordinate_wrap.cxx +5 -3
- data/ext/gps_pvt/GPS/GPS_wrap.cxx +4444 -671
- data/ext/gps_pvt/SylphideMath/SylphideMath_wrap.cxx +284 -19
- data/ext/ninja-scan-light/tool/navigation/GPS.h +12 -46
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver.h +61 -100
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver_Base.h +87 -25
- data/ext/ninja-scan-light/tool/navigation/QZSS.h +62 -0
- data/ext/ninja-scan-light/tool/navigation/RINEX.h +335 -27
- data/ext/ninja-scan-light/tool/navigation/SBAS.h +2330 -0
- data/ext/ninja-scan-light/tool/navigation/SBAS_Solver.h +306 -0
- data/ext/ninja-scan-light/tool/param/bit_array.h +4 -3
- data/ext/ninja-scan-light/tool/swig/GPS.i +429 -138
- data/ext/ninja-scan-light/tool/swig/SylphideMath.i +53 -6
- data/ext/ninja-scan-light/tool/swig/spec/GPS_spec.rb +37 -6
- data/ext/ninja-scan-light/tool/swig/spec/SylphideMath_spec.rb +38 -4
- data/gps_pvt.gemspec +63 -0
- data/lib/gps_pvt/receiver.rb +281 -140
- data/lib/gps_pvt/version.rb +1 -1
- metadata +7 -3
data/lib/gps_pvt/receiver.rb
CHANGED
@@ -7,99 +7,125 @@ require_relative 'GPS'
|
|
7
7
|
|
8
8
|
module GPS_PVT
|
9
9
|
class Receiver
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
}
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
10
|
+
def self.pvt_items(opt = {})
|
11
|
+
opt = {
|
12
|
+
:system => [[:GPS, 1..32]],
|
13
|
+
:satellites => (1..32).to_a,
|
14
|
+
}.merge(opt)
|
15
|
+
[[
|
16
|
+
[:week, :itow_rcv, :year, :month, :mday, :hour, :min, :sec],
|
17
|
+
proc{|pvt|
|
18
|
+
[:week, :seconds, :c_tm].collect{|f| pvt.receiver_time.send(f)}.flatten
|
19
|
+
}
|
20
|
+
]] + [[
|
21
|
+
[:receiver_clock_error_meter, :longitude, :latitude, :height, :rel_E, :rel_N, :rel_U],
|
22
|
+
proc{|pvt|
|
23
|
+
next [nil] * 7 unless pvt.position_solved?
|
24
|
+
[
|
25
|
+
pvt.receiver_error,
|
26
|
+
pvt.llh.lng / Math::PI * 180,
|
27
|
+
pvt.llh.lat / Math::PI * 180,
|
28
|
+
pvt.llh.alt,
|
29
|
+
] + (pvt.rel_ENU.to_a rescue [nil] * 3)
|
30
|
+
}
|
31
|
+
]] + [proc{
|
32
|
+
labels = [:g, :p, :h, :v, :t].collect{|k| "#{k}dop".to_sym}
|
19
33
|
[
|
20
|
-
|
21
|
-
pvt
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
[
|
29
|
-
labels,
|
34
|
+
labels,
|
35
|
+
proc{|pvt|
|
36
|
+
next [nil] * 5 unless pvt.position_solved?
|
37
|
+
labels.collect{|k| pvt.send(k)}
|
38
|
+
}
|
39
|
+
]
|
40
|
+
}.call] + [[
|
41
|
+
[:v_north, :v_east, :v_down, :receiver_clock_error_dot_ms],
|
30
42
|
proc{|pvt|
|
31
|
-
next [nil] *
|
32
|
-
|
43
|
+
next [nil] * 4 unless pvt.velocity_solved?
|
44
|
+
[:north, :east, :down].collect{|k| pvt.velocity.send(k)} \
|
45
|
+
+ [pvt.receiver_error_rate]
|
33
46
|
}
|
34
|
-
]
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
}
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
sats = pvt.used_satellite_list
|
58
|
-
r, w = [:delta_r, :W].collect{|f| pvt.send(f)}
|
59
|
-
(1..32).collect{|i|
|
60
|
-
next ([nil] * 6) unless i2 = sats.index(i)
|
61
|
-
[r[i2, 0], w[i2, i2]] +
|
62
|
-
[:azimuth, :elevation].collect{|f|
|
63
|
-
pvt.send(f)[i] / Math::PI * 180
|
64
|
-
} + [pvt.slopeH[i], pvt.slopeV[i]]
|
65
|
-
}.flatten
|
66
|
-
},
|
67
|
-
]] + [[
|
68
|
-
[:wssr, :wssr_sf, :weight_max,
|
69
|
-
:slopeH_max, :slopeH_max_PRN, :slopeH_max_elevation,
|
70
|
-
:slopeV_max, :slopeV_max_PRN, :slopeV_max_elevation],
|
71
|
-
proc{|pvt|
|
72
|
-
next [nil] * 9 unless fd = pvt.fd
|
73
|
-
el_deg = [4, 6].collect{|i| pvt.elevation[fd[i]] / Math::PI * 180}
|
74
|
-
fd[0..4] + [el_deg[0]] + fd[5..6] + [el_deg[1]]
|
75
|
-
}
|
76
|
-
]] + [[
|
77
|
-
[:wssr_FDE_min, :wssr_FDE_min_PRN, :wssr_FDE_2nd, :wssr_FDE_2nd_PRN],
|
78
|
-
proc{|pvt|
|
79
|
-
[:fde_min, :fde_2nd].collect{|f|
|
80
|
-
info = pvt.send(f)
|
81
|
-
next ([nil] * 2) if (!info) || info.empty?
|
82
|
-
[info[0], info[-3]]
|
83
|
-
}.flatten
|
84
|
-
}
|
85
|
-
]]
|
86
|
-
|
87
|
-
OUTPUT_MEAS_ITEMS = [[
|
88
|
-
(1..32).collect{|prn|
|
89
|
-
[:L1_range, :L1_rate].collect{|str| "#{str}(#{prn})"}
|
90
|
-
}.flatten,
|
91
|
-
proc{|meas|
|
92
|
-
meas_hash = Hash[*(meas.collect{|prn, k, v| [[prn, k], v]}.flatten(1))]
|
93
|
-
(1..32).collect{|prn|
|
94
|
-
[:L1_PSEUDORANGE, [:L1_DOPPLER, GPS::SpaceNode.L1_WaveLength]].collect{|k, sf|
|
95
|
-
meas_hash[[prn, GPS::Measurement.const_get(k)]] * (sf || 1) rescue nil
|
47
|
+
]] + [
|
48
|
+
[:used_satellites, proc{|pvt| pvt.used_satellites}],
|
49
|
+
] + opt[:system].collect{|sys, range|
|
50
|
+
bit_flip = if range.kind_of?(Array) then
|
51
|
+
proc{|res, i|
|
52
|
+
res[i] = "1" if i = range.index(i)
|
53
|
+
res
|
54
|
+
}
|
55
|
+
else # expect Range
|
56
|
+
base_prn = range.min
|
57
|
+
proc{|res, i|
|
58
|
+
res[i - base_prn] = "1" if range.include?(i)
|
59
|
+
res
|
60
|
+
}
|
61
|
+
end
|
62
|
+
["#{sys}_PRN", proc{|pvt|
|
63
|
+
pvt.used_satellite_list.inject("0" * range.size, &bit_flip) \
|
64
|
+
.scan(/.{1,8}/).join('_').reverse
|
65
|
+
}]
|
66
|
+
} + [[
|
67
|
+
opt[:satellites].collect{|prn, label|
|
68
|
+
[:range_residual, :weight, :azimuth, :elevation, :slopeH, :slopeV].collect{|str|
|
69
|
+
"#{str}(#{label || prn})"
|
96
70
|
}
|
71
|
+
}.flatten,
|
72
|
+
proc{|pvt|
|
73
|
+
next ([nil] * 6 * opt[:satellites].size) unless pvt.position_solved?
|
74
|
+
sats = pvt.used_satellite_list
|
75
|
+
r, w = [:delta_r, :W].collect{|f| pvt.send(f)}
|
76
|
+
opt[:satellites].collect{|prn, label|
|
77
|
+
next ([nil] * 6) unless i2 = sats.index(prn)
|
78
|
+
[r[i2, 0], w[i2, i2]] +
|
79
|
+
[:azimuth, :elevation].collect{|f|
|
80
|
+
pvt.send(f)[prn] / Math::PI * 180
|
81
|
+
} + [pvt.slopeH[prn], pvt.slopeV[prn]]
|
82
|
+
}.flatten
|
83
|
+
},
|
84
|
+
]] + [[
|
85
|
+
[:wssr, :wssr_sf, :weight_max,
|
86
|
+
:slopeH_max, :slopeH_max_PRN, :slopeH_max_elevation,
|
87
|
+
:slopeV_max, :slopeV_max_PRN, :slopeV_max_elevation],
|
88
|
+
proc{|pvt|
|
89
|
+
next [nil] * 9 unless fd = pvt.fd
|
90
|
+
el_deg = [4, 6].collect{|i| pvt.elevation[fd[i]] / Math::PI * 180}
|
91
|
+
fd[0..4] + [el_deg[0]] + fd[5..6] + [el_deg[1]]
|
97
92
|
}
|
93
|
+
]] + [[
|
94
|
+
[:wssr_FDE_min, :wssr_FDE_min_PRN, :wssr_FDE_2nd, :wssr_FDE_2nd_PRN],
|
95
|
+
proc{|pvt|
|
96
|
+
[:fde_min, :fde_2nd].collect{|f|
|
97
|
+
info = pvt.send(f)
|
98
|
+
next ([nil] * 2) if (!info) || info.empty?
|
99
|
+
[info[0], info[-3]]
|
100
|
+
}.flatten
|
101
|
+
}
|
102
|
+
]]
|
103
|
+
end
|
104
|
+
|
105
|
+
def self.meas_items(opt = {})
|
106
|
+
opt = {
|
107
|
+
:satellites => (1..32).to_a,
|
108
|
+
}.merge(opt)
|
109
|
+
keys = [:PSEUDORANGE, :RANGE_RATE, :DOPPLER, :FREQUENCY].collect{|k|
|
110
|
+
GPS::Measurement.const_get("L1_#{k}".to_sym)
|
98
111
|
}
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
112
|
+
[[
|
113
|
+
opt[:satellites].collect{|prn, label|
|
114
|
+
[:L1_range, :L1_rate].collect{|str| "#{str}(#{label || prn})"}
|
115
|
+
}.flatten,
|
116
|
+
proc{|meas|
|
117
|
+
meas_hash = meas.to_hash
|
118
|
+
opt[:satellites].collect{|prn, label|
|
119
|
+
pr, rate, doppler, freq = keys.collect{|k| meas_hash[prn][k] rescue nil}
|
120
|
+
freq ||= GPS::SpaceNode.L1_Frequency
|
121
|
+
[pr, rate || ((doppler * GPS::SpaceNode::light_speed / freq) rescue nil)]
|
122
|
+
}
|
123
|
+
}
|
124
|
+
]]
|
125
|
+
end
|
126
|
+
|
127
|
+
def header
|
128
|
+
(@output[:pvt] + @output[:meas]).transpose[0].flatten.join(',')
|
103
129
|
end
|
104
130
|
|
105
131
|
attr_accessor :solver
|
@@ -107,16 +133,30 @@ class Receiver
|
|
107
133
|
|
108
134
|
def initialize(options = {})
|
109
135
|
@solver = GPS::Solver::new
|
110
|
-
@solver.hooks[:relative_property] = proc{|prn, rel_prop, rcv_e, t_arv, usr_pos, usr_vel|
|
136
|
+
@solver.hooks[:relative_property] = proc{|prn, rel_prop, meas, rcv_e, t_arv, usr_pos, usr_vel|
|
111
137
|
rel_prop[0] = 1 if rel_prop[0] > 0 # weight = 1
|
112
138
|
rel_prop
|
113
139
|
}
|
140
|
+
@debug = {}
|
141
|
+
[:gps_options, :sbas_options].each{|target|
|
142
|
+
opt = @solver.send(target) # default solver options
|
143
|
+
opt.elevation_mask = 0.0 / 180 * Math::PI # 0 deg (use satellite over horizon)
|
144
|
+
opt.residual_mask = 1E4 # 10 km (without residual filter, practically)
|
145
|
+
}
|
146
|
+
output_options = {
|
147
|
+
:system => [[:GPS, 1..32], [:QZSS, 193..202]],
|
148
|
+
:satellites => (1..32).to_a + (193..202).to_a, # [idx, ...] or [[idx, label], ...] is acceptable
|
149
|
+
}
|
114
150
|
options = options.reject{|k, v|
|
115
151
|
case k
|
152
|
+
when :debug
|
153
|
+
v = v.split(/,/)
|
154
|
+
@debug[v[0].upcase.to_sym] = v[1..-1]
|
155
|
+
next true
|
116
156
|
when :weight
|
117
157
|
case v.to_sym
|
118
158
|
when :elevation # (same as underneath C++ library)
|
119
|
-
@solver.hooks[:relative_property] = proc{|prn, rel_prop, rcv_e, t_arv, usr_pos, usr_vel|
|
159
|
+
@solver.hooks[:relative_property] = proc{|prn, rel_prop, meas, rcv_e, t_arv, usr_pos, usr_vel|
|
120
160
|
if rel_prop[0] > 0 then
|
121
161
|
elv = Coordinate::ENU::relative_rel(
|
122
162
|
Coordinate::XYZ::new(*rel_prop[4..6]), usr_pos).elevation
|
@@ -156,14 +196,65 @@ class Receiver
|
|
156
196
|
llh[0..1].collect{|rad| rad / Math::PI * 180} + [llh[2]]
|
157
197
|
}"
|
158
198
|
next true
|
199
|
+
when :with, :without
|
200
|
+
[v].flatten.each{|spec| # array is acceptable
|
201
|
+
sys, svid = case spec
|
202
|
+
when Integer
|
203
|
+
[nil, spec]
|
204
|
+
when /^([a-zA-Z]+)(?::(-?\d+))?$/
|
205
|
+
[$1.upcase.to_sym, (Integer($2) rescue nil)]
|
206
|
+
when /^-?\d+$/
|
207
|
+
[nil, $&.to_i]
|
208
|
+
else
|
209
|
+
next false
|
210
|
+
end
|
211
|
+
mode = if svid && (svid < 0) then
|
212
|
+
svid *= -1
|
213
|
+
(k == :with) ? :exclude : :include
|
214
|
+
else
|
215
|
+
(k == :with) ? :include : :exclude
|
216
|
+
end
|
217
|
+
update_output = proc{|sys_target, prns, labels|
|
218
|
+
unless (i = output_options[:system].index{|sys, range| sys == sys_target}) then
|
219
|
+
i = -1
|
220
|
+
output_options[:system] << [sys_target, []]
|
221
|
+
else
|
222
|
+
output_options[:system][i].reject!{|prn| prns.include?(prn)}
|
223
|
+
end
|
224
|
+
output_options[:satellites].reject!{|prn, label| prns.include?(prn)}
|
225
|
+
if mode == :include then
|
226
|
+
output_options[:system][i][1] += prns
|
227
|
+
output_options[:satellites] += (labels ? prns.zip(labels) : prns)
|
228
|
+
end
|
229
|
+
}
|
230
|
+
check_sys_svid = proc{|sys_target, range_in_sys, offset|
|
231
|
+
next range_in_sys.include?(svid - (offset || 0)) unless sys # svid is specified without system
|
232
|
+
next false unless sys == sys_target
|
233
|
+
next true unless svid # All satellites in a target system (svid == nil)
|
234
|
+
range_in_sys.include?(svid)
|
235
|
+
}
|
236
|
+
if check_sys_svid.call(:GPS, 1..32) then
|
237
|
+
[svid || (1..32).to_a].flatten.each{|prn| @solver.gps_options.send(mode, prn)}
|
238
|
+
elsif check_sys_svid.call(:SBAS, 120..158) then
|
239
|
+
prns = [svid || (120..158).to_a].flatten
|
240
|
+
update_output.call(:SBAS, prns)
|
241
|
+
prns.each{|prn| @solver.sbas_options.send(mode, prn)}
|
242
|
+
elsif check_sys_svid.call(:QZSS, 193..202) then
|
243
|
+
[svid || (193..202).to_a].flatten.each{|prn| @solver.gps_options.send(mode, prn)}
|
244
|
+
else
|
245
|
+
raise "Unknown satellite: #{spec}"
|
246
|
+
end
|
247
|
+
$stderr.puts "#{mode.capitalize} satellite: #{[sys, svid].compact.join(':')}"
|
248
|
+
}
|
249
|
+
next true
|
159
250
|
end
|
160
251
|
false
|
161
252
|
}
|
162
253
|
raise "Unknown receiver options: #{options.inspect}" unless options.empty?
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
}
|
254
|
+
@output = {
|
255
|
+
:pvt => Receiver::pvt_items(output_options),
|
256
|
+
:meas => Receiver::meas_items(output_options),
|
257
|
+
}
|
167
258
|
end
|
168
259
|
|
169
260
|
GPS::Measurement.class_eval{
|
@@ -202,10 +293,11 @@ class Receiver
|
|
202
293
|
pvt.define_singleton_method(:rel_ENU){
|
203
294
|
Coordinate::ENU::relative(xyz, ref_pos)
|
204
295
|
} if (ref_pos && pvt.position_solved?)
|
296
|
+
output = @output
|
205
297
|
pvt.define_singleton_method(:to_s){
|
206
|
-
(
|
298
|
+
(output[:pvt].transpose[1].collect{|task|
|
207
299
|
task.call(pvt)
|
208
|
-
} +
|
300
|
+
} + output[:meas].transpose[1].collect{|task|
|
209
301
|
task.call(meas)
|
210
302
|
}).flatten.join(',')
|
211
303
|
}
|
@@ -226,7 +318,7 @@ class Receiver
|
|
226
318
|
self.instance_variable_set(k, Hash[*(sats.zip(values).flatten(1))])
|
227
319
|
}
|
228
320
|
[:@slopeH, :@slopeV] \
|
229
|
-
.zip((self.slope_HV_enu.to_a.transpose
|
321
|
+
.zip((self.fd ? self.slope_HV_enu.to_a.transpose : [nil, nil])) \
|
230
322
|
.each{|k, values|
|
231
323
|
self.instance_variable_set(k,
|
232
324
|
Hash[*(values ? sats.zip(values).flatten(1) : [])])
|
@@ -239,30 +331,41 @@ class Receiver
|
|
239
331
|
}
|
240
332
|
|
241
333
|
proc{
|
242
|
-
eph_list = Hash[*(1..32).collect{|prn|
|
334
|
+
eph_list = Hash[*((1..32).to_a + (193..202).to_a).collect{|prn|
|
243
335
|
eph = GPS::Ephemeris::new
|
244
336
|
eph.svid = prn
|
245
337
|
[prn, eph]
|
246
338
|
}.flatten(1)]
|
247
|
-
define_method(:register_ephemeris){|t_meas, prn, bcast_data|
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
339
|
+
define_method(:register_ephemeris){|t_meas, sys, prn, bcast_data|
|
340
|
+
case sys
|
341
|
+
when :GPS, :QZSS
|
342
|
+
next unless eph = eph_list[prn]
|
343
|
+
sn = @solver.gps_space_node
|
344
|
+
subframe, iodc_or_iode = eph.parse(bcast_data)
|
345
|
+
if iodc_or_iode < 0 then
|
346
|
+
begin
|
347
|
+
sn.update_iono_utc(
|
348
|
+
GPS::Ionospheric_UTC_Parameters::parse(bcast_data))
|
349
|
+
[:alpha, :beta].each{|k|
|
350
|
+
$stderr.puts "Iono #{k}: #{sn.iono_utc.send(k)}"
|
351
|
+
} if false
|
352
|
+
rescue
|
353
|
+
end
|
354
|
+
next
|
355
|
+
end
|
356
|
+
if t_meas and eph.consistent? then
|
357
|
+
eph.WN = ((t_meas.week / 1024).to_i * 1024) + (eph.WN % 1024)
|
358
|
+
sn.register_ephemeris(prn, eph)
|
359
|
+
eph.invalidate
|
360
|
+
end
|
361
|
+
when :SBAS
|
362
|
+
case @solver.sbas_space_node.decode_message(bcast_data[0..7], prn, t_meas)
|
363
|
+
when 26
|
364
|
+
['', "IGP broadcasted by PRN#{prn} @ #{Time::utc(*t_meas.c_tm)}",
|
365
|
+
@solver.sbas_space_node.ionospheric_grid_points(prn)].each{|str|
|
366
|
+
$stderr.puts str
|
367
|
+
} if @debug[:SBAS_IGP]
|
259
368
|
end
|
260
|
-
next
|
261
|
-
end
|
262
|
-
if t_meas and eph.consistent? then
|
263
|
-
eph.WN = ((t_meas.week / 1024).to_i * 1024) + (eph.WN % 1024)
|
264
|
-
sn.register_ephemeris(prn, eph)
|
265
|
-
eph.invalidate
|
266
369
|
end
|
267
370
|
}
|
268
371
|
}.call
|
@@ -276,6 +379,24 @@ class Receiver
|
|
276
379
|
|
277
380
|
after_run = b || proc{|pvt| puts pvt.to_s}
|
278
381
|
|
382
|
+
gnss_serial = proc{|svid, sys|
|
383
|
+
if sys then # new numbering
|
384
|
+
sys = [:GPS, :SBAS, :Galileo, :BeiDou, :IMES, :QZSS, :GLONASS][sys] if sys.kind_of?(Integer)
|
385
|
+
case sys
|
386
|
+
when :QZSS; svid += 192
|
387
|
+
end
|
388
|
+
else # old numbering
|
389
|
+
sys = case svid
|
390
|
+
when 1..32; :GPS
|
391
|
+
when 120..158; :SBAS
|
392
|
+
when 193..202; :QZSS
|
393
|
+
when 65..96; svid -= 64; :GLONASS
|
394
|
+
when 255; :GLONASS
|
395
|
+
end
|
396
|
+
end
|
397
|
+
[sys, svid]
|
398
|
+
}
|
399
|
+
|
279
400
|
t_meas = nil
|
280
401
|
ubx.each_packet.with_index(1){|packet, i|
|
281
402
|
$stderr.print '.' if i % 1000 == 0
|
@@ -320,8 +441,11 @@ class Receiver
|
|
320
441
|
v = post.call(v) if post
|
321
442
|
v
|
322
443
|
}
|
323
|
-
|
324
|
-
|
444
|
+
sys, svid = gnss_serial.call(*loader.call(36, 2).reverse)
|
445
|
+
case sys
|
446
|
+
when :GPS, :QZSS;
|
447
|
+
else; next
|
448
|
+
end
|
325
449
|
trk_stat = loader.call(46, 1)[0]
|
326
450
|
{
|
327
451
|
:L1_PSEUDORANGE => [16, 8, "E", proc{|v| (trk_stat & 0x1 == 0x1) ? v : nil}],
|
@@ -343,17 +467,19 @@ class Receiver
|
|
343
467
|
}
|
344
468
|
after_run.call(run(meas, t_meas), [meas, t_meas])
|
345
469
|
when [0x02, 0x11] # RXM-SFRB
|
470
|
+
sys, svid = gnss_serial.call(packet[6 + 1])
|
346
471
|
register_ephemeris(
|
347
472
|
t_meas,
|
348
|
-
|
473
|
+
sys, svid,
|
349
474
|
packet.slice(6 + 2, 40).each_slice(4).collect{|v|
|
350
|
-
|
475
|
+
res = v.pack("C*").unpack("V")[0]
|
476
|
+
(sys == :GPS) ? ((res & 0xFFFFFF) << 6) : res
|
351
477
|
})
|
352
478
|
when [0x02, 0x13] # RXM-SFRBX
|
353
|
-
|
479
|
+
sys, svid = gnss_serial.call(packet[6 + 1], packet[6])
|
354
480
|
register_ephemeris(
|
355
481
|
t_meas,
|
356
|
-
|
482
|
+
sys, svid,
|
357
483
|
packet.slice(6 + 8, 4 * packet[6 + 4]).each_slice(4).collect{|v|
|
358
484
|
v.pack("C*").unpack("V")[0]
|
359
485
|
})
|
@@ -363,8 +489,15 @@ class Receiver
|
|
363
489
|
end
|
364
490
|
|
365
491
|
def parse_rinex_nav(fname)
|
366
|
-
|
367
|
-
|
492
|
+
items = [
|
493
|
+
@solver.gps_space_node,
|
494
|
+
@solver.sbas_space_node,
|
495
|
+
].inject(0){|res, sn|
|
496
|
+
loaded_items = sn.send(:read, fname)
|
497
|
+
raise "Format error! (Not RINEX) #{fname}" if loaded_items < 0
|
498
|
+
res + loaded_items
|
499
|
+
}
|
500
|
+
$stderr.puts "Read RINEX NAV file (%s): %d items."%[fname, items]
|
368
501
|
end
|
369
502
|
|
370
503
|
def parse_rinex_obs(fname, &b)
|
@@ -375,26 +508,34 @@ class Receiver
|
|
375
508
|
GPS::RINEX_Observation::read(fname){|item|
|
376
509
|
$stderr.print '.' if (count += 1) % 1000 == 0
|
377
510
|
t_meas = item[:time]
|
378
|
-
|
511
|
+
|
512
|
+
types ||= Hash[*(item[:meas_types].collect{|sys, values|
|
513
|
+
[sys, values.collect.with_index{|type_, i|
|
514
|
+
case type_
|
515
|
+
when "C1", "C1C"
|
516
|
+
[i, :L1_PSEUDORANGE]
|
517
|
+
when "L1", "L1C"
|
518
|
+
[i, :L1_CARRIER_PHASE]
|
519
|
+
when "D1", "D1C"
|
520
|
+
[i, :L1_DOPPLER]
|
521
|
+
when "S1", "S1C"
|
522
|
+
[i, :L1_SIGNAL_STRENGTH_dBHz]
|
523
|
+
else
|
524
|
+
nil
|
525
|
+
end
|
526
|
+
}.compact]
|
527
|
+
}.flatten(1))]
|
528
|
+
|
379
529
|
meas = GPS::Measurement::new
|
380
|
-
types ||= (item[:meas_types]['G'] || item[:meas_types][' ']).collect.with_index{|type_, i|
|
381
|
-
case type_
|
382
|
-
when "C1", "C1C"
|
383
|
-
[i, :L1_PSEUDORANGE]
|
384
|
-
when "L1", "L1C"
|
385
|
-
[i, :L1_CARRIER_PHASE]
|
386
|
-
when "D1", "D1C"
|
387
|
-
[i, :L1_DOPPLER]
|
388
|
-
when "S1", "S1C"
|
389
|
-
[i, :L1_SIGNAL_STRENGTH_dBHz]
|
390
|
-
else
|
391
|
-
nil
|
392
|
-
end
|
393
|
-
}.compact
|
394
530
|
item[:meas].each{|k, v|
|
395
531
|
sys, prn = k
|
396
|
-
|
397
|
-
|
532
|
+
case sys
|
533
|
+
when 'G', ' '
|
534
|
+
when 'J'; prn += 192
|
535
|
+
else; next
|
536
|
+
end
|
537
|
+
types[sys] = (types[' '] || []) unless types[sys]
|
538
|
+
types[sys].each{|i, type_|
|
398
539
|
meas.add(prn, type_, v[i][0]) if v[i]
|
399
540
|
}
|
400
541
|
}
|
data/lib/gps_pvt/version.rb
CHANGED
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.
|
4
|
+
version: 0.2.3
|
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
|
+
date: 2022-02-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -69,7 +69,10 @@ files:
|
|
69
69
|
- ext/ninja-scan-light/tool/navigation/GPS_Solver_RAIM.h
|
70
70
|
- ext/ninja-scan-light/tool/navigation/MagneticField.h
|
71
71
|
- ext/ninja-scan-light/tool/navigation/NTCM.h
|
72
|
+
- ext/ninja-scan-light/tool/navigation/QZSS.h
|
72
73
|
- ext/ninja-scan-light/tool/navigation/RINEX.h
|
74
|
+
- ext/ninja-scan-light/tool/navigation/SBAS.h
|
75
|
+
- ext/ninja-scan-light/tool/navigation/SBAS_Solver.h
|
73
76
|
- ext/ninja-scan-light/tool/navigation/WGS84.h
|
74
77
|
- ext/ninja-scan-light/tool/navigation/coordinate.h
|
75
78
|
- ext/ninja-scan-light/tool/param/bit_array.h
|
@@ -86,6 +89,7 @@ files:
|
|
86
89
|
- ext/ninja-scan-light/tool/swig/makefile
|
87
90
|
- ext/ninja-scan-light/tool/swig/spec/GPS_spec.rb
|
88
91
|
- ext/ninja-scan-light/tool/swig/spec/SylphideMath_spec.rb
|
92
|
+
- gps_pvt.gemspec
|
89
93
|
- lib/gps_pvt.rb
|
90
94
|
- lib/gps_pvt/receiver.rb
|
91
95
|
- lib/gps_pvt/ubx.rb
|
@@ -111,7 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
111
115
|
- !ruby/object:Gem::Version
|
112
116
|
version: '0'
|
113
117
|
requirements: []
|
114
|
-
rubygems_version: 3.
|
118
|
+
rubygems_version: 3.3.7
|
115
119
|
signing_key:
|
116
120
|
specification_version: 4
|
117
121
|
summary: GPS position, velocity, and time (PVT) solver
|