gps_pvt 0.9.2 → 0.9.3
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/ext/gps_pvt/Coordinate/Coordinate_wrap.cxx +31 -19
- data/ext/gps_pvt/GPS/GPS_wrap.cxx +577 -4113
- data/ext/gps_pvt/SylphideMath/SylphideMath_wrap.cxx +829 -2574
- data/ext/ninja-scan-light/tool/swig/Coordinate.i +12 -12
- data/ext/ninja-scan-light/tool/swig/GPS.i +88 -80
- data/ext/ninja-scan-light/tool/swig/SylphideMath.i +52 -32
- data/ext/ninja-scan-light/tool/swig/spec/GPS_spec.rb +1 -1
- data/ext/ninja-scan-light/tool/swig/spec/SylphideMath_spec.rb +8 -8
- data/lib/gps_pvt/receiver/rtcm3.rb +103 -22
- data/lib/gps_pvt/receiver.rb +1 -0
- data/lib/gps_pvt/rtcm3.rb +44 -0
- data/lib/gps_pvt/version.rb +1 -1
- metadata +2 -2
@@ -18,6 +18,13 @@ class Receiver
|
|
18
18
|
else; raise "reference time (#{ref_time}) should be GPS::Time or Time"
|
19
19
|
end
|
20
20
|
leap_sec = ref_time.leap_seconds
|
21
|
+
ref_pos = opt[:ref_pos] || if src_io.respond_to?(:property) then
|
22
|
+
Coordinate::LLH::new(*(src_io.property.values_at(:latitude, :longitude).collect{|v|
|
23
|
+
v.to_f / 180 * Math::PI
|
24
|
+
} + [0])).xyz
|
25
|
+
else
|
26
|
+
defined?(@base_station) ? @base_station : nil
|
27
|
+
end
|
21
28
|
after_run = b || proc{|pvt| puts pvt.to_s if pvt}
|
22
29
|
t_meas, meas = [nil, {}]
|
23
30
|
# meas := {msg_num => [[], ...]} due to duplicated observation such as 1074 and 1077
|
@@ -26,7 +33,9 @@ class Receiver
|
|
26
33
|
meas.sort.each{|k, values| # larger msg_num entries have higher priority
|
27
34
|
values.each{|prn_k_v| meas_.add(*prn_k_v)}
|
28
35
|
}
|
29
|
-
|
36
|
+
pvt = nil
|
37
|
+
after_run.call(pvt = run(meas_, t_meas), [meas_, ref_time = t_meas]) if t_meas
|
38
|
+
ref_pos = pvt.xyz if pvt && pvt.position_solved?
|
30
39
|
t_meas, meas = [nil, {}]
|
31
40
|
}
|
32
41
|
dt_threshold = GPS::Time::Seconds_week / 2
|
@@ -53,6 +62,63 @@ class Receiver
|
|
53
62
|
GPS::Time::new(ref_time.week, 0) + tod + 60 * 60 * 24 * ref_dow
|
54
63
|
end
|
55
64
|
}
|
65
|
+
restore_ranges = proc{
|
66
|
+
c_1ms = 299_792.458
|
67
|
+
threshold = c_1ms / 10 # 100 us =~ 30 km
|
68
|
+
cache = {} # {[sys, svid] => [range, t], ...}
|
69
|
+
get_rough = proc{|t, sys_svid_list|
|
70
|
+
sn_list = sys_svid_list.collect{|sys, svid|
|
71
|
+
case sys
|
72
|
+
when :GPS, :QZSS; @solver.gps_space_node
|
73
|
+
when :SBAS; @solver.sbas_space_node
|
74
|
+
when :GLONASS; @solver.glonass_space_node
|
75
|
+
end
|
76
|
+
}
|
77
|
+
critical{
|
78
|
+
sn_list.uniq.compact{|sn| sn.update_all_ephemeris(t)}
|
79
|
+
sys_svid_list.zip(sn_list).each{|(sys, svid), sn|
|
80
|
+
next unless sn
|
81
|
+
eph = sn.ephemeris(svid)
|
82
|
+
cache[[sys, svid]] = [if eph.valid?(t) then
|
83
|
+
sv_pos, clk_err = eph.constellation(t).values_at(0, 2)
|
84
|
+
sv_pos.dist(ref_pos) - (clk_err * c_1ms * 1E3)
|
85
|
+
end, t]
|
86
|
+
}
|
87
|
+
}
|
88
|
+
}
|
89
|
+
per_kind = proc{|t, sys_svid_list, ranges_rem|
|
90
|
+
get_rough.call(t, sys_svid_list.uniq.reject{|sys, svid|
|
91
|
+
next true unless sys
|
92
|
+
range, t2 = cache[[sys, svid]]
|
93
|
+
range && ((t2 - t).abs <= 60)
|
94
|
+
})
|
95
|
+
ranges_rem.zip(sys_svid_list).collect{|rem_in, (sys, svid)|
|
96
|
+
range_ref, t2 = cache[[sys, svid]]
|
97
|
+
next nil unless range_ref
|
98
|
+
q, rem_ref = range_ref.divmod(c_1ms)
|
99
|
+
delta = rem_in - rem_ref
|
100
|
+
res = if delta.abs <= threshold then
|
101
|
+
q * c_1ms + rem_in
|
102
|
+
elsif -delta + c_1ms <= threshold
|
103
|
+
(q - 1) * c_1ms + rem_in
|
104
|
+
elsif delta + c_1ms <= threshold
|
105
|
+
(q + 1) * c_1ms + rem_in
|
106
|
+
end
|
107
|
+
#p [sys, svid, q, rem_in, rem_ref, res]
|
108
|
+
(cache[[sys, svid]] = [res, t])[0]
|
109
|
+
}
|
110
|
+
}
|
111
|
+
proc{|t, sys_svid_list, ranges|
|
112
|
+
[
|
113
|
+
:pseudo_range, # for MT 1001/3/9/11, MSM1/3
|
114
|
+
:phase_range, # for MT 1003/11, MSM2/3
|
115
|
+
].each{|k|
|
116
|
+
next if ranges[k]
|
117
|
+
k_rem = "#{k}_rem".to_sym
|
118
|
+
ranges[k] = per_kind.call(t, sys_svid_list, ranges[k_rem]) if ranges[k_rem]
|
119
|
+
}
|
120
|
+
}
|
121
|
+
}.call
|
56
122
|
|
57
123
|
while packet = rtcm3.read_packet
|
58
124
|
msg_num = packet.message_number
|
@@ -66,15 +132,19 @@ class Receiver
|
|
66
132
|
when 1001..1004
|
67
133
|
t_meas2 = tow2t.call(parsed[2][0]) # DF004
|
68
134
|
ranges = parsed.ranges
|
69
|
-
|
70
|
-
[:sat, :pseudo_range, :phase_range, :cn].collect{|k|
|
71
|
-
ranges[k] || ([nil] * item_size)
|
72
|
-
}.transpose.each{|svid, pr, cpr, cn|
|
135
|
+
sys_svid_list = ranges[:sat].collect{|svid|
|
73
136
|
case svid
|
74
|
-
when 1..32;
|
75
|
-
when 40..58; svid
|
76
|
-
else;
|
137
|
+
when 1..32; [:GPS, svid]
|
138
|
+
when 40..58; [:SBAS, svid + 80]
|
139
|
+
else; [nil, svid]
|
77
140
|
end
|
141
|
+
}
|
142
|
+
restore_ranges.call(t_meas2, sys_svid_list, ranges)
|
143
|
+
item_size = sys_svid_list.size
|
144
|
+
([sys_svid_list] + [:pseudo_range, :phase_range, :cn].collect{|k|
|
145
|
+
ranges[k] || ([nil] * item_size)
|
146
|
+
}).transpose.each{|(sys, svid), pr, cpr, cn|
|
147
|
+
next unless sys
|
78
148
|
meas2 << [svid, :L1_PSEUDORANGE, pr] if pr
|
79
149
|
meas2 << [svid, :L1_CARRIER_PHASE, cpr / GPS::SpaceNode.L1_WaveLength] if cpr
|
80
150
|
meas2 << [svid, :L1_SIGNAL_STRENGTH_dBHz, cn] if cn
|
@@ -82,25 +152,34 @@ class Receiver
|
|
82
152
|
when 1009..1012
|
83
153
|
t_meas2 = utc2t.call(parsed[2][0] - 60 * 60 * 3) # DF034 UTC(SU)+3hr, time of day[sec]
|
84
154
|
ranges = parsed.ranges
|
85
|
-
|
86
|
-
[:sat, :freq_ch, :pseudo_range, :phase_range, :cn].collect{|k|
|
87
|
-
ranges[k] || ([nil] * item_size)
|
88
|
-
}.transpose.each{|svid, freq_ch, pr, cpr, cn|
|
155
|
+
sys_svid_list = ranges[:sat].collect{|svid|
|
89
156
|
case svid
|
90
|
-
when 1..24
|
157
|
+
when 1..24; [:GLONASS, svid]
|
158
|
+
when 40..58; [:SBAS, svid + 80]
|
159
|
+
else; [nil, svid]
|
160
|
+
end
|
161
|
+
}
|
162
|
+
restore_ranges.call(t_meas2, sys_svid_list, ranges)
|
163
|
+
item_size = sys_svid_list.size
|
164
|
+
([sys_svid_list] + [:freq_ch, :pseudo_range, :phase_range, :cn].collect{|k|
|
165
|
+
ranges[k] || ([nil] * item_size)
|
166
|
+
}).transpose.each{|(sys, svid), freq_ch, pr, cpr, cn|
|
167
|
+
case sys
|
168
|
+
when :GLONASS
|
91
169
|
svid += 0x100
|
92
170
|
freq = GPS::SpaceNode_GLONASS::L1_frequency(freq_ch)
|
93
171
|
len = GPS::SpaceNode_GLONASS.light_speed / freq
|
94
172
|
meas2 << [svid, :L1_FREQUENCY, freq]
|
95
173
|
meas2 << [svid, :L1_CARRIER_PHASE, cpr / len] if cpr
|
96
|
-
when
|
97
|
-
svid += 80 # SBAS
|
174
|
+
when :SBAS
|
98
175
|
meas2 << [svid, :L1_CARRIER_PHASE, cpr / GPS::SpaceNode.L1_WaveLength] if cpr
|
99
176
|
else; next
|
100
177
|
end
|
101
178
|
meas2 << [svid, :L1_PSEUDORANGE, pr] if pr
|
102
179
|
meas2 << [svid, :L1_SIGNAL_STRENGTH_dBHz, cn] if cn
|
103
180
|
}
|
181
|
+
when 1013
|
182
|
+
leap_sec = parsed[5][0]
|
104
183
|
when 1019, 1044
|
105
184
|
params = parsed.params
|
106
185
|
if msg_num == 1044
|
@@ -162,22 +241,24 @@ class Receiver
|
|
162
241
|
}.compact.flatten(1))]
|
163
242
|
}
|
164
243
|
end
|
165
|
-
sig_list, svid_offset = case msg_num / 10
|
244
|
+
sig_list, sys, svid_offset = case msg_num / 10
|
166
245
|
when 107 # GPS
|
167
246
|
[{2 => [:L1, GPS::SpaceNode.L1_WaveLength],
|
168
247
|
15 => [:L2CM, GPS::SpaceNode.L2_WaveLength],
|
169
|
-
16 => [:L2CL, GPS::SpaceNode.L2_WaveLength]}, 0]
|
248
|
+
16 => [:L2CL, GPS::SpaceNode.L2_WaveLength]}, :GPS, 0]
|
170
249
|
when 108 # GLONASS
|
171
|
-
[{2 => [:L1, nil]}, 0x100]
|
250
|
+
[{2 => [:L1, nil]}, :GLONASS, 0x100]
|
172
251
|
when 110 # SBAS
|
173
|
-
[{2 => [:L1, GPS::SpaceNode.L1_WaveLength]}, 120]
|
252
|
+
[{2 => [:L1, GPS::SpaceNode.L1_WaveLength]}, :SBAS, 120]
|
174
253
|
when 111 # QZSS
|
175
254
|
[{2 => [:L1, GPS::SpaceNode.L1_WaveLength],
|
176
255
|
15 => [:L2CM, GPS::SpaceNode.L2_WaveLength],
|
177
|
-
16 => [:L2CL, GPS::SpaceNode.L2_WaveLength]}, 192]
|
178
|
-
else; [{}, 0]
|
256
|
+
16 => [:L2CL, GPS::SpaceNode.L2_WaveLength]}, :QZSS, 192]
|
257
|
+
else; [{}, nil, 0]
|
179
258
|
end
|
180
|
-
|
259
|
+
sys_svid_list = ranges[:sat_sig].collect{|sat, sig| [sys, (sat + svid_offset) & 0xFF]}
|
260
|
+
restore_ranges.call(t_meas2, sys_svid_list, ranges)
|
261
|
+
item_size = sys_svid_list.size
|
181
262
|
[:sat_sig, :pseudo_range, :phase_range, :phase_range_rate, :cn].collect{|k|
|
182
263
|
ranges[k] || ([nil] * item_size)
|
183
264
|
}.transpose.each{|(svid, sig), pr, cpr, dr, cn|
|
data/lib/gps_pvt/receiver.rb
CHANGED
@@ -416,6 +416,7 @@ class Receiver
|
|
416
416
|
opt = options[0] || {}
|
417
417
|
case sys
|
418
418
|
when :GPS, :QZSS
|
419
|
+
return unless bcast_data.size == 10 # 8 for QZSS(SAIF)
|
419
420
|
return unless eph = @eph_list[prn]
|
420
421
|
sn = @solver.gps_space_node
|
421
422
|
subframe, iodc_or_iode = eph.parse(bcast_data)
|
data/lib/gps_pvt/rtcm3.rb
CHANGED
@@ -95,6 +95,13 @@ class RTCM3
|
|
95
95
|
48 => invalidate.call(num_gen.call(20, Rational(5, 10000)), 0x80000), # [m]
|
96
96
|
49 => 7,
|
97
97
|
50 => invalidate.call(unum_gen.call(8, Rational(1, 4)), 0), # [db-Hz]
|
98
|
+
51 => 16,
|
99
|
+
52 => 17,
|
100
|
+
53 => 5,
|
101
|
+
54 => 8,
|
102
|
+
55 => 12,
|
103
|
+
56 => 1,
|
104
|
+
57 => 16,
|
98
105
|
71 => 8,
|
99
106
|
76 => 10,
|
100
107
|
77 => proc{
|
@@ -237,12 +244,14 @@ class RTCM3
|
|
237
244
|
1001..1004 => (2..8).to_a,
|
238
245
|
1005 => [2, 3, 21, 22, 23, 24, 141, 25, 142, [1, 1], 26, 364, 27],
|
239
246
|
1009..1012 => [2, 3, 34, 5, 35, 36, 37],
|
247
|
+
1013 => [2, 3, 51, 52, 53, 54],
|
240
248
|
1019 => [2, 9, (76..79).to_a, 71, (81..103).to_a, 137].flatten, # 488 bits @see Table 3.5-21
|
241
249
|
1020 => [2, 38, 40, (104..136).to_a].flatten, # 360 bits @see Table 3.5-21
|
242
250
|
1043 => [2] + [:prn, :iodn, :tod, :ura,
|
243
251
|
[:xy] * 2, :z, [:dxy] * 2, :dz, [:ddxy] * 2, :ddz,
|
244
252
|
:agf0, :agf1].flatten.collect{|k| "SBAS_#{k}".to_sym}, # @see BNC Ntrip client RTCM3Decorder.cpp
|
245
253
|
1044 => [2, (429..457).to_a].flatten, # 485 bits
|
254
|
+
1070..1229 => [2, [:uint, 12], [:uint, 30], 393], # 55 bits part of messages will be overwritten
|
246
255
|
1071..1077 => [2, 3, 4, 393, 409, [1, 7], 411, 412, 417, 418, 394, 395], # 169 bits @see Table 3.5-78
|
247
256
|
1081..1087 => [2, 3, 416, 34, 393, 409, [1, 7], 411, 412, 417, 418, 394, 395], # 169 bits @see Table 3.5-93
|
248
257
|
1091..1097 => [2, 3, 248, 393, 409, [1, 7], 411, 412, 417, 418, 394, 395], # 169 bits @see Table 3.5-98
|
@@ -392,6 +401,29 @@ class RTCM3
|
|
392
401
|
end
|
393
402
|
SPEED_OF_LIGHT = 299_792_458
|
394
403
|
end
|
404
|
+
module MSM1_2_3
|
405
|
+
include MSM
|
406
|
+
def ranges
|
407
|
+
sats, cells, offset = property.values_at(:sats, :cells, :header_items)
|
408
|
+
nsat, ncell = [sats.size, cells.size]
|
409
|
+
res = {:sat_sig => cells}
|
410
|
+
range_rough = cells.collect{|sat, sig| # DF398
|
411
|
+
self[offset + sats.find_index(sat)][0]
|
412
|
+
}
|
413
|
+
add_proc = proc{|idx_cell|
|
414
|
+
values = self[offset + (nsat * 1) + (ncell * idx_cell), ncell]
|
415
|
+
next if values.empty?
|
416
|
+
k = {400 => :pseudo_range_rem, 401 => :phase_range_rem}[values[0][1]]
|
417
|
+
next unless k
|
418
|
+
res[k] = values.zip(range_rough).collect{|(v, df), v_base|
|
419
|
+
((v_base + v) * SPEED_OF_LIGHT) rescue nil
|
420
|
+
}
|
421
|
+
}
|
422
|
+
add_proc.call(0)
|
423
|
+
add_proc.call(1)
|
424
|
+
res
|
425
|
+
end
|
426
|
+
end
|
395
427
|
module MSM4_6
|
396
428
|
include MSM
|
397
429
|
def ranges
|
@@ -468,6 +500,9 @@ class RTCM3
|
|
468
500
|
1012 => (38..50).to_a,
|
469
501
|
}[msg_num]] * nsat).flatten), offset)
|
470
502
|
attributes << GLONASS_Observation
|
503
|
+
when 1013
|
504
|
+
add_proc.call(DataFrame.generate_prop(
|
505
|
+
((55..57).to_a * values[4]).flatten), 24 + mt[:bits_total])
|
471
506
|
when 1019
|
472
507
|
attributes << GPS_Ephemeris
|
473
508
|
when 1020
|
@@ -492,6 +527,15 @@ class RTCM3
|
|
492
527
|
add_proc.call(msm_sig, offset)
|
493
528
|
}
|
494
529
|
case msg_num % 10
|
530
|
+
when 1
|
531
|
+
attributes << MSM1_2_3
|
532
|
+
msm_proc.call([398], [400])
|
533
|
+
when 2
|
534
|
+
attributes << MSM1_2_3
|
535
|
+
msm_proc.call([398], [401, 402, 420])
|
536
|
+
when 3
|
537
|
+
attributes << MSM1_2_3
|
538
|
+
msm_proc.call([398], [400, 401, 402, 420])
|
495
539
|
when 4
|
496
540
|
attributes << MSM4_6
|
497
541
|
msm_proc.call([397, 398], [400, 401, 402, 420, 403])
|
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.9.
|
4
|
+
version: 0.9.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: 2023-
|
11
|
+
date: 2023-03-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubyserial
|