23 const size_t&
IODE,
const size_t&
IODC,
24 const std::array<double, 3>&
a,
27 const double&
Cis,
const double&
Cic,
const double&
Crs,
const double&
Crc,
62GPSEphemeris::GPSEphemeris(int32_t year, int32_t month, int32_t day, int32_t hour, int32_t minute,
double second,
double svClockBias,
double svClockDrift,
double svClockDriftRate,
63 double IODE,
double Crs,
double delta_n,
double M_0,
64 double Cuc,
double e,
double Cus,
double sqrt_A,
65 double Toe,
double Cic,
double Omega_0,
double Cis,
66 double i_0,
double Crc,
double omega,
double Omega_dot,
67 double i_dot,
double L2ChannelCodes,
double GPSWeek,
double L2DataFlagPCode,
68 double svAccuracy,
double svHealth,
double T_GD,
double IODC,
69 double ,
double fitInterval,
double ,
double )
73 IODE(static_cast<size_t>(IODE)),
74 IODC(static_cast<size_t>(IODC)),
75 a({ svClockBias, svClockDrift, svClockDriftRate }),
91 svAccuracy(svAccuracy),
92 svHealth(
static_cast<uint8_t
>(svHealth)),
93 L2ChannelCodes(
static_cast<uint8_t
>(L2ChannelCodes)),
94 L2DataFlagPCode(
static_cast<bool>(L2DataFlagPCode)),
96 fitInterval(fitInterval)
112 LOG_DATA(
" A {} [m] (Semi-major axis)", A);
113 auto n_0 = std::sqrt(mu / std::pow(A, 3));
114 LOG_DATA(
" n_0 {} [rad/s] (Computed mean motion)", n_0);
116 LOG_DATA(
" n {} [rad/s] (Corrected mean motion)", n);
121 InsTime transTime = transTime0;
122 LOG_DATA(
" Iterating Time at transmission");
124 double clkDrift = 0.0;
126 for (
size_t i = 0; i < 2; i++)
132 auto t_minus_toc =
static_cast<double>((transTime -
toc).count());
133 LOG_DATA(
" transTime - toc {} [s]", t_minus_toc);
136 double t_k =
static_cast<double>((transTime -
toe).count());
137 LOG_DATA(
" transTime - toe {} [s] (t_k = Time difference from ephemeris reference epoch)", t_k);
140 auto M_k =
M_0 + n * t_k;
141 LOG_DATA(
" M_k {} [s] (Mean anomaly)", M_k);
145 double E_k_old = 0.0;
147 for (
size_t i = 0; std::abs(E_k - E_k_old) > 1
e-13 && i < 10; i++)
150 E_k = M_k +
e * sin(E_k);
154 double dt_r = F *
e *
sqrt_A * std::sin(E_k);
155 LOG_DATA(
" dt_r {} [s] (Relativistic correction term)", dt_r);
158 dt_sv =
a[0] +
a[1] * t_minus_toc +
a[2] * std::pow(t_minus_toc, 2) + dt_r;
164 LOG_DATA(
" dt_sv {} [s] (SV PRN code phase time offset)", dt_sv);
167 clkDrift =
a[1] +
a[2] / 2.0 * t_minus_toc;
170 transTime = transTime0 - std::chrono::duration<double>(dt_sv);
174 return { .transmitTime = transTime, .bias = dt_sv, .drift = clkDrift };
179 Eigen::Vector3d e_pos = Eigen::Vector3d::Zero();
180 Eigen::Vector3d e_vel = Eigen::Vector3d::Zero();
181 Eigen::Vector3d e_accel = Eigen::Vector3d::Zero();
189 LOG_DATA(
" toe {} (Time of ephemeris)",
toe.toGPSweekTow());
192 LOG_DATA(
" A {} [m] (Semi-major axis)", A);
193 auto n_0 = std::sqrt(mu / std::pow(A, 3));
194 LOG_DATA(
" n_0 {} [rad/s] (Computed mean motion)", n_0);
196 LOG_DATA(
" n {} [rad/s] (Corrected mean motion)", n);
202 double t_k =
static_cast<double>((transTime -
toe).count());
203 LOG_DATA(
" t_k {} [s] (Time difference from ephemeris reference epoch)", t_k);
206 auto M_k =
M_0 + n * t_k;
207 LOG_DATA(
" M_k {} [s] (Mean anomaly)", M_k);
210 double E_k_old = 0.0;
212 LOG_DATA(
" E_k {} [rad] (Eccentric anomaly)", E_k);
213 for (
size_t i = 0; std::abs(E_k - E_k_old) > 1
e-13 && i < 10; i++)
216 E_k = E_k + (M_k - E_k +
e * std::sin(E_k)) / (1 -
e * std::cos(E_k));
217 LOG_DATA(
" E_k {} [rad] (Eccentric anomaly)", E_k);
222 auto v_k = std::atan2(std::sqrt(1 -
e *
e) * std::sin(E_k), (std::cos(E_k) -
e));
223 LOG_DATA(
" v_k {} [rad] (True Anomaly (unambiguous quadrant))", v_k);
224 auto Phi_k = v_k +
omega;
225 LOG_DATA(
" Phi_k {} [rad] (Argument of Latitude)", Phi_k);
228 auto delta_u_k =
Cus * std::sin(2 * Phi_k) +
Cuc * std::cos(2 * Phi_k);
229 LOG_DATA(
" delta_u_k {} [rad] (Argument of Latitude Correction)", delta_u_k);
230 auto delta_r_k =
Crs * std::sin(2 * Phi_k) +
Crc * std::cos(2 * Phi_k);
231 LOG_DATA(
" delta_r_k {} [m] (Radius Correction)", delta_r_k);
232 auto delta_i_k =
Cis * std::sin(2 * Phi_k) +
Cic * std::cos(2 * Phi_k);
233 LOG_DATA(
" delta_i_k {} [rad] (Inclination Correction)", delta_i_k);
235 auto u_k = Phi_k + delta_u_k;
236 LOG_DATA(
" u_k {} [rad] (Corrected Argument of Latitude)", u_k);
237 auto r_k = A * (1 -
e * std::cos(E_k)) + delta_r_k;
238 LOG_DATA(
" r_k {} [m] (Corrected Radius)", r_k);
239 auto i_k =
i_0 + delta_i_k +
i_dot * t_k;
240 LOG_DATA(
" i_k {} [rad] (Corrected Inclination)", i_k);
242 auto x_k_op = r_k * std::cos(u_k);
243 LOG_DATA(
" x_k_op {} [m] (Position in orbital plane)", x_k_op);
244 auto y_k_op = r_k * std::sin(u_k);
245 LOG_DATA(
" y_k_op {} [m] (Position in orbital plane)", y_k_op);
248 auto Omega_k =
Omega_0 + (
Omega_dot - Omega_e_dot) * t_k - Omega_e_dot *
static_cast<double>(
toe.toGPSweekTow().tow);
249 LOG_DATA(
" Omega_k {} [rad] (Corrected longitude of ascending node)", Omega_k);
252 auto x_k = x_k_op * std::cos(Omega_k) - y_k_op * std::cos(i_k) * std::sin(Omega_k);
253 LOG_DATA(
" x_k {} [m] (Earth-fixed x coordinates)", x_k);
255 auto y_k = x_k_op * std::sin(Omega_k) + y_k_op * std::cos(i_k) * std::cos(Omega_k);
256 LOG_DATA(
" y_k {} [m] (Earth-fixed y coordinates)", y_k);
258 auto z_k = y_k_op * std::sin(i_k);
259 LOG_DATA(
" z_k {} [m] (Earth-fixed z coordinates)", z_k);
261 e_pos = Eigen::Vector3d{ x_k, y_k, z_k };
266 auto E_k_dot = n / (1 -
e * std::cos(E_k));
268 auto v_k_dot = E_k_dot * std::sqrt(1 -
e *
e) / (1 -
e * std::cos(E_k));
270 auto i_k_dot =
i_dot + 2 * v_k_dot * (
Cis * std::cos(2 * Phi_k) -
Cic * std::sin(2 * Phi_k));
272 auto u_k_dot = v_k_dot + 2 * v_k_dot * (
Cus * std::cos(2 * Phi_k) -
Cuc * std::sin(2 * Phi_k));
274 auto r_k_dot =
e * A * E_k_dot * std::sin(E_k) + 2 * v_k_dot * (
Crs * std::cos(2 * Phi_k) -
Crc * std::sin(2 * Phi_k));
276 auto Omega_k_dot =
Omega_dot - Omega_e_dot;
278 auto vx_k_op = r_k_dot * std::cos(u_k) - r_k * u_k_dot * std::sin(u_k);
280 auto vy_k_op = r_k_dot * std::sin(u_k) + r_k * u_k_dot * std::cos(u_k);
282 auto vx_k = -x_k_op * Omega_k_dot * std::sin(Omega_k) + vx_k_op * std::cos(Omega_k) - vy_k_op * std::sin(Omega_k) * std::cos(i_k)
283 - y_k_op * (Omega_k_dot * std::cos(Omega_k) * std::cos(i_k) - i_k_dot * std::sin(Omega_k) * std::sin(i_k));
285 auto vy_k = x_k_op * Omega_k_dot * std::cos(Omega_k) + vx_k_op * std::sin(Omega_k) + vy_k_op * std::cos(Omega_k) * std::cos(i_k)
286 - y_k_op * (Omega_k_dot * std::sin(Omega_k) * std::cos(i_k) + i_k_dot * std::cos(Omega_k) * std::sin(i_k));
288 auto vz_k = vy_k_op * std::sin(i_k) + y_k_op * i_k_dot * std::cos(i_k);
292 e_vel = Eigen::Vector3d{ vx_k, vy_k, vz_k };
300 auto ax_k = -mu * (x_k / std::pow(r_k, 3)) + F * ((1.0 - 5.0 * std::pow(z_k / r_k, 2)) * (x_k / r_k))
301 + 2 * vy_k * Omega_e_dot + x_k * std::pow(Omega_e_dot, 2);
303 auto ay_k = -mu * (y_k / std::pow(r_k, 3)) + F * ((1.0 - 5.0 * std::pow(z_k / r_k, 2)) * (y_k / r_k))
304 + 2 * vx_k * Omega_e_dot + y_k * std::pow(Omega_e_dot, 2);
306 auto az_k = -mu * (z_k / std::pow(r_k, 3)) + F * ((3.0 - 5.0 * std::pow(z_k / r_k, 2)) * (z_k / r_k));
308 e_accel = Eigen::Vector3d{ ax_k, ay_k, az_k };
312 return { .e_pos = e_pos,
314 .e_accel = e_accel };
GPS Ephemeris information.
Utility class for logging to console and file.
#define LOG_DATA
All output which occurs repeatedly every time observations are received.
Frequency definition for different satellite systems.
Broadcasted ephemeris message data.
double Crc
Amplitude of the cosine harmonic correction term to the orbit radius [m].
double Cuc
Amplitude of the cosine harmonic correction term to the argument of latitude [rad].
bool isHealthy() const final
Checks whether the signal is healthy.
double i_dot
Rate of change of inclination [rad/s].
double svAccuracy
SV accuracy [m].
size_t IODC
Issue of Data, Clock.
double Cic
Amplitude of the cosine harmonic correction term to the angle of inclination [rad].
double T_GD
Estimated Group Delay Differential. L1 and L2 correction term [s].
double Cus
Amplitude of the sine harmonic correction term to the argument of latitude [rad].
double i_0
Inclination angle at reference time [rad].
Corrections calcClockCorrections(const InsTime &recvTime, double dist, const Frequency &freq) const final
Calculates clock bias and drift of the satellite.
double delta_n
Mean motion difference from computed value [rad/s].
bool L2DataFlagPCode
Data Flag for L2 P-Code.
std::array< double, 3 > a
uint8_t L2ChannelCodes
Indicate which code(s) is (are) commanded ON for the in-phase component of the L2 channel.
double sqrt_A
Square root of the semi-major axis [m^1/2].
double omega
Argument of perigee [rad].
GPSEphemeris(const InsTime &toc)
Default Constructor.
double calcSatellitePositionVariance() const final
Calculates the Variance of the satellite position in [m^2].
uint8_t svHealth
SV health.
double M_0
Mean anomaly at reference time [rad].
double Omega_dot
Rate of change of right ascension [rad/s].
size_t IODE
Issue of Data, Ephemeris.
PosVelAccel calcSatelliteData(const InsTime &transTime, Orbit::Calc calc) const final
Calculates position, velocity and acceleration of the satellite at transmission time.
double fitInterval
Fit Interval of ephemerides [h].
InsTime toc
Time of Clock.
double Cis
Amplitude of the sine harmonic correction term to the angle of inclination [rad].
double Crs
Amplitude of the sine harmonic correction term to the orbit radius [m].
double e
Eccentricity [-].
double Omega_0
Longitude of the ascending node at reference time [rad].
InsTime toe
Time of Ephemeris.
static constexpr double R_E
Earth Equatorial Radius [m].
static constexpr double J2
Oblate Earth Gravity Coefficient [-].
static constexpr double F
Relativistic constant F for GPS clock corrections [s/√m] (-2*√µ/c²)
static constexpr double MU
Gravitational constant GPS [m³/s²]. See is-gps-200m IS-GPS-200M p. 106.
static constexpr double omega_ie
Earth angular velocity GPS [rad/s]. See is-gps-200m IS-GPS-200M p. 106.
static constexpr double C
Speed of light [m/s].
The class is responsible for all time-related tasks.
constexpr InsTime_GPSweekTow toGPSweekTow(TimeSystem timesys=GPST) const
Converts this time object into a different format.
constexpr InsTime_YMDHMS toYMDHMS(TimeSystem timesys=UTC, int digits=-1) const
Converts this time object into a different format.
@ Calc_Velocity
Velocity calculation flag.
@ Calc_Acceleration
Acceleration calculation flag.
Satellite Navigation data (to calculate SatNavData and clock)
SatNavData(Type type, const InsTime &refTime)
Constructor.
@ GPSEphemeris
GPS Broadcast Ephemeris.
double ratioFreqSquared(Frequency f1, Frequency f2, int8_t num1, int8_t num2)
Calculates the ration of the frequencies squared γ
@ G01
GPS L1 (1575.42 MHz).
@ G05
GPS L5 (1176.45 MHz).
@ GPS
Global Positioning System.
Satellite clock corrections.
Satellite Position, Velocity and Acceleration.