gps_pvt 0.6.1 → 0.6.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -114,19 +114,17 @@ class SBAS_SinglePositioning : public SolverBaseT {
114
114
  static inline const typename space_node_t::Satellite &sat(const void *ptr) {
115
115
  return *reinterpret_cast<const typename space_node_t::Satellite *>(ptr);
116
116
  }
117
- static xyz_t position(const void *ptr, const gps_time_t &t, const float_t &pseudo_range) {
118
- return sat(ptr).ephemeris().constellation(t, pseudo_range, false).position;
117
+ static xyz_t position(const void *ptr, const gps_time_t &t_tx, const float_t &dt_transit) {
118
+ return sat(ptr).ephemeris().constellation(t_tx, dt_transit, false).position;
119
119
  }
120
- static xyz_t velocity(const void *ptr, const gps_time_t &t, const float_t &pseudo_range) {
121
- return sat(ptr).ephemeris().constellation(t, pseudo_range, true).velocity;
120
+ static xyz_t velocity(const void *ptr, const gps_time_t &t_tx, const float_t &dt_transit) {
121
+ return sat(ptr).ephemeris().constellation(t_tx, dt_transit, true).velocity;
122
122
  }
123
- static float_t clock_error(const void *ptr, const gps_time_t &t, const float_t &pseudo_range) {
124
- // Clock correction is taken into account in position()
125
- return 0;
123
+ static float_t clock_error(const void *ptr, const gps_time_t &t_tx) {
124
+ return sat(ptr).ephemeris().clock_error(t_tx);
126
125
  }
127
- static float_t clock_error_dot(const void *ptr, const gps_time_t &t, const float_t &pseudo_range) {
128
- // Clock rate error is taken in account in velocity()
129
- return 0;
126
+ static float_t clock_error_dot(const void *ptr, const gps_time_t &t_tx) {
127
+ return sat(ptr).ephemeris().clock_error_dot(t_tx);
130
128
  }
131
129
  };
132
130
  satellite_t res = {
@@ -257,20 +255,25 @@ class SBAS_SinglePositioning : public SolverBaseT {
257
255
 
258
256
  range -= receiver_error;
259
257
 
258
+ static const float_t &c(GPS_SpaceNode<float_t>::light_speed);
259
+
260
260
  // Clock error correction
261
261
  range += ((range_error.unknown_flag & range_error_t::SATELLITE_CLOCK)
262
- ? (sat.clock_error(time_arrival, range) * GPS_SpaceNode<float_t>::light_speed)
262
+ ? (sat.clock_error(time_arrival - range / c) * c)
263
263
  : range_error.value[range_error_t::SATELLITE_CLOCK]);
264
264
 
265
265
  // TODO WAAS long term clock correction (2.1.1.4.11)
266
266
 
267
267
  // Calculate satellite position
268
- xyz_t sat_pos(sat.position(time_arrival, range));
268
+ float_t dt_transit(range / c);
269
+ gps_time_t t_tx(time_arrival - dt_transit);
270
+ xyz_t sat_pos(sat.position(t_tx, dt_transit));
269
271
  float_t geometric_range(usr_pos.xyz.dist(sat_pos));
270
272
 
271
- // Calculate residual with Sagnac correction (A.4.4.11)
273
+ // Calculate residual without Sagnac correction (A.4.4.11),
274
+ // because of the satellite position is calculated in the reception time ECEF.
272
275
  res.range_residual = range
273
- + space_node_t::sagnac_correction(sat_pos, usr_pos.xyz)
276
+ // + space_node_t::sagnac_correction(sat_pos, usr_pos.xyz)
274
277
  - geometric_range;
275
278
 
276
279
  // Setup design matrix
@@ -312,12 +315,12 @@ class SBAS_SinglePositioning : public SolverBaseT {
312
315
 
313
316
  res.range_corrected = range;
314
317
 
315
- xyz_t rel_vel(sat.velocity(time_arrival, range) - usr_vel); // Calculate velocity
318
+ xyz_t rel_vel(sat.velocity(t_tx, dt_transit) - usr_vel); // Calculate velocity
316
319
 
317
320
  res.rate_relative_neg = res.los_neg[0] * rel_vel.x()
318
321
  + res.los_neg[1] * rel_vel.y()
319
322
  + res.los_neg[2] * rel_vel.z()
320
- + sat.clock_error_dot(time_arrival, range) * GPS_SpaceNode<float_t>::light_speed;
323
+ + sat.clock_error_dot(t_tx) * c;
321
324
 
322
325
  return res;
323
326
  }
@@ -41,7 +41,6 @@
41
41
  #include <cstring>
42
42
  #include <map>
43
43
  #include <set>
44
- #include <algorithm>
45
44
  #include <stdexcept>
46
45
 
47
46
  #include "util/text_helper.h"
@@ -61,22 +60,15 @@ struct SP3_Product {
61
60
  typedef std::map<GPS_Time<FloatT>, prop_t> history_t;
62
61
  history_t pos_history;
63
62
  history_t vel_history;
64
-
65
- static const struct interpolate_cnd_t {
66
- std::size_t max_epochs; ///< maximum number of epochs used for interpolation
67
- FloatT max_delta_t; ///< maximum acceptable absolute time difference between t and epoch
68
- } interpolate_cnd_default;
63
+
64
+ typedef InterpolatableSet<GPS_Time<FloatT>, prop_t, FloatT> interpolator_t;
65
+ typedef typename interpolator_t::condition_t interpolate_cnd_t;
66
+ static const interpolate_cnd_t interpolate_cnd_default;
69
67
 
70
68
  mutable struct {
71
- struct target_t {
72
-
73
- typedef typename std::vector<std::pair<GPS_Time<FloatT>, prop_t> > buf_t;
74
- buf_t buf;
75
- GPS_Time<FloatT> t0;
76
- std::vector<FloatT> dt;
77
- bool updated_full_cnd;
69
+ struct target_t : public interpolator_t {
78
70
 
79
- target_t() : t0(0, 0), updated_full_cnd(false) {}
71
+ target_t() : interpolator_t() {}
80
72
 
81
73
  /**
82
74
  * update interpolation source
@@ -88,58 +80,13 @@ struct SP3_Product {
88
80
  const bool &force_update = false,
89
81
  const interpolate_cnd_t &cnd = interpolate_cnd_default){
90
82
 
91
- FloatT t_diff(t0 - t);
92
- if((!force_update)
93
- && ((std::abs(t_diff) <= 10)
94
- || ((dt.size() >= 2)
95
- && (std::abs(t_diff + dt[0]) <= std::abs(t_diff + dt[1])))) ){
96
- return *this;
97
- }
98
-
99
- // If the 1st and 2nd nearest epochs are changed, then recalculate interpolation targets.
100
- struct {
101
- const GPS_Time<FloatT> &t_base;
102
- bool operator()(
103
- const typename history_t::value_type &rhs,
104
- const typename history_t::value_type &lhs) const {
105
- return std::abs(rhs.first - t_base) < std::abs(lhs.first - t_base);
106
- }
107
- } cmp = {(t0 = t)};
108
-
109
- buf.resize(cnd.max_epochs);
110
- dt.clear();
111
- // extract t where t0-dt <= t <= t0+dt, then sort by ascending order of |t-t0|
112
- for(typename buf_t::const_iterator
113
- it(buf.begin()),
114
- it_end(std::partial_sort_copy(
115
- history.lower_bound(t - cnd.max_delta_t),
116
- history.upper_bound(t + cnd.max_delta_t),
117
- buf.begin(), buf.end(), cmp));
118
- it != it_end; ++it){
119
- dt.push_back(it->first - t0);
120
- }
121
- updated_full_cnd = (dt.size() >= cnd.max_epochs);
122
-
83
+ if((!force_update) && (std::abs(t - interpolator_t::x0) <= 10)){return *this;}
84
+ interpolator_t::update(t, history, cnd, force_update);
123
85
  return *this;
124
86
  }
125
87
 
126
- template <class Ty, class Ty_Array>
127
- Ty interpolate(
128
- const GPS_Time<FloatT> &t, const Ty_Array &y,
129
- Ty *derivative = NULL) const {
130
- int order(dt.size() - 1);
131
- do{
132
- if(order > 0){break;}
133
- if((order == 0) && (!derivative)){return y[0];}
134
- throw std::range_error("Insufficient records for interpolation");
135
- }while(false);
136
- std::vector<Ty> y_buf(order), dy_buf(order);
137
- interpolate_Neville(
138
- dt, y, t - t0, y_buf, order,
139
- &dy_buf, derivative ? 1 : 0);
140
- if(derivative){*derivative = dy_buf[0];}
141
- return y_buf[0];
142
- }
88
+ typedef typename interpolator_t::buffer_t buf_t;
89
+
143
90
  Vector3<FloatT> interpolate_xyz(
144
91
  const GPS_Time<FloatT> &t,
145
92
  Vector3<FloatT> *derivative = NULL) const {
@@ -149,8 +96,8 @@ struct SP3_Product {
149
96
  const Vector3<FloatT> &operator[](const int &n) const {
150
97
  return buf_t::const_iterator::operator[](n).second.xyz;
151
98
  }
152
- } xyz(buf.begin());
153
- return interpolate(t, xyz, derivative);
99
+ } xyz(interpolator_t::buf.begin());
100
+ return interpolator_t::interpolate2(t, xyz, derivative);
154
101
  }
155
102
  FloatT interpolate_clk(
156
103
  const GPS_Time<FloatT> &t,
@@ -161,8 +108,8 @@ struct SP3_Product {
161
108
  const FloatT &operator[](const int &n) const {
162
109
  return buf_t::const_iterator::operator[](n).second.clk;
163
110
  }
164
- } clk(buf.begin());
165
- return interpolate(t, clk, derivative);
111
+ } clk(interpolator_t::buf.begin());
112
+ return interpolator_t::interpolate2(t, clk, derivative);
166
113
  }
167
114
  } pos_clk, vel_rate;
168
115
  } subset;
@@ -175,7 +122,7 @@ struct SP3_Product {
175
122
  bool precheck(const GPS_Time<FloatT> &t) const {
176
123
  // Only position/clock is checked, because velocity/rate can be calculated based on pos/clk.
177
124
  subset.pos_clk.update(t, pos_history);
178
- return subset.pos_clk.updated_full_cnd;
125
+ return subset.pos_clk.ready;
179
126
  }
180
127
 
181
128
  typename GPS_SpaceNode<FloatT>::SatelliteProperties::constellation_t
@@ -224,22 +171,17 @@ struct SP3_Product {
224
171
  static inline const per_satellite_t &sat(const void *ptr) {
225
172
  return *reinterpret_cast<const per_satellite_t *>(ptr);
226
173
  }
227
- static inline float_t pr2sec(const float_t &pr){
228
- return pr / GPS_SpaceNode<FloatT>::light_speed;
229
- }
230
- static xyz_t position(const void *ptr, const gt_t &t, const float_t &pr) {
231
- float_t delta_t(pr2sec(pr));
232
- return sat(ptr).position(t - delta_t).after(delta_t);
174
+ static xyz_t position(const void *ptr, const gt_t &t_tx, const float_t &dt_transit) {
175
+ return sat(ptr).position(t_tx).after(dt_transit);
233
176
  }
234
- static xyz_t velocity(const void *ptr, const gt_t &t, const float_t &pr) {
235
- float_t delta_t(pr2sec(pr));
236
- return sat(ptr).velocity(t - delta_t).after(delta_t);
177
+ static xyz_t velocity(const void *ptr, const gt_t &t_tx, const float_t &dt_transit) {
178
+ return sat(ptr).velocity(t_tx).after(dt_transit);
237
179
  }
238
- static float_t clock_error(const void *ptr, const gt_t &t, const float_t &pr) {
239
- return sat(ptr).clock_error(t - pr2sec(pr));
180
+ static float_t clock_error(const void *ptr, const gt_t &t_tx) {
181
+ return sat(ptr).clock_error(t_tx);
240
182
  }
241
- static float_t clock_error_dot(const void *ptr, const gt_t &t, const float_t &pr) {
242
- return sat(ptr).clock_error_dot(t - pr2sec(pr));
183
+ static float_t clock_error_dot(const void *ptr, const gt_t &t_tx) {
184
+ return sat(ptr).clock_error_dot(t_tx);
243
185
  }
244
186
  };
245
187
  typename GPS_Solver_Base<FloatT>::satellite_t res = {
@@ -386,8 +328,11 @@ static typename GPS_Solver_Base<FloatT>::satellite_t select_ ## sys( \
386
328
  template <class FloatT>
387
329
  const typename SP3_Product<FloatT>::per_satellite_t::interpolate_cnd_t
388
330
  SP3_Product<FloatT>::per_satellite_t::interpolate_cnd_default = {
389
- 9, // max_epochs
390
- 60 * 60 * 2, // max_delta_t, default is 2 hr = 15 min interval records; (2 hr * 2 / (9 - 1) = 15 min)
331
+ 9, // maximum number of epochs used for interpolation
332
+ /* maximum acceptable absolute time difference between t and epoch,
333
+ * default is 2 hr = 15 min interval records; (2 hr * 2 / (9 - 1) = 15 min)
334
+ */
335
+ 60 * 60 * 2,
391
336
  };
392
337
 
393
338
  template <class FloatT>
@@ -302,6 +302,10 @@ struct GPS_Ephemeris : public GPS_SpaceNode<FloatT>::SatelliteProperties::Epheme
302
302
  GPS_Ephemeris(const typename GPS_SpaceNode<FloatT>::SatelliteProperties::Ephemeris &eph)
303
303
  : GPS_SpaceNode<FloatT>::SatelliteProperties::Ephemeris(eph),
304
304
  iode_subframe3(eph.iode) {}
305
+ struct constellation_res_t {
306
+ System_XYZ<FloatT, WGS84> position, velocity;
307
+ FloatT clock_error, clock_error_dot;
308
+ };
305
309
  };
306
310
  %}
307
311
  %extend GPS_Ephemeris {
@@ -389,20 +393,21 @@ struct GPS_Ephemeris : public GPS_SpaceNode<FloatT>::SatelliteProperties::Epheme
389
393
  break;
390
394
  }
391
395
  }
392
- %typemap(in,numinputs=0) System_XYZ<FloatT, WGS84> & (System_XYZ<FloatT, WGS84> temp) %{
393
- $1 = &temp;
394
- %}
395
- %typemap(argout) System_XYZ<FloatT, WGS84> & {
396
- %append_output(SWIG_NewPointerObj((new $*1_ltype(*$1)), $1_descriptor, SWIG_POINTER_OWN));
397
- }
398
- void constellation(
399
- System_XYZ<FloatT, WGS84> &position, System_XYZ<FloatT, WGS84> &velocity,
400
- const GPS_Time<FloatT> &t, const FloatT &pseudo_range = 0,
401
- const bool &with_velocity = true) const {
402
- typename GPS_SpaceNode<FloatT>::SatelliteProperties::constellation_t res(
403
- self->constellation(t, pseudo_range, with_velocity));
404
- position = res.position;
405
- velocity = res.velocity;
396
+ %typemap(out) constellation_res_t {
397
+ %append_output(SWIG_NewPointerObj((new System_XYZ<FloatT, WGS84>($1.position)),
398
+ $descriptor(System_XYZ<FloatT, WGS84> *), SWIG_POINTER_OWN));
399
+ %append_output(SWIG_NewPointerObj((new System_XYZ<FloatT, WGS84>($1.velocity)),
400
+ $descriptor(System_XYZ<FloatT, WGS84> *), SWIG_POINTER_OWN));
401
+ %append_output(swig::from($1.clock_error));
402
+ %append_output(swig::from($1.clock_error_dot));
403
+ }
404
+ typename GPS_Ephemeris<FloatT>::constellation_res_t constellation(
405
+ const GPS_Time<FloatT> &t_tx, const FloatT &dt_transit = 0) const {
406
+ typename GPS_SpaceNode<FloatT>::SatelliteProperties::constellation_t pv(
407
+ self->constellation(t_tx, dt_transit, true));
408
+ typename GPS_Ephemeris<FloatT>::constellation_res_t res = {
409
+ pv.position, pv.velocity, self->clock_error(t_tx), self->clock_error_dot(t_tx)};
410
+ return res;
406
411
  }
407
412
  #if defined(SWIGRUBY)
408
413
  %rename("consistent?") is_consistent;
@@ -461,15 +466,14 @@ struct SBAS_Ephemeris : public SBAS_SpaceNode<FloatT>::SatelliteProperties::Ephe
461
466
  MAKE_ACCESSOR(ddx, FloatT); MAKE_ACCESSOR(ddy, FloatT); MAKE_ACCESSOR(ddz, FloatT);
462
467
  MAKE_ACCESSOR(a_Gf0, FloatT);
463
468
  MAKE_ACCESSOR(a_Gf1, FloatT);
464
- %apply GPS_Ephemeris::System_XYZ<FloatT, WGS84> & { System_XYZ<FloatT, WGS84> & }; // TODO ineffective?
465
- void constellation(
466
- System_XYZ<FloatT, WGS84> &position, System_XYZ<FloatT, WGS84> &velocity,
467
- const GPS_Time<FloatT> &t, const FloatT &pseudo_range = 0,
469
+ typename GPS_Ephemeris<FloatT>::constellation_res_t constellation(
470
+ const GPS_Time<FloatT> &t_tx, const FloatT &dt_transit = 0,
468
471
  const bool &with_velocity = true) const {
469
- typename SBAS_SpaceNode<FloatT>::SatelliteProperties::constellation_t res(
470
- self->constellation(t, pseudo_range, with_velocity));
471
- position = res.position;
472
- velocity = res.velocity;
472
+ typename SBAS_SpaceNode<FloatT>::SatelliteProperties::constellation_t pv(
473
+ self->constellation(t_tx, dt_transit, with_velocity));
474
+ typename GPS_Ephemeris<FloatT>::constellation_res_t res = {
475
+ pv.position, pv.velocity, self->clock_error(t_tx), self->clock_error_dot(t_tx)};
476
+ return res;
473
477
  }
474
478
  }
475
479
 
@@ -612,23 +616,13 @@ struct GLONASS_Ephemeris
612
616
  self->has_string = has_string;
613
617
  return updated;
614
618
  }
615
- FloatT clock_error(
616
- const GPS_Time<FloatT> &t_arrival, const FloatT &pseudo_range = 0) const {
617
- return self->clock_error(t_arrival, pseudo_range);
618
- }
619
- %typemap(in,numinputs=0) System_XYZ<FloatT, WGS84> & (System_XYZ<FloatT, WGS84> temp) %{
620
- $1 = &temp;
621
- %}
622
- %typemap(argout) System_XYZ<FloatT, WGS84> & {
623
- %append_output(SWIG_NewPointerObj((new $*1_ltype(*$1)), $1_descriptor, SWIG_POINTER_OWN));
624
- }
625
- void constellation(
626
- System_XYZ<FloatT, WGS84> &position, System_XYZ<FloatT, WGS84> &velocity,
627
- const GPS_Time<FloatT> &t, const FloatT &pseudo_range = 0) const {
628
- typename GPS_SpaceNode<FloatT>::SatelliteProperties::constellation_t res(
629
- self->constellation(t, pseudo_range));
630
- position = res.position;
631
- velocity = res.velocity;
619
+ typename GPS_Ephemeris<FloatT>::constellation_res_t constellation(
620
+ const GPS_Time<FloatT> &t_tx, const FloatT &dt_transit = 0) const {
621
+ typename GPS_SpaceNode<FloatT>::SatelliteProperties::constellation_t pv(
622
+ self->constellation(t_tx, dt_transit));
623
+ typename GPS_Ephemeris<FloatT>::constellation_res_t res = {
624
+ pv.position, pv.velocity, self->clock_error(t_tx), self->clock_error_dot()};
625
+ return res;
632
626
  }
633
627
  #if defined(SWIGRUBY)
634
628
  %rename("consistent?") is_consistent;
data/gps_pvt.gemspec CHANGED
@@ -53,6 +53,9 @@ Gem::Specification.new do |spec|
53
53
  }.flatten
54
54
  }.call
55
55
 
56
+ spec.rdoc_options << '--exclude=ext/ninja-scan-light'
57
+ spec.extra_rdoc_files = []
58
+
56
59
  # Uncomment to register a new dependency of your gem
57
60
  # spec.add_dependency "example-gem", "~> 1.0"
58
61
  spec.add_development_dependency "rake"
@@ -410,7 +410,7 @@ class Receiver
410
410
  @solver.sbas_space_node.ionospheric_grid_points(prn)].each{|str|
411
411
  $stderr.puts str
412
412
  } if @debug[:SBAS_IGP]
413
- end
413
+ end if t_meas
414
414
  when :GLONASS
415
415
  next unless eph = eph_glonass_list[prn]
416
416
  leap_sec = @solver.gps_space_node.is_valid_utc ?
@@ -508,10 +508,10 @@ class Receiver
508
508
  {
509
509
  :L1_PSEUDORANGE => [16, 8, "E", proc{|v| (trk_stat & 0x1 == 0x1) ? v : nil}],
510
510
  :L1_PSEUDORANGE_SIGMA => [43, 1, nil, proc{|v|
511
- (trk_stat & 0x1 == 0x1) ? (1E-2 * (v[0] & 0xF)) : nil
511
+ (trk_stat & 0x1 == 0x1) ? (1E-2 * (1 << (v[0] & 0xF))) : nil
512
512
  }],
513
513
  :L1_DOPPLER => [32, 4, "e"],
514
- :L1_DOPPLER_SIGMA => [45, 1, nil, proc{|v| 2E-3 * (v[0] & 0xF)}],
514
+ :L1_DOPPLER_SIGMA => [45, 1, nil, proc{|v| 2E-3 * (1 << (v[0] & 0xF))}],
515
515
  :L1_CARRIER_PHASE => [24, 8, "E", proc{|v| (trk_stat & 0x2 == 0x2) ? v : nil}],
516
516
  :L1_CARRIER_PHASE_SIGMA => [44, 1, nil, proc{|v|
517
517
  (trk_stat & 0x2 == 0x2) ? (0.004 * (v[0] & 0xF)) : nil
@@ -1,5 +1,5 @@
1
- # frozen_string_literal: true
2
-
3
- module GPS_PVT
4
- VERSION = "0.6.1"
5
- end
1
+ # frozen_string_literal: true
2
+
3
+ module GPS_PVT
4
+ VERSION = "0.6.4"
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.6.1
4
+ version: 0.6.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: 2022-07-21 00:00:00.000000000 Z
11
+ date: 2022-08-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -44,6 +44,7 @@ email:
44
44
  - fenrir.naru@gmail.com
45
45
  executables:
46
46
  - gps_pvt
47
+ - to_ubx
47
48
  extensions:
48
49
  - ext/gps_pvt/extconf.rb
49
50
  extra_rdoc_files: []
@@ -57,6 +58,7 @@ files:
57
58
  - bin/console
58
59
  - bin/setup
59
60
  - exe/gps_pvt
61
+ - exe/to_ubx
60
62
  - ext/gps_pvt/Coordinate/Coordinate_wrap.cxx
61
63
  - ext/gps_pvt/GPS/GPS_wrap.cxx
62
64
  - ext/gps_pvt/SylphideMath/SylphideMath_wrap.cxx
@@ -109,7 +111,8 @@ metadata:
109
111
  homepage_uri: https://github.com/fenrir-naru/gps_pvt
110
112
  source_code_uri: https://github.com/fenrir-naru/gps_pvt
111
113
  post_install_message:
112
- rdoc_options: []
114
+ rdoc_options:
115
+ - "--exclude=ext/ninja-scan-light"
113
116
  require_paths:
114
117
  - lib
115
118
  required_ruby_version: !ruby/object:Gem::Requirement