gps_pvt 0.10.2 → 0.10.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/Rakefile +27 -16
- data/exe/gps2ubx +111 -17
- data/ext/gps_pvt/SylphideMath/SylphideMath_wrap.cxx +10 -10
- data/ext/ninja-scan-light/tool/navigation/GPS.h +22 -3
- data/ext/ninja-scan-light/tool/swig/Coordinate.i +6 -0
- data/ext/ninja-scan-light/tool/swig/SylphideMath.i +37 -0
- data/ext/ninja-scan-light/tool/swig/spec/SylphideMath_spec.rb +6 -4
- data/gps_pvt.gemspec +1 -0
- data/lib/gps_pvt/ntrip.rb +6 -3
- data/lib/gps_pvt/pvt.rb +83 -0
- data/lib/gps_pvt/receiver/almanac.rb +137 -0
- data/lib/gps_pvt/receiver/extension.rb +3 -6
- data/lib/gps_pvt/receiver.rb +2 -1
- data/lib/gps_pvt/supl.rb +162 -55
- data/lib/gps_pvt/util.rb +8 -2
- data/lib/gps_pvt/version.rb +1 -1
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 60413c3add439fa66e0ff908f43f0049ad306fcefca50e2c485bc28790597143
|
4
|
+
data.tar.gz: 788f430151ca35a95abd4f96e4f30239e9f53768014af9ddc5897305b25b7fb9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9c0ddc7d6a4f589cf3b3692eacde62405c78890f20cadf5abde07d189ae35bda83fd0b9e905728e4fecaf111aeee14bfb615166ef72d355fcac1a3368330ee89
|
7
|
+
data.tar.gz: 457d23f7e4032549961e499638403b3d01d681a8051231616ee2dde5183967c119028bd2a4475f2fe1c1e3ae2ffda61729162ced5d30b33113bfe21c161c188e
|
data/README.md
CHANGED
@@ -43,7 +43,7 @@ The format of file is automatically determined with its extension, such as .ubx
|
|
43
43
|
| --antex=file_or_URI | [Antenna Exchange Format](https://igs.org/wg/antenna#files) (supported gps_pvt version >= 0.6.0) |
|
44
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) |
|
45
45
|
| <a name=opt_rtcm3>--rtcm3=file_or_URI</a> | [RTCM 10403.x](https://rtcm.myshopify.com/collections/differential-global-navigation-satellite-dgnss-standards). (supported gps_pvt version >= 0.9.0) The latest version uses message type Observation(GPS: 1001..1004; GLONASS: 1009..1012), Epehemris(GPS: 1019; GLOANSS: 1020; SBAS: 1043; QZSS: 1044), MSM(GPS: 1071..1077; GLONASS: 1081..1087; SBAS: 1101..1107; QZSS: 1111..1117) |
|
46
|
-
| <a name=opt_supl>--supl=URI</a> | [SUPL, secure user plane location](https://www.openmobilealliance.org/release/SUPL/). (supported gps_pvt version >= 0.10.0)
|
46
|
+
| <a name=opt_supl>--supl=URI</a> | [SUPL, secure user plane location](https://www.openmobilealliance.org/release/SUPL/). (supported gps_pvt version >= 0.10.0) Whether [LPP(default)](https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=3710) or [RRLP](https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=2688) are internally used, which can be manually selected by adding ```?protocol=lpp_or_rrlp``` URI query string. |
|
47
47
|
|
48
48
|
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
|
49
49
|
|
data/Rakefile
CHANGED
@@ -11,6 +11,14 @@ Rake::ExtensionTask.new("gps_pvt") do |ext|
|
|
11
11
|
ext.lib_dir = "lib/gps_pvt"
|
12
12
|
end
|
13
13
|
|
14
|
+
require "yard"
|
15
|
+
|
16
|
+
YARD::Rake::YardocTask.new do |t|
|
17
|
+
#t.files = ['lib/**/*.rb', 'ext/**/*_wrap.cxx']
|
18
|
+
t.options = ['--embed-mixins']
|
19
|
+
#t.stats_options = ['--list-undoc']
|
20
|
+
end
|
21
|
+
|
14
22
|
namespace :git do
|
15
23
|
task :version do
|
16
24
|
@git_version ||= proc{
|
@@ -83,25 +91,28 @@ end
|
|
83
91
|
|
84
92
|
desc "Generate SWIG wrapper codes"
|
85
93
|
task :swig do
|
86
|
-
swig_dir = File::join(File::dirname(__FILE__), 'ext', 'ninja-scan-light', 'tool', 'swig')
|
87
94
|
out_base_dir = File::join(File::dirname(__FILE__), 'ext', 'gps_pvt')
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
95
|
+
[
|
96
|
+
File::join(File::dirname(__FILE__), 'ext', 'ninja-scan-light', 'tool', 'swig'),
|
97
|
+
].each{|swig_dir|
|
98
|
+
Dir::chdir(swig_dir){
|
99
|
+
Dir::glob("*.i"){|src|
|
100
|
+
mod_name = File::basename(src, '.*')
|
101
|
+
out_dir = File::join(out_base_dir, mod_name)
|
102
|
+
sh "mkdir -p #{out_dir}"
|
103
|
+
wrapper = File::join(out_dir, "#{mod_name}_wrap.cxx")
|
104
|
+
sh [:make, :clean, wrapper,
|
105
|
+
"BUILD_DIR=#{out_dir}",
|
106
|
+
"SWIGFLAGS='-c++ -ruby -prefix \"GPS_PVT::\"#{" -D__MINGW__" if ENV["MSYSTEM"]}'"].join(' ')
|
107
|
+
open(wrapper, 'r+'){|io|
|
108
|
+
lines = io.read.lines.collect{|line|
|
109
|
+
line.sub(/rb_require\(\"([^\"]+)\"\)/){ # from camel to underscore downcase style
|
110
|
+
"rb_require(\"#{$1.sub('GPS_PVT', 'gps_pvt')}\")"
|
111
|
+
}
|
101
112
|
}
|
113
|
+
io.rewind
|
114
|
+
io.write(lines.join)
|
102
115
|
}
|
103
|
-
io.rewind
|
104
|
-
io.write(lines.join)
|
105
116
|
}
|
106
117
|
}
|
107
118
|
}
|
data/exe/gps2ubx
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'gps_pvt'
|
4
4
|
require 'uri'
|
5
5
|
require 'gps_pvt/ubx'
|
6
|
+
require 'gps_pvt/pvt'
|
6
7
|
|
7
8
|
# Convert file(s) to ubx format
|
8
9
|
# TODO currently only RINEX observation file is supported.
|
@@ -25,6 +26,7 @@ options = []
|
|
25
26
|
misc_options = {
|
26
27
|
:broadcast_data => false,
|
27
28
|
:ubx_rawx => false,
|
29
|
+
:ubx_nav => false,
|
28
30
|
:eph_interval => 60 * 5,
|
29
31
|
}
|
30
32
|
|
@@ -32,7 +34,7 @@ misc_options = {
|
|
32
34
|
files = ARGV.collect{|arg|
|
33
35
|
next [arg, nil] unless arg =~ /^--([^=]+)=?/
|
34
36
|
k, v = [$1.downcase.to_sym, $']
|
35
|
-
next [v, k] if [:rinex_nav, :rinex_obs, :ubx, :rtcm3].include?(k) # file type
|
37
|
+
next [v, k] if [:rinex_nav, :rinex_obs, :ubx, :rtcm3, :pvt_csv].include?(k) # file type
|
36
38
|
options << [$1.to_sym, $']
|
37
39
|
nil
|
38
40
|
}.compact
|
@@ -43,6 +45,7 @@ files.collect!{|fname, ftype|
|
|
43
45
|
when /\.\d{2}[nhqg](?:\.gz)?$/; :rinex_nav
|
44
46
|
when /\.\d{2}o(?:\.gz)?$/; :rinex_obs
|
45
47
|
when /\.ubx$/; :ubx
|
48
|
+
when /\.csv$/; misc_options[:ubx_nav] = true; :pvt_csv
|
46
49
|
end
|
47
50
|
if (!(uri = URI::parse(fname)).instance_of?(URI::Generic) rescue false) then
|
48
51
|
ftype ||= case uri
|
@@ -57,7 +60,7 @@ files.collect!{|fname, ftype|
|
|
57
60
|
|
58
61
|
options.reject!{|opt|
|
59
62
|
case opt[0]
|
60
|
-
when :ubx_rawx, :broadcast_data, :eph_interval
|
63
|
+
when :ubx_rawx, :ubx_nav, :broadcast_data, :eph_interval
|
61
64
|
misc_options[opt[0]] = opt[1]
|
62
65
|
true
|
63
66
|
when :online_ephemeris
|
@@ -70,10 +73,13 @@ options.reject!{|opt|
|
|
70
73
|
|
71
74
|
rcv = GPS_PVT::Receiver::new(options)
|
72
75
|
|
73
|
-
|
74
|
-
rcv.
|
75
|
-
|
76
|
-
|
76
|
+
outputs = Queue::new # [[time, item1, item2, ...], ...]
|
77
|
+
rcv.instance_eval{
|
78
|
+
nav_task = misc_options[:ubx_nav] ? method(:run) : proc{}
|
79
|
+
define_singleton_method(:run){|meas, t_meas, *args|
|
80
|
+
outputs << [t_meas, meas, nav_task.call(meas, t_meas, *args)].compact
|
81
|
+
nil
|
82
|
+
}
|
77
83
|
}
|
78
84
|
|
79
85
|
proc{|src|
|
@@ -106,6 +112,9 @@ threads = files.collect{|fname, ftype|
|
|
106
112
|
when :rtcm3; proc{rcv.parse_rtcm3(fname){}}
|
107
113
|
when :supl; proc{rcv.parse_supl(fname)}
|
108
114
|
when :rinex_nav; proc{}
|
115
|
+
when :pvt_csv; proc{GPS_PVT::GPS::PVT_minimal::parse_csv(fname){|t, pvt|
|
116
|
+
outputs << [t, pvt]
|
117
|
+
}}
|
109
118
|
end
|
110
119
|
case fname
|
111
120
|
when URI::Ntrip, URI::Supl; Thread::new(&task)
|
@@ -113,9 +122,9 @@ threads = files.collect{|fname, ftype|
|
|
113
122
|
end
|
114
123
|
}.compact
|
115
124
|
|
116
|
-
|
125
|
+
outputs = proc{
|
117
126
|
tmp = []
|
118
|
-
tmp <<
|
127
|
+
tmp << outputs.pop until outputs.empty?
|
119
128
|
tmp
|
120
129
|
}.call.sort!{|a, b| b[0] <=> a[0]} if threads.empty? # Sort by measurement time
|
121
130
|
|
@@ -124,7 +133,7 @@ gen_gpstime = proc{
|
|
124
133
|
tmpl = [0xB5, 0x62, 0x01, 0x20, 16, 0]
|
125
134
|
gpst = GPS_PVT::GPS::Time
|
126
135
|
t_next = gpst::new(*gpst::leap_second_events.find{|wn, sec, leap| leap == 1}[0..1])
|
127
|
-
proc{|t_meas
|
136
|
+
proc{|t_meas|
|
128
137
|
next nil if t_meas < t_next
|
129
138
|
t_next = t_meas + 60 # 1 min. interval
|
130
139
|
ubx = tmpl.clone
|
@@ -374,17 +383,102 @@ gen_rawx = proc{|t_meas, meas| # Convert to RXM-RAWX(0x15)
|
|
374
383
|
GPS_PVT::UBX::update(ubx).pack("C*")
|
375
384
|
}
|
376
385
|
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
386
|
+
gen_nav = proc{|t_meas, pvt|
|
387
|
+
t_msec = (t_meas.seconds * 1E3).round
|
388
|
+
packet = []
|
389
|
+
|
390
|
+
proc{ # Convert to NAV-SOL (0x01-0x06)
|
391
|
+
ubx_sol = [0xB5, 0x62, 0x01, 0x06, 52, 0]
|
392
|
+
ubx_sol += [
|
393
|
+
t_msec,
|
394
|
+
0, # frac
|
395
|
+
t_meas.week, # week
|
396
|
+
if (pvt.position_solved? and pvt.velocity_solved?) then
|
397
|
+
[
|
398
|
+
0x03, # 3D-Fix
|
399
|
+
0x0D, # GPSfixOK, WKNSET, TOWSET
|
400
|
+
pvt.xyz.to_a.collect{|v| (v * 1E2).to_i}, # ECEF_XYZ [cm]
|
401
|
+
(Math::sqrt((pvt.hsigma ** 2) + (pvt.vsigma ** 2)) * 1E2).to_i, # 3D pos accuracy [cm]
|
402
|
+
(pvt.velocity.absolute(pvt.xyz) - pvt.xyz).to_a.collect{|v| (v * 1E2).to_i}, # ECEF_VXYZ [cm/s]
|
403
|
+
(pvt.vel_sigma * 1E2).to_i, # Speed accuracy [cm/s]
|
404
|
+
(pvt.pdop * 1E2).to_i, # PDOP [0.01]
|
405
|
+
]
|
406
|
+
else
|
407
|
+
[
|
408
|
+
0, # 3D-Fix
|
409
|
+
0x08, # TOWSET
|
410
|
+
[0] * 3, # ECEF_XYZ [cm]
|
411
|
+
0, # 3D pos accuracy [cm]
|
412
|
+
[0] * 3, # ECEF_VXYZ [cm/s]
|
413
|
+
0, # Speed accuracy [cm/s]
|
414
|
+
0, # PDOP
|
415
|
+
]
|
416
|
+
end,
|
417
|
+
0,
|
418
|
+
pvt.used_satellites,
|
419
|
+
0].flatten.pack('V2vc2l<3Vl<3VvC2V').unpack('C*')
|
420
|
+
packet += GPS_PVT::UBX::update(ubx_sol + [0, 0])
|
421
|
+
}.call
|
422
|
+
|
423
|
+
# Convert to NAV-POSLLH (0x01-0x02)
|
424
|
+
if pvt.position_solved? then
|
425
|
+
llh = pvt.llh
|
426
|
+
ubx_posllh = [0xB5, 0x62, 0x01, 0x02, 28, 0]
|
427
|
+
ubx_posllh += [
|
428
|
+
t_msec,
|
429
|
+
(llh.lng / Math::PI * 180 * 1E7).to_i, # Longitude [1E-7 deg]
|
430
|
+
(llh.lat / Math::PI * 180 * 1E7).to_i, # Latitude [1E-7 deg]
|
431
|
+
(llh.alt * 1E3).to_i, # WGS-84 altitude [mm]
|
432
|
+
(llh.alt * 1E3).to_i, # mean sea level TODO fix
|
433
|
+
(pvt.hsigma * 1E3).to_i, # HAcc [mm]
|
434
|
+
(pvt.vsigma * 1E3).to_i, # VAcc [mm]
|
435
|
+
].pack('V*').unpack("C*")
|
436
|
+
packet += GPS_PVT::UBX::update(ubx_posllh + [0, 0])
|
437
|
+
end
|
438
|
+
|
439
|
+
# Convert to NAV-VELNED (0x01-0x12)
|
440
|
+
if pvt.velocity_solved? then
|
441
|
+
vel = pvt.velocity
|
442
|
+
ubx_velned = [0xB5, 0x62, 0x01, 0x12, 36, 0]
|
443
|
+
ubx_velned += [
|
444
|
+
t_msec,
|
445
|
+
(vel.n * 1E2).to_i, # N speed [cm/s]
|
446
|
+
(vel.e * 1E2).to_i, # E speed [cm/s]
|
447
|
+
(vel.d * 1E2).to_i, # D speed [cm/s]
|
448
|
+
(vel.distance * 1E2).to_i, # 3D speed [cm/s]
|
449
|
+
(vel.horizontal * 1E2).to_i, # 2D speed [cm/s]
|
450
|
+
(vel.azimuth / Math::PI * 180 * 1E5).to_i, # Heading [1E-5 deg]
|
451
|
+
(pvt.vel_sigma * 1E2).to_i, # sAcc speed accuracy [cm/s]
|
452
|
+
(2 * 1E5).to_i, # cAcc heading accuracy [1E-5 deg] TODO
|
453
|
+
].pack('V*').unpack("C*")
|
454
|
+
packet += GPS_PVT::UBX::update(ubx_velned + [0, 0])
|
455
|
+
end
|
456
|
+
|
457
|
+
(gen_gpstime.call(t_meas) || '') + packet.pack('C*')
|
458
|
+
}
|
459
|
+
|
460
|
+
gen_list = Hash[*({
|
461
|
+
:Measurement => proc{
|
462
|
+
gen_ary = []
|
463
|
+
gen_ary << gen_gpstime unless misc_options[:ubx_rawx]
|
464
|
+
gen_ary << (misc_options[:ubx_rawx] ? gen_sfrbx : gen_sfrb) if misc_options[:broadcast_data]
|
465
|
+
gen_ary << (misc_options[:ubx_rawx] ? gen_rawx : gen_raw)
|
466
|
+
proc{|t_meas, meas|
|
467
|
+
meas = meas.to_hash
|
468
|
+
gen_ary.collect{|gen| gen.call(t_meas, meas)}.join
|
469
|
+
}
|
470
|
+
}.call,
|
471
|
+
:PVT => gen_nav,
|
472
|
+
:PVT_minimal => gen_nav,
|
473
|
+
}.collect{|k, v| [GPS_PVT::GPS.const_get(k), v]}.flatten(1))]
|
381
474
|
STDOUT.binmode
|
382
475
|
|
383
476
|
task_dump = proc{
|
384
|
-
until
|
385
|
-
t_meas,
|
386
|
-
|
387
|
-
|
477
|
+
until outputs.empty? do
|
478
|
+
t_meas, *items = outputs.pop
|
479
|
+
items.each{|item|
|
480
|
+
print gen_list[item.class].call(t_meas, item)
|
481
|
+
}
|
388
482
|
end
|
389
483
|
}
|
390
484
|
if threads.empty? then
|
@@ -8495,7 +8495,7 @@ _wrap_Matrix_FrozenD_each__SWIG_0(int argc, VALUE *argv, VALUE self) {
|
|
8495
8495
|
(&_e)->regenerate();
|
8496
8496
|
SWIG_fail;
|
8497
8497
|
}
|
8498
|
-
vresult =
|
8498
|
+
vresult = self;
|
8499
8499
|
return vresult;
|
8500
8500
|
fail:
|
8501
8501
|
return Qnil;
|
@@ -8531,7 +8531,7 @@ _wrap_Matrix_FrozenD_each__SWIG_1(int argc, VALUE *argv, VALUE self) {
|
|
8531
8531
|
(&_e)->regenerate();
|
8532
8532
|
SWIG_fail;
|
8533
8533
|
}
|
8534
|
-
vresult =
|
8534
|
+
vresult = self;
|
8535
8535
|
return vresult;
|
8536
8536
|
fail:
|
8537
8537
|
return Qnil;
|
@@ -11940,7 +11940,7 @@ _wrap_Matrix_FrozenD_f_each__SWIG_0(int argc, VALUE *argv, VALUE self) {
|
|
11940
11940
|
(&_e)->regenerate();
|
11941
11941
|
SWIG_fail;
|
11942
11942
|
}
|
11943
|
-
vresult =
|
11943
|
+
vresult = self;
|
11944
11944
|
return vresult;
|
11945
11945
|
fail:
|
11946
11946
|
return Qnil;
|
@@ -11976,7 +11976,7 @@ _wrap_Matrix_FrozenD_f_each__SWIG_1(int argc, VALUE *argv, VALUE self) {
|
|
11976
11976
|
(&_e)->regenerate();
|
11977
11977
|
SWIG_fail;
|
11978
11978
|
}
|
11979
|
-
vresult =
|
11979
|
+
vresult = self;
|
11980
11980
|
return vresult;
|
11981
11981
|
fail:
|
11982
11982
|
return Qnil;
|
@@ -13956,7 +13956,7 @@ _wrap_MatrixD_resizeN___(int argc, VALUE *argv, VALUE self) {
|
|
13956
13956
|
}
|
13957
13957
|
}
|
13958
13958
|
result = (Matrix< double,Array2D_Dense< double > > *) &Matrix_Sl_double_Sc_Array2D_Dense_Sl_double_Sg__Sg__resize(arg1,(unsigned int const *)arg2,(unsigned int const *)arg3);
|
13959
|
-
vresult =
|
13959
|
+
vresult = self;
|
13960
13960
|
return vresult;
|
13961
13961
|
fail:
|
13962
13962
|
return Qnil;
|
@@ -16448,7 +16448,7 @@ _wrap_Matrix_FrozenComplexD_each__SWIG_0(int argc, VALUE *argv, VALUE self) {
|
|
16448
16448
|
(&_e)->regenerate();
|
16449
16449
|
SWIG_fail;
|
16450
16450
|
}
|
16451
|
-
vresult =
|
16451
|
+
vresult = self;
|
16452
16452
|
return vresult;
|
16453
16453
|
fail:
|
16454
16454
|
return Qnil;
|
@@ -16484,7 +16484,7 @@ _wrap_Matrix_FrozenComplexD_each__SWIG_1(int argc, VALUE *argv, VALUE self) {
|
|
16484
16484
|
(&_e)->regenerate();
|
16485
16485
|
SWIG_fail;
|
16486
16486
|
}
|
16487
|
-
vresult =
|
16487
|
+
vresult = self;
|
16488
16488
|
return vresult;
|
16489
16489
|
fail:
|
16490
16490
|
return Qnil;
|
@@ -19891,7 +19891,7 @@ _wrap_Matrix_FrozenComplexD_f_each__SWIG_0(int argc, VALUE *argv, VALUE self) {
|
|
19891
19891
|
(&_e)->regenerate();
|
19892
19892
|
SWIG_fail;
|
19893
19893
|
}
|
19894
|
-
vresult =
|
19894
|
+
vresult = self;
|
19895
19895
|
return vresult;
|
19896
19896
|
fail:
|
19897
19897
|
return Qnil;
|
@@ -19927,7 +19927,7 @@ _wrap_Matrix_FrozenComplexD_f_each__SWIG_1(int argc, VALUE *argv, VALUE self) {
|
|
19927
19927
|
(&_e)->regenerate();
|
19928
19928
|
SWIG_fail;
|
19929
19929
|
}
|
19930
|
-
vresult =
|
19930
|
+
vresult = self;
|
19931
19931
|
return vresult;
|
19932
19932
|
fail:
|
19933
19933
|
return Qnil;
|
@@ -21903,7 +21903,7 @@ _wrap_MatrixComplexD_resizeN___(int argc, VALUE *argv, VALUE self) {
|
|
21903
21903
|
}
|
21904
21904
|
}
|
21905
21905
|
result = (Matrix< Complex< double >,Array2D_Dense< Complex< double > > > *) &Matrix_Sl_Complex_Sl_double_Sg__Sc_Array2D_Dense_Sl_Complex_Sl_double_Sg__Sg__Sg__resize(arg1,(unsigned int const *)arg2,(unsigned int const *)arg3);
|
21906
|
-
vresult =
|
21906
|
+
vresult = self;
|
21907
21907
|
return vresult;
|
21908
21908
|
fail:
|
21909
21909
|
return Qnil;
|
@@ -95,6 +95,11 @@ class GPS_Signal {
|
|
95
95
|
PRN::content <<= 1;
|
96
96
|
PRN::content[0] = tmp;
|
97
97
|
}
|
98
|
+
void previous(){
|
99
|
+
bool tmp(PRN::content[3] ^ PRN::content[0]);
|
100
|
+
PRN::content >>= 1;
|
101
|
+
PRN::content[9] = tmp;
|
102
|
+
}
|
98
103
|
};
|
99
104
|
|
100
105
|
class G2 : public PRN {
|
@@ -114,6 +119,16 @@ class GPS_Signal {
|
|
114
119
|
PRN::content <<= 1;
|
115
120
|
PRN::content[0] = tmp;
|
116
121
|
}
|
122
|
+
void previous(){
|
123
|
+
bool tmp(PRN::content[2]
|
124
|
+
^ PRN::content[3]
|
125
|
+
^ PRN::content[6]
|
126
|
+
^ PRN::content[8]
|
127
|
+
^ PRN::content[9]
|
128
|
+
^ PRN::content[0]);
|
129
|
+
PRN::content >>= 1;
|
130
|
+
PRN::content[9] = tmp;
|
131
|
+
}
|
117
132
|
static G2 get_G2(const int &prn){
|
118
133
|
switch(prn){
|
119
134
|
case 1: return G2(1, 5);
|
@@ -160,9 +175,9 @@ class GPS_Signal {
|
|
160
175
|
class CA_Code {
|
161
176
|
public:
|
162
177
|
typedef FloatT float_t;
|
163
|
-
static const float_t
|
178
|
+
static const float_t FREQUENCY;
|
164
179
|
static const float_t length_1chip() {
|
165
|
-
static const float_t res(1. /
|
180
|
+
static const float_t res(1. / FREQUENCY);
|
166
181
|
return res;
|
167
182
|
}
|
168
183
|
protected:
|
@@ -177,11 +192,15 @@ class GPS_Signal {
|
|
177
192
|
g1.next();
|
178
193
|
g2.next();
|
179
194
|
}
|
195
|
+
void previous(){
|
196
|
+
g1.previous();
|
197
|
+
g2.previous();
|
198
|
+
}
|
180
199
|
};
|
181
200
|
};
|
182
201
|
|
183
202
|
template <class FloatT>
|
184
|
-
const typename GPS_Signal<FloatT>::float_t GPS_Signal<FloatT>::CA_Code::
|
203
|
+
const typename GPS_Signal<FloatT>::float_t GPS_Signal<FloatT>::CA_Code::FREQUENCY = 1.023E6;
|
185
204
|
|
186
205
|
template <class FloatT = double>
|
187
206
|
struct GPS_Time {
|
@@ -73,6 +73,8 @@ struct native_exception : public std::exception {
|
|
73
73
|
values[i] = (*self)[i];
|
74
74
|
}
|
75
75
|
}
|
76
|
+
%typemap(in) FloatT values[3];
|
77
|
+
%typemap(argout) FloatT values[3];
|
76
78
|
#endif
|
77
79
|
%typemap(in,numinputs=0) const void *check_block {
|
78
80
|
#ifdef SWIGRUBY
|
@@ -98,6 +100,7 @@ struct native_exception : public std::exception {
|
|
98
100
|
#endif
|
99
101
|
}
|
100
102
|
}
|
103
|
+
%clear const void *check_block;
|
101
104
|
};
|
102
105
|
#ifdef SWIGRUBY
|
103
106
|
%mixin System_3D "Enumerable";
|
@@ -170,6 +173,9 @@ struct native_exception : public std::exception {
|
|
170
173
|
%template(XYZ) System_XYZ<type, WGS84>;
|
171
174
|
%template(LLH) System_LLH<type, WGS84>;
|
172
175
|
%template(ENU) System_ENU<type, WGS84>;
|
176
|
+
%typemap(out) FloatT &;
|
177
|
+
%typemap(in) (type (&res)[3][3]);
|
178
|
+
%typemap(argout) (type (&res)[3][3]);
|
173
179
|
%enddef
|
174
180
|
|
175
181
|
CONCRETIZE(double);
|
@@ -960,6 +960,7 @@ struct MatrixUtil {
|
|
960
960
|
std::string("Unknown enumerate direction: ").append(inspect_str($1)).c_str());
|
961
961
|
}
|
962
962
|
}
|
963
|
+
%typemap(out) const Matrix_Frozen<T, Array2D_Type, ViewType> & "$result = self;"
|
963
964
|
%catches(native_exception) each;
|
964
965
|
const Matrix_Frozen<T, Array2D_Type, ViewType> &each(
|
965
966
|
void (*each_func)(
|
@@ -970,6 +971,7 @@ struct MatrixUtil {
|
|
970
971
|
return *$self;
|
971
972
|
}
|
972
973
|
%alias each "each_with_index";
|
974
|
+
%typemap(out) const Matrix_Frozen<T, Array2D_Type, ViewType> &;
|
973
975
|
|
974
976
|
%catches(native_exception, std::invalid_argument) map;
|
975
977
|
Matrix<T, Array2D_Dense<T> > map(
|
@@ -1005,6 +1007,7 @@ struct MatrixUtil {
|
|
1005
1007
|
(RTEST(idx_selector) ? 1 : 0), &idx_selector,
|
1006
1008
|
(rb_block_call_func_t)rb_equal, value);
|
1007
1009
|
}
|
1010
|
+
%typemap(check) VALUE idx_selector;
|
1008
1011
|
%alias index "find_index";
|
1009
1012
|
|
1010
1013
|
SWIG_Object to_a() const {
|
@@ -1020,6 +1023,20 @@ struct MatrixUtil {
|
|
1020
1023
|
return res;
|
1021
1024
|
}
|
1022
1025
|
#endif
|
1026
|
+
%typemap(in)
|
1027
|
+
Matrix<T, Array2D_Dense<T> > &output_L,
|
1028
|
+
Matrix<T, Array2D_Dense<T> > &output_U,
|
1029
|
+
Matrix<T, Array2D_Dense<T> > &output_P,
|
1030
|
+
Matrix<T, Array2D_Dense<T> > &output_D,
|
1031
|
+
Matrix<T, Array2D_Dense<T> > &output_Q,
|
1032
|
+
Matrix<T, Array2D_Dense<T> > &output_R;
|
1033
|
+
%typemap(argout)
|
1034
|
+
Matrix<T, Array2D_Dense<T> > &output_L,
|
1035
|
+
Matrix<T, Array2D_Dense<T> > &output_U,
|
1036
|
+
Matrix<T, Array2D_Dense<T> > &output_P,
|
1037
|
+
Matrix<T, Array2D_Dense<T> > &output_D,
|
1038
|
+
Matrix<T, Array2D_Dense<T> > &output_Q,
|
1039
|
+
Matrix<T, Array2D_Dense<T> > &output_R;
|
1023
1040
|
};
|
1024
1041
|
|
1025
1042
|
#if defined(SWIGRUBY)
|
@@ -1171,6 +1188,15 @@ MAKE_TO_S(Matrix_Frozen)
|
|
1171
1188
|
%rename("map!") map_bang;
|
1172
1189
|
%alias map_bang "collect!,map_with_index!,collect_with_index!";
|
1173
1190
|
#endif
|
1191
|
+
|
1192
|
+
%typemap(in)
|
1193
|
+
void (*each_func)(const T &src, T *dst, const unsigned int &i, const unsigned int &j);
|
1194
|
+
%typemap(typecheck) const typename MatrixUtil::each_which_t each_which;
|
1195
|
+
%typemap(in) const typename MatrixUtil::each_which_t each_which;
|
1196
|
+
%typemap(typecheck) const void *replacer;
|
1197
|
+
%typemap(in) const void *replacer;
|
1198
|
+
%typemap(in) self_t *self_p;
|
1199
|
+
%typemap(argout) self_t *self_p;
|
1174
1200
|
};
|
1175
1201
|
|
1176
1202
|
%define INSTANTIATE_MATRIX_TRANSPOSE(type, storage, view_from, view_to)
|
@@ -1251,6 +1277,12 @@ MAKE_TO_S(Matrix_Frozen)
|
|
1251
1277
|
}
|
1252
1278
|
output_D = D;
|
1253
1279
|
}
|
1280
|
+
%typemap(in)
|
1281
|
+
Matrix<ctype, Array2D_Dense<ctype > > &output_D,
|
1282
|
+
Matrix<ctype, Array2D_Dense<ctype > > &output_V;
|
1283
|
+
%typemap(argout)
|
1284
|
+
Matrix<ctype, Array2D_Dense<ctype > > &output_D,
|
1285
|
+
Matrix<ctype, Array2D_Dense<ctype > > &output_V;
|
1254
1286
|
};
|
1255
1287
|
%enddef
|
1256
1288
|
%define INSTANTIATE_MATRIX_EIGEN(type, ctype)
|
@@ -1366,6 +1398,7 @@ INSTANTIATE_MATRIX_PARTIAL(type, Array2D_Dense<type >, MatView_pt, MatView_pt);
|
|
1366
1398
|
#endif
|
1367
1399
|
else{SWIG_exception(SWIG_TypeError, "$*1_ltype is expected");}
|
1368
1400
|
}
|
1401
|
+
%typemap(out) Matrix<type, Array2D_Dense<type > > & "$result = self;"
|
1369
1402
|
Matrix<type, Array2D_Dense<type > > &resize(
|
1370
1403
|
const unsigned int *r_p, const unsigned int *c_p){
|
1371
1404
|
unsigned int r(r_p ? *r_p : $self->rows()), c(c_p ? *c_p : $self->columns());
|
@@ -1376,6 +1409,10 @@ INSTANTIATE_MATRIX_PARTIAL(type, Array2D_Dense<type >, MatView_pt, MatView_pt);
|
|
1376
1409
|
mat_new.partial(r_min, c_min).replace($self->partial(r_min, c_min), false);
|
1377
1410
|
return (*($self) = mat_new);
|
1378
1411
|
}
|
1412
|
+
%clear Matrix<type, Array2D_Dense<type > > &;
|
1413
|
+
|
1414
|
+
//%typemap(in) unsigned int *r_p, unsigned int *c_p; // NG; remove custom typemap before Matrix::resize! generation
|
1415
|
+
%clear unsigned int *r_p, unsigned int *c_p; // OK, work around version
|
1379
1416
|
};
|
1380
1417
|
|
1381
1418
|
%template(Matrix ## suffix) Matrix<type, Array2D_Dense<type > >;
|
@@ -286,7 +286,7 @@ shared_examples 'Matrix' do
|
|
286
286
|
].each{|arg|
|
287
287
|
mat_orig = mat[0].copy
|
288
288
|
mat_replaced = arg.kind_of?(Proc) ? mat_orig.send(:replace!, &arg) : mat_orig.send(:replace!, arg)
|
289
|
-
expect(mat_replaced).to
|
289
|
+
expect(mat_replaced).to be(mat_orig)
|
290
290
|
expect(mat_replaced).not_to equal(mat[1])
|
291
291
|
expect(mat_replaced.to_a).to eq(mat[1].to_a)
|
292
292
|
}
|
@@ -306,7 +306,7 @@ shared_examples 'Matrix' do
|
|
306
306
|
idxs[a], idxs[b] = [b, a]
|
307
307
|
mat_builtin = Matrix::columns(mat_builtin.column_vectors.values_at(*idxs))
|
308
308
|
end
|
309
|
-
expect(mat_mod).to
|
309
|
+
expect(mat_mod).to be(mat[0])
|
310
310
|
expect(mat[0].to_a).to eq(mat_builtin.to_a)
|
311
311
|
}
|
312
312
|
}
|
@@ -391,11 +391,12 @@ shared_examples 'Matrix' do
|
|
391
391
|
candidates = (func.to_s =~ /with_index$/) \
|
392
392
|
? indices.collect{|i, j| [compare_with[i][j], i, j]} \
|
393
393
|
: indices.collect{|i, j| [compare_with[i][j]]}
|
394
|
-
mat.send(*[func, k].compact){|*v|
|
394
|
+
mat2 = mat.send(*[func, k].compact){|*v|
|
395
395
|
i = candidates.find_index(v)
|
396
396
|
expect(i).not_to be(nil)
|
397
397
|
candidates.delete_at(i)
|
398
398
|
}
|
399
|
+
expect(mat2).to be(mat)
|
399
400
|
expect(candidates.empty?).to be(true)
|
400
401
|
}
|
401
402
|
}
|
@@ -449,7 +450,7 @@ shared_examples 'Matrix' do
|
|
449
450
|
v[0] * 2
|
450
451
|
}
|
451
452
|
expect(candidates.empty?).to be(true)
|
452
|
-
expect(mat2
|
453
|
+
expect(mat2).to be(mat)
|
453
454
|
expect(mat2.to_a).to eq(compare_with.collect.with_index{|values, i|
|
454
455
|
values.collect.with_index{|v, j|
|
455
456
|
indices.include?([i, j]) ? (v * 2) : v
|
@@ -541,6 +542,7 @@ shared_examples 'Matrix' do
|
|
541
542
|
}
|
542
543
|
mat_orig = mat[0].to_a
|
543
544
|
r, c = [:rows, :columns].collect{|f| mat[0].send(f)}
|
545
|
+
expect(mat[0].resize!(r, c)).to be(mat[0])
|
544
546
|
expect(mat[0].resize!(r, c).to_a).to eq(mat_orig)
|
545
547
|
expect(mat[0].resize!(r, nil).to_a).to eq(mat_orig)
|
546
548
|
expect(mat[0].resize!(nil, c).to_a).to eq(mat_orig)
|
data/gps_pvt.gemspec
CHANGED
@@ -64,6 +64,7 @@ Gem::Specification.new do |spec|
|
|
64
64
|
spec.add_development_dependency "rspec", "~> 3.0"
|
65
65
|
spec.add_development_dependency "matrix" if GPS_PVT::version_compare(RUBY_VERSION, "3.1") >= 0
|
66
66
|
spec.add_development_dependency "racc"
|
67
|
+
spec.add_development_dependency "yard"
|
67
68
|
spec.add_development_dependency "github_changelog_generator" unless ((Gem::Platform.local.os =~ /mingw/) && (GPS_PVT::version_compare(RUBY_VERSION, "3.1") >= 0))
|
68
69
|
|
69
70
|
# For more information and examples about making a new gem, checkout our
|
data/lib/gps_pvt/ntrip.rb
CHANGED
@@ -129,13 +129,16 @@ OpenURI.class_eval{
|
|
129
129
|
def OpenURI.open_ntrip(buf, target, proxy, options) # :nodoc:
|
130
130
|
GPS_PVT::Ntrip.start(target.host, target.port){|ntrip|
|
131
131
|
# get source table
|
132
|
-
|
132
|
+
tbl_str = ntrip.get_source_table(options){|str| str}
|
133
133
|
if target.root? then
|
134
|
-
buf <<
|
134
|
+
buf << tbl_str
|
135
135
|
buf.io.rewind
|
136
|
+
buf.io.define_singleton_method(:source_table){
|
137
|
+
GPS_PVT::Ntrip::parse_source_table(tbl_str)
|
138
|
+
}
|
136
139
|
next
|
137
140
|
end
|
138
|
-
tbl = GPS_PVT::Ntrip::parse_source_table(
|
141
|
+
tbl = GPS_PVT::Ntrip::parse_source_table(tbl_str)
|
139
142
|
|
140
143
|
# check mount point
|
141
144
|
mnt_pt = target.mount_point
|
data/lib/gps_pvt/pvt.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'gps_pvt/GPS'
|
2
|
+
require 'gps_pvt/Coordinate'
|
3
|
+
|
4
|
+
module GPS_PVT
|
5
|
+
class GPS::PVT_minimal
|
6
|
+
def initialize
|
7
|
+
# GLOBAL POSITIONING SYSTEM STANDARD POSITIONING SERVICE
|
8
|
+
# PERFORMANCE STANDARD 5th edition (Apr. 2020) 3.8
|
9
|
+
@hsigma = 8.0 # 95%
|
10
|
+
@vsigma = 13.0 # 95%
|
11
|
+
@pdop = 6.0 # 98% global
|
12
|
+
@vel_sigma = 0.2 # 85%
|
13
|
+
@use_satellites = 0 # unknown
|
14
|
+
end
|
15
|
+
def position_solved?; @xyz || @llh; end
|
16
|
+
def velocity_solved?; @velocity; end
|
17
|
+
def xyz; @xyz || @llh.xyz; end
|
18
|
+
def llh; @xyz ? @xyz.llh : @llh; end
|
19
|
+
def xyz=(args); @xyz = Coordinate::XYZ::new(*args); end
|
20
|
+
def llh=(args); @llh = Coordinate::LLH::new(*args); end
|
21
|
+
def velocity=(args); @velocity = Coordinate::ENU::new(*args); end
|
22
|
+
attr_reader :velocity
|
23
|
+
attr_accessor :hsigma, :vsigma, :pdop, :vel_sigma, :used_satellites
|
24
|
+
class <<self
|
25
|
+
def parse_csv(csv_fname, &b)
|
26
|
+
require_relative 'util'
|
27
|
+
$stderr.puts "Reading CSV file (%s) "%[csv_fname]
|
28
|
+
io = open(Util::get_txt(csv_fname), 'r')
|
29
|
+
|
30
|
+
header = io.readline.chomp.split(/ *, */)
|
31
|
+
idx_table = [
|
32
|
+
:week, [:tow, /^i?t(?:ime_)?o(?:f_)?w(?:eek)?/],
|
33
|
+
:year, :month, :mday, :hour, :min, [:sec, /^sec/],
|
34
|
+
[:lng, /^(?:long(?:itude)?|lng)/], [:lat, /^lat(?:itude)/],
|
35
|
+
[:alt, /^(?:alt(?:itude)?|h(?:$|eight|_))/], # assumption: [deg], [deg], [m]
|
36
|
+
:x, :y, :z, # ECEF xyz
|
37
|
+
:hsigma, :vsigma, :pdop,
|
38
|
+
[:vn, /^v(?:el)?_?n(?:orth)?/], [:ve, /^v(?:el)?_?e(?:ast)?/],
|
39
|
+
[:vd, /^v(?:el)?_?d(?:own)?/], [:vu, /^v(?:el)?_?u(?:p)?/],
|
40
|
+
:vx, :vy, :vz, # ECEF xyz
|
41
|
+
[:vel_sigma, /^v(?:el)?_sigma/],
|
42
|
+
[:used_satellites, /^(?:used_)?sat(?:ellite)?s/],
|
43
|
+
].collect{|k, re|
|
44
|
+
re ||= k.to_s
|
45
|
+
idx = header.find_index{|str| re === str}
|
46
|
+
idx && [k, idx]
|
47
|
+
}.compact
|
48
|
+
enum = Enumerator::new{|y|
|
49
|
+
io.each_line{|line|
|
50
|
+
values = line.chomp.split(/ *, */)
|
51
|
+
items = Hash[*(idx_table.collect{|k, idx|
|
52
|
+
v = values[idx]
|
53
|
+
(v == '') ? nil : [k, (Integer(v) rescue Float(v))]
|
54
|
+
}.compact.flatten(1))]
|
55
|
+
if items.include?(:week) then
|
56
|
+
t = GPS::Time::new(items[:week], items[:tow])
|
57
|
+
else
|
58
|
+
# UTC assumption, thus leap seconds must be added.
|
59
|
+
t = GPS::Time::new([:year, :month, :mday, :hour, :min, :sec].collect{|k| items[k]})
|
60
|
+
t += GPS::Time::guess_leap_seconds(t)
|
61
|
+
end
|
62
|
+
pvt = GPS::PVT_minimal::new
|
63
|
+
if items.include?(:lat) then
|
64
|
+
pvt.llh = ([:lat, :lng].collect{|k| Math::PI / 180 * items[k]} + [items[:alt]])
|
65
|
+
elsif items.include?(:xyz) then
|
66
|
+
pvt.xyz = [:x, :y, :z].collect{|k| items[k]}
|
67
|
+
end
|
68
|
+
if items.include?(:vn) then
|
69
|
+
pvt.velocity = ([:vn, :ve].collect{|k| items[k]} + [items[:vu] || -items[:vd]])
|
70
|
+
elsif items.include?(:vx) then
|
71
|
+
pvt.velocity = Coordinate::ENU::relative_rel(
|
72
|
+
Coordinate::XYZ::new(*([:vx, :vy, :vz].collect{|k| items[k]})),
|
73
|
+
pvt.llh)
|
74
|
+
end
|
75
|
+
[:pdop, :hsigma, :vsigma, :vel_sigma, :used_satellites].each{|k| pvt.send("#{k}=", items[k])}
|
76
|
+
y.yield(t, pvt)
|
77
|
+
}
|
78
|
+
}
|
79
|
+
b ? enum.each{|*res| b.call(*res)} : enum
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
=begin
|
2
|
+
Additional Almanac handler for receiver
|
3
|
+
=end
|
4
|
+
|
5
|
+
module GPS_PVT
|
6
|
+
class Receiver
|
7
|
+
def correct_week_sem_yuma_almanac(src, week_rem = 0)
|
8
|
+
t_ref = case src.to_s
|
9
|
+
when /www\.navcen\.uscg\.gov\/.*\/(\d{4})\//
|
10
|
+
# ex) https://www.navcen.uscg.gov/sites/default/files/gps/almanac/20XX/(Sem|Yuma)/003.(al3|alm)
|
11
|
+
GPS_PVT::GPS::Time::new(Time::new($1.to_i).to_a.slice(0, 6).reverse)
|
12
|
+
when /www\.navcen\.uscg\.gov\/.*\/current_(sem|yuma)/
|
13
|
+
GPS_PVT::GPS::Time::now
|
14
|
+
else
|
15
|
+
raise
|
16
|
+
end
|
17
|
+
q, rem = t_ref.week.divmod(1024)
|
18
|
+
delta = rem - (week_rem % 1024)
|
19
|
+
if delta <= -512 then
|
20
|
+
q -= 1
|
21
|
+
elsif delta > 512 then
|
22
|
+
q += 1
|
23
|
+
end
|
24
|
+
q * 1024 + week_rem
|
25
|
+
end
|
26
|
+
|
27
|
+
def parse_sem_almanac(src)
|
28
|
+
src_io = open(Util::get_txt(src))
|
29
|
+
raise unless src_io.readline =~ /(\d+)\s+(\S+)/ # line 1
|
30
|
+
num, name = [$1.to_i, $2]
|
31
|
+
raise unless src_io.readline =~ /(\d+)\s+(\d+)/ # line 2
|
32
|
+
week, t_oa = [$1.to_i, $2.to_i]
|
33
|
+
week = correct_week_sem_yuma_almanac(src, week)
|
34
|
+
src_io.readline # line 3
|
35
|
+
|
36
|
+
num.times.each{
|
37
|
+
eph = GPS::Ephemeris::new
|
38
|
+
9.times{|i| # line R-1..9
|
39
|
+
case i
|
40
|
+
when 0, 1, 2, 6, 7
|
41
|
+
# N/A items; 1 => SV reference number, 7 => configuration code
|
42
|
+
k = {0 => :svid, 2 => :URA_index, 6 => :SV_health}[i]
|
43
|
+
v = Integer(src_io.readline)
|
44
|
+
eph.send("#{k}=".to_sym, v) if k
|
45
|
+
when 3..5
|
46
|
+
res = src_io.readline.scan(/[+-]?\d+(?:\.\d+)?(?:E[+-]\d+)?/).collect{|s| Float(s)}
|
47
|
+
raise unless res.size == 3
|
48
|
+
res.zip({
|
49
|
+
3 => [:e, [:i0, GPS::GPS_SC2RAD], [:dot_Omega0, GPS::GPS_SC2RAD]],
|
50
|
+
4 => [:sqrt_A, [:Omega0, GPS::GPS_SC2RAD], [:omega, GPS::GPS_SC2RAD]],
|
51
|
+
5 => [[:M0, GPS::GPS_SC2RAD], :a_f0, :a_f1],
|
52
|
+
}[i]).each{|v, (k, sf)|
|
53
|
+
eph.send("#{k}=".to_sym, sf ? (sf * v) : v)
|
54
|
+
}
|
55
|
+
when 8
|
56
|
+
src_io.readline
|
57
|
+
end
|
58
|
+
}
|
59
|
+
eph.i0 = GPS::GPS_SC2RAD * 0.3 + eph.i0
|
60
|
+
eph.WN = week
|
61
|
+
eph.t_oc = eph.t_oe = t_oa
|
62
|
+
[:iodc, :t_GD, :a_f2, :iode, :c_rs, :delta_n,
|
63
|
+
:c_uc, :c_us, :c_ic, :c_is, :c_rc, :dot_i0, :iode_subframe3].each{|k|
|
64
|
+
eph.send("#{k}=", 0)
|
65
|
+
}
|
66
|
+
critical{@solver.gps_space_node.register_ephemeris(eph.svid, eph)}
|
67
|
+
}
|
68
|
+
|
69
|
+
$stderr.puts "Read SEM Almanac file (%s): %d items."%[src, num]
|
70
|
+
end
|
71
|
+
|
72
|
+
YUMA_ITEMS = [
|
73
|
+
[proc{|s| s.to_i}, {
|
74
|
+
:ID => :svid,
|
75
|
+
:Health => :SV_health,
|
76
|
+
:week => :WN,
|
77
|
+
}],
|
78
|
+
[proc{|s| Float(s)}, {
|
79
|
+
:Eccentricity => :e,
|
80
|
+
"Time of Applicability" => [:t_oc, :t_oe],
|
81
|
+
"Orbital Inclination" => :i0,
|
82
|
+
"Rate of Right Ascen" => :dot_Omega0,
|
83
|
+
'SQRT\(A\)' => :sqrt_A,
|
84
|
+
"Right Ascen at Week" => :Omega0,
|
85
|
+
"Argument of Perigee" => :omega,
|
86
|
+
"Mean Anom" => :M0,
|
87
|
+
"Af0" => :a_f0,
|
88
|
+
"Af1" => :a_f1,
|
89
|
+
}],
|
90
|
+
].collect{|cnv, key_list|
|
91
|
+
key_list.collect{|k1, k2_list|
|
92
|
+
[/#{k1}[^:]*:/, cnv,
|
93
|
+
*([k2_list].flatten(1).collect{|k2|
|
94
|
+
"#{k2}=".to_sym
|
95
|
+
})]
|
96
|
+
}
|
97
|
+
}.flatten(1)
|
98
|
+
|
99
|
+
def parse_yuma_almanac(src)
|
100
|
+
src_io = open(Util::get_txt(src))
|
101
|
+
num = 0
|
102
|
+
|
103
|
+
idx_line = -1
|
104
|
+
eph, items = nil
|
105
|
+
while !src_io.eof?
|
106
|
+
line = src_io.readline.chomp
|
107
|
+
if idx_line < 0 then
|
108
|
+
if line =~ /^\*{8}/ then
|
109
|
+
eph = GPS::Ephemeris::new
|
110
|
+
items = YUMA_ITEMS.clone
|
111
|
+
idx_line = 0
|
112
|
+
end
|
113
|
+
next
|
114
|
+
end
|
115
|
+
raise unless i = items.index{|re, cnv, *k_list|
|
116
|
+
next false unless re =~ line
|
117
|
+
v = cnv.call($')
|
118
|
+
k_list.each{|k| eph.send(k, v)}
|
119
|
+
true
|
120
|
+
}
|
121
|
+
items.delete_at(i)
|
122
|
+
next unless items.empty?
|
123
|
+
|
124
|
+
[:iodc, :t_GD, :a_f2, :iode, :c_rs, :delta_n,
|
125
|
+
:c_uc, :c_us, :c_ic, :c_is, :c_rc, :dot_i0, :iode_subframe3].each{|k|
|
126
|
+
eph.send("#{k}=", 0)
|
127
|
+
}
|
128
|
+
eph.WN = correct_week_sem_yuma_almanac(src, eph.WN)
|
129
|
+
critical{@solver.gps_space_node.register_ephemeris(eph.svid, eph)}
|
130
|
+
num += 1
|
131
|
+
idx_line = -1
|
132
|
+
end
|
133
|
+
|
134
|
+
$stderr.puts "Read YUMA Almanac file (%s): %d items."%[src, num]
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -58,13 +58,11 @@ class Receiver
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
-
module GPS
|
62
|
-
|
63
61
|
[
|
64
|
-
Ionospheric_UTC_Parameters,
|
65
|
-
Ephemeris, Ephemeris_SBAS, Ephemeris_GLONASS,
|
62
|
+
:Ionospheric_UTC_Parameters,
|
63
|
+
:Ephemeris, :Ephemeris_SBAS, :Ephemeris_GLONASS,
|
66
64
|
].each{|cls|
|
67
|
-
cls.class_eval{
|
65
|
+
GPS.const_get(cls).class_eval{
|
68
66
|
proc{|func_list|
|
69
67
|
func_list.select!{|func|
|
70
68
|
(/=$/ !~ func.to_s) && func_list.include?("#{func}=".to_sym)
|
@@ -78,4 +76,3 @@ module GPS
|
|
78
76
|
}
|
79
77
|
}
|
80
78
|
end
|
81
|
-
end
|
data/lib/gps_pvt/receiver.rb
CHANGED
@@ -50,7 +50,7 @@ class Receiver
|
|
50
50
|
}.call] + [[
|
51
51
|
[:v_north, :v_east, :v_down, :receiver_clock_error_dot_ms, :vel_sigma],
|
52
52
|
proc{|pvt|
|
53
|
-
next [nil] *
|
53
|
+
next [nil] * 5 unless pvt.velocity_solved?
|
54
54
|
[:north, :east, :down].collect{|k| pvt.velocity.send(k)} \
|
55
55
|
+ [pvt.receiver_error_rate, pvt.vel_sigma]
|
56
56
|
}
|
@@ -732,4 +732,5 @@ end
|
|
732
732
|
|
733
733
|
require_relative 'receiver/rtcm3'
|
734
734
|
require_relative 'receiver/agps'
|
735
|
+
require_relative 'receiver/almanac'
|
735
736
|
require_relative 'receiver/extension'
|
data/lib/gps_pvt/supl.rb
CHANGED
@@ -16,6 +16,7 @@ class SUPL_Client
|
|
16
16
|
:port => 7275,
|
17
17
|
:debug => 0,
|
18
18
|
:protocol => [:lpp, :rrlp],
|
19
|
+
:req_data => [:ephemeris], # :almanac
|
19
20
|
}.merge(opts)
|
20
21
|
end
|
21
22
|
|
@@ -152,6 +153,16 @@ class SUPL_Client
|
|
152
153
|
cmd[:sessionID] = @session_id
|
153
154
|
proc{|posinit|
|
154
155
|
posinit[:sETCapabilities] = @capability
|
156
|
+
req_data = [
|
157
|
+
@opts[:req_data].find_index(:almanac) && :almanacRequested,
|
158
|
+
:utcModelRequested,
|
159
|
+
:ionosphericModelRequested,
|
160
|
+
:referenceLocationRequested,
|
161
|
+
:referenceTimeRequested,
|
162
|
+
:acquisitionAssistanceRequested,
|
163
|
+
:realTimeIntegrityRequested,
|
164
|
+
@opts[:req_data].find_index(:ephemeris) && :navigationModelRequested,
|
165
|
+
].compact
|
155
166
|
posinit[:requestedAssistData] = Hash[*([
|
156
167
|
:almanacRequested,
|
157
168
|
:utcModelRequested,
|
@@ -163,15 +174,7 @@ class SUPL_Client
|
|
163
174
|
:realTimeIntegrityRequested,
|
164
175
|
:navigationModelRequested,
|
165
176
|
].collect{|k|
|
166
|
-
[k,
|
167
|
-
:utcModelRequested,
|
168
|
-
:ionosphericModelRequested,
|
169
|
-
:referenceLocationRequested,
|
170
|
-
:referenceTimeRequested,
|
171
|
-
:acquisitionAssistanceRequested,
|
172
|
-
:realTimeIntegrityRequested,
|
173
|
-
:navigationModelRequested,
|
174
|
-
].include?(k)]
|
177
|
+
[k, req_data.include?(k)]
|
175
178
|
}.flatten(1))]
|
176
179
|
posinit[:requestedAssistData][:"ver2-RequestedAssistData-extension"] = {
|
177
180
|
:ganssRequestedCommonAssistanceDataList => {
|
@@ -185,18 +188,21 @@ class SUPL_Client
|
|
185
188
|
:ganssRequestedGenericAssistanceDataList => [
|
186
189
|
# SBAS
|
187
190
|
{:ganssId => 1, :ganssSBASid => [0, 1, 0], # MSAS
|
188
|
-
:ganssRealTimeIntegrity => true,
|
189
|
-
:ganssNavigationModelData => {:ganssWeek => 0, :ganssToe => 0, :"t-toeLimit" => 0},
|
191
|
+
:ganssRealTimeIntegrity => true,
|
190
192
|
:ganssReferenceMeasurementInfo => false, :ganssUTCModel => true, :ganssAuxiliaryInformation => false},
|
191
193
|
# QZSS
|
192
|
-
{:ganssId => 3, :ganssRealTimeIntegrity => true,
|
193
|
-
:ganssNavigationModelData => {:ganssWeek => 0, :ganssToe => 0, :"t-toeLimit" => 0},
|
194
|
+
{:ganssId => 3, :ganssRealTimeIntegrity => true,
|
194
195
|
:ganssReferenceMeasurementInfo => false, :ganssUTCModel => true, :ganssAuxiliaryInformation => false},
|
195
196
|
# GLONASS
|
196
|
-
{:ganssId => 4, :ganssRealTimeIntegrity => true,
|
197
|
-
:ganssNavigationModelData => {:ganssWeek => 0, :ganssToe => 0, :"t-toeLimit" => 0},
|
197
|
+
{:ganssId => 4, :ganssRealTimeIntegrity => true,
|
198
198
|
:ganssReferenceMeasurementInfo => false, :ganssUTCModel => true, :ganssAuxiliaryInformation => false},
|
199
|
-
]
|
199
|
+
].collect{|items|
|
200
|
+
items[:ganssAlmanac] = @opts[:req_data].include?(:almanac)
|
201
|
+
items[:ganssNavigationModelData] = {
|
202
|
+
:ganssWeek => 0, :ganssToe => 0, :"t-toeLimit" => 0
|
203
|
+
} if @opts[:req_data].include?(:ephemeris)
|
204
|
+
items
|
205
|
+
},
|
200
206
|
}
|
201
207
|
posinit[:requestedAssistData][:navigationModelData] = {
|
202
208
|
:gpsWeek => 0,
|
@@ -302,7 +308,25 @@ class SUPL_Client
|
|
302
308
|
:ephemL2Pflag
|
303
309
|
:ephemAODA
|
304
310
|
=end
|
305
|
-
|
311
|
+
|
312
|
+
ALM_KEY_TBL_RRLP = Hash[*({
|
313
|
+
:e => [:almanacE, -21],
|
314
|
+
:i0 => [:almanacKsii, -19, true],
|
315
|
+
:dot_Omega0 => [:almanacOmegaDot, -38, true],
|
316
|
+
:SV_health => :almanacSVhealth,
|
317
|
+
:sqrt_A => [:almanacAPowerHalf, -11],
|
318
|
+
:Omega0 => [:almanacOmega0, -23, true],
|
319
|
+
:omega => [:almanacW, -23, true],
|
320
|
+
:M0 => [:almanacM0, -23, true],
|
321
|
+
:a_f0 => [:almanacAF0, -20],
|
322
|
+
:a_f1 => [:almanacAF1, -38],
|
323
|
+
}.collect{|dst_k, (src_k, sf_pow2, sc2rad)|
|
324
|
+
sf_pow2 ||= 0
|
325
|
+
sf = sf_pow2 < 0 ? Rational(1, 1 << -sf_pow2) : (1 << sf_pow2)
|
326
|
+
sf = sf.to_f * GPS::GPS_SC2RAD if sc2rad
|
327
|
+
["#{dst_k}=".to_sym, [src_k, sf]]
|
328
|
+
}.flatten(1))]
|
329
|
+
|
306
330
|
def attach_rrlp(msg)
|
307
331
|
t_gps = proc{
|
308
332
|
week_rem, sec008 = [:gpsWeek, :gpsTOW23b].collect{|k| msg[:referenceTime][:gpsTime][k]}
|
@@ -337,10 +361,11 @@ class SUPL_Client
|
|
337
361
|
params
|
338
362
|
}
|
339
363
|
msg.define_singleton_method(:ephemeris){
|
340
|
-
self[:navigationModel]
|
364
|
+
next [] unless (model = self[:navigationModel])
|
365
|
+
model[:navModelList].collect{|sat|
|
341
366
|
eph = GPS::Ephemeris::new
|
342
|
-
eph.svid =
|
343
|
-
eph_src =
|
367
|
+
eph.svid = sat[:satelliteID] + 1
|
368
|
+
eph_src = sat[:satStatus][:newSatelliteAndModelUC]
|
344
369
|
EPH_KEY_TBL_RRLP.each{|dst_k, (src_k, sf)|
|
345
370
|
v = sf * eph_src[src_k]
|
346
371
|
eph.send(dst_k, v.kind_of?(Rational) ? v.to_f : v)
|
@@ -357,6 +382,30 @@ class SUPL_Client
|
|
357
382
|
eph
|
358
383
|
}
|
359
384
|
}
|
385
|
+
msg.define_singleton_method(:almanac){
|
386
|
+
next [] unless (model = self[:almanac])
|
387
|
+
week = self[:almanac][:alamanacWNa]
|
388
|
+
week += (t_gps.week >> 8) << 8
|
389
|
+
model[:almanacList].collect{|sat|
|
390
|
+
eph = GPS::Ephemeris::new
|
391
|
+
eph.svid = sat[:satelliteID] + 1
|
392
|
+
ALM_KEY_TBL_RRLP.each{|dst_k, (src_k, sf)|
|
393
|
+
v = sf * sat[src_k]
|
394
|
+
eph.send(dst_k, v.kind_of?(Rational) ? v.to_f : v)
|
395
|
+
}
|
396
|
+
eph.i0 = GPS::GPS_SC2RAD * 0.3 + eph.i0
|
397
|
+
eph.WN = week
|
398
|
+
eph.t_oc = eph.t_oe = sat[:alamanacToa] << 12
|
399
|
+
[:iodc, :t_GD, :a_f2, :iode, :c_rs, :delta_n,
|
400
|
+
:c_uc, :c_us, :c_ic, :c_is, :c_rc, :dot_i0, :iode_subframe3].each{|k|
|
401
|
+
eph.send("#{k}=", 0)
|
402
|
+
}
|
403
|
+
eph.URA_index = -1
|
404
|
+
#eph.fit_interval
|
405
|
+
eph
|
406
|
+
}
|
407
|
+
}
|
408
|
+
:alamanacToa # typo in TS
|
360
409
|
msg
|
361
410
|
end
|
362
411
|
|
@@ -412,6 +461,25 @@ class SUPL_Client
|
|
412
461
|
:N_T=, :p=, :delta_tau_n=, :P4=,
|
413
462
|
:tau_GPS=, :tau_c=, :day_of_year=, :year=, :n=, :freq_ch=
|
414
463
|
=end
|
464
|
+
|
465
|
+
ALM_KEY_TBL_LPP = Hash[*({
|
466
|
+
:e => [:E, -21],
|
467
|
+
:i0 => [:DeltaI, -19, true],
|
468
|
+
:dot_Omega0 => [:OMEGADOT, -38, true],
|
469
|
+
:SV_health => :SVHealth,
|
470
|
+
:sqrt_A => [:SqrtA, -11],
|
471
|
+
:Omega0 => [:OMEGAo, -23, true],
|
472
|
+
:omega => [:Omega, -23, true],
|
473
|
+
:M0 => [:Mo, -23, true],
|
474
|
+
:a_f0 => [:af0, -20],
|
475
|
+
:a_f1 => [:af1, -38],
|
476
|
+
}.collect{|dst_k, (src_k, sf_pow2, sc2rad)|
|
477
|
+
sf_pow2 ||= 0
|
478
|
+
sf = sf_pow2 < 0 ? Rational(1, 1 << -sf_pow2) : (1 << sf_pow2)
|
479
|
+
sf = sf.to_f * GPS::GPS_SC2RAD if sc2rad
|
480
|
+
["#{dst_k}=".to_sym,
|
481
|
+
[(src_k.kind_of?(Symbol) ? "navAlm#{src_k}" : src_k).to_sym, sf]]
|
482
|
+
}.flatten(1))]
|
415
483
|
|
416
484
|
def attach_lpp(msg)
|
417
485
|
t_gps = proc{|data|
|
@@ -460,9 +528,9 @@ class SUPL_Client
|
|
460
528
|
}.call
|
461
529
|
leap_seconds = iono_utc.delta_t_LS rescue t_gps.leap_seconds
|
462
530
|
msg.define_singleton_method(:iono_utc){iono_utc}
|
463
|
-
extract_gps_ephemeris = proc{|
|
531
|
+
extract_gps_ephemeris = proc{|model, sys|
|
464
532
|
offset = {:gps => 1, :qzss => 193}[sys]
|
465
|
-
|
533
|
+
model[:"gnss-SatelliteList"].collect{|v|
|
466
534
|
eph = GPS::Ephemeris::new
|
467
535
|
eph.svid = v[:svID][:"satellite-id"] + offset
|
468
536
|
eph_src = v[:"gnss-ClockModel"][:"nav-ClockModel"].merge(v[:"gnss-OrbitModel"][:"nav-KeplerianSet"])
|
@@ -489,42 +557,81 @@ class SUPL_Client
|
|
489
557
|
[:"provideAssistanceData-r9"][:"a-gnss-ProvideAssistanceData"] \
|
490
558
|
[:"gnss-GenericAssistData"]
|
491
559
|
res = [:gps, :qzss].collect{|k|
|
492
|
-
|
493
|
-
|
494
|
-
|
560
|
+
model = assist_data.find{|v| v[:"gnss-ID"][:"gnss-id"] == k}[:"gnss-NavigationModel"] rescue nil
|
561
|
+
next [] unless model
|
562
|
+
extract_gps_ephemeris.call(model, k)
|
495
563
|
}.flatten(1)
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
eph = GPS::Ephemeris_GLONASS::new
|
504
|
-
eph.svid = sat[:svID][:"satellite-id"] + 1
|
505
|
-
eph_src = sat[:"gnss-ClockModel"][:"glonass-ClockModel"].merge(
|
506
|
-
sat[:"gnss-OrbitModel"][:"glonass-ECEF"])
|
507
|
-
(EPH_KEY_TBL_LPP_GLO.collect{|dst_k, (src_k, sf)|
|
508
|
-
v = eph_src[src_k]
|
509
|
-
[dst_k, sf.send(sf.kind_of?(Proc) ? :call : :*, case v
|
510
|
-
when Array; Integer(v.join, 2)
|
511
|
-
when true; 1
|
512
|
-
when false; 0
|
513
|
-
else; v
|
514
|
-
end)]
|
515
|
-
} + utc_params_glo).each{|dst_k, v|
|
516
|
-
eph.send(dst_k, v.kind_of?(Rational) ? v.to_f : v)
|
564
|
+
proc{|assist_data_glo|
|
565
|
+
next unless assist_data_glo
|
566
|
+
next unless nav_model = assist_data_glo[:"gnss-NavigationModel"]
|
567
|
+
utc_params_glo = {
|
568
|
+
:tau_c= => [:tauC, Rational(1, 1 << 31)],
|
569
|
+
}.collect{|dst_k, (src_k, sf)|
|
570
|
+
[dst_k, sf * assist_data_glo[:"gnss-UTC-Model"][:utcModel3][src_k]]
|
517
571
|
}
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
572
|
+
res += nav_model[:"gnss-SatelliteList"].collect{|sat|
|
573
|
+
eph = GPS::Ephemeris_GLONASS::new
|
574
|
+
eph.svid = sat[:svID][:"satellite-id"] + 1
|
575
|
+
eph_src = sat[:"gnss-ClockModel"][:"glonass-ClockModel"].merge(
|
576
|
+
sat[:"gnss-OrbitModel"][:"glonass-ECEF"])
|
577
|
+
(EPH_KEY_TBL_LPP_GLO.collect{|dst_k, (src_k, sf)|
|
578
|
+
v = eph_src[src_k]
|
579
|
+
[dst_k, sf.send(sf.kind_of?(Proc) ? :call : :*, case v
|
580
|
+
when Array; Integer(v.join, 2)
|
581
|
+
when true; 1
|
582
|
+
when false; 0
|
583
|
+
else; v
|
584
|
+
end)]
|
585
|
+
} + utc_params_glo).each{|dst_k, v|
|
586
|
+
eph.send(dst_k, v.kind_of?(Rational) ? v.to_f : v)
|
587
|
+
}
|
588
|
+
eph.B_n = sat[:svHealth][0]
|
589
|
+
eph.F_T_index = Integer(sat[:svHealth][1..4].join, 2)
|
590
|
+
eph.t_b = Integer(sat[:iod][4..-1].join, 2) * 15 * 60
|
591
|
+
eph.set_date((t_gps + 3 * 60 * 60).c_tm(leap_seconds)) # UTC -> Moscow time
|
592
|
+
eph.N_T = eph.NA
|
593
|
+
eph.rehash(leap_seconds)
|
594
|
+
eph
|
595
|
+
}
|
596
|
+
}.call(assist_data.find{|v| v[:"gnss-ID"][:"gnss-id"] == :glonass})
|
526
597
|
res
|
527
598
|
}
|
599
|
+
extract_gps_almanac = proc{|alm, sys|
|
600
|
+
next [] unless alm
|
601
|
+
offset = {:gps => 1, :qzss => 193}[sys]
|
602
|
+
week = alm[:weekNumber] # optional but required for non-GLONASS
|
603
|
+
week += (t_gps.week >> 8) << 8
|
604
|
+
t_oa = alm[:toa] << 12 # optional but required for non-GLONASS
|
605
|
+
alm[:"gnss-AlmanacList"].collect{|v|
|
606
|
+
next unless v = v[:"keplerianNAV-Almanac"]
|
607
|
+
eph = GPS::Ephemeris::new
|
608
|
+
eph.svid = v[:svID][:"satellite-id"] + offset
|
609
|
+
ALM_KEY_TBL_LPP.each{|dst_k, (src_k, sf)|
|
610
|
+
v2 = sf * v[src_k]
|
611
|
+
eph.send(dst_k, v2.kind_of?(Rational) ? v2.to_f : v2)
|
612
|
+
}
|
613
|
+
eph.i0 = GPS::GPS_SC2RAD * 0.3 + eph.i0
|
614
|
+
eph.WN = week
|
615
|
+
eph.t_oc = eph.t_oe = t_oa
|
616
|
+
[:iodc, :t_GD, :a_f2, :iode, :c_rs, :delta_n,
|
617
|
+
:c_uc, :c_us, :c_ic, :c_is, :c_rc, :dot_i0, :iode_subframe3].each{|k|
|
618
|
+
eph.send("#{k}=", 0)
|
619
|
+
}
|
620
|
+
eph.URA_index = -1
|
621
|
+
#eph.fit_interval
|
622
|
+
eph
|
623
|
+
}.compact
|
624
|
+
}
|
625
|
+
msg.define_singleton_method(:almanac){
|
626
|
+
assist_data = self[:c1][:provideAssistanceData][:criticalExtensions][:c1] \
|
627
|
+
[:"provideAssistanceData-r9"][:"a-gnss-ProvideAssistanceData"] \
|
628
|
+
[:"gnss-GenericAssistData"]
|
629
|
+
[:gps, :qzss].collect{|k|
|
630
|
+
model = assist_data.find{|v| v[:"gnss-ID"][:"gnss-id"] == k}[:"gnss-Almanac"] rescue nil
|
631
|
+
next [] unless model
|
632
|
+
extract_gps_almanac.call(model, k)
|
633
|
+
}.flatten(1)
|
634
|
+
}
|
528
635
|
msg
|
529
636
|
end
|
530
637
|
end
|
@@ -537,7 +644,7 @@ OpenURI.class_eval{
|
|
537
644
|
options[:port] = target.port
|
538
645
|
URI.decode_www_form(target.query || "").each{|k, v|
|
539
646
|
case k = k.to_sym
|
540
|
-
when :protocol
|
647
|
+
when :protocol, :req_data
|
541
648
|
(options[k] ||= []) << v.to_sym
|
542
649
|
end
|
543
650
|
}
|
data/lib/gps_pvt/util.rb
CHANGED
@@ -88,9 +88,15 @@ module Util
|
|
88
88
|
end
|
89
89
|
nil
|
90
90
|
}.call
|
91
|
-
is_file = src.kind_of?(File) || src.kind_of?(Tempfile)
|
92
91
|
|
93
|
-
|
92
|
+
case src
|
93
|
+
when File
|
94
|
+
next src.path
|
95
|
+
when Tempfile
|
96
|
+
# Preserve tempfile after leaving open-uri block
|
97
|
+
src.define_singleton_method(:close!){close(false)}
|
98
|
+
next src # Kernel.open(obj) redirects to obj.open if obj responds to :open
|
99
|
+
end unless compressed
|
94
100
|
|
95
101
|
Tempfile::open(File::basename($0, '.*')){|dst|
|
96
102
|
dst.binmode
|
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.10.
|
4
|
+
version: 0.10.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: 2024-
|
11
|
+
date: 2024-12-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubyserial
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: yard
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: github_changelog_generator
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -166,8 +180,10 @@ files:
|
|
166
180
|
- lib/gps_pvt/asn1/asn1.y
|
167
181
|
- lib/gps_pvt/asn1/per.rb
|
168
182
|
- lib/gps_pvt/ntrip.rb
|
183
|
+
- lib/gps_pvt/pvt.rb
|
169
184
|
- lib/gps_pvt/receiver.rb
|
170
185
|
- lib/gps_pvt/receiver/agps.rb
|
186
|
+
- lib/gps_pvt/receiver/almanac.rb
|
171
187
|
- lib/gps_pvt/receiver/extension.rb
|
172
188
|
- lib/gps_pvt/receiver/rtcm3.rb
|
173
189
|
- lib/gps_pvt/rtcm3.rb
|