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.
@@ -34,6 +34,9 @@
34
34
 
35
35
  #include <cstddef>
36
36
  #include <vector>
37
+ #include <map>
38
+ #include <algorithm>
39
+ #include <stdexcept>
37
40
 
38
41
  /*
39
42
  * perform Neville's interpolation (with derivative)
@@ -118,4 +121,107 @@ Ty interpolate_Neville(
118
121
  return interpolate_Neville(x_given, y_given, x, y_buf, n)[0];
119
122
  }
120
123
 
124
+ template <class Tx, class Ty, class Tx_delta = Tx>
125
+ struct InterpolatableSet {
126
+ struct condition_t {
127
+ std::size_t max_x_size; ///< maximum number of data used for interpolation
128
+ Tx_delta max_dx_range; ///< maximum acceptable absolute difference between x and x0
129
+ };
130
+
131
+ typedef typename std::vector<std::pair<Tx, Ty> > buffer_t;
132
+ buffer_t buf;
133
+ Tx x0, x_lower, x_upper;
134
+ std::vector<Tx_delta> dx;
135
+ bool ready;
136
+
137
+ InterpolatableSet() : x0(), dx(), ready(false) {}
138
+
139
+ /**
140
+ * update interpolation source
141
+ * @param force_update If true, update is forcibly performed irrespective of current state
142
+ * @param cnd condition for source data selection
143
+ */
144
+ InterpolatableSet &update(
145
+ const Tx &x, const std::map<Tx, Ty> &xy_table,
146
+ const condition_t &cnd,
147
+ const bool &force_update = false){
148
+
149
+ do{
150
+ if(force_update){break;}
151
+ if(dx.size() <= 2){break;}
152
+ if(x < x_lower){break;}
153
+ if(x > x_upper){break;}
154
+ return *this;
155
+ }while(false);
156
+
157
+ // If the 1st and 2nd nearest items are changed, then recalculate interpolation targets.
158
+ struct {
159
+ const Tx &x_base;
160
+ bool operator()(
161
+ const typename std::map<Tx, Ty>::value_type &rhs,
162
+ const typename std::map<Tx, Ty>::value_type &lhs) const {
163
+ return std::abs(rhs.first - x_base) < std::abs(lhs.first - x_base);
164
+ }
165
+ } cmp = {(x0 = x)};
166
+
167
+ buf.resize(cnd.max_x_size);
168
+ dx.clear();
169
+ // extract x where x0-dx_range <= x <= x0+dx_range, then sort by ascending order of |x-x0|
170
+ for(typename buffer_t::const_iterator
171
+ it(buf.begin()),
172
+ it_end(std::partial_sort_copy(
173
+ xy_table.lower_bound(x - cnd.max_dx_range),
174
+ xy_table.upper_bound(x + cnd.max_dx_range),
175
+ buf.begin(), buf.end(), cmp));
176
+ it != it_end; ++it){
177
+ dx.push_back(it->first - x0);
178
+ }
179
+ if(dx.size() >= 2){ // calculate a necessary condition to update samples for new x
180
+ // According to Nth nearest points, x range in which the order of extracted samples
181
+ // is retained can be calculated.
182
+ bool ascending(buf[0].first <= buf[1].first);
183
+ Tx &xa(ascending ? x_lower : x_upper), &xb(ascending ? x_upper : x_lower);
184
+ xa = x0;
185
+ for(std::size_t i(2); i < buf.size(); ++i){
186
+ if(ascending ? (dx[1] <= dx[i]) : (dx[1] >= dx[i])){continue;}
187
+ xa = x0 + (dx[1] + dx[i]) / 2;
188
+ break;
189
+ }
190
+ xb = x0 + (dx[0] + dx[1]) / 2;
191
+ }
192
+ ready = (dx.size() >= cnd.max_x_size);
193
+
194
+ return *this;
195
+ }
196
+
197
+ template <class Ty2, class Ty2_Iterator>
198
+ Ty2 interpolate2(
199
+ const Tx &x, const Ty2_Iterator &y,
200
+ Ty2 *derivative = NULL) const {
201
+ int order(dx.size() - 1);
202
+ do{
203
+ if(order > 0){break;}
204
+ if((order == 0) && (!derivative)){return y[0];}
205
+ throw std::range_error("Insufficient records for interpolation");
206
+ }while(false);
207
+ std::vector<Ty2> y_buf(order), dy_buf(order);
208
+ interpolate_Neville(
209
+ dx, y, x - x0, y_buf, order,
210
+ &dy_buf, derivative ? 1 : 0);
211
+ if(derivative){*derivative = dy_buf[0];}
212
+ return y_buf[0];
213
+ }
214
+
215
+ Ty interpolate(const Tx &x, Ty *derivative = NULL) const {
216
+ struct second_iterator : public buffer_t::const_iterator {
217
+ second_iterator(const typename buffer_t::const_iterator &it)
218
+ : buffer_t::const_iterator(it) {}
219
+ const Ty &operator[](const int &n) const {
220
+ return buffer_t::const_iterator::operator[](n).second;
221
+ }
222
+ } y_it(buf.begin());
223
+ return interpolate2(x, y_it, derivative);
224
+ }
225
+ };
226
+
121
227
  #endif /* __INTERPOLATE_H__ */
@@ -998,17 +998,18 @@ if(std::abs(TARGET - eph.TARGET) > raw_t::sf[raw_t::SF_ ## TARGET]){break;}
998
998
  bool is_equivalent(const Ephemeris_with_Time &eph) const {
999
999
  return Ephemeris::is_equivalent(eph) && TimeProperties::is_equivalent(eph);
1000
1000
  }
1001
- float_t calculate_clock_error(float_t delta_t, const float_t &pseudo_range = 0) const {
1002
- delta_t -= pseudo_range / light_speed;
1001
+ float_t calculate_clock_error(const float_t &delta_t) const {
1003
1002
  return -TimeProperties::tau_c - Ephemeris::tau_n + Ephemeris::gamma_n * delta_t;
1004
1003
  }
1005
1004
  /**
1006
- * @param t_arrival_onboard signal arrival time in onboard time scale,
1005
+ * @param t_depature_onboard signal depature time in onboard time scale,
1007
1006
  * which is along to glonass time scale (UTC + 3 hr) but is shifted in gradually changing length.
1008
1007
  */
1009
- float_t clock_error(
1010
- const float_t &t_arrival_onboard, const float_t &pseudo_range = 0) const {
1011
- return calculate_clock_error(t_arrival_onboard - Ephemeris::t_b, pseudo_range);
1008
+ float_t clock_error(const float_t &t_depature_onboard) const {
1009
+ return calculate_clock_error(t_depature_onboard - Ephemeris::t_b);
1010
+ }
1011
+ const float_t &clock_error_dot() const {
1012
+ return Ephemeris::gamma_n;
1012
1013
  }
1013
1014
  /**
1014
1015
  * Calculate absolute constellation(t) based on constellation(t_0).
@@ -1064,23 +1065,22 @@ if(std::abs(TARGET - eph.TARGET) > raw_t::sf[raw_t::SF_ ## TARGET]){break;}
1064
1065
  * @param pseudo_range measured pusedo_range to correct delta_t, default is 0.
1065
1066
  */
1066
1067
  constellation_t calculate_constellation(
1067
- const float_t &delta_t, const float_t &pseudo_range = 0) const {
1068
+ const float_t &delta_t, const float_t &dt_transit = 0) const {
1068
1069
 
1069
- float_t delta_t_to_transmit(delta_t - pseudo_range / light_speed);
1070
1070
  constellation_t res(
1071
- constellation_abs(delta_t_to_transmit, xa_t_b, float_t(0)));
1071
+ constellation_abs(delta_t, xa_t_b, float_t(0)));
1072
1072
 
1073
1073
  return res.rel_corrdinate(
1074
- sidereal_t_b_rad + (constellation_t::omega_E * delta_t)); // transform from abs to PZ-90.02
1074
+ sidereal_t_b_rad + (constellation_t::omega_E * (delta_t + dt_transit))); // transform from abs to PZ-90.02
1075
1075
  }
1076
1076
  /**
1077
- * @param t_arrival_glonass signal arrival time in glonass time scale,
1077
+ * @param t_depature_glonass signal depature time in glonass time scale,
1078
1078
  * which is the corrected onboard time by removing clock error.
1079
1079
  */
1080
1080
  constellation_t constellation(
1081
- const float_t &t_arrival_glonass, const float_t &pseudo_range = 0) const {
1081
+ const float_t &t_depature_glonass, const float_t &dt_transit = 0) const {
1082
1082
  return calculate_constellation(
1083
- t_arrival_glonass - Ephemeris::t_b, pseudo_range); // measure in UTC + 3hr scale
1083
+ t_depature_glonass - Ephemeris::t_b, dt_transit); // measure in UTC + 3hr scale
1084
1084
  }
1085
1085
  };
1086
1086
 
@@ -1107,14 +1107,13 @@ if(std::abs(TARGET - eph.TARGET) > raw_t::sf[raw_t::SF_ ## TARGET]){break;}
1107
1107
  return std::abs(t_b_gps.interval(t)) <= 60 * 60; // 1 hour
1108
1108
  }
1109
1109
  using Ephemeris_with_Time::clock_error;
1110
- float_t clock_error(
1111
- const GPS_Time<float_t> &t_arrival_onboard, const float_t &pseudo_range = 0) const {
1112
- return Ephemeris_with_Time::calculate_clock_error(t_arrival_onboard - t_b_gps, pseudo_range);
1110
+ float_t clock_error(const GPS_Time<float_t> &t_depature_onboard) const {
1111
+ return Ephemeris_with_Time::calculate_clock_error(t_depature_onboard - t_b_gps);
1113
1112
  }
1114
1113
  using Ephemeris_with_Time::constellation;
1115
1114
  typename Ephemeris_with_Time::constellation_t constellation(
1116
- const GPS_Time<float_t> &t_arrival_gps, const float_t &pseudo_range = 0) const {
1117
- return this->calculate_constellation(t_arrival_gps - t_b_gps, pseudo_range);
1115
+ const GPS_Time<float_t> &t_depature_gps, const float_t &dt_transit = 0) const {
1116
+ return this->calculate_constellation(t_depature_gps - t_b_gps, dt_transit);
1118
1117
  }
1119
1118
  };
1120
1119
  };
@@ -1130,25 +1129,25 @@ if(std::abs(TARGET - eph.TARGET) > raw_t::sf[raw_t::SF_ ## TARGET]){break;}
1130
1129
  eph_cached_t(const eph_t &eph) : eph_t(eph), xa_t_0(eph.xa_t_b), t_0_from_t_b(0) {}
1131
1130
  using eph_t::constellation;
1132
1131
  typename eph_t::constellation_t constellation(
1133
- const GPS_Time<float_t> &t_arrival_gps, const float_t &pseudo_range = 0) const {
1134
- float_t delta_t(t_arrival_gps - eph_t::t_b_gps);
1135
- float_t delta_t_transmit_from_t_0(delta_t - pseudo_range / light_speed - t_0_from_t_b);
1132
+ const GPS_Time<float_t> &t_depature_gps, const float_t &dt_transit = 0) const {
1133
+ float_t delta_t(t_depature_gps - eph_t::t_b_gps);
1134
+ float_t delta_t_depature_from_t_0(delta_t - t_0_from_t_b);
1136
1135
 
1137
- float_t t_step_max(delta_t_transmit_from_t_0 >= 0
1136
+ float_t t_step_max(delta_t_depature_from_t_0 >= 0
1138
1137
  ? eph_t::time_step_max_per_one_integration
1139
1138
  : -eph_t::time_step_max_per_one_integration);
1140
1139
 
1141
- int big_steps(std::floor(delta_t_transmit_from_t_0 / t_step_max));
1140
+ int big_steps(std::floor(delta_t_depature_from_t_0 / t_step_max));
1142
1141
  if(big_steps > 0){ // perform integration and update cache
1143
1142
  xa_t_0 = eph_t::constellation_abs(t_step_max, big_steps, xa_t_0, t_0_from_t_b);
1144
1143
  float_t delta_t_updated(t_step_max * big_steps);
1145
1144
  t_0_from_t_b += delta_t_updated;
1146
- delta_t_transmit_from_t_0 -= delta_t_updated;
1145
+ delta_t_depature_from_t_0 -= delta_t_updated;
1147
1146
  }
1148
1147
 
1149
- return eph_t::constellation_abs(delta_t_transmit_from_t_0, 1, xa_t_0, t_0_from_t_b)
1150
- .rel_corrdinate(
1151
- eph_t::sidereal_t_b_rad + (eph_t::constellation_t::omega_E * delta_t)); // transform from abs to PZ-90.02
1148
+ return eph_t::constellation_abs(delta_t_depature_from_t_0, 1, xa_t_0, t_0_from_t_b)
1149
+ .rel_corrdinate( // transform from abs to PZ-90.02
1150
+ eph_t::sidereal_t_b_rad + (eph_t::constellation_t::omega_E * (delta_t + dt_transit)));
1152
1151
  }
1153
1152
  };
1154
1153
 
@@ -1190,22 +1189,25 @@ if(std::abs(TARGET - eph.TARGET) > raw_t::sf[raw_t::SF_ ## TARGET]){break;}
1190
1189
  return eph_history.select(target_time, &eph_t::is_valid);
1191
1190
  }
1192
1191
 
1193
- float_t clock_error(const GPS_Time<float_t> &t, const float_t &pseudo_range = 0) const{
1194
- return ephemeris().clock_error(t, pseudo_range);
1192
+ float_t clock_error(const GPS_Time<float_t> &t_tx) const{
1193
+ return ephemeris().clock_error(t_tx);
1194
+ }
1195
+ float_t clock_error_dot(const GPS_Time<float_t> &t_tx) const{
1196
+ return ephemeris().clock_error_dot();
1195
1197
  }
1196
1198
 
1197
1199
  typename GPS_SpaceNode<float_t>::SatelliteProperties::constellation_t constellation(
1198
- const GPS_Time<float_t> &t, const float_t &pseudo_range = 0) const {
1200
+ const GPS_Time<float_t> &t_tx, const float_t &dt_transit = 0) const {
1199
1201
  return (typename GPS_SpaceNode<float_t>::SatelliteProperties::constellation_t)(
1200
- eph_history.current().constellation(t, pseudo_range));
1202
+ eph_history.current().constellation(t_tx, dt_transit));
1201
1203
  }
1202
1204
 
1203
- typename GPS_SpaceNode<float_t>::xyz_t position(const GPS_Time<float_t> &t, const float_t &pseudo_range = 0) const {
1204
- return constellation(t, pseudo_range).position;
1205
+ typename GPS_SpaceNode<float_t>::xyz_t position(const GPS_Time<float_t> &t_tx, const float_t &dt_transit= 0) const {
1206
+ return constellation(t_tx, dt_transit).position;
1205
1207
  }
1206
1208
 
1207
- typename GPS_SpaceNode<float_t>::xyz_t velocity(const GPS_Time<float_t> &t, const float_t &pseudo_range = 0) const {
1208
- return constellation(t, pseudo_range).velocity;
1209
+ typename GPS_SpaceNode<float_t>::xyz_t velocity(const GPS_Time<float_t> &t_tx, const float_t &dt_transit = 0) const {
1210
+ return constellation(t_tx, dt_transit).velocity;
1209
1211
  }
1210
1212
  };
1211
1213
  public:
@@ -119,18 +119,17 @@ class GLONASS_SinglePositioning : public SolverBaseT {
119
119
  static inline const typename space_node_t::Satellite &sat(const void *ptr) {
120
120
  return *reinterpret_cast<const typename space_node_t::Satellite *>(ptr);
121
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;
122
+ static xyz_t position(const void *ptr, const gps_time_t &t_tx, const float_t &dt_transit) {
123
+ return sat(ptr).constellation(t_tx, dt_transit).position;
124
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;
125
+ static xyz_t velocity(const void *ptr, const gps_time_t &t_tx, const float_t &dt_transit) {
126
+ return sat(ptr).constellation(t_tx, dt_transit).velocity;
127
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);
128
+ static float_t clock_error(const void *ptr, const gps_time_t &t_tx) {
129
+ return sat(ptr).clock_error(t_tx);
130
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;
131
+ static float_t clock_error_dot(const void *ptr, const gps_time_t &t_tx) {
132
+ return sat(ptr).clock_error_dot(t_tx);
134
133
  }
135
134
  };
136
135
  satellite_t res = {
@@ -250,16 +249,20 @@ class GLONASS_SinglePositioning : public SolverBaseT {
250
249
 
251
250
  range -= receiver_error;
252
251
 
252
+ static const float_t &c(space_node_t::light_speed);
253
+
253
254
  // Clock correction, which will be considered in the next constellation()
254
255
  // as extra transmission time by using extra psuedo range.
255
256
  if(range_error.unknown_flag & range_error_t::SATELLITE_CLOCK){
256
- range += (sat.clock_error(time_arrival, range) * space_node_t::light_speed);
257
+ range += (sat.clock_error(time_arrival - range / c) * c);
257
258
  }else{
258
259
  range += range_error.value[range_error_t::SATELLITE_CLOCK];
259
260
  }
260
261
 
261
262
  // Calculate satellite position
262
- xyz_t sat_pos(sat.position(time_arrival, range));
263
+ float_t dt_transit(range / c);
264
+ gps_time_t t_tx(time_arrival - dt_transit);
265
+ xyz_t sat_pos(sat.position(t_tx, dt_transit));
263
266
  float_t geometric_range(usr_pos.xyz.dist(sat_pos));
264
267
 
265
268
  // Calculate residual
@@ -307,12 +310,12 @@ class GLONASS_SinglePositioning : public SolverBaseT {
307
310
 
308
311
  res.range_corrected = range;
309
312
 
310
- xyz_t rel_vel(sat.velocity(time_arrival, range) - usr_vel); // Calculate velocity
313
+ xyz_t rel_vel(sat.velocity(t_tx, dt_transit) - usr_vel); // Calculate velocity
311
314
 
312
315
  res.rate_relative_neg = res.los_neg[0] * rel_vel.x()
313
316
  + res.los_neg[1] * rel_vel.y()
314
317
  + res.los_neg[2] * rel_vel.z()
315
- + sat.clock_error_dot(time_arrival, range) * space_node_t::light_speed;
318
+ + sat.clock_error_dot(t_tx) * c;
316
319
 
317
320
  return res;
318
321
  }
@@ -1113,16 +1113,14 @@ static s ## bits ## _t name(const InputT *buf){ \
1113
1113
  * Calculate correction value in accordance with clock error model
1114
1114
  *
1115
1115
  * @param t current time
1116
- * @param pseudo_range pseudo range in meters
1117
1116
  * @param gamma factor for compensation of group delay
1118
1117
  * L1 = 1, L2 = (77/60)^2, see ICD 20.3.3.3.3.2 L1 - L2 Correction
1119
1118
  * @return in seconds
1120
1119
  */
1121
- float_t clock_error(const gps_time_t &t, const float_t &pseudo_range = 0,
1120
+ float_t clock_error(const gps_time_t &t,
1122
1121
  const float_t &gamma = 1) const{
1123
1122
 
1124
- float_t transit_time(pseudo_range / light_speed);
1125
- float_t tk(period_from_time_of_clock(t) - transit_time);
1123
+ float_t tk(period_from_time_of_clock(t));
1126
1124
  float_t Ek(eccentric_anomaly(tk));
1127
1125
 
1128
1126
  // Relativistic correction term
@@ -1134,10 +1132,9 @@ static s ## bits ## _t name(const InputT *buf){ \
1134
1132
  return dt_sv - (gamma * t_GD);
1135
1133
  }
1136
1134
 
1137
- float_t clock_error_dot(const gps_time_t &t, const float_t &pseudo_range = 0) const {
1135
+ float_t clock_error_dot(const gps_time_t &t) const {
1138
1136
 
1139
- float_t transit_time(pseudo_range / light_speed);
1140
- float_t tk(period_from_time_of_clock(t) - transit_time);
1137
+ float_t tk(period_from_time_of_clock(t));
1141
1138
  float_t Ek(eccentric_anomaly(tk));
1142
1139
  float_t Ek_dot(eccentric_anomaly_dot(Ek));
1143
1140
 
@@ -1150,17 +1147,24 @@ static s ## bits ## _t name(const InputT *buf){ \
1150
1147
  return dt_sv_dot;
1151
1148
  }
1152
1149
 
1150
+ /**
1151
+ * Return satellite position and velocity at the transmission time in EFEC.
1152
+ * @param t_tx transmission time
1153
+ * @param dt_transit Transit time. default is zero.
1154
+ * If zero, the returned value is along with the ECEF at the transmission time.
1155
+ * Otherwise (non-zero), they are along with the ECEF at the reception time,
1156
+ * that is, the transmission time added by the transit time.
1157
+ * @param with_velocity If true, velocity calculation is performed,
1158
+ * otherwise invalid velocity is returned.
1159
+ */
1153
1160
  constellation_t constellation(
1154
- const gps_time_t &t, const float_t &pseudo_range = 0,
1161
+ const gps_time_t &t_tx, const float_t &dt_transit = 0,
1155
1162
  const bool &with_velocity = true) const {
1156
1163
 
1157
1164
  constellation_t res;
1158
1165
 
1159
1166
  // Time from ephemeris reference epoch (tk)
1160
- float_t tk0(period_from_time_of_ephemeris(t));
1161
-
1162
- // Remove transit time
1163
- float_t tk(tk0 - pseudo_range / light_speed);
1167
+ float_t tk(period_from_time_of_ephemeris(t_tx));
1164
1168
 
1165
1169
  // Eccentric Anomaly (Ek)
1166
1170
  float_t Ek(eccentric_anomaly(tk));
@@ -1207,12 +1211,12 @@ static s ## bits ## _t name(const InputT *buf){ \
1207
1211
  float_t Omegak(Omega0);
1208
1212
  if(false){ // __MISUNDERSTANDING_ABOUT_OMEGA0_CORRECTION__
1209
1213
  Omegak += (
1210
- (dot_Omega0 - WGS84::Omega_Earth_IAU) * tk0
1214
+ (dot_Omega0 - WGS84::Omega_Earth_IAU) * tk
1211
1215
  - WGS84::Omega_Earth_IAU * t_oe);
1212
1216
  }else{
1213
1217
  Omegak += (
1214
- dot_Omega0 * tk // corrected with the time when the wave is transmitted
1215
- - WGS84::Omega_Earth_IAU * (t_oe + tk0)); // corrected with the time when the wave is received
1218
+ dot_Omega0 * tk // correction (at the transmission)
1219
+ - WGS84::Omega_Earth_IAU * (t_oe + tk + dt_transit)); // correction and coordinate transformation
1216
1220
  }
1217
1221
 
1218
1222
  float_t Omegak_sin(sin(Omegak)),
@@ -2013,26 +2017,26 @@ if(std::abs(TARGET - eph.TARGET) > raw_t::sf[raw_t::SF_ ## TARGET]){break;}
2013
2017
  &eph_t::period_from_time_of_clock) || is_valid;
2014
2018
  }
2015
2019
 
2016
- float_t clock_error(const gps_time_t &t, const float_t &pseudo_range = 0) const{
2017
- return ephemeris().clock_error(t, pseudo_range);
2020
+ float_t clock_error(const gps_time_t &t_tx) const{
2021
+ return ephemeris().clock_error(t_tx);
2018
2022
  }
2019
2023
 
2020
- float_t clock_error_dot(const gps_time_t &t, const float_t &pseudo_range = 0) const {
2021
- return ephemeris().clock_error_dot(t, pseudo_range);
2024
+ float_t clock_error_dot(const gps_time_t &t_tx) const {
2025
+ return ephemeris().clock_error_dot(t_tx);
2022
2026
  }
2023
2027
 
2024
2028
  typename SatelliteProperties::constellation_t constellation(
2025
- const gps_time_t &t, const float_t &pseudo_range = 0,
2029
+ const gps_time_t &t_tx, const float_t &dt_transit = 0,
2026
2030
  const bool &with_velocity = true) const {
2027
- return ephemeris().constellation(t, pseudo_range, with_velocity);
2031
+ return ephemeris().constellation(t_tx, dt_transit, with_velocity);
2028
2032
  }
2029
2033
 
2030
- xyz_t position(const gps_time_t &t, const float_t &pseudo_range = 0) const {
2031
- return constellation(t, pseudo_range, false).position;
2034
+ xyz_t position(const gps_time_t &t_tx, const float_t &dt_transit = 0) const {
2035
+ return constellation(t_tx, dt_transit, false).position;
2032
2036
  }
2033
2037
 
2034
- xyz_t velocity(const gps_time_t &t, const float_t &pseudo_range = 0) const {
2035
- return constellation(t, pseudo_range, true).velocity;
2038
+ xyz_t velocity(const gps_time_t &t_tx, const float_t &dt_transit = 0) const {
2039
+ return constellation(t_tx, dt_transit, true).velocity;
2036
2040
  }
2037
2041
  };
2038
2042
  public:
@@ -143,17 +143,17 @@ class GPS_SinglePositioning : public SolverBaseT {
143
143
  static inline const typename space_node_t::Satellite &sat(const void *ptr) {
144
144
  return *reinterpret_cast<const typename space_node_t::Satellite *>(ptr);
145
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);
146
+ static xyz_t position(const void *ptr, const gps_time_t &t_tx, const float_t &dt_transit) {
147
+ return sat(ptr).position(t_tx, dt_transit);
148
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);
149
+ static xyz_t velocity(const void *ptr, const gps_time_t &t_tx, const float_t &dt_transit) {
150
+ return sat(ptr).velocity(t_tx, dt_transit);
151
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);
152
+ static float_t clock_error(const void *ptr, const gps_time_t &t_tx) {
153
+ return sat(ptr).clock_error(t_tx);
154
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);
155
+ static float_t clock_error_dot(const void *ptr, const gps_time_t &t_tx) {
156
+ return sat(ptr).clock_error_dot(t_tx);
157
157
  }
158
158
  };
159
159
  satellite_t res = {
@@ -272,13 +272,16 @@ class GPS_SinglePositioning : public SolverBaseT {
272
272
  residual_t &residual,
273
273
  const range_error_t &error = range_error_t::not_corrected) const {
274
274
 
275
+ static const float_t &c(space_node_t::light_speed);
276
+
275
277
  // Clock error correction
276
278
  range += ((error.unknown_flag & range_error_t::SATELLITE_CLOCK)
277
- ? (sat.clock_error(time_arrival, range) * space_node_t::light_speed)
279
+ ? (sat.clock_error(time_arrival - range / c) * c)
278
280
  : error.value[range_error_t::SATELLITE_CLOCK]);
279
281
 
280
282
  // Calculate satellite position
281
- xyz_t sat_pos(sat.position(time_arrival, range));
283
+ float_t dt_transit(range / c);
284
+ xyz_t sat_pos(sat.position(time_arrival - dt_transit, dt_transit));
282
285
  float_t geometric_range(usr_pos.xyz.dist(sat_pos));
283
286
 
284
287
  // Calculate residual
@@ -344,11 +347,15 @@ class GPS_SinglePositioning : public SolverBaseT {
344
347
  const xyz_t &usr_vel,
345
348
  const float_t &los_neg_x, const float_t &los_neg_y, const float_t &los_neg_z) const {
346
349
 
347
- xyz_t rel_vel(sat.velocity(time_arrival, range) - usr_vel); // Calculate velocity
350
+ static const float_t &c(space_node_t::light_speed);
351
+
352
+ float_t dt_transit(range / c);
353
+ gps_time_t t_tx(time_arrival - dt_transit);
354
+ xyz_t rel_vel(sat.velocity(t_tx, dt_transit) - usr_vel); // Calculate velocity
348
355
  return los_neg_x * rel_vel.x()
349
356
  + los_neg_y * rel_vel.y()
350
357
  + los_neg_z * rel_vel.z()
351
- + sat.clock_error_dot(time_arrival, range) * space_node_t::light_speed; // considering clock rate error
358
+ + sat.clock_error_dot(t_tx) * c; // considering clock error rate
352
359
  }
353
360
 
354
361
  /**
@@ -230,29 +230,49 @@ struct GPS_Solver_Base {
230
230
  const void *impl;
231
231
  xyz_t (*impl_position)(const void *, const gps_time_t &, const float_t &);
232
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 &);
233
+ float_t (*impl_clock_error)(const void *, const gps_time_t &);
234
+ float_t (*impl_clock_error_dot)(const void *, const gps_time_t &);
235
235
  inline bool is_available() const {
236
236
  return impl != NULL;
237
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);
238
+ /**
239
+ * Return satellite position at the transmission time in EFEC.
240
+ * @param t_tx transmission time
241
+ * @param dt_transit Transit time. default is zero.
242
+ * If zero, the returned value is along with the ECEF at the transmission time.
243
+ * Otherwise (non-zero), they are along with the ECEF at the reception time,
244
+ * that is, the transmission time added by the transit time.
245
+ */
246
+ inline xyz_t position(const gps_time_t &t_tx, const float_t &dt_transit = 0) const {
247
+ return impl_position(impl, t_tx, dt_transit);
240
248
  }
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);
249
+ /**
250
+ * Return satellite velocity at the transmission time in EFEC.
251
+ * @see position
252
+ */
253
+ inline xyz_t velocity(const gps_time_t &t_tx, const float_t &dt_transit = 0) const {
254
+ return impl_velocity(impl, t_tx, dt_transit);
243
255
  }
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);
256
+ /**
257
+ * Return satellite clock error [s] at the transmission time.
258
+ * @param t_tx transmission time
259
+ */
260
+ inline float_t clock_error(const gps_time_t &t_tx) const {
261
+ return impl_clock_error(impl, t_tx);
246
262
  }
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);
263
+ /**
264
+ * Return satellite clock error derivative [s/s] at the transmission time.
265
+ * @param t_tx transmission time
266
+ */
267
+ inline float_t clock_error_dot(const gps_time_t &t_tx) const {
268
+ return impl_clock_error_dot(impl, t_tx);
249
269
  }
250
270
  static const satellite_t &unavailable() {
251
271
  struct impl_t {
252
272
  static xyz_t v3(const void *, const gps_time_t &, const float_t &){
253
273
  return xyz_t(0, 0, 0);
254
274
  }
255
- static float_t v(const void *, const gps_time_t &, const float_t &){
275
+ static float_t v(const void *, const gps_time_t &){
256
276
  return float_t(0);
257
277
  }
258
278
  };
@@ -1768,30 +1768,38 @@ sf[SF_ ## TARGET] * msg_t::TARGET(buf)
1768
1768
  return (delta_t < 0) || (delta_t > Timing::values[Timing::GEO_NAVIGATION_DATA].interval);
1769
1769
  }
1770
1770
 
1771
- constellation_t constellation(
1772
- const gps_time_t &t_rx, const float_t &pseudo_range = 0,
1773
- const bool &with_velocity = true) const {
1771
+ float_t clock_error(const gps_time_t &t) const {
1772
+ float_t t_G(-t.interval(WN, 0)); // t_0 is expected to be modified as time of week
1773
+ return a_Gf0 + a_Gf1 * (t_G - t_0); // Eq.(A-45), delay is positive
1774
+ }
1774
1775
 
1775
- float_t t_G(-t_rx.interval(WN, 0) - (pseudo_range / gps_space_node_t::light_speed));
1776
+ float_t clock_error_dot(const gps_time_t &t) const {
1777
+ return a_Gf1;
1778
+ }
1776
1779
 
1777
- float_t t(t_G - (a_Gf0 + a_Gf1 * (t_G - t_0))); // Eq.(A-45)
1778
- float_t t_dot(1.0 - a_Gf1);
1780
+ constellation_t constellation(
1781
+ const gps_time_t &t_tx, const float_t &dt_transit = 0,
1782
+ const bool &with_velocity = true) const {
1779
1783
 
1780
- float_t delta_t(t - t_0), delta_t2(delta_t * delta_t / 2);
1784
+ float_t delta_t(-t_tx.interval(WN, t_0)), delta_t2(delta_t * delta_t / 2);
1781
1785
 
1782
1786
  constellation_t res = {
1783
1787
  xyz_t(
1784
1788
  x + dx * delta_t + ddx * delta_t2,
1785
1789
  y + dy * delta_t + ddy * delta_t2,
1786
- z + dz * delta_t + ddz * delta_t2), // Eq. (A-44)
1790
+ z + dz * delta_t + ddz * delta_t2).after(dt_transit), // Eq. (A-44)
1787
1791
  xyz_t(
1788
- (dx + ddx * delta_t) * t_dot,
1789
- (dy + ddy * delta_t) * t_dot,
1790
- (dz + ddz * delta_t) * t_dot),
1792
+ dx + ddx * delta_t,
1793
+ dy + ddy * delta_t,
1794
+ dz + ddz * delta_t).after(dt_transit),
1791
1795
  };
1792
1796
 
1793
- // Be careful, Sagnac correction must be performed before geometric distance calculation
1794
- // @see SBAS_SpaceNode::sagnac_correction
1797
+ /* Sagnac correction, which is expected to perform before geometric distance calculation,
1798
+ * can be skipped by using non-zero dt_transit.
1799
+ * This is because the return values is corrected to be along with the coordinate
1800
+ * at the reception time.
1801
+ * @see SBAS_SpaceNode::sagnac_correction
1802
+ */
1795
1803
 
1796
1804
  return res;
1797
1805
  }