gps_pvt 0.9.4 → 0.10.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +9 -7
- data/Rakefile +18 -1
- data/exe/gps2ubx +12 -5
- data/exe/gps_pvt +7 -2
- data/ext/gps_pvt/GPS/GPS_wrap.cxx +837 -52
- data/ext/ninja-scan-light/tool/navigation/GLONASS_Solver.h +11 -3
- data/ext/ninja-scan-light/tool/navigation/GPS.h +2 -1
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver.h +20 -16
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver_Base.h +84 -46
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver_RAIM.h +2 -1
- data/ext/ninja-scan-light/tool/navigation/SBAS_Solver.h +10 -2
- data/ext/ninja-scan-light/tool/swig/GPS.i +76 -5
- data/ext/ninja-scan-light/tool/swig/spec/GPS_spec.rb +7 -7
- data/gps_pvt.gemspec +3 -2
- data/lib/gps_pvt/asn1/asn1.rb +888 -0
- data/lib/gps_pvt/asn1/asn1.y +903 -0
- data/lib/gps_pvt/asn1/per.rb +182 -0
- data/lib/gps_pvt/receiver/agps.rb +31 -0
- data/lib/gps_pvt/receiver/extension.rb +21 -0
- data/lib/gps_pvt/receiver/rtcm3.rb +2 -1
- data/lib/gps_pvt/receiver.rb +28 -20
- data/lib/gps_pvt/rtcm3.rb +17 -32
- data/lib/gps_pvt/supl.rb +567 -0
- data/lib/gps_pvt/ubx.rb +15 -0
- data/lib/gps_pvt/upl/LPP-V17_5_0-Release17.asn +6441 -0
- data/lib/gps_pvt/upl/RRLP-V17_0_0-Release17.asn +2780 -0
- data/lib/gps_pvt/upl/ULP-V2_0_6-20200720-D.asn +2185 -0
- data/lib/gps_pvt/upl/upl.json.gz +0 -0
- data/lib/gps_pvt/upl/upl.rb +99 -0
- data/lib/gps_pvt/util.rb +1 -0
- data/lib/gps_pvt/version.rb +1 -1
- metadata +26 -2
@@ -0,0 +1,182 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
module GPS_PVT
|
4
|
+
|
5
|
+
# @see ISO/IEC 8825-2:2003(E)
|
6
|
+
# @see http://www5d.biglobe.ne.jp/~stssk/asn1/per.html
|
7
|
+
module PER
|
8
|
+
module Basic_Unaligned
|
9
|
+
module Encoder
|
10
|
+
class <<self
|
11
|
+
def non_negative_binary_integer2(v, bits) # 10.3
|
12
|
+
"%0#{bits}b" % v
|
13
|
+
end
|
14
|
+
def non_negative_binary_integer(v, align = 1) # 10.3
|
15
|
+
non_negative_binary_integer2(
|
16
|
+
v, (Math::log2(v + 1) / align).ceil * align)
|
17
|
+
end
|
18
|
+
def twos_complement_binary_integer(v) # 10.4
|
19
|
+
if v >= 0 then
|
20
|
+
bits = ((Math::log2(v + 1) + 1) / 8).ceil * 8
|
21
|
+
"%0#{bits}b" % v
|
22
|
+
else
|
23
|
+
bits = ((Math::log2(-v) + 1) / 8).ceil * 8 - 1
|
24
|
+
"1%0#{bits}b" % (v + (1 << bits))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
def constrainted_whole_number2(v, v_min, v_max) # 10.5.6
|
28
|
+
non_negative_binary_integer2(
|
29
|
+
v - v_min,
|
30
|
+
Math::log2(v_max - v_min + 1).ceil)
|
31
|
+
end
|
32
|
+
def constrainted_whole_number(v, v_range) # 10.5.6
|
33
|
+
constrainted_whole_number2(v, *v_range.minmax)
|
34
|
+
end
|
35
|
+
def normally_small_non_negative_whole_number(v, *len_enc) # 10.6
|
36
|
+
if v <= 63 then
|
37
|
+
"0%06b" % v # 10.6.1
|
38
|
+
else
|
39
|
+
"1#{semi_constrained_whole_number(v, 0, *len_enc)}" # 10.6.2
|
40
|
+
end
|
41
|
+
end
|
42
|
+
def semi_constrained_whole_number(v, v_min, *len_enc) # 10.7
|
43
|
+
len_enc = :length_otherwise if len_enc.empty?
|
44
|
+
bf = non_negative_binary_integer(v - v_min, 8).scan(/.{8}/)
|
45
|
+
with_length(bf.size, *len_enc).collect{|len_str, range|
|
46
|
+
len_str + bf[range].join
|
47
|
+
}.join
|
48
|
+
end
|
49
|
+
def unconstrained_whole_number(v, *len_enc) # 10.8
|
50
|
+
len_enc = :length_otherwise if len_enc.empty?
|
51
|
+
bf = twos_complement_binary_integer(v).scan(/.{8}/)
|
52
|
+
with_length(bf.size, *len_enc).collect{|len_str, range|
|
53
|
+
len_str + bf[range].join
|
54
|
+
}.join
|
55
|
+
end
|
56
|
+
def length_constrained_whole_number(len, len_range)
|
57
|
+
if len_range.max < 65536 then # 10.9.4.1
|
58
|
+
(len_range.min == len_range.max) ?
|
59
|
+
"" :
|
60
|
+
constrainted_whole_number(len, len_range)
|
61
|
+
else
|
62
|
+
length_otherwise(len)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
def length_normally_small_length(len) # 10.9.4.2 -> 10.9.3.4
|
66
|
+
if len <= 64 then
|
67
|
+
normally_small_non_negative_whole_number(len - 1)
|
68
|
+
else
|
69
|
+
len_enc, len_remain = length_otherwise(len)
|
70
|
+
len_enc = "1#{len_enc}"
|
71
|
+
len_remain ? [len_enc, len_remain] : len_enc
|
72
|
+
end
|
73
|
+
end
|
74
|
+
def length_otherwise(len) # 10.9.4.2 -> 10.9.3.5-8
|
75
|
+
if len <= 127 then # 10.9.3.6
|
76
|
+
non_negative_binary_integer2(len, 8)
|
77
|
+
elsif len < 16384 then # 10.9.3.7
|
78
|
+
"10#{non_negative_binary_integer2(len, 14)}"
|
79
|
+
else # 10.9.3.8
|
80
|
+
q, r = len.divmod(16384)
|
81
|
+
q2 = [q, 4].min
|
82
|
+
res = "11#{non_negative_binary_integer2(q2, 6)}"
|
83
|
+
((r == 0) && (q <= 4)) ? res : [res, len - (q2 * 16384)]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
def with_length(len, *len_enc)
|
87
|
+
Enumerator::new{|y|
|
88
|
+
len_str, len_remain = len_enc[0].kind_of?(Symbol) ? send(len_enc[0], len, *len_enc[1..-1]) : len_enc
|
89
|
+
loop{
|
90
|
+
if len_remain then
|
91
|
+
y << [len_str, -len..-(len_remain+1)]
|
92
|
+
else
|
93
|
+
y << [len_str, -len..-1]
|
94
|
+
break
|
95
|
+
end
|
96
|
+
len_str, len_remain = length_otherwise(len = len_remain) # fragmentation
|
97
|
+
}
|
98
|
+
}
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
module Decoder
|
103
|
+
class <<self
|
104
|
+
def non_negative_binary_integer(str, bits) # 10.3
|
105
|
+
str.slice!(0, bits).to_i(2)
|
106
|
+
end
|
107
|
+
def twos_complement_binary_integer(str, bits) # 10.4
|
108
|
+
bits -= 1
|
109
|
+
case str.slice!(0)
|
110
|
+
when '0'; 0
|
111
|
+
when '1'; -(1 << bits)
|
112
|
+
end + non_negative_binary_integer(str, bits)
|
113
|
+
end
|
114
|
+
def constrainted_whole_number2(str, v_min, v_max) # 10.5.6
|
115
|
+
non_negative_binary_integer(
|
116
|
+
str,
|
117
|
+
Math::log2(v_max - v_min + 1).ceil) + v_min
|
118
|
+
end
|
119
|
+
def constrainted_whole_number(str, v_range) # 10.5.6
|
120
|
+
constrainted_whole_number2(str, *v_range.minmax)
|
121
|
+
end
|
122
|
+
def normally_small_non_negative_whole_number(str, *len_dec) # 10.6
|
123
|
+
case str.slice!(0)
|
124
|
+
when '0'; str.slice!(0, 6).to_i(2) # 10.6.1
|
125
|
+
when '1'; semi_constrained_whole_number(str, 0, *len_dec) # 10.6.2
|
126
|
+
end
|
127
|
+
end
|
128
|
+
def semi_constrained_whole_number(str, v_min, *len_dec) # 10.7
|
129
|
+
len_dec = :length_otherwise if len_dec.empty?
|
130
|
+
v_str = with_length(str, *len_dec).collect{|len_oct|
|
131
|
+
str.slice!(0, len_oct * 8)
|
132
|
+
}.join
|
133
|
+
non_negative_binary_integer(v_str, v_str.size) + v_min
|
134
|
+
end
|
135
|
+
def unconstrained_whole_number(str, *len_dec) # 10.8
|
136
|
+
len_dec = :length_otherwise if len_dec.empty?
|
137
|
+
v_str = with_length(str, *len_dec).collect{|len_oct|
|
138
|
+
str.slice!(0, len_oct * 8)
|
139
|
+
}.join
|
140
|
+
twos_complement_binary_integer(v_str, v_str.size)
|
141
|
+
end
|
142
|
+
def length_constrained_whole_number(str, len_range)
|
143
|
+
if len_range.max < 65536 then # 10.9.4.1
|
144
|
+
(len_range.min == len_range.max) ?
|
145
|
+
len_range.min :
|
146
|
+
constrainted_whole_number(str, len_range)
|
147
|
+
else
|
148
|
+
length_otherwise(str)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
def length_normally_small_length(str) # 10.9.4.2 -> 10.9.3.4
|
152
|
+
case str.slice!(0)
|
153
|
+
when '0'; str.slice!(0, 6).to_i(2) + 1
|
154
|
+
when '1'; length_otherwise(str)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
def length_otherwise(str) # 10.9.4.2 -> 10.9.3.5-8
|
158
|
+
case str.slice!(0)
|
159
|
+
when '0'; non_negative_binary_integer(str, 7) # 10.9.3.6
|
160
|
+
when '1';
|
161
|
+
case str.slice!(0)
|
162
|
+
when '0'; non_negative_binary_integer(str, 14) # 10.9.3.7
|
163
|
+
when '1'; [non_negative_binary_integer(str, 6) * (1 << 14), true] # 10.9.3.8
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
def with_length(str, *len_dec)
|
168
|
+
Enumerator::new{|y|
|
169
|
+
len, cnt = len_dec[0].kind_of?(Symbol) ? send(len_dec[0], str, *len_dec[1..-1]) : len_dec
|
170
|
+
loop{
|
171
|
+
y << len
|
172
|
+
break unless cnt
|
173
|
+
len, cnt = length_otherwise(str) # fragmentation
|
174
|
+
}
|
175
|
+
}
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
=begin
|
2
|
+
AGPS handler for receiver
|
3
|
+
=end
|
4
|
+
|
5
|
+
module GPS_PVT
|
6
|
+
class Receiver
|
7
|
+
def parse_supl(src, opt = {}, &b)
|
8
|
+
$stderr.print "A-GPS (%s) "%[src]
|
9
|
+
opt = {
|
10
|
+
:interval => 60 * 10, # 10 min.
|
11
|
+
}.merge(opt)
|
12
|
+
require_relative '../supl'
|
13
|
+
src_io = Util::open(src)
|
14
|
+
while data = src_io.get_assisted_data
|
15
|
+
data.ephemeris.each{|eph|
|
16
|
+
target = case eph
|
17
|
+
when GPS::Ephemeris; @solver.gps_space_node
|
18
|
+
when GPS::Ephemeris_GLONASS; @solver.glonass_space_node
|
19
|
+
when GPS::Ephemeris_SBAS; @solver.sbas_space_node
|
20
|
+
else nil
|
21
|
+
end
|
22
|
+
critical{target.register_ephemeris(eph.svid, eph)} if target
|
23
|
+
} if data.respond_to?(:ephemeris)
|
24
|
+
critical{
|
25
|
+
@solver.gps_space_node.update_iono_utc(data.iono_utc)
|
26
|
+
} if data.respond_to?(:iono_utc)
|
27
|
+
sleep(opt[:interval])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -57,4 +57,25 @@ class Receiver
|
|
57
57
|
}
|
58
58
|
end
|
59
59
|
end
|
60
|
+
|
61
|
+
module GPS
|
62
|
+
|
63
|
+
[
|
64
|
+
Ionospheric_UTC_Parameters,
|
65
|
+
Ephemeris, Ephemeris_SBAS, Ephemeris_GLONASS,
|
66
|
+
].each{|cls|
|
67
|
+
cls.class_eval{
|
68
|
+
proc{|func_list|
|
69
|
+
func_list.select!{|func|
|
70
|
+
(/=$/ !~ func.to_s) && func_list.include?("#{func}=".to_sym)
|
71
|
+
}
|
72
|
+
define_method(:to_hash){
|
73
|
+
Hash[*(func_list.collect{|func|
|
74
|
+
[func, send(func)]
|
75
|
+
}.flatten(1))]
|
76
|
+
}
|
77
|
+
}.call(instance_methods(false))
|
78
|
+
}
|
79
|
+
}
|
80
|
+
end
|
60
81
|
end
|
@@ -195,7 +195,7 @@ class Receiver
|
|
195
195
|
when 1020
|
196
196
|
params = parsed.params
|
197
197
|
eph = GPS::Ephemeris_GLONASS::new
|
198
|
-
|
198
|
+
eph.F_T = 10 # [m], default to be overwritten
|
199
199
|
params.each{|k, v|
|
200
200
|
next if [:P3, :NA, :N_4].include?(k)
|
201
201
|
eph.send("#{k}=".to_sym, v)
|
@@ -205,6 +205,7 @@ class Receiver
|
|
205
205
|
? date_src \
|
206
206
|
: [(ref_time + 3 * 60 * 60).c_tm(leap_sec)])) # UTC -> Moscow time
|
207
207
|
}.call([:N_4, :NA].collect{|k| params[k]})
|
208
|
+
eph.N_T = params[:NA] || eph.NA unless params[:N_T] # N_T is available only for GLONASS-M
|
208
209
|
eph.rehash(leap_sec)
|
209
210
|
critical{
|
210
211
|
@solver.glonass_space_node.register_ephemeris(eph.svid, eph)
|
data/lib/gps_pvt/receiver.rb
CHANGED
@@ -38,20 +38,21 @@ class Receiver
|
|
38
38
|
] + (pvt.rel_ENU.to_a rescue [nil] * 3)
|
39
39
|
}
|
40
40
|
]] + [proc{
|
41
|
-
labels = [:g, :p, :h, :v, :t].collect{|k| "#{k}dop".to_sym}
|
41
|
+
labels = [:g, :p, :h, :v, :t].collect{|k| "#{k}dop".to_sym} \
|
42
|
+
+ [:h, :v, :t].collect{|k| "#{k}sigma".to_sym}
|
42
43
|
[
|
43
44
|
labels,
|
44
45
|
proc{|pvt|
|
45
|
-
next [nil] *
|
46
|
+
next [nil] * 8 unless pvt.position_solved?
|
46
47
|
labels.collect{|k| pvt.send(k)}
|
47
48
|
}
|
48
49
|
]
|
49
50
|
}.call] + [[
|
50
|
-
[:v_north, :v_east, :v_down, :receiver_clock_error_dot_ms],
|
51
|
+
[:v_north, :v_east, :v_down, :receiver_clock_error_dot_ms, :vel_sigma],
|
51
52
|
proc{|pvt|
|
52
53
|
next [nil] * 4 unless pvt.velocity_solved?
|
53
54
|
[:north, :east, :down].collect{|k| pvt.velocity.send(k)} \
|
54
|
-
+ [pvt.receiver_error_rate]
|
55
|
+
+ [pvt.receiver_error_rate, pvt.vel_sigma]
|
55
56
|
}
|
56
57
|
]] + [
|
57
58
|
[:used_satellites, proc{|pvt| pvt.used_satellites}],
|
@@ -135,7 +136,7 @@ class Receiver
|
|
135
136
|
opt[:satellites].collect{|prn, label|
|
136
137
|
pr, rate, doppler, freq = keys.collect{|k| meas_hash[prn][k] rescue nil}
|
137
138
|
freq ||= GPS::SpaceNode.L1_Frequency
|
138
|
-
[pr, rate || ((doppler * GPS::SpaceNode::light_speed / freq) rescue nil)]
|
139
|
+
[pr, rate || ((-doppler * GPS::SpaceNode::light_speed / freq) rescue nil)]
|
139
140
|
}
|
140
141
|
}
|
141
142
|
]]
|
@@ -324,25 +325,31 @@ class Receiver
|
|
324
325
|
end
|
325
326
|
|
326
327
|
GPS::Measurement.class_eval{
|
327
|
-
proc{
|
328
|
-
key2sym = []
|
329
|
-
GPS::Measurement.constants.each{|k|
|
330
|
-
i = GPS::Measurement.const_get(k)
|
331
|
-
key2sym[i] = k if i.kind_of?(Integer)
|
332
|
-
}
|
333
|
-
define_method(:to_a2){
|
334
|
-
to_a.collect{|prn, k, v| [prn, key2sym[k] || k, v]}
|
335
|
-
}
|
336
|
-
define_method(:to_hash2){
|
337
|
-
Hash[*(to_hash.collect{|prn, k_v|
|
338
|
-
[prn, Hash[*(k_v.collect{|k, v| [key2sym[k] || k, v]}.flatten(1))]]
|
339
|
-
}.flatten(1))]
|
340
|
-
}
|
341
|
-
}.call
|
342
328
|
add_orig = instance_method(:add)
|
343
329
|
define_method(:add){|prn, key, value|
|
344
330
|
add_orig.bind(self).call(prn, key.kind_of?(Symbol) ? GPS::Measurement.const_get(key) : key, value)
|
345
331
|
}
|
332
|
+
key2sym = GPS::Measurement.constants.inject([]){|res, k|
|
333
|
+
res[GPS::Measurement.const_get(k)] = k if /^L\d/ =~ k.to_s
|
334
|
+
res
|
335
|
+
}
|
336
|
+
define_method(:to_a2){
|
337
|
+
collect{|prn, k, v| [prn, key2sym[k] || k, v]}
|
338
|
+
}
|
339
|
+
cl_hash2 = Class::new(Hash){
|
340
|
+
define_method(:to_meas){
|
341
|
+
GPS::Measurement::new.tap{|res|
|
342
|
+
each{|prn, k_v|
|
343
|
+
k_v.each{|k, v| res.add(prn, k, v)}
|
344
|
+
}
|
345
|
+
}
|
346
|
+
}
|
347
|
+
}
|
348
|
+
define_method(:to_hash2){
|
349
|
+
cl_hash2::new.tap{|res|
|
350
|
+
each{|prn, k, v| (res[prn] ||= {})[key2sym[k] || k] = v}
|
351
|
+
}
|
352
|
+
}
|
346
353
|
}
|
347
354
|
|
348
355
|
def run(meas, t_meas, ref_pos = @base_station)
|
@@ -724,4 +731,5 @@ end
|
|
724
731
|
end
|
725
732
|
|
726
733
|
require_relative 'receiver/rtcm3'
|
734
|
+
require_relative 'receiver/agps'
|
727
735
|
require_relative 'receiver/extension'
|
data/lib/gps_pvt/rtcm3.rb
CHANGED
@@ -104,12 +104,7 @@ class RTCM3
|
|
104
104
|
57 => 16,
|
105
105
|
71 => 8,
|
106
106
|
76 => 10,
|
107
|
-
77 =>
|
108
|
-
idx2meter = [
|
109
|
-
2.40, 3.40, 4.85, 6.85, 9.65, 13.65, 24.00, 48.00,
|
110
|
-
96.00, 192.00, 384.00, 768.00, 1536.00, 3072.00, 6144.00]
|
111
|
-
[4, proc{|v| (v >= idx2meter.size) ? (idx2meter[-1] * 2) : idx2meter[v]}]
|
112
|
-
}.call, # [m]
|
107
|
+
77 => 4,
|
113
108
|
78 => 2,
|
114
109
|
79 => num_gen.call(14, Rational(sc2rad, 1 << 43)), # [rad/s]
|
115
110
|
81 => unum_gen.call(16, 1 << 4), # [sec]
|
@@ -137,7 +132,7 @@ class RTCM3
|
|
137
132
|
103 => 1,
|
138
133
|
104 => 1,
|
139
134
|
105 => 1,
|
140
|
-
106 =>
|
135
|
+
106 => 2,
|
141
136
|
107 => [12, proc{|v|
|
142
137
|
hh, mm, ss = [v >> 7, (v & 0x7E) >> 1, (v & 0x1) > 0 ? 30 : 0]
|
143
138
|
hh * 3600 + mm * 60 + ss # [sec]
|
@@ -156,15 +151,13 @@ class RTCM3
|
|
156
151
|
125 => num_sign_gen.call(5, Rational(1, 1 << 30)), # [sec], (M)
|
157
152
|
126 => 5, # [day]
|
158
153
|
127 => 1, # (M)
|
159
|
-
128 =>
|
160
|
-
|
161
|
-
}], # [m] (M)
|
162
|
-
129 => 11, # [day]
|
154
|
+
128 => 4, # (M)
|
155
|
+
129 => invalidate.call(unum_gen.call(11), 0), # [day]
|
163
156
|
130 => 2, # 1 => GLONASS-M, (M) fields are active
|
164
157
|
131 => 1,
|
165
|
-
132 => 11, # [day]
|
158
|
+
132 => invalidate.call(unum_gen.call(11), 0), # [day]
|
166
159
|
133 => num_sign_gen.call(32, Rational(1, 1 << 31)), # [sec]
|
167
|
-
134 => 5, # [4year], (M)
|
160
|
+
134 => invalidate.call(unum_gen.call(5), 0), # [4year], (M)
|
168
161
|
135 => num_sign_gen.call(22, Rational(1, 1 << 30)), # [sec], (M)
|
169
162
|
136 => 1, # (M)
|
170
163
|
137 => 1,
|
@@ -247,9 +240,11 @@ class RTCM3
|
|
247
240
|
1013 => [2, 3, 51, 52, 53, 54],
|
248
241
|
1019 => [2, 9, (76..79).to_a, 71, (81..103).to_a, 137].flatten, # 488 bits @see Table 3.5-21
|
249
242
|
1020 => [2, 38, 40, (104..136).to_a].flatten, # 360 bits @see Table 3.5-21
|
243
|
+
# @see BNC Ntrip client DecodeSBASEphemeris() of RTCM3Decorder.cpp
|
244
|
+
# https://software.rtcm-ntrip.org/browser/ntrip/trunk/BNC/src/RTCM3/RTCM3Decoder.cpp
|
250
245
|
1043 => [2] + [:prn, :iodn, :tod, :ura,
|
251
246
|
[:xy] * 2, :z, [:dxy] * 2, :dz, [:ddxy] * 2, :ddz,
|
252
|
-
:agf0, :agf1].flatten.collect{|k| "SBAS_#{k}".to_sym},
|
247
|
+
:agf0, :agf1].flatten.collect{|k| "SBAS_#{k}".to_sym},
|
253
248
|
1044 => [2, (429..457).to_a].flatten, # 485 bits
|
254
249
|
1070..1229 => [2, [:uint, 12], [:uint, 30], 393], # 55 bits part of messages will be overwritten
|
255
250
|
1071..1077 => [2, 3, 4, 393, 409, [1, 7], 411, 412, 417, 418, 394, 395], # 169 bits @see Table 3.5-78
|
@@ -311,7 +306,7 @@ class RTCM3
|
|
311
306
|
end
|
312
307
|
end
|
313
308
|
module GPS_Ephemeris
|
314
|
-
KEY2IDX = {:svid => 1, :WN => 2, :
|
309
|
+
KEY2IDX = {:svid => 1, :WN => 2, :URA_index => 3, :dot_i0 => 5, :iode => 6, :t_oc => 7,
|
315
310
|
:a_f2 => 8, :a_f1 => 9, :a_f0 => 10, :iodc => 11, :c_rs => 12, :delta_n => 13,
|
316
311
|
:M0 => 14, :c_uc => 15, :e => 16, :c_us => 17, :sqrt_A => 18, :t_oe => 19, :c_ic => 20,
|
317
312
|
:Omega0 => 21, :c_is => 22, :i0 => 23, :c_rc => 24, :omega => 25, :dot_Omega0 => 26,
|
@@ -319,22 +314,12 @@ class RTCM3
|
|
319
314
|
def params
|
320
315
|
# TODO WN is truncated to 0-1023
|
321
316
|
res = Hash[*(KEY2IDX.collect{|k, i| [k, self[i][0]]}.flatten(1))]
|
322
|
-
res[:fit_interval] = (
|
323
|
-
when 240..247; 8
|
324
|
-
when 248..255, 496; 14
|
325
|
-
when 497..503; 26
|
326
|
-
when 504..510; 50
|
327
|
-
when 511, 752..756; 74
|
328
|
-
when 757..763; 98
|
329
|
-
when 764..767, 1088..1010; 122
|
330
|
-
when 1011..1020; 146
|
331
|
-
else; 6
|
332
|
-
end) * 60 * 60
|
317
|
+
res[:fit_interval] = (self[29][0] != 0)
|
333
318
|
res
|
334
319
|
end
|
335
320
|
end
|
336
321
|
module SBAS_Ephemeris
|
337
|
-
KEY2IDX = {:svid => 1, :iodn => 2, :tod => 3, :
|
322
|
+
KEY2IDX = {:svid => 1, :iodn => 2, :tod => 3, :URA_index => 4,
|
338
323
|
:x => 5, :y => 6, :z => 7,
|
339
324
|
:dx => 8, :dy => 9, :dz => 10,
|
340
325
|
:ddx => 11, :ddy => 12, :ddz => 13,
|
@@ -349,18 +334,18 @@ class RTCM3
|
|
349
334
|
# TODO insufficient: :n => ?(String4); extra: :P3
|
350
335
|
# TODO generate time with t_b, N_T, NA, N_4
|
351
336
|
# TODO GPS.i is required to modify to generate EPhemeris_with_GPS_Time
|
352
|
-
k_i = {:svid => 1, :freq_ch => 2, :
|
337
|
+
k_i = {:svid => 1, :freq_ch => 2, :P1_index => 5, :t_k => 6, :B_n => 7, :P2 => 8, :t_b => 9,
|
353
338
|
:xn_dot => 10, :xn => 11, :xn_ddot => 12,
|
354
339
|
:yn_dot => 13, :yn => 14, :yn_ddot => 15,
|
355
340
|
:zn_dot => 16, :zn => 17, :zn_ddot => 18,
|
356
341
|
:P3 => 19, :gamma_n => 20, :p => 21, :tau_n => 23, :delta_tau_n => 24, :E_n => 25,
|
357
|
-
:P4 => 26, :
|
342
|
+
:P4 => 26, :F_T_index => 27, :N_T => 28, :M => 29}
|
358
343
|
k_i.merge!({:NA => 31, :tau_c => 32, :N_4 => 33, :tau_GPS => 34}) if self[30][0] == 1 # check DF131
|
359
344
|
res = Hash[*(k_i.collect{|k, i| [k, self[i][0]]}.flatten(1))]
|
360
345
|
res.reject!{|k, v|
|
361
346
|
case k
|
362
347
|
when :N_T; v == 0
|
363
|
-
when :p, :delta_tau_n, :P4, :
|
348
|
+
when :p, :delta_tau_n, :P4, :F_T_index, :N_4, :tau_GPS; true # TODO sometimes delta_tau_n is valid?
|
364
349
|
else; false
|
365
350
|
end
|
366
351
|
} if (res[:M] != 1) # check DF130
|
@@ -372,12 +357,12 @@ class RTCM3
|
|
372
357
|
:iode => 6, :c_rs => 7, :delta_n => 8, :M0 => 9, :c_uc => 10, :e => 11,
|
373
358
|
:c_us => 12, :sqrt_A => 13, :t_oe => 14, :c_ic => 15, :Omega0 => 16,
|
374
359
|
:c_is => 17, :i0 => 18, :c_rc => 19, :omega => 20, :dot_Omega0 => 21,
|
375
|
-
:dot_i0 => 22, :WN => 24, :
|
360
|
+
:dot_i0 => 22, :WN => 24, :URA_index => 25, :SV_health => 26,
|
376
361
|
:t_GD => 27, :iodc => 28}
|
377
362
|
def params
|
378
363
|
# TODO PRN = svid + 192, WN is truncated to 0-1023
|
379
364
|
res = Hash[*(KEY2IDX.collect{|k, i| [k, self[i][0]]}.flatten(1))]
|
380
|
-
res[:fit_interval] = (self[29]
|
365
|
+
res[:fit_interval] = (self[29][0] != 0)
|
381
366
|
res
|
382
367
|
end
|
383
368
|
end
|