gps_pvt 0.5.1 → 0.6.2

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.
@@ -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
  }
@@ -452,7 +452,7 @@ struct GPS_Time {
452
452
  struct {
453
453
  int week;
454
454
  float_t seconds;
455
- } uncorrected; // to work around of "incomplete type" error within g++
455
+ } uncorrected, corrected; // to work around of "incomplete type" error within g++
456
456
  leap_second_event_t(
457
457
  const int &year, const int &month, const int &day,
458
458
  const int &leap)
@@ -462,9 +462,11 @@ struct GPS_Time {
462
462
  t.tm_year = tm_year;
463
463
  t.tm_mon = tm_mon;
464
464
  t.tm_mday = tm_mday;
465
- GPS_Time t_gps(t);
466
- uncorrected.week = t_gps.week;
467
- uncorrected.seconds = t_gps.seconds;
465
+ GPS_Time t_gps_uc(t), t_gps(t_gps_uc + leap);
466
+ uncorrected.week = t_gps_uc.week;
467
+ uncorrected.seconds = t_gps_uc.seconds;
468
+ corrected.week = t_gps.week;
469
+ corrected.seconds = t_gps.seconds;
468
470
  }
469
471
  };
470
472
  static const leap_second_event_t leap_second_events[];
@@ -484,6 +486,92 @@ struct GPS_Time {
484
486
  }
485
487
  return 0;
486
488
  }
489
+
490
+ int leap_seconds() const {
491
+ // Treat *this as (normal) GPS time, to which leap seconds are added when it is converted from std::tm
492
+ for(const leap_second_event_t *i(&leap_second_events[0]); i->leap_seconds > 0; ++i){
493
+ if(*this >= GPS_Time(i->corrected.week, i->corrected.seconds)){return i->leap_seconds;}
494
+ }
495
+ return 0;
496
+ }
497
+ float_t julian_date() const {
498
+ struct conv_t {
499
+ static int ymd2jd(const int &year, const int &month, const int &day){
500
+ // @see https://en.wikipedia.org/wiki/Julian_day#Converting_Gregorian_calendar_date_to_Julian_Day_Number
501
+ return std::div(1461 * (year + 4800 + std::div(month - 14, 12).quot), 4).quot
502
+ + std::div(367 * (month - 2 - 12 * std::div((month - 14), 12).quot), 12).quot
503
+ - std::div(3 * std::div((year + 4900 + std::div(month - 14, 12).quot), 100).quot, 4).quot
504
+ + day - 32075;
505
+ }
506
+ };
507
+ // origin of Julian day is "noon (not midnight)" BC4713/1/1
508
+ static const float_t t0(conv_t::ymd2jd(1980, 1, 6) - 0.5);
509
+ // GPS Time is advanced by leap seconds compared with UTC.
510
+ // The following calculation is incorrect for a day in which a leap second is inserted or truncated.
511
+ // @see https://en.wikipedia.org/wiki/Julian_day#Julian_date_calculation
512
+ return t0 + week * 7 + (seconds - leap_seconds()) / seconds_day;
513
+ }
514
+ float_t julian_date_2000() const {
515
+ static const std::tm tm_2000 = {0, 0, 12, 1, 0, 2000 - 1900};
516
+ static const float_t jd2000(GPS_Time(tm_2000, 13).julian_date());
517
+ return julian_date() - jd2000;
518
+ }
519
+ std::tm utc() const {return c_tm(leap_seconds());}
520
+
521
+ float_t greenwich_mean_sidereal_time_sec_ires1996(const float_t &delta_ut1 = float_t(0)) const {
522
+ float_t jd2000(julian_date_2000() + delta_ut1 / seconds_day);
523
+ float_t jd2000_day(float_t(0.5) + std::floor(jd2000 - 0.5)); // +/-0.5, +/-1.5, ...
524
+
525
+ // @see Chapter 2 of Orbits(978-3540785217) by Xu Guochang
526
+ // @see Chapter 5 of IERS Conventions (1996) https://www.iers.org/IERS/EN/Publications/TechnicalNotes/tn21.html
527
+ float_t jc(jd2000_day / 36525), // Julian century
528
+ jc2(std::pow(jc, 2)), jc3(std::pow(jc, 3));
529
+ float_t gmst0(24110.54841 // = 6h 41m 50.54841s
530
+ + jc * 8640184.812866
531
+ + jc2 * 0.093104
532
+ - jc3 * 6.2E-6);
533
+ // ratio of universal to sidereal time as given by Aoki et al. (1982)
534
+ float_t r(1.002737909350795 // 7.2921158553E-5 = 1.002737909350795 / 86400 * 2pi
535
+ + jc * 5.9006E-11 // 4.3E-15 = 5.9E-11 / 86400 * 2pi
536
+ - jc2 * 5.9E-15); // in seconds
537
+ return gmst0 + r * (jd2000 - jd2000_day) * seconds_day;
538
+ }
539
+
540
+ /**
541
+ * ERA (Earth rotation rate) defined in Sec. 5.5.3 in IERS 2010(Technical Note No.36)
542
+ */
543
+ float_t earth_rotation_angle(const float_t &delta_ut1 = float_t(0),
544
+ const float_t &scale_factor = float_t(M_PI * 2)) const {
545
+ float_t jd2000(julian_date_2000() + delta_ut1 / seconds_day);
546
+ return (jd2000 * 1.00273781191135448 + 0.7790572732640) * scale_factor; // Eq.(5.14)
547
+ }
548
+
549
+ float_t greenwich_mean_sidereal_time_sec_ires2010(const float_t &delta_ut1 = float_t(0)) const {
550
+ float_t era(earth_rotation_angle(delta_ut1, seconds_day));
551
+
552
+ float_t t(julian_date_2000() / 36525);
553
+ // @see Eq.(5.32) Chapter 5 of IERS Conventions (2010)
554
+ #define AS2SEC(as) (((float_t)seconds_day / (360 * 3600)) * (as))
555
+ return era
556
+ + AS2SEC(0.014506)
557
+ + t * AS2SEC(4612.156534)
558
+ + std::pow(t, 2) * AS2SEC(1.3915817)
559
+ - std::pow(t, 3) * AS2SEC(0.00000044)
560
+ - std::pow(t, 4) * AS2SEC(0.000029956)
561
+ - std::pow(t, 5) * AS2SEC(0.0000000368);
562
+ #undef AS2SEC
563
+ }
564
+
565
+ /**
566
+ * Calculate Greenwich mean sidereal time (GMST) in seconds
567
+ * Internally, greenwich_mean_sidereal_time_sec_ired2010() is called.
568
+ * @param delta_ut1 time difference of UTC and UT1; UT1 = UTC + delta_UT1,
569
+ * @return GMST in seconds. 86400 seconds correspond to one rotation
570
+ * @see greenwich_mean_sidereal_time_sec_ires2010()
571
+ */
572
+ float_t greenwich_mean_sidereal_time_sec(const float_t &delta_ut1 = float_t(0)) const {
573
+ return greenwich_mean_sidereal_time_sec_ires2010(delta_ut1);
574
+ }
487
575
  };
488
576
 
489
577
  template <class FloatT>
@@ -1025,16 +1113,14 @@ static s ## bits ## _t name(const InputT *buf){ \
1025
1113
  * Calculate correction value in accordance with clock error model
1026
1114
  *
1027
1115
  * @param t current time
1028
- * @param pseudo_range pseudo range in meters
1029
1116
  * @param gamma factor for compensation of group delay
1030
1117
  * L1 = 1, L2 = (77/60)^2, see ICD 20.3.3.3.3.2 L1 - L2 Correction
1031
1118
  * @return in seconds
1032
1119
  */
1033
- 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,
1034
1121
  const float_t &gamma = 1) const{
1035
1122
 
1036
- float_t transit_time(pseudo_range / light_speed);
1037
- float_t tk(period_from_time_of_clock(t) - transit_time);
1123
+ float_t tk(period_from_time_of_clock(t));
1038
1124
  float_t Ek(eccentric_anomaly(tk));
1039
1125
 
1040
1126
  // Relativistic correction term
@@ -1046,10 +1132,9 @@ static s ## bits ## _t name(const InputT *buf){ \
1046
1132
  return dt_sv - (gamma * t_GD);
1047
1133
  }
1048
1134
 
1049
- 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 {
1050
1136
 
1051
- float_t transit_time(pseudo_range / light_speed);
1052
- float_t tk(period_from_time_of_clock(t) - transit_time);
1137
+ float_t tk(period_from_time_of_clock(t));
1053
1138
  float_t Ek(eccentric_anomaly(tk));
1054
1139
  float_t Ek_dot(eccentric_anomaly_dot(Ek));
1055
1140
 
@@ -1062,17 +1147,24 @@ static s ## bits ## _t name(const InputT *buf){ \
1062
1147
  return dt_sv_dot;
1063
1148
  }
1064
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
+ */
1065
1160
  constellation_t constellation(
1066
- const gps_time_t &t, const float_t &pseudo_range = 0,
1161
+ const gps_time_t &t_tx, const float_t &dt_transit = 0,
1067
1162
  const bool &with_velocity = true) const {
1068
1163
 
1069
1164
  constellation_t res;
1070
1165
 
1071
1166
  // Time from ephemeris reference epoch (tk)
1072
- float_t tk0(period_from_time_of_ephemeris(t));
1073
-
1074
- // Remove transit time
1075
- float_t tk(tk0 - pseudo_range / light_speed);
1167
+ float_t tk(period_from_time_of_ephemeris(t_tx));
1076
1168
 
1077
1169
  // Eccentric Anomaly (Ek)
1078
1170
  float_t Ek(eccentric_anomaly(tk));
@@ -1119,12 +1211,12 @@ static s ## bits ## _t name(const InputT *buf){ \
1119
1211
  float_t Omegak(Omega0);
1120
1212
  if(false){ // __MISUNDERSTANDING_ABOUT_OMEGA0_CORRECTION__
1121
1213
  Omegak += (
1122
- (dot_Omega0 - WGS84::Omega_Earth_IAU) * tk0
1214
+ (dot_Omega0 - WGS84::Omega_Earth_IAU) * tk
1123
1215
  - WGS84::Omega_Earth_IAU * t_oe);
1124
1216
  }else{
1125
1217
  Omegak += (
1126
- dot_Omega0 * tk // corrected with the time when the wave is transmitted
1127
- - 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
1128
1220
  }
1129
1221
 
1130
1222
  float_t Omegak_sin(sin(Omegak)),
@@ -1925,26 +2017,26 @@ if(std::abs(TARGET - eph.TARGET) > raw_t::sf[raw_t::SF_ ## TARGET]){break;}
1925
2017
  &eph_t::period_from_time_of_clock) || is_valid;
1926
2018
  }
1927
2019
 
1928
- float_t clock_error(const gps_time_t &t, const float_t &pseudo_range = 0) const{
1929
- 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);
1930
2022
  }
1931
2023
 
1932
- float_t clock_error_dot(const gps_time_t &t, const float_t &pseudo_range = 0) const {
1933
- 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);
1934
2026
  }
1935
2027
 
1936
2028
  typename SatelliteProperties::constellation_t constellation(
1937
- const gps_time_t &t, const float_t &pseudo_range = 0,
2029
+ const gps_time_t &t_tx, const float_t &dt_transit = 0,
1938
2030
  const bool &with_velocity = true) const {
1939
- return ephemeris().constellation(t, pseudo_range, with_velocity);
2031
+ return ephemeris().constellation(t_tx, dt_transit, with_velocity);
1940
2032
  }
1941
2033
 
1942
- xyz_t position(const gps_time_t &t, const float_t &pseudo_range = 0) const {
1943
- 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;
1944
2036
  }
1945
2037
 
1946
- xyz_t velocity(const gps_time_t &t, const float_t &pseudo_range = 0) const {
1947
- 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;
1948
2040
  }
1949
2041
  };
1950
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,25 +230,53 @@ 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
- static const satellite_t res = {NULL};
271
+ struct impl_t {
272
+ static xyz_t v3(const void *, const gps_time_t &, const float_t &){
273
+ return xyz_t(0, 0, 0);
274
+ }
275
+ static float_t v(const void *, const gps_time_t &){
276
+ return float_t(0);
277
+ }
278
+ };
279
+ static const satellite_t res = {NULL, impl_t::v3, impl_t::v3, impl_t::v, impl_t::v};
252
280
  return res;
253
281
  }
254
282
  };