gps_pvt 0.5.0 → 0.5.1

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: 83dff6013480dd4df4faacde170a901d712a605093fa006d0d4542c58f43ac45
4
- data.tar.gz: 33728f6f9c4969f04ed528831e14977f3f90846b0f740ce0644f06de18ac7322
3
+ metadata.gz: 6b4f5df780c4ff0977b025fab381c327b04a3e8fae742cc6ff672e08839d9c51
4
+ data.tar.gz: cbbb233acbe548944d9b317449160465ec04d2041e56f54decc286a900503723
5
5
  SHA512:
6
- metadata.gz: fd13f81c590a85ffeed54fe62dfb45858373cf687b08e5dc37bf45805f54398c50ad71f03e512a28015d214239e189c0581317d703cb4af99f4f9d258d162d12
7
- data.tar.gz: 64df6a70a7b02f94e6f94c878ada85bc293871e5478698a5fdc285f77418fd2d27ecf9aece5b42ca197d6a3dc79ab9294f81b06411b83ca008f3428011245b83
6
+ metadata.gz: a724b51f5fe55fe9c0d74d02176c26dbad63bcc1fc1fbd477c7a0707e06f832df5110f4a80c5c2807ac5e1ae2d0717846858a30365eec874847c96fb11e12b5e
7
+ data.tar.gz: 97b3670fd401bc860d9f16ab473fe4c6c33ee87fcf6855757490ec724d8405a6aeb7df22aabaf7e37f559d80ce9b4ce1c764c550acccf591bb940805b3c660a6
@@ -2671,10 +2671,9 @@ struct GPS_Solver
2671
2671
  const typename base_t::gps_time_t &time_arrival,
2672
2672
  const typename base_t::pos_t &usr_pos,
2673
2673
  const typename base_t::xyz_t &usr_vel) const;
2674
- virtual typename base_t::xyz_t *satellite_position(
2674
+ virtual typename base_t::satellite_t select_satellite(
2675
2675
  const typename base_t::prn_t &prn,
2676
- const typename base_t::gps_time_t &time,
2677
- typename base_t::xyz_t &res) const;
2676
+ const typename base_t::gps_time_t &time) const;
2678
2677
  virtual bool update_position_solution(
2679
2678
  const typename base_t::geometric_matrices_t &geomat,
2680
2679
  typename base_t::user_pvt_t &res) const;
@@ -3867,47 +3866,17 @@ SWIGINTERN double const &GPS_SolverOptions_Common_Sl_double_Sg__get_residual_mas
3867
3866
  return super_t::update_position_solution(geomat, res);
3868
3867
  }
3869
3868
  template <>
3870
- GPS_Solver<double>::base_t::xyz_t *GPS_Solver<double>::satellite_position(
3869
+ GPS_Solver<double>::base_t::satellite_t GPS_Solver<double>::select_satellite(
3871
3870
  const GPS_Solver<double>::base_t::prn_t &prn,
3872
- const GPS_Solver<double>::base_t::gps_time_t &time,
3873
- GPS_Solver<double>::base_t::xyz_t &buf) const {
3874
- GPS_Solver<double>::base_t::xyz_t *res(
3875
- select_solver(prn).satellite_position(prn, time, buf));
3871
+ const GPS_Solver<double>::base_t::gps_time_t &time) const {
3872
+ GPS_Solver<double>::base_t::satellite_t res(
3873
+ select_solver(prn).select_satellite(prn, time));
3876
3874
 
3877
- do{
3878
- static const VALUE key(ID2SYM(rb_intern("satellite_position")));
3875
+ if(!res.is_available()){
3876
+ static const VALUE key(ID2SYM(rb_intern("relative_property")));
3879
3877
  VALUE hook(rb_hash_lookup(hooks, key));
3880
- if(NIL_P(hook)){break;}
3881
- VALUE values[] = {
3882
- SWIG_From_int (prn), // prn
3883
- SWIG_NewPointerObj( // time
3884
- new base_t::gps_time_t(time), SWIGTYPE_p_GPS_TimeT_double_t, SWIG_POINTER_OWN),
3885
- (res // position (internally calculated)
3886
- ? SWIG_NewPointerObj(res, SWIGTYPE_p_System_XYZT_double_WGS84_t, 0)
3887
- : Qnil)};
3888
- VALUE res_hook(proc_call_throw_if_error(hook, sizeof(values) / sizeof(values[0]), values));
3889
- if(NIL_P(res_hook)){ // unknown position
3890
- res = NULL;
3891
- break;
3892
- }else if(RB_TYPE_P(res_hook, T_ARRAY) && (RARRAY_LEN(res_hook) == 3)){
3893
- int i(0);
3894
- for(; i < 3; ++i){
3895
- VALUE v(RARRAY_AREF(res_hook, i));
3896
- if(!SWIG_IsOK(swig::asval(v, &buf[i]))){break;}
3897
- }
3898
- if(i == 3){
3899
- res = &buf;
3900
- break;
3901
- }
3902
- }else if(SWIG_IsOK(SWIG_ConvertPtr(
3903
- res_hook, (void **)&res, SWIGTYPE_p_System_XYZT_double_WGS84_t, 0))){
3904
- res = &(buf = *res);
3905
- break;
3906
- }
3907
- throw std::runtime_error(
3908
- std::string("System_XYZ or [d * 3] is expected (d: " "double" "), however ")
3909
- .append(inspect_str(res_hook)));
3910
- }while(false);
3878
+ if(!NIL_P(hook)){res.impl = this;}
3879
+ }
3911
3880
 
3912
3881
  return res;
3913
3882
  }
@@ -75,7 +75,6 @@ class GLONASS_SinglePositioning : public SolverBaseT {
75
75
 
76
76
  typedef GLONASS_SpaceNode<float_t> space_node_t;
77
77
  inheritate_type(gps_time_t);
78
- typedef typename space_node_t::Satellite satellite_t;
79
78
 
80
79
  inheritate_type(xyz_t);
81
80
  inheritate_type(enu_t);
@@ -83,9 +82,10 @@ class GLONASS_SinglePositioning : public SolverBaseT {
83
82
  inheritate_type(pos_t);
84
83
 
85
84
  typedef typename base_t::measurement_t measurement_t;
86
- inheritate_type(range_error_t);
87
- inheritate_type(range_corrector_t);
88
- inheritate_type(range_correction_t);
85
+ typedef typename base_t::satellite_t satellite_t;
86
+ typedef typename base_t::range_error_t range_error_t;
87
+ typedef typename base_t::range_corrector_t range_corrector_t;
88
+ typedef typename base_t::range_correction_t range_correction_t;
89
89
 
90
90
  inheritate_type(relative_property_t);
91
91
  typedef typename super_t::measurement_items_t measurement_items_t;
@@ -97,11 +97,51 @@ class GLONASS_SinglePositioning : public SolverBaseT {
97
97
  GLONASS_SinglePositioning_Options<float_t>, base_t> options_t;
98
98
 
99
99
  protected:
100
- const space_node_t &_space_node;
101
100
  GLONASS_SinglePositioning_Options<float_t> _options;
102
101
 
103
102
  public:
104
- const space_node_t &space_node() const {return _space_node;}
103
+ struct satellites_t {
104
+ const void *impl;
105
+ satellite_t (*impl_select)(const void *, const prn_t &, const gps_time_t &);
106
+ inline satellite_t select(const prn_t &prn, const gps_time_t &receiver_time) const {
107
+ return impl_select(impl, prn, receiver_time);
108
+ }
109
+ static satellite_t select_broadcast(
110
+ const void *ptr, const prn_t &prn, const gps_time_t &receiver_time){
111
+ const typename space_node_t::satellites_t &sats(
112
+ reinterpret_cast<const space_node_t *>(ptr)->satellites());
113
+ const typename space_node_t::satellites_t::const_iterator it_sat(sats.find(prn));
114
+ if((it_sat == sats.end()) // has ephemeris?
115
+ || (!it_sat->second.ephemeris().is_valid(receiver_time))){ // valid ephemeris?
116
+ return satellite_t::unavailable();
117
+ }
118
+ struct impl_t {
119
+ static inline const typename space_node_t::Satellite &sat(const void *ptr) {
120
+ return *reinterpret_cast<const typename space_node_t::Satellite *>(ptr);
121
+ }
122
+ static xyz_t position(const void *ptr, const gps_time_t &t, const float_t &pseudo_range) {
123
+ return sat(ptr).constellation(t, pseudo_range).position;
124
+ }
125
+ static xyz_t velocity(const void *ptr, const gps_time_t &t, const float_t &pseudo_range) {
126
+ return sat(ptr).constellation(t, pseudo_range).velocity;
127
+ }
128
+ static float_t clock_error(const void *ptr, const gps_time_t &t, const float_t &pseudo_range) {
129
+ return sat(ptr).clock_error(t, pseudo_range);
130
+ }
131
+ static float_t clock_error_dot(const void *ptr, const gps_time_t &t, const float_t &pseudo_range) {
132
+ // Clock rate error is already taken into account in constellation()
133
+ return 0;
134
+ }
135
+ };
136
+ satellite_t res = {
137
+ &(it_sat->second),
138
+ impl_t::position, impl_t::velocity,
139
+ impl_t::clock_error, impl_t::clock_error_dot};
140
+ return res;
141
+ }
142
+ satellites_t(const space_node_t &sn)
143
+ : impl(&sn), impl_select(select_broadcast) {}
144
+ } satellites;
105
145
 
106
146
  range_correction_t ionospheric_correction, tropospheric_correction;
107
147
 
@@ -120,7 +160,8 @@ class GLONASS_SinglePositioning : public SolverBaseT {
120
160
  }
121
161
 
122
162
  GLONASS_SinglePositioning(const space_node_t &sn, const options_t &opt_wish = options_t())
123
- : base_t(), _space_node(sn), _options(available_options(opt_wish)),
163
+ : base_t(), _options(available_options(opt_wish)),
164
+ satellites(sn),
124
165
  ionospheric_correction(), tropospheric_correction() {
125
166
 
126
167
  // default ionospheric correction: no correction
@@ -163,25 +204,18 @@ class GLONASS_SinglePositioning : public SolverBaseT {
163
204
  }
164
205
 
165
206
  /**
166
- * Check availability of a satellite with which observation is associated
207
+ * Select satellite by using PRN and time
167
208
  *
168
209
  * @param prn satellite number
169
210
  * @param receiver_time receiver time
170
- * @return (const satellite_t *) If available, const pointer to satellite is returned,
171
- * otherwise NULL.
211
+ * @return (satellite_t) If available, satellite.is_available() returning true is returned.
172
212
  */
173
- const satellite_t *is_available(
174
- const typename space_node_t::satellites_t::key_type &prn,
213
+ satellite_t select_satellite(
214
+ const prn_t &prn,
175
215
  const gps_time_t &receiver_time) const {
176
-
177
- const typename space_node_t::satellites_t &sats(_space_node.satellites());
178
- const typename space_node_t::satellites_t::const_iterator it_sat(sats.find(prn & 0xFF));
179
- if((it_sat == sats.end()) // has ephemeris?
180
- || (!it_sat->second.ephemeris().is_valid(receiver_time))){ // valid ephemeris?
181
- return NULL;
182
- }
183
-
184
- return &(it_sat->second);
216
+ prn_t prn_(prn & 0xFF);
217
+ if(_options.exclude_prn[prn_]){return satellite_t::unavailable();}
218
+ return satellites.select(prn_, receiver_time);
185
219
  }
186
220
 
187
221
  /**
@@ -205,32 +239,27 @@ class GLONASS_SinglePositioning : public SolverBaseT {
205
239
 
206
240
  relative_property_t res = {0};
207
241
 
208
- if(_options.exclude_prn[prn & 0xFF]){return res;}
209
-
210
242
  float_t range;
211
243
  range_error_t range_error;
212
244
  if(!this->range(measurement, range, &range_error)){
213
245
  return res; // If no range entry, return with weight = 0
214
246
  }
215
247
 
216
- const satellite_t *sat(is_available(prn, time_arrival));
217
- if(!sat){return res;} // If satellite is unavailable, return with weight = 0
248
+ satellite_t sat(select_satellite(prn, time_arrival));
249
+ if(!sat.is_available()){return res;} // If satellite is unavailable, return with weight = 0
218
250
 
219
251
  range -= receiver_error;
220
252
 
221
253
  // Clock correction, which will be considered in the next constellation()
222
254
  // as extra transmission time by using extra psuedo range.
223
255
  if(range_error.unknown_flag & range_error_t::SATELLITE_CLOCK){
224
- range += (sat->clock_error(time_arrival, range) * space_node_t::light_speed);
256
+ range += (sat.clock_error(time_arrival, range) * space_node_t::light_speed);
225
257
  }else{
226
258
  range += range_error.value[range_error_t::SATELLITE_CLOCK];
227
259
  }
228
260
 
229
- // Calculate satellite position and velocity
230
- typename GPS_SpaceNode<float_t>::SatelliteProperties::constellation_t sat_pos_vel(
231
- sat->constellation(time_arrival, range));
232
-
233
- const xyz_t &sat_pos(sat_pos_vel.position);
261
+ // Calculate satellite position
262
+ xyz_t sat_pos(sat.position(time_arrival, range));
234
263
  float_t geometric_range(usr_pos.xyz.dist(sat_pos));
235
264
 
236
265
  // Calculate residual
@@ -278,24 +307,15 @@ class GLONASS_SinglePositioning : public SolverBaseT {
278
307
 
279
308
  res.range_corrected = range;
280
309
 
281
- xyz_t rel_vel(sat_pos_vel.velocity - usr_vel); // Calculate velocity
310
+ xyz_t rel_vel(sat.velocity(time_arrival, range) - usr_vel); // Calculate velocity
282
311
 
283
- // Note: clock rate error is already accounted for in constellation()
284
312
  res.rate_relative_neg = res.los_neg[0] * rel_vel.x()
285
313
  + res.los_neg[1] * rel_vel.y()
286
- + res.los_neg[2] * rel_vel.z();
314
+ + res.los_neg[2] * rel_vel.z()
315
+ + sat.clock_error_dot(time_arrival, range) * space_node_t::light_speed;
287
316
 
288
317
  return res;
289
318
  }
290
-
291
- xyz_t *satellite_position(
292
- const prn_t &prn,
293
- const gps_time_t &time,
294
- xyz_t &res) const {
295
-
296
- const satellite_t *sat(is_available(prn, time));
297
- return sat ? &(res = sat->position(time)) : NULL;
298
- }
299
319
  };
300
320
 
301
321
  template <class FloatT, class SolverBaseT>
@@ -95,7 +95,6 @@ class GPS_SinglePositioning : public SolverBaseT {
95
95
 
96
96
  typedef typename base_t::space_node_t space_node_t;
97
97
  inheritate_type(gps_time_t);
98
- typedef typename space_node_t::Satellite satellite_t;
99
98
 
100
99
  inheritate_type(xyz_t);
101
100
  inheritate_type(llh_t);
@@ -106,6 +105,7 @@ class GPS_SinglePositioning : public SolverBaseT {
106
105
  inheritate_type(prn_obs_t);
107
106
  typedef typename base_t::measurement_t measurement_t;
108
107
  inheritate_type(measurement_items_t);
108
+ typedef typename base_t::satellite_t satellite_t;
109
109
  typedef typename base_t::range_error_t range_error_t;
110
110
  typedef typename base_t::range_corrector_t range_corrector_t;
111
111
  typedef typename base_t::range_correction_t range_correction_t;
@@ -119,11 +119,52 @@ class GPS_SinglePositioning : public SolverBaseT {
119
119
  GPS_SinglePositioning_Options<float_t>, base_t> options_t;
120
120
 
121
121
  protected:
122
- const space_node_t &_space_node;
123
122
  GPS_SinglePositioning_Options<float_t> _options;
124
123
 
125
124
  public:
126
- const space_node_t &space_node() const {return _space_node;}
125
+ struct satellites_t {
126
+ const void *impl;
127
+ satellite_t (*impl_select)(const void *, const prn_t &, const gps_time_t &);
128
+ inline satellite_t select(const prn_t &prn, const gps_time_t &receiver_time) const {
129
+ return impl_select(impl, prn, receiver_time);
130
+ }
131
+ static satellite_t select_broadcast(
132
+ const void *ptr, const prn_t &prn, const gps_time_t &receiver_time){
133
+ // If this static function is defined in inner struct,
134
+ // C2440 error raises with VC2010
135
+ const typename space_node_t::satellites_t &sats(
136
+ reinterpret_cast<const space_node_t *>(ptr)->satellites());
137
+ const typename space_node_t::satellites_t::const_iterator it_sat(sats.find(prn));
138
+ if((it_sat == sats.end()) // has ephemeris?
139
+ || (!it_sat->second.ephemeris().is_valid(receiver_time))){ // valid ephemeris?
140
+ return satellite_t::unavailable();
141
+ }
142
+ struct impl_t {
143
+ static inline const typename space_node_t::Satellite &sat(const void *ptr) {
144
+ return *reinterpret_cast<const typename space_node_t::Satellite *>(ptr);
145
+ }
146
+ static xyz_t position(const void *ptr, const gps_time_t &t, const float_t &pseudo_range) {
147
+ return sat(ptr).position(t, pseudo_range);
148
+ }
149
+ static xyz_t velocity(const void *ptr, const gps_time_t &t, const float_t &pseudo_range) {
150
+ return sat(ptr).velocity(t, pseudo_range);
151
+ }
152
+ static float_t clock_error(const void *ptr, const gps_time_t &t, const float_t &pseudo_range) {
153
+ return sat(ptr).clock_error(t, pseudo_range);
154
+ }
155
+ static float_t clock_error_dot(const void *ptr, const gps_time_t &t, const float_t &pseudo_range) {
156
+ return sat(ptr).clock_error_dot(t, pseudo_range);
157
+ }
158
+ };
159
+ satellite_t res = {
160
+ &(it_sat->second),
161
+ impl_t::position, impl_t::velocity,
162
+ impl_t::clock_error, impl_t::clock_error_dot};
163
+ return res;
164
+ }
165
+ satellites_t(const space_node_t &sn)
166
+ : impl(&sn), impl_select(select_broadcast) {}
167
+ } satellites;
127
168
 
128
169
  struct klobuchar_t : public range_corrector_t {
129
170
  const space_node_t &space_node;
@@ -134,6 +175,7 @@ class GPS_SinglePositioning : public SolverBaseT {
134
175
  float_t *calculate(
135
176
  const gps_time_t &t, const pos_t &usr_pos, const enu_t &sat_rel_pos,
136
177
  float_t &buf) const {
178
+ if(!is_available(t)){return NULL;}
137
179
  return &(buf = space_node.iono_correction(sat_rel_pos, usr_pos.llh, t));
138
180
  }
139
181
  } ionospheric_klobuchar;
@@ -185,7 +227,8 @@ class GPS_SinglePositioning : public SolverBaseT {
185
227
  }
186
228
 
187
229
  GPS_SinglePositioning(const space_node_t &sn)
188
- : base_t(), _space_node(sn), _options(available_options(options_t())),
230
+ : base_t(), _options(available_options(options_t())),
231
+ satellites(sn),
189
232
  ionospheric_klobuchar(sn), ionospheric_ntcm_gl(),
190
233
  tropospheric_simplified(),
191
234
  ionospheric_correction(), tropospheric_correction() {
@@ -309,27 +352,17 @@ class GPS_SinglePositioning : public SolverBaseT {
309
352
  }
310
353
 
311
354
  /**
312
- * Check availability of a satellite with which observation is associated
355
+ * Select satellite by using PRN and time
313
356
  *
314
357
  * @param prn satellite number
315
358
  * @param receiver_time receiver time
316
- * @return (const satellite_t *) If available, const pointer to satellite is returned,
317
- * otherwise NULL.
359
+ * @return (satellite_t) If available, satellite.is_available() returning true is returned.
318
360
  */
319
- const satellite_t *is_available(
320
- const typename space_node_t::satellites_t::key_type &prn,
361
+ satellite_t select_satellite(
362
+ const prn_t &prn,
321
363
  const gps_time_t &receiver_time) const {
322
-
323
- if(_options.exclude_prn[prn]){return NULL;}
324
-
325
- const typename space_node_t::satellites_t &sats(_space_node.satellites());
326
- const typename space_node_t::satellites_t::const_iterator it_sat(sats.find(prn));
327
- if((it_sat == sats.end()) // has ephemeris?
328
- || (!it_sat->second.ephemeris().is_valid(receiver_time))){ // valid ephemeris?
329
- return NULL;
330
- }
331
-
332
- return &(it_sat->second);
364
+ if(_options.exclude_prn[prn]){return satellite_t::unavailable();}
365
+ return satellites.select(prn, receiver_time);
333
366
  }
334
367
 
335
368
  /**
@@ -359,8 +392,8 @@ class GPS_SinglePositioning : public SolverBaseT {
359
392
  return res; // If no range entry, return with weight = 0
360
393
  }
361
394
 
362
- const satellite_t *sat(is_available(prn, time_arrival));
363
- if(!sat){return res;} // If satellite is unavailable, return with weight = 0
395
+ satellite_t sat(select_satellite(prn, time_arrival));
396
+ if(!sat.is_available()){return res;} // If satellite is unavailable, return with weight = 0
364
397
 
365
398
  residual_t residual = {
366
399
  res.range_residual,
@@ -369,9 +402,9 @@ class GPS_SinglePositioning : public SolverBaseT {
369
402
  };
370
403
 
371
404
  res.range_corrected = range_corrected(
372
- *sat, range - receiver_error, time_arrival,
405
+ sat, range - receiver_error, time_arrival,
373
406
  usr_pos, residual, range_error);
374
- res.rate_relative_neg = rate_relative_neg(*sat, res.range_corrected, time_arrival, usr_vel,
407
+ res.rate_relative_neg = rate_relative_neg(sat, res.range_corrected, time_arrival, usr_vel,
375
408
  res.los_neg[0], res.los_neg[1], res.los_neg[2]);
376
409
 
377
410
  return res;
@@ -415,7 +448,7 @@ class GPS_SinglePositioning : public SolverBaseT {
415
448
  float_t range;
416
449
  if(!this->range(it->second, range)){continue;} // No range entry
417
450
 
418
- if(!is_available(it->first, receiver_time)){continue;} // No satellite
451
+ if(!(select_satellite(it->first, receiver_time).is_available())){continue;} // No satellite
419
452
 
420
453
  typename base_t::measurement2_t::value_type v = {
421
454
  it->first, &(it->second), this}; // prn, measurement, solver
@@ -426,15 +459,6 @@ class GPS_SinglePositioning : public SolverBaseT {
426
459
  measurement2, receiver_time, user_position_init, receiver_error_init,
427
460
  typename base_t::user_pvt_opt_t(good_init, with_velocity));
428
461
  }
429
-
430
- xyz_t *satellite_position(
431
- const prn_t &prn,
432
- const gps_time_t &time,
433
- xyz_t &res) const {
434
-
435
- const satellite_t *sat(is_available(prn, time));
436
- return sat ? &(res = sat->position(time)) : NULL;
437
- }
438
462
  };
439
463
 
440
464
  #endif /* __GPS_SOLVER_H__ */
@@ -226,6 +226,47 @@ struct GPS_Solver_Base {
226
226
  return res;
227
227
  }
228
228
 
229
+ struct satellite_t {
230
+ const void *impl;
231
+ xyz_t (*impl_position)(const void *, const gps_time_t &, const float_t &);
232
+ xyz_t (*impl_velocity)(const void *, const gps_time_t &, const float_t &);
233
+ float_t (*impl_clock_error)(const void *, const gps_time_t &, const float_t &);
234
+ float_t (*impl_clock_error_dot)(const void *, const gps_time_t &, const float_t &);
235
+ inline bool is_available() const {
236
+ return impl != NULL;
237
+ }
238
+ inline xyz_t position(const gps_time_t &t, const float_t &pseudo_range = 0) const {
239
+ return impl_position(impl, t, pseudo_range);
240
+ }
241
+ inline xyz_t velocity(const gps_time_t &t, const float_t &pseudo_range = 0) const {
242
+ return impl_velocity(impl, t, pseudo_range);
243
+ }
244
+ inline float_t clock_error(const gps_time_t &t, const float_t &pseudo_range = 0) const {
245
+ return impl_clock_error(impl, t, pseudo_range);
246
+ }
247
+ inline float_t clock_error_dot(const gps_time_t &t, const float_t &pseudo_range = 0) const {
248
+ return impl_clock_error_dot(impl, t, pseudo_range);
249
+ }
250
+ static const satellite_t &unavailable() {
251
+ static const satellite_t res = {NULL};
252
+ return res;
253
+ }
254
+ };
255
+
256
+ /**
257
+ * Select satellite by using PRN and time
258
+ * This function should be overridden.
259
+ *
260
+ * @param prn satellite number
261
+ * @param receiver_time receiver time
262
+ * @return (satellite_t) If available, satellite.is_available() returning true is returned.
263
+ */
264
+ virtual satellite_t select_satellite(
265
+ const prn_t &prn,
266
+ const gps_time_t &receiver_time) const {
267
+ return satellite_t::unavailable();
268
+ }
269
+
229
270
  struct range_corrector_t {
230
271
  virtual ~range_corrector_t() {}
231
272
  virtual bool is_available(const gps_time_t &t) const {
@@ -838,21 +879,6 @@ protected:
838
879
  }
839
880
 
840
881
  public:
841
- /**
842
- * Calculate satellite position
843
- *
844
- * @param prn satellite number
845
- * @param time GPS time
846
- * @param res object to which results are stored
847
- * @return If position is available, &res will be returned, otherwise NULL.
848
- */
849
- virtual xyz_t *satellite_position(
850
- const prn_t &prn,
851
- const gps_time_t &time,
852
- xyz_t &res) const {
853
- return NULL;
854
- }
855
-
856
882
  /**
857
883
  * Calculate User position/velocity with hint
858
884
  * This is multi-constellation version,
@@ -882,8 +908,7 @@ public:
882
908
  it != it_end; ++it){
883
909
  typename measurement2_t::value_type v = {
884
910
  it->first, &(it->second), &select(it->first)}; // prn, measurement, solver
885
- xyz_t sat;
886
- if(!v.solver->satellite_position(v.prn, receiver_time, sat)){
911
+ if(!v.solver->select_satellite(v.prn, receiver_time).is_available()){
887
912
  // pre-check satellite availability; remove it when its position is unknown
888
913
  continue;
889
914
  }
@@ -62,8 +62,6 @@ class RINEX_Reader {
62
62
  typedef RINEX_Reader<U> self_t;
63
63
  typedef std::map<std::string, std::vector<std::string> > header_t;
64
64
 
65
- protected:
66
- header_t _header;
67
65
  struct src_stream_t : public std::istream {
68
66
  src_stream_t(std::istream &is) : std::istream(is.rdbuf()) {}
69
67
  /**
@@ -106,7 +104,11 @@ class RINEX_Reader {
106
104
  }
107
105
  return *this;
108
106
  }
109
- } src;
107
+ };
108
+
109
+ protected:
110
+ header_t _header;
111
+ src_stream_t src;
110
112
  bool _has_next;
111
113
 
112
114
  public:
@@ -198,7 +200,7 @@ class RINEX_Reader {
198
200
  return true;
199
201
  }
200
202
  }
201
- static bool f(
203
+ static bool f_pure(
202
204
  std::string &buf, const int &offset, const int &length, void *value, const int &precision = 0, const bool &str2val = true){
203
205
  if(str2val){
204
206
  std::stringstream ss(buf.substr(offset, length));
@@ -209,22 +211,30 @@ class RINEX_Reader {
209
211
  ss << std::setfill(' ') << std::right << std::setw(length)
210
212
  << std::setprecision(precision) << std::fixed
211
213
  << *(T *)value;
212
- std::string s(ss.str());
214
+ buf.replace(offset, length, ss.str());
215
+ return true;
216
+ }
217
+ }
218
+ static bool f(
219
+ std::string &buf, const int &offset, const int &length, void *value, const int &precision = 0, const bool &str2val = true){
220
+ bool res(f_pure(buf, offset, length, value, precision, str2val));
221
+ if((!str2val) && res){
213
222
  if((*(T *)value) >= 0){
214
223
  if((*(T *)value) < 1){
215
224
  int i(length - precision - 2);
216
- if(i >= 0){s[i] = ' ';}
225
+ // 0.12345 => .12345
226
+ if(i >= 0){buf[i + offset] = ' ';}
217
227
  }
218
228
  }else{
219
229
  if((*(T *)value) > -1){
220
230
  int i(length - precision - 2);
221
- if(i >= 0){s[i] = '-';}
222
- if(--i >= 0){s[i] = ' ';}
231
+ // -0.12345 => -.12345
232
+ if(i >= 0){buf[i + offset] = '-';}
233
+ if(--i >= 0){buf[i + offset] = ' ';}
223
234
  }
224
235
  }
225
- buf.replace(offset, length, s);
226
- return true;
227
236
  }
237
+ return res;
228
238
  }
229
239
  static bool e(
230
240
  std::string &buf, const int &offset, const int &length, void *value, const int &precision = 0, const bool &str2val = true){
@@ -268,6 +278,14 @@ class RINEX_Reader {
268
278
  std::string &buf, const int &offset, const int &length, void *value, const int &opt = 0, const bool &str2val = true){
269
279
  return conv_t<T, false>::d(buf, offset, length, value, opt, str2val);
270
280
  }
281
+ static bool f_pure(
282
+ std::string &buf, const int &offset, const int &length, void *value, const int &precision = 0, const bool &str2val = true){
283
+ double v(*(T *)value);
284
+ bool res(
285
+ conv_t<double, false>::f_pure(buf, offset, length, &v, precision, str2val));
286
+ *(T *)value = static_cast<T>(v);
287
+ return res;
288
+ }
271
289
  static bool f(
272
290
  std::string &buf, const int &offset, const int &length, void *value, const int &precision = 0, const bool &str2val = true){
273
291
  double v(*(T *)value);
@@ -2183,10 +2183,11 @@ template <typename T>
2183
2183
  typename SBAS_SpaceNode<FloatT>::KnownSatellites::list_t
2184
2184
  SBAS_SpaceNode<FloatT>::KnownSatellites::sort(T sorter){
2185
2185
  static const typename SBAS_SpaceNode<FloatT>::RangingCode codes[] = {
2186
+ {120, 145, 01106, 5, "ASECNA (A-SBAS)"},
2186
2187
  {121, 175, 01241, 5, "EGNOS (Eutelsat 5WB)"},
2187
2188
  {122, 52, 00267, 143.5, "SPAN (INMARSAT 4F1)"},
2188
2189
  {123, 21, 00232, 31.5, "EGNOS (ASTRA 5B)"},
2189
- {124, 237, 01617, 0, "EGNOS (Reserved)"},
2190
+ //{124, 237, 01617, 0, "(Reserved)"},
2190
2191
  {125, 235, 01076, -16, "SDCM (Luch-5A)"},
2191
2192
  {126, 886, 01764, 63.9, "EGNOS (INMARSAT 4F2)"},
2192
2193
  {127, 657, 00717, 55, "GAGAN (GSAT-8)"},
@@ -2198,16 +2199,30 @@ typename SBAS_SpaceNode<FloatT>::KnownSatellites::list_t
2198
2199
  {133, 603, 01731, -129, "WAAS (SES-15)"},
2199
2200
  {134, 130, 00706, 91.5, "KASS (MEASAT-3D)"},
2200
2201
  {135, 359, 01216, -125, "WAAS (Intelsat Galaxy 30)"},
2201
- {136, 595, 00740, 5, "EGNOS (SES-5)"},
2202
+ {136, 595, 00740, 5, "EGNOS (HOTBIRD 13G)"},
2202
2203
  {137, 68, 01007, 127, "MSAS (QZS-3)"},
2203
2204
  {138, 386, 00450, 107.3, "WAAS (ANIK F1R)"},
2205
+ //{139, 797, 00305, 0, "MSAS (QZS-7)"},
2204
2206
  {140, 456, 01653, 95, "SDCM (Luch-5V)"},
2205
2207
  {141, 499, 01411, 167, "SDCM (Luch-5A)"},
2208
+ //{142, 883, 01644, 0, "(Unallocated)"},
2206
2209
  {143, 307, 01312, 110.5, "BDSBAS (G3)"},
2207
2210
  {144, 127, 01060, 80, "BDSBAS (G2)"},
2208
- {147, 118, 00355, 42.5, "NSAS (NIGCOMSAT-1R)"},
2211
+ //{145, 211, 01560, 0, "(Unallocated)"},
2212
+ //{146, 121, 00035, 0, "(Unallocated)"},
2213
+ {147, 118, 00355, 5, "ASECNA (A-SBAS)"},
2209
2214
  {148, 163, 00335, -24.8, "ASAL (ALCOMSAT-1)"},
2210
- }; ///< @see https://www.gps.gov/technical/prn-codes/L1-CA-PRN-code-assignments-2020-Apr.pdf
2215
+ //{149, 628, 01254, 0, "(Unallocated)"},
2216
+ //{150, 853, 01041, 0, "EGNOS"},
2217
+ //{151, 484, 00142, 0, "(Unallocated)"},
2218
+ //{152, 289, 01641, 0, "(Unallocated)"},
2219
+ //{153, 811, 01504, 0, "(Unallocated)"},
2220
+ //{154, 202, 00751, 0, "(Unallocated)"},
2221
+ //{155, 1021, 01774, 0, "(Unallocated)"},
2222
+ //{156, 463, 00107, 0, "(Unallocated)"},
2223
+ //{157, 568, 01153, 0, "(Unallocated)"},
2224
+ //{158, 904, 01542, 0, "(Unallocated)"},
2225
+ }; ///< @see https://www.gps.gov/technical/prn-codes/L1-CA-PRN-code-assignments-2021-Jun.pdf
2211
2226
  list_t res;
2212
2227
  res.reserve(sizeof(codes) / sizeof(codes[0]));
2213
2228
  for(unsigned int i(0); i < sizeof(codes) / sizeof(codes[0]); ++i){
@@ -73,7 +73,6 @@ class SBAS_SinglePositioning : public SolverBaseT {
73
73
 
74
74
  typedef SBAS_SpaceNode<float_t> space_node_t;
75
75
  inheritate_type(gps_time_t);
76
- typedef typename space_node_t::Satellite satellite_t;
77
76
 
78
77
  inheritate_type(xyz_t);
79
78
  inheritate_type(enu_t);
@@ -81,6 +80,7 @@ class SBAS_SinglePositioning : public SolverBaseT {
81
80
  inheritate_type(pos_t);
82
81
 
83
82
  typedef typename base_t::measurement_t measurement_t;
83
+ typedef typename base_t::satellite_t satellite_t;
84
84
  typedef typename base_t::range_error_t range_error_t;
85
85
  typedef typename base_t::range_corrector_t range_corrector_t;
86
86
  typedef typename base_t::range_correction_t range_correction_t;
@@ -92,11 +92,52 @@ class SBAS_SinglePositioning : public SolverBaseT {
92
92
  SBAS_SinglePositioning_Options<float_t>, base_t> options_t;
93
93
 
94
94
  protected:
95
- const space_node_t &_space_node;
96
95
  SBAS_SinglePositioning_Options<float_t> _options;
97
96
 
98
97
  public:
99
- const space_node_t &space_node() const {return _space_node;}
98
+ struct satellites_t {
99
+ const void *impl;
100
+ satellite_t (*impl_select)(const void *, const prn_t &, const gps_time_t &);
101
+ inline satellite_t select(const prn_t &prn, const gps_time_t &receiver_time) const {
102
+ return impl_select(impl, prn, receiver_time);
103
+ }
104
+ static satellite_t select_broadcast(
105
+ const void *ptr, const prn_t &prn, const gps_time_t &receiver_time){
106
+ const typename space_node_t::satellites_t &sats(
107
+ reinterpret_cast<const space_node_t *>(ptr)->satellites());
108
+ const typename space_node_t::satellites_t::const_iterator it_sat(sats.find(prn));
109
+ if((it_sat == sats.end()) // has ephemeris?
110
+ || (!it_sat->second.ephemeris().is_valid(receiver_time))){ // valid ephemeris?
111
+ return satellite_t::unavailable();
112
+ }
113
+ struct impl_t {
114
+ static inline const typename space_node_t::Satellite &sat(const void *ptr) {
115
+ return *reinterpret_cast<const typename space_node_t::Satellite *>(ptr);
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;
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;
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;
126
+ }
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;
130
+ }
131
+ };
132
+ satellite_t res = {
133
+ &(it_sat->second),
134
+ impl_t::position, impl_t::velocity,
135
+ impl_t::clock_error, impl_t::clock_error_dot};
136
+ return res;
137
+ }
138
+ satellites_t(const space_node_t &sn)
139
+ : impl(&sn), impl_select(select_broadcast) {}
140
+ } satellites;
100
141
 
101
142
  struct ionospheric_sbas_t : public range_corrector_t {
102
143
  const space_node_t &space_node;
@@ -155,7 +196,8 @@ class SBAS_SinglePositioning : public SolverBaseT {
155
196
  }
156
197
 
157
198
  SBAS_SinglePositioning(const space_node_t &sn)
158
- : base_t(), _space_node(sn), _options(available_options(options_t())),
199
+ : base_t(), _options(available_options(options_t())),
200
+ satellites(sn),
159
201
  ionospheric_sbas(sn), tropospheric_sbas() {
160
202
 
161
203
  // default ionospheric correction: Broadcasted IGP.
@@ -168,25 +210,17 @@ class SBAS_SinglePositioning : public SolverBaseT {
168
210
  ~SBAS_SinglePositioning(){}
169
211
 
170
212
  /**
171
- * Check availability of a satellite with which observation is associated
213
+ * Select satellite by using PRN and time
172
214
  *
173
215
  * @param prn satellite number
174
216
  * @param receiver_time receiver time
175
- * @return (const satellite_t *) If available, const pointer to satellite is returned,
176
- * otherwise NULL.
217
+ * @return (satellite_t) If available, satellite.is_available() returning true is returned.
177
218
  */
178
- const satellite_t *is_available(
179
- const typename space_node_t::satellites_t::key_type &prn,
219
+ satellite_t select_satellite(
220
+ const prn_t &prn,
180
221
  const gps_time_t &receiver_time) const {
181
-
182
- const typename space_node_t::satellites_t &sats(_space_node.satellites());
183
- const typename space_node_t::satellites_t::const_iterator it_sat(sats.find(prn));
184
- if((it_sat == sats.end()) // has ephemeris?
185
- || (!it_sat->second.ephemeris().is_valid(receiver_time))){ // valid ephemeris?
186
- return NULL;
187
- }
188
-
189
- return &(it_sat->second);
222
+ if(_options.exclude_prn[prn]){return satellite_t::unavailable();}
223
+ return satellites.select(prn, receiver_time);
190
224
  }
191
225
 
192
226
  /**
@@ -210,33 +244,28 @@ class SBAS_SinglePositioning : public SolverBaseT {
210
244
 
211
245
  relative_property_t res = {0};
212
246
 
213
- if(_options.exclude_prn[prn]){return res;}
214
-
215
247
  float_t range;
216
248
  range_error_t range_error;
217
249
  if(!this->range(measurement, range, &range_error)){
218
250
  return res; // If no range entry, return with weight = 0
219
251
  }
220
252
 
221
- const satellite_t *sat(is_available(prn, time_arrival));
222
- if(!sat){return res;} // If satellite is unavailable, return with weight = 0
253
+ satellite_t sat(select_satellite(prn, time_arrival));
254
+ if(!sat.is_available()){return res;} // If satellite is unavailable, return with weight = 0
223
255
 
224
256
  ///< The following procedure is based on Appendix.S with modification
225
257
 
226
258
  range -= receiver_error;
227
259
 
228
- // Clock correction will be performed in the following constellation()
229
- if(!(range_error.unknown_flag & range_error_t::SATELLITE_CLOCK)){
230
- range += range_error.value[range_error_t::SATELLITE_CLOCK];
231
- }
260
+ // Clock error correction
261
+ range += ((range_error.unknown_flag & range_error_t::SATELLITE_CLOCK)
262
+ ? (sat.clock_error(time_arrival, range) * GPS_SpaceNode<float_t>::light_speed)
263
+ : range_error.value[range_error_t::SATELLITE_CLOCK]);
232
264
 
233
265
  // TODO WAAS long term clock correction (2.1.1.4.11)
234
266
 
235
- // Calculate satellite position and velocity
236
- typename space_node_t::SatelliteProperties::constellation_t sat_pos_vel(
237
- sat->ephemeris().constellation(time_arrival, range));
238
-
239
- const xyz_t &sat_pos(sat_pos_vel.position);
267
+ // Calculate satellite position
268
+ xyz_t sat_pos(sat.position(time_arrival, range));
240
269
  float_t geometric_range(usr_pos.xyz.dist(sat_pos));
241
270
 
242
271
  // Calculate residual with Sagnac correction (A.4.4.11)
@@ -283,24 +312,15 @@ class SBAS_SinglePositioning : public SolverBaseT {
283
312
 
284
313
  res.range_corrected = range;
285
314
 
286
- xyz_t rel_vel(sat_pos_vel.velocity - usr_vel); // Calculate velocity
315
+ xyz_t rel_vel(sat.velocity(time_arrival, range) - usr_vel); // Calculate velocity
287
316
 
288
- // Note: clock rate error is already accounted for in constellation()
289
317
  res.rate_relative_neg = res.los_neg[0] * rel_vel.x()
290
318
  + res.los_neg[1] * rel_vel.y()
291
- + res.los_neg[2] * rel_vel.z();
319
+ + res.los_neg[2] * rel_vel.z()
320
+ + sat.clock_error_dot(time_arrival, range) * GPS_SpaceNode<float_t>::light_speed;
292
321
 
293
322
  return res;
294
323
  }
295
-
296
- xyz_t *satellite_position(
297
- const prn_t &prn,
298
- const gps_time_t &time,
299
- xyz_t &res) const {
300
-
301
- const satellite_t *sat(is_available(prn, time));
302
- return sat ? &(res = sat->ephemeris().constellation(time).position) : NULL;
303
- }
304
324
  };
305
325
 
306
326
  #endif /* __SBAS_SOLVER_H__ */
@@ -1104,7 +1104,7 @@ struct GPS_RangeCorrector
1104
1104
  %ignore glonass;
1105
1105
  %ignore select_solver;
1106
1106
  %ignore relative_property;
1107
- %ignore satellite_position;
1107
+ %ignore select_satellite;
1108
1108
  %ignore update_position_solution;
1109
1109
  %ignore user_correctors_t;
1110
1110
  %ignore user_correctors;
@@ -1201,47 +1201,17 @@ struct GPS_RangeCorrector
1201
1201
  return super_t::update_position_solution(geomat, res);
1202
1202
  }
1203
1203
  template <>
1204
- GPS_Solver<FloatT>::base_t::xyz_t *GPS_Solver<FloatT>::satellite_position(
1204
+ GPS_Solver<FloatT>::base_t::satellite_t GPS_Solver<FloatT>::select_satellite(
1205
1205
  const GPS_Solver<FloatT>::base_t::prn_t &prn,
1206
- const GPS_Solver<FloatT>::base_t::gps_time_t &time,
1207
- GPS_Solver<FloatT>::base_t::xyz_t &buf) const {
1208
- GPS_Solver<FloatT>::base_t::xyz_t *res(
1209
- select_solver(prn).satellite_position(prn, time, buf));
1206
+ const GPS_Solver<FloatT>::base_t::gps_time_t &time) const {
1207
+ GPS_Solver<FloatT>::base_t::satellite_t res(
1208
+ select_solver(prn).select_satellite(prn, time));
1210
1209
  #ifdef SWIGRUBY
1211
- do{
1212
- static const VALUE key(ID2SYM(rb_intern("satellite_position")));
1210
+ if(!res.is_available()){
1211
+ static const VALUE key(ID2SYM(rb_intern("relative_property")));
1213
1212
  VALUE hook(rb_hash_lookup(hooks, key));
1214
- if(NIL_P(hook)){break;}
1215
- VALUE values[] = {
1216
- SWIG_From(int)(prn), // prn
1217
- SWIG_NewPointerObj( // time
1218
- new base_t::gps_time_t(time), $descriptor(GPS_Time<FloatT> *), SWIG_POINTER_OWN),
1219
- (res // position (internally calculated)
1220
- ? SWIG_NewPointerObj(res, $descriptor(System_XYZ<FloatT, WGS84> *), 0)
1221
- : Qnil)};
1222
- VALUE res_hook(proc_call_throw_if_error(hook, sizeof(values) / sizeof(values[0]), values));
1223
- if(NIL_P(res_hook)){ // unknown position
1224
- res = NULL;
1225
- break;
1226
- }else if(RB_TYPE_P(res_hook, T_ARRAY) && (RARRAY_LEN(res_hook) == 3)){
1227
- int i(0);
1228
- for(; i < 3; ++i){
1229
- VALUE v(RARRAY_AREF(res_hook, i));
1230
- if(!SWIG_IsOK(swig::asval(v, &buf[i]))){break;}
1231
- }
1232
- if(i == 3){
1233
- res = &buf;
1234
- break;
1235
- }
1236
- }else if(SWIG_IsOK(SWIG_ConvertPtr(
1237
- res_hook, (void **)&res, $descriptor(System_XYZ<FloatT, WGS84> *), 0))){
1238
- res = &(buf = *res);
1239
- break;
1240
- }
1241
- throw std::runtime_error(
1242
- std::string("System_XYZ or [d * 3] is expected (d: " %str(FloatT) "), however ")
1243
- .append(inspect_str(res_hook)));
1244
- }while(false);
1213
+ if(!NIL_P(hook)){res.impl = this;}
1214
+ }
1245
1215
  #endif
1246
1216
  return res;
1247
1217
  }
@@ -1481,10 +1451,9 @@ struct GPS_Solver
1481
1451
  const typename base_t::gps_time_t &time_arrival,
1482
1452
  const typename base_t::pos_t &usr_pos,
1483
1453
  const typename base_t::xyz_t &usr_vel) const;
1484
- virtual typename base_t::xyz_t *satellite_position(
1454
+ virtual typename base_t::satellite_t select_satellite(
1485
1455
  const typename base_t::prn_t &prn,
1486
- const typename base_t::gps_time_t &time,
1487
- typename base_t::xyz_t &res) const;
1456
+ const typename base_t::gps_time_t &time) const;
1488
1457
  virtual bool update_position_solution(
1489
1458
  const typename base_t::geometric_matrices_t &geomat,
1490
1459
  typename base_t::user_pvt_t &res) const;
@@ -375,22 +375,6 @@ __RINEX_OBS_TEXT__
375
375
  expect(mat).to respond_to(:resize!)
376
376
  }
377
377
  }
378
- solver.hooks[:satellite_position] = proc{
379
- i = 0
380
- proc{|prn, time, pos|
381
- expect(input[:measurement]).to include(prn)
382
- expect(pos).to be_a_kind_of(Coordinate::XYZ).or eq(nil)
383
- # System_XYZ or [x,y,z] or nil(= unknown position) are acceptable
384
- case (i += 1) % 5
385
- when 0
386
- nil
387
- when 1
388
- pos.to_a
389
- else
390
- pos
391
- end
392
- }
393
- }.call
394
378
  pvt = solver.solve(
395
379
  input[:measurement].collect{|prn, items|
396
380
  items.collect{|k, v| [prn, k, v]}
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GPS_PVT
4
- VERSION = "0.5.0"
4
+ VERSION = "0.5.1"
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.5.0
4
+ version: 0.5.1
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-04-11 00:00:00.000000000 Z
11
+ date: 2022-05-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake