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.
- 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
|
};
|