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.
- checksums.yaml +4 -4
- data/README.md +11 -7
- data/Rakefile +42 -23
- data/exe/gps_pvt +13 -6
- data/ext/gps_pvt/Coordinate/Coordinate_wrap.cxx +44 -0
- data/ext/gps_pvt/GPS/GPS_wrap.cxx +9015 -7695
- data/ext/ninja-scan-light/tool/algorithm/interpolate.h +121 -0
- data/ext/ninja-scan-light/tool/navigation/ANTEX.h +747 -0
- data/ext/ninja-scan-light/tool/navigation/GLONASS.h +37 -35
- data/ext/ninja-scan-light/tool/navigation/GLONASS_Solver.h +16 -13
- data/ext/ninja-scan-light/tool/navigation/GPS.h +121 -29
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver.h +19 -12
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver_Base.h +39 -11
- data/ext/ninja-scan-light/tool/navigation/RINEX.h +40 -171
- data/ext/ninja-scan-light/tool/navigation/SBAS.h +21 -13
- data/ext/ninja-scan-light/tool/navigation/SBAS_Solver.h +19 -16
- data/ext/ninja-scan-light/tool/navigation/SP3.h +1189 -0
- data/ext/ninja-scan-light/tool/navigation/coordinate.h +81 -1
- data/ext/ninja-scan-light/tool/swig/GPS.i +153 -40
- data/ext/ninja-scan-light/tool/swig/spec/GPS_spec.rb +503 -0
- data/ext/ninja-scan-light/tool/util/text_helper.h +248 -0
- data/lib/gps_pvt/receiver.rb +24 -0
- data/lib/gps_pvt/util.rb +25 -7
- data/lib/gps_pvt/version.rb +1 -1
- metadata +6 -2
@@ -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(
|
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
|
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
|
-
|
1011
|
-
|
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 &
|
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(
|
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
|
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 &
|
1081
|
+
const float_t &t_depature_glonass, const float_t &dt_transit = 0) const {
|
1082
1082
|
return calculate_constellation(
|
1083
|
-
|
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
|
-
|
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> &
|
1117
|
-
return this->calculate_constellation(
|
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> &
|
1134
|
-
float_t delta_t(
|
1135
|
-
float_t
|
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(
|
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(
|
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
|
-
|
1145
|
+
delta_t_depature_from_t_0 -= delta_t_updated;
|
1147
1146
|
}
|
1148
1147
|
|
1149
|
-
return eph_t::constellation_abs(
|
1150
|
-
.rel_corrdinate(
|
1151
|
-
eph_t::sidereal_t_b_rad + (eph_t::constellation_t::omega_E * delta_t));
|
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> &
|
1194
|
-
return ephemeris().clock_error(
|
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> &
|
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(
|
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> &
|
1204
|
-
return constellation(
|
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> &
|
1208
|
-
return constellation(
|
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 &
|
123
|
-
return sat(ptr).constellation(
|
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 &
|
126
|
-
return sat(ptr).constellation(
|
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 &
|
129
|
-
return sat(ptr).clock_error(
|
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 &
|
132
|
-
|
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
|
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
|
-
|
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(
|
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(
|
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
|
466
|
-
uncorrected.week =
|
467
|
-
uncorrected.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,
|
1120
|
+
float_t clock_error(const gps_time_t &t,
|
1034
1121
|
const float_t &gamma = 1) const{
|
1035
1122
|
|
1036
|
-
float_t
|
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
|
1135
|
+
float_t clock_error_dot(const gps_time_t &t) const {
|
1050
1136
|
|
1051
|
-
float_t
|
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 &
|
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
|
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) *
|
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
|
1127
|
-
- WGS84::Omega_Earth_IAU * (t_oe +
|
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 &
|
1929
|
-
return ephemeris().clock_error(
|
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 &
|
1933
|
-
return ephemeris().clock_error_dot(
|
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 &
|
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(
|
2031
|
+
return ephemeris().constellation(t_tx, dt_transit, with_velocity);
|
1940
2032
|
}
|
1941
2033
|
|
1942
|
-
xyz_t position(const gps_time_t &
|
1943
|
-
return constellation(
|
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 &
|
1947
|
-
return constellation(
|
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 &
|
147
|
-
return sat(ptr).position(
|
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 &
|
150
|
-
return sat(ptr).velocity(
|
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 &
|
153
|
-
return sat(ptr).clock_error(
|
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 &
|
156
|
-
return sat(ptr).clock_error_dot(
|
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
|
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
|
-
|
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
|
-
|
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(
|
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
|
234
|
-
float_t (*impl_clock_error_dot)(const void *, const gps_time_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
|
-
|
239
|
-
|
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
|
-
|
242
|
-
|
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
|
-
|
245
|
-
|
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
|
-
|
248
|
-
|
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 {
|
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
|
};
|