gps_pvt 0.7.0 → 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 +4 -4
- data/README.md +2 -2
- data/exe/gps_pvt +3 -2
- data/ext/gps_pvt/GPS/GPS_wrap.cxx +116 -1
- data/ext/ninja-scan-light/tool/navigation/GLONASS.h +4 -11
- data/ext/ninja-scan-light/tool/navigation/GLONASS_Solver.h +25 -13
- data/ext/ninja-scan-light/tool/navigation/GPS.h +21 -18
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver.h +42 -25
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver_Base.h +38 -17
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver_RAIM.h +29 -1
- data/ext/ninja-scan-light/tool/navigation/RINEX.h +2 -6
- data/ext/ninja-scan-light/tool/navigation/SBAS.h +31 -3
- data/ext/ninja-scan-light/tool/navigation/SBAS_Solver.h +26 -14
- data/ext/ninja-scan-light/tool/navigation/SP3.h +3 -2
- data/ext/ninja-scan-light/tool/param/bit_array.h +2 -2
- data/ext/ninja-scan-light/tool/swig/GPS.i +29 -1
- data/ext/ninja-scan-light/tool/swig/spec/GPS_spec.rb +134 -13
- data/gps_pvt.gemspec +1 -0
- data/lib/gps_pvt/receiver.rb +82 -55
- data/lib/gps_pvt/util.rb +33 -1
- data/lib/gps_pvt/version.rb +1 -1
- metadata +16 -2
data/lib/gps_pvt/receiver.rb
CHANGED
@@ -19,6 +19,7 @@ class Receiver
|
|
19
19
|
opt = {
|
20
20
|
:system => [[:GPS, 1..32]],
|
21
21
|
:satellites => (1..32).to_a,
|
22
|
+
:FDE => true,
|
22
23
|
}.merge(opt)
|
23
24
|
[[
|
24
25
|
[:week, :itow_rcv, :year, :month, :mday, :hour, :min, :sec_rcv_UTC],
|
@@ -106,7 +107,7 @@ class Receiver
|
|
106
107
|
el_deg = [4, 6].collect{|i| pvt.elevation[fd[i]] / Math::PI * 180}
|
107
108
|
fd[0..4] + [el_deg[0]] + fd[5..6] + [el_deg[1]]
|
108
109
|
}
|
109
|
-
]] + [[
|
110
|
+
]] + (opt[:FDE] ? [[
|
110
111
|
[:wssr_FDE_min, :wssr_FDE_min_PRN, :wssr_FDE_2nd, :wssr_FDE_2nd_PRN],
|
111
112
|
proc{|pvt|
|
112
113
|
[:fde_min, :fde_2nd].collect{|f|
|
@@ -115,7 +116,7 @@ class Receiver
|
|
115
116
|
[info[0], info[-3]]
|
116
117
|
}.flatten
|
117
118
|
}
|
118
|
-
]]
|
119
|
+
]] : [])
|
119
120
|
end
|
120
121
|
|
121
122
|
def self.meas_items(opt = {})
|
@@ -149,11 +150,11 @@ class Receiver
|
|
149
150
|
|
150
151
|
def initialize(options = {})
|
151
152
|
@solver = GPS::Solver::new
|
152
|
-
@solver.
|
153
|
-
|
154
|
-
rel_prop
|
153
|
+
@solver.options = {
|
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
|
}
|
@@ -165,8 +166,10 @@ class Receiver
|
|
165
166
|
output_options = {
|
166
167
|
:system => [[:GPS, 1..32], [:QZSS, 193..202]],
|
167
168
|
:satellites => (1..32).to_a + (193..202).to_a, # [idx, ...] or [[idx, label], ...] is acceptable
|
169
|
+
:FDE => false,
|
168
170
|
}
|
169
171
|
options = options.reject{|k, v|
|
172
|
+
def v.to_b; !(self =~ /^(?:false|0|f|off)$/i); end
|
170
173
|
case k
|
171
174
|
when :debug
|
172
175
|
v = v.split(/,/)
|
@@ -174,7 +177,7 @@ class Receiver
|
|
174
177
|
next true
|
175
178
|
when :weight
|
176
179
|
case v.to_sym
|
177
|
-
when :elevation # (same as underneath C++ library)
|
180
|
+
when :elevation # (same as underneath C++ library except for ignoring broadcasted/calculated URA)
|
178
181
|
@solver.hooks[:relative_property] = proc{|prn, rel_prop, meas, rcv_e, t_arv, usr_pos, usr_vel|
|
179
182
|
if rel_prop[0] > 0 then
|
180
183
|
elv = Coordinate::ENU::relative_rel(
|
@@ -184,7 +187,11 @@ class Receiver
|
|
184
187
|
rel_prop
|
185
188
|
}
|
186
189
|
next true
|
187
|
-
when :identical # same
|
190
|
+
when :identical # treat each satellite range having same accuracy
|
191
|
+
@solver.hooks[:relative_property] = proc{|prn, rel_prop, meas, rcv_e, t_arv, usr_pos, usr_vel|
|
192
|
+
rel_prop[0] = 1 if rel_prop[0] > 0 # weight = 1
|
193
|
+
rel_prop
|
194
|
+
}
|
188
195
|
next true
|
189
196
|
end
|
190
197
|
when :elevation_mask_deg
|
@@ -280,6 +287,9 @@ class Receiver
|
|
280
287
|
$stderr.puts "#{mode.capitalize} satellite: #{[sys, svid].compact.join(':')}"
|
281
288
|
}
|
282
289
|
next true
|
290
|
+
when :fault_exclusion
|
291
|
+
@solver.options = {:skip_exclusion => !(output_options[:FDE] = v.to_b)}
|
292
|
+
next true
|
283
293
|
end
|
284
294
|
false
|
285
295
|
}
|
@@ -289,6 +299,24 @@ class Receiver
|
|
289
299
|
:meas => Receiver::meas_items(output_options),
|
290
300
|
}
|
291
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
|
292
320
|
|
293
321
|
GPS::Measurement.class_eval{
|
294
322
|
proc{
|
@@ -322,7 +350,7 @@ class Receiver
|
|
322
350
|
=end
|
323
351
|
|
324
352
|
#@solver.gps_space_node.update_all_ephemeris(t_meas) # internally called in the following solver.solve
|
325
|
-
pvt = @solver.solve(meas, t_meas)
|
353
|
+
pvt = critical{@solver.solve(meas, t_meas)}
|
326
354
|
pvt.define_singleton_method(:rel_ENU){
|
327
355
|
Coordinate::ENU::relative(xyz, ref_pos)
|
328
356
|
} if (ref_pos && pvt.position_solved?)
|
@@ -369,60 +397,59 @@ class Receiver
|
|
369
397
|
}
|
370
398
|
}
|
371
399
|
|
372
|
-
|
373
|
-
eph_list
|
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|
|
374
402
|
eph = GPS::Ephemeris::new
|
375
403
|
eph.svid = prn
|
376
404
|
[prn, eph]
|
377
405
|
}.flatten(1)]
|
378
|
-
eph_glonass_list
|
406
|
+
@eph_glonass_list ||= Hash[*(1..24).collect{|num|
|
379
407
|
eph = GPS::Ephemeris_GLONASS::new
|
380
408
|
eph.svid = num
|
381
409
|
[num, eph]
|
382
410
|
}.flatten(1)]
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
rescue
|
398
|
-
end
|
399
|
-
next
|
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
|
400
425
|
end
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
when :SBAS
|
407
|
-
case @solver.sbas_space_node.decode_message(bcast_data[0..7], prn, t_meas)
|
408
|
-
when 26
|
409
|
-
['', "IGP broadcasted by PRN#{prn} @ #{Time::utc(*t_meas.c_tm)}",
|
410
|
-
@solver.sbas_space_node.ionospheric_grid_points(prn)].each{|str|
|
411
|
-
$stderr.puts str
|
412
|
-
} if @debug[:SBAS_IGP]
|
413
|
-
end if t_meas
|
414
|
-
when :GLONASS
|
415
|
-
next unless eph = eph_glonass_list[prn]
|
416
|
-
leap_sec = @solver.gps_space_node.is_valid_utc ?
|
417
|
-
@solver.gps_space_node.iono_utc.delta_t_LS :
|
418
|
-
GPS::Time::guess_leap_seconds(t_meas)
|
419
|
-
next unless eph.parse(bcast_data[0..3], leap_sec)
|
420
|
-
eph.freq_ch = opt[:freq_ch] || 0
|
421
|
-
@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)
|
422
431
|
eph.invalidate
|
423
432
|
end
|
424
|
-
|
425
|
-
|
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
|
426
453
|
|
427
454
|
def parse_ubx(ubx_fname, &b)
|
428
455
|
$stderr.print "Reading UBX file (%s) "%[ubx_fname]
|
@@ -555,7 +582,7 @@ class Receiver
|
|
555
582
|
@solver.sbas_space_node,
|
556
583
|
@solver.glonass_space_node,
|
557
584
|
].inject(0){|res, sn|
|
558
|
-
loaded_items = sn.send(:read, fname)
|
585
|
+
loaded_items = critical{sn.send(:read, fname)}
|
559
586
|
raise "Format error! (Not RINEX) #{src}" if loaded_items < 0
|
560
587
|
res + loaded_items
|
561
588
|
}
|
@@ -639,7 +666,7 @@ class Receiver
|
|
639
666
|
next unless /^SYS_(?!SYSTEMS)(.*)/ =~ sys.to_s
|
640
667
|
idx, sys_name = [@sp3.class.const_get(sys), $1]
|
641
668
|
next unless sats[idx] > 0
|
642
|
-
next unless @sp3.push(@solver, idx)
|
669
|
+
next unless critical{@sp3.push(@solver, idx)}
|
643
670
|
$stderr.puts "Change ephemeris source of #{sys_name} to SP3"
|
644
671
|
}
|
645
672
|
end
|
@@ -647,7 +674,7 @@ class Receiver
|
|
647
674
|
def attach_antex(src)
|
648
675
|
fname = Util::get_txt(src)
|
649
676
|
raise "Specify SP3 before ANTEX application!" unless @sp3
|
650
|
-
applied_items = @sp3.apply_antex(fname)
|
677
|
+
applied_items = critical{@sp3.apply_antex(fname)}
|
651
678
|
raise "Format error! (Not ANTEX) #{src}" unless applied_items >= 0
|
652
679
|
$stderr.puts "SP3 correction with ANTEX file (%s): %d items have been processed."%[src, applied_items]
|
653
680
|
end
|
@@ -663,7 +690,7 @@ class Receiver
|
|
663
690
|
next unless /^SYS_(?!SYSTEMS)(.*)/ =~ sys.to_s
|
664
691
|
idx, sys_name = [@clk.class.const_get(sys), $1]
|
665
692
|
next unless sats[idx] > 0
|
666
|
-
next unless @clk.push(@solver, idx)
|
693
|
+
next unless critical{@clk.push(@solver, idx)}
|
667
694
|
$stderr.puts "Change clock error source of #{sys_name} to RINEX clock"
|
668
695
|
}
|
669
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
|
data/lib/gps_pvt/version.rb
CHANGED
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.
|
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-
|
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
|