gps_pvt 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
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