gps_pvt 0.5.1 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
  };