gps_pvt 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 58f4afe48f4ffe54827ee4cdcefa0f1f05b34f933ec58ba8eeeaf271bca1efec
4
- data.tar.gz: f0f606b68eeac175d84c6b9befdef25a3e1ca61bac1b2de078cff9c0e36073b0
3
+ metadata.gz: c46c810a11cabe3d24070a87094b797ad7b7412784d758722fe6e6f19bf10058
4
+ data.tar.gz: ce287cf3d49d328b5f9c80258c71037737a53088c7069f3a4221f26b0ad1fef9
5
5
  SHA512:
6
- metadata.gz: f21951df16944c44a9ff009307860bbb4c815ff5b5ebabac61853c22c4d85b3f61db463754c0775f63fc301b2f7cb425bd46c9f32e9e6f653a86d2f92faa02fc
7
- data.tar.gz: d51d26bd9fbcfcd28dfb2a660c965bca1d9b697936d53ebba87a4c79014bf0bb7b0fb5447e8a33aecf258eca0c8344cee5545e0798b0a500c3bd3ec1cd35e359
6
+ metadata.gz: 55c493e05404597dedfe870c8490458624cc5b9fa7dcaf339a5b171985dcd4a2fe2e941c15b546381d1a5d6a0d7b46722a66b62dffc10d55fe6c547c5167ab1a
7
+ data.tar.gz: 49663577f15d4a8547a80aaed57d554656255056e76bf085b01357ee94327109e7ef4c543981cce59b1ba16587373d3a5809bce26e85e7f365c0d75c06d82de9
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  GPS_PVT is a Ruby GPS (Global positioning system) PVT (position, velocity and time) solver. It accepts RINEX NAV and OBS files in addition to u-blox ubx format. Its significant features are easy to use with highly flexibility to customize internal solver behavior such as weight for each available satellite.
4
4
 
5
- The PVT solution is obtained with a stand alone positioning (i.e. neither differential nor kinematic) with least square. Its main internal codes are derived from ones of [ninja-scan-light](https://github.com/fenrir-naru/ninja-scan-light) having capability to calculate tightly-coupled GNSS/INS integrated solution. These codes are written by C++, and wrapped by [SWIG](http://www.swig.org/).
5
+ The PVT solution is obtained with a stand alone positioning (i.e. neither differential nor kinematic) with application of least square to each snapshot. Its main internal codes are derived from ones of [ninja-scan-light](https://github.com/fenrir-naru/ninja-scan-light) having capability to calculate tightly-coupled GNSS/INS integrated solution. These codes are written by C++, and wrapped by [SWIG](http://www.swig.org/).
6
6
 
7
7
  [![Gem Version](https://badge.fury.io/rb/gps_pvt.svg)](https://badge.fury.io/rb/gps_pvt)
8
8
  [![Ruby](https://github.com/fenrir-naru/gps_pvt/actions/workflows/main.yml/badge.svg)](https://github.com/fenrir-naru/gps_pvt/actions/workflows/main.yml)
@@ -46,7 +46,8 @@ receiver.parse_rinex_obs(rinex_obs_file)
46
46
 
47
47
  # Or precise control of outputs
48
48
  receiver.parse_rinex_obs(rinex_obs_file){|pvt, meas| # per epoch
49
- meas # => measurement, array of [prn, key, value]; key is represented by GPS_PVT::GPS::Measurement::L1_PSEUDORANGE
49
+ meas.to_a # => measurement, array of [prn, key, value]; key is represented by GPS_PVT::GPS::Measurement::L1_PSEUDORANGE; instead of .to_a, .to_hash returns {prn => {key => value, ...}, ...}
50
+
50
51
  pvt # => PVT solution, all properties are shown by pvt.methods
51
52
  # for example
52
53
  if(pvt.position_solved?){
@@ -59,6 +60,9 @@ receiver.parse_rinex_obs(rinex_obs_file){|pvt, meas| # per epoch
59
60
  pvt.receiver_error_rate # clock error rate in m/s
60
61
  }
61
62
  pvt.used_satellite_list # array of used, i.e., visible and weight>0, satellite
63
+ pvt.azimuth # azimuth angle [rad] to used satellites in Hash {prn => value, ...}
64
+ pvt.elevation # elevation angle [rad]
65
+
62
66
  pvt.G # design matrix in Earth-centered-Earth-fixed (ECEF); .to_a returns double array converted from matrix. its row corresponds to one of used_satellite_list
63
67
  pvt.G_enu # design matrix in East-North-Up (ENU)
64
68
  pvt.W # weight for each satellite
@@ -73,11 +77,28 @@ receiver.solver.options.include(prn) # Discard previous setting of exclusion
73
77
  receiver.solver.hooks[:relative_property] = proc{|prn, rel_prop, rcv_e, t_arv, usr_pos, usr_vel|
74
78
  # control weight per satellite per iteration
75
79
  weight, range_c, range_r, rate_rel_neg, *los_neg = rel_prop # relative property
76
- weight = 1 # default; same weight
80
+ # rcv_e, t_arv, usr_pos, usr_vel are temporary solution of
81
+ # receiver clock error [m], time of arrival [s], user position and velocity in ECEF, respectively.
82
+
83
+ weight = 1 # same as default; identical weight for each visible satellite
77
84
  # or weight based on elevation
78
85
  # elv = GPS_PVT::Coordinate::ENU::relative_rel(GPS_PVT::Coordinate::XYZ::new(*los_neg), usr_pos).elevation
79
86
  # weight = (Math::sin(elv)/0.8)**2
80
- [weight, range_c, range_r, rate_rel_neg] + los_neg
87
+
88
+ [weight, range_c, range_r, rate_rel_neg] + los_neg # must return relative property
89
+ }
90
+
91
+ # Dynamic customization of weight for each epoch
92
+ (class << receiver; self; end).instance_eval{ # do before parse_XXX
93
+ alias_method(:run_orig, :run)
94
+ define_method(:run){|meas, t_meas, &b|
95
+ meas # observation, same as the 2nd argument of parse_XXX
96
+ receiver.solver.hooks[:relative_property] = proc{|prn, rel_prop, rcv_e, t_arv, usr_pos, usr_vel|
97
+ # Do something based on meas, t_meas.
98
+ rel_prop
99
+ }
100
+ run_orig(meas, t_meas, &b)
101
+ }
81
102
  }
82
103
  ```
83
104
 
@@ -138,15 +138,15 @@ class Receiver
138
138
  end
139
139
 
140
140
  def run(meas, t_meas)
141
- #$stderr.puts "Measurement time: #{t_meas.to_a} (a.k.a #{"%d/%d/%d %d:%d:%d UTC"%[*t_meas.c_tm]})"
142
- sn = @solver.gps_space_node
143
- sn.update_all_ephemeris(t_meas)
144
-
141
+ =begin
142
+ $stderr.puts "Measurement time: #{t_meas.to_a} (a.k.a #{"%d/%d/%d %d:%d:%d UTC"%[*t_meas.c_tm]})"
145
143
  meas.to_a.collect{|prn, k, v| prn}.uniq.each{|prn|
146
- eph = sn.ephemeris(prn)
144
+ eph = @solver.gps_space_node.ephemeris(prn)
147
145
  $stderr.puts "XYZ(PRN:#{prn}): #{eph.constellation(t_meas)[0].to_a} (iodc: #{eph.iodc}, iode: #{eph.iode})"
148
- } if false
146
+ }
147
+ =end
149
148
 
149
+ #@solver.gps_space_node.update_all_ephemeris(t_meas) # internally called in the following solver.solve
150
150
  pvt = @solver.solve(meas, t_meas)
151
151
  pvt.define_singleton_method(:to_s){
152
152
  (OUTPUT_PVT_ITEMS.transpose[1].collect{|task|
@@ -242,9 +242,15 @@ class Receiver
242
242
  {
243
243
  :L1_PSEUDORANGE => [16, 8, "E"],
244
244
  :L1_DOPPLER => [24, 4, "e"],
245
+ :L1_CARRIER_PHASE => [8, 8, "E"],
246
+ :L1_SIGNAL_STRENGTH_dBHz => [30, 1, "c"],
245
247
  }.each{|k, prop|
246
248
  meas.add(prn, GPS::Measurement.const_get(k), loader.call(*prop))
247
249
  }
250
+ # bit 0 of RINEX LLI (loss of lock indicator) shows lost lock
251
+ # between previous and current observation, which maps negative lock seconds
252
+ meas.add(prn, GPS::Measurement::L1_LOCK_SEC,
253
+ (packet[6 + 31 + (i * 24)] & 0x01 == 0x01) ? -1 : 0)
248
254
  }
249
255
  after_run.call(run(meas, t_meas), [meas, t_meas])
250
256
  when [0x02, 0x15] # RXM-RAWX
@@ -270,6 +276,12 @@ class Receiver
270
276
  }],
271
277
  :L1_DOPPLER => [32, 4, "e"],
272
278
  :L1_DOPPLER_SIGMA => [45, 1, nil, proc{|v| 2E-3 * (v[0] & 0xF)}],
279
+ :L1_CARRIER_PHASE => [24, 8, "E", proc{|v| (trk_stat & 0x2 == 0x2) ? v : nil}],
280
+ :L1_CARRIER_PHASE_SIGMA => [44, 1, nil, proc{|v|
281
+ (trk_stat & 0x2 == 0x2) ? (0.004 * (v[0] & 0xF)) : nil
282
+ }],
283
+ :L1_SIGNAL_STRENGTH_dBHz => [42, 1],
284
+ :L1_LOCK_SEC => [40, 2, "v", proc{|v| 1E-3 * v}],
273
285
  }.each{|k, prop|
274
286
  next unless v = loader.call(*prop)
275
287
  meas.add(svid, GPS::Measurement.const_get(k), v)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GPS_PVT
4
- VERSION = "0.1.3"
4
+ VERSION = "0.1.4"
5
5
  end
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.1.3
4
+ version: 0.1.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: 2021-12-21 00:00:00.000000000 Z
11
+ date: 2021-12-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake