gps_pvt 0.9.2 → 0.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
- after_run.call(run(meas_, t_meas), [meas_, ref_time = t_meas]) if t_meas
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
- item_size = ranges[:sat].size
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; # GPS
75
- when 40..58; svid += 80 # SBAS
76
- else; next
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
- item_size = ranges[:sat].size
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 # GLONASS
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 40..58
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
- item_size = ranges[:sat_sig].size
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|
@@ -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])
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GPS_PVT
4
- VERSION = "0.9.2"
4
+ VERSION = "0.9.3"
5
5
 
6
6
  def GPS_PVT.version_compare(a, b)
7
7
  Gem::Version::new(a) <=> Gem::Version::new(b)
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.2
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-02-13 00:00:00.000000000 Z
11
+ date: 2023-03-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubyserial