gps_pvt 0.5.0 → 0.5.1

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: 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