18#include <Eigen/src/Core/Matrix.h>
24 const size_t&
AODE,
const size_t&
AODC,
25 const std::array<double, 3>&
a,
28 const double&
Cis,
const double&
Cic,
const double&
Crs,
const double&
Crc,
60BDSEphemeris::BDSEphemeris(int32_t satNum, int32_t year, int32_t month, int32_t day, int32_t hour, int32_t minute,
double second,
double svClockBias,
double svClockDrift,
double svClockDriftRate,
61 double AODE,
double Crs,
double delta_n,
double M_0,
62 double Cuc,
double e,
double Cus,
double sqrt_A,
63 double Toe,
double Cic,
double Omega_0,
double Cis,
64 double i_0,
double Crc,
double omega,
double Omega_dot,
65 double i_dot,
double ,
double BDTWeek,
double ,
66 double svAccuracy,
double satH1,
double T_GD1,
double T_GD2,
67 double ,
double AODC,
double ,
double )
69 satNum(static_cast<uint16_t>(satNum)),
72 AODE(static_cast<size_t>(AODE)),
73 AODC(static_cast<size_t>(AODC)),
74 a({ svClockBias, svClockDrift, svClockDriftRate }),
90 svAccuracy(svAccuracy),
91 satH1(
static_cast<uint8_t
>(satH1)),
109 LOG_DATA(
" A {} [m] (Semi-major axis)", A);
110 auto n_0 = std::sqrt(mu / std::pow(A, 3));
111 LOG_DATA(
" n_0 {} [rad/s] (Computed mean motion)", n_0);
113 LOG_DATA(
" n {} [rad/s] (Corrected mean motion)", n);
118 InsTime transTime = transTime0;
119 LOG_DATA(
" Iterating Time at transmission");
121 double clkDrift = 0.0;
123 for (
size_t i = 0; i < 2; i++)
128 auto t_minus_toc =
static_cast<double>((transTime -
toc).count());
129 LOG_DATA(
" transTime - toc {} [s]", t_minus_toc);
132 double t_k =
static_cast<double>((transTime -
toe).count());
133 LOG_DATA(
" transTime - toe {} [s] (t_k = Time difference from ephemeris reference epoch)", t_k);
136 auto M_k =
M_0 + n * t_k;
137 LOG_DATA(
" M_k {} [s] (Mean anomaly)", M_k);
141 double E_k_old = 0.0;
143 for (
size_t i = 0; std::abs(E_k - E_k_old) > 1
e-13 && i < 10; i++)
146 E_k = M_k +
e * sin(E_k);
150 double dt_r = F *
e *
sqrt_A * std::sin(E_k);
151 LOG_DATA(
" dt_r {} [s] (Relativistic correction term)", dt_r);
154 dt_sv =
a[0] +
a[1] * t_minus_toc +
a[2] * std::pow(t_minus_toc, 2) + dt_r;
160 LOG_DATA(
" dt_sv {} [s] (SV PRN code phase time offset)", dt_sv);
163 clkDrift =
a[1] +
a[2] / 2.0 * t_minus_toc;
166 transTime = transTime0 - std::chrono::duration<double>(dt_sv);
169 return { .transmitTime = transTime, .bias = dt_sv, .drift = clkDrift };
174 Eigen::Vector3d e_pos = Eigen::Vector3d::Zero();
175 Eigen::Vector3d e_vel = Eigen::Vector3d::Zero();
176 Eigen::Vector3d e_accel = Eigen::Vector3d::Zero();
187 LOG_DATA(
" A {} [m] (Semi-major axis)", A);
188 auto n_0 = std::sqrt(mu / std::pow(A, 3));
189 LOG_DATA(
" n_0 {} [rad/s] (Computed mean motion)", n_0);
191 LOG_DATA(
" n {} [rad/s] (Corrected mean motion)", n);
197 double t_k =
static_cast<double>((transTime -
toe).count());
198 LOG_DATA(
" t_k {} [s] (Time difference from ephemeris reference epoch)", t_k);
201 auto M_k =
M_0 + n * t_k;
202 LOG_DATA(
" M_k {} [s] (Mean anomaly)", M_k);
205 double E_k_old = 0.0;
207 LOG_DATA(
" E_k {} [rad] (Eccentric anomaly)", E_k);
208 for (
size_t i = 0; std::abs(E_k - E_k_old) > 1
e-13 && i < 10; i++)
211 E_k = E_k + (M_k - E_k +
e * std::sin(E_k)) / (1 -
e * std::cos(E_k));
212 LOG_DATA(
" E_k {} [rad] (Eccentric anomaly)", E_k);
216 auto v_k = std::atan2(std::sqrt(1 -
e *
e) * std::sin(E_k), (std::cos(E_k) -
e));
217 LOG_DATA(
" v_k {} [rad] (True Anomaly (unambiguous quadrant))", v_k);
219 auto Phi_k = v_k +
omega;
220 LOG_DATA(
" Phi_k {} [rad] (Argument of Latitude)", Phi_k);
223 auto delta_u_k =
Cus * std::sin(2 * Phi_k) +
Cuc * std::cos(2 * Phi_k);
224 LOG_DATA(
" delta_u_k {} [rad] (Argument of Latitude Correction)", delta_u_k);
225 auto delta_r_k =
Crs * std::sin(2 * Phi_k) +
Crc * std::cos(2 * Phi_k);
226 LOG_DATA(
" delta_r_k {} [m] (Radius Correction)", delta_r_k);
227 auto delta_i_k =
Cis * std::sin(2 * Phi_k) +
Cic * std::cos(2 * Phi_k);
228 LOG_DATA(
" delta_i_k {} [rad] (Inclination Correction)", delta_i_k);
230 auto u_k = Phi_k + delta_u_k;
231 LOG_DATA(
" u_k {} [rad] (Corrected Argument of Latitude)", u_k);
232 auto r_k = A * (1 -
e * std::cos(E_k)) + delta_r_k;
233 LOG_DATA(
" r_k {} [m] (Corrected Radius)", r_k);
234 auto i_k =
i_0 + delta_i_k +
i_dot * t_k;
235 LOG_DATA(
" i_k {} [rad] (Corrected Inclination)", i_k);
237 auto x_k_op = r_k * std::cos(u_k);
238 LOG_DATA(
" x_k_op {} [m] (Position in orbital plane)", x_k_op);
239 auto y_k_op = r_k * std::sin(u_k);
240 LOG_DATA(
" y_k_op {} [m] (Position in orbital plane)", y_k_op);
242 double Omega_k = 0.0;
251 LOG_DATA(
" Omega_k {} [rad] (Corrected longitude of ascending node)", Omega_k);
253 Eigen::Vector3d X_GK{ 0, 0, 0 };
255 X_GK(0) = x_k_op * std::cos(Omega_k) - y_k_op * std::cos(i_k) * std::sin(Omega_k);
256 X_GK(1) = x_k_op * std::sin(Omega_k) + y_k_op * std::cos(i_k) * std::cos(Omega_k);
257 X_GK(2) = y_k_op * std::sin(i_k);
259 auto Rx = [](
double phi) -> Eigen::Matrix3d {
262 0, std::cos(phi), std::sin(phi),
263 0, -std::sin(phi), std::cos(phi);
266 auto Rz = [](
double phi) -> Eigen::Matrix3d {
268 C << std::cos(phi), std::sin(phi), 0,
269 -std::sin(phi), std::cos(phi), 0,
274 e_pos = Rz(Omega_e_dot * t_k) * Rx(
deg2rad(-5)) * X_GK;
276 return { .e_pos = e_pos,
277 .e_vel = Eigen::Vector3d::Zero(),
278 .e_accel = Eigen::Vector3d::Zero() };
283 Omega_k =
Omega_0 + (
Omega_dot - Omega_e_dot) * t_k - Omega_e_dot *
static_cast<double>(
toe.toGPSweekTow(
BDT).tow);
284 LOG_DATA(
" Omega_k {} [rad] (Corrected longitude of ascending node)", Omega_k);
287 x_k = x_k_op * std::cos(Omega_k) - y_k_op * std::cos(i_k) * std::sin(Omega_k);
288 LOG_DATA(
" x_k {} [m] (Earth-fixed x coordinates)", x_k);
290 y_k = x_k_op * std::sin(Omega_k) + y_k_op * std::cos(i_k) * std::cos(Omega_k);
291 LOG_DATA(
" y_k {} [m] (Earth-fixed y coordinates)", y_k);
293 z_k = y_k_op * std::sin(i_k);
294 LOG_DATA(
" z_k {} [m] (Earth-fixed z coordinates)", z_k);
296 e_pos = Eigen::Vector3d{ x_k, y_k, z_k };
301 auto E_k_dot = n / (1 -
e * std::cos(E_k));
303 auto v_k_dot = E_k_dot * std::sqrt(1 -
e *
e) / (1 -
e * std::cos(E_k));
305 auto i_k_dot =
i_dot + 2 * v_k_dot * (
Cis * std::cos(2 * Phi_k) -
Cic * std::sin(2 * Phi_k));
307 auto u_k_dot = v_k_dot + 2 * v_k_dot * (
Cus * std::cos(2 * Phi_k) -
Cuc * std::sin(2 * Phi_k));
309 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));
311 auto Omega_k_dot =
Omega_dot - Omega_e_dot;
313 auto vx_k_op = r_k_dot * std::cos(u_k) - r_k * u_k_dot * std::sin(u_k);
315 auto vy_k_op = r_k_dot * std::sin(u_k) + r_k * u_k_dot * std::cos(u_k);
317 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)
318 - 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));
320 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)
321 - 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));
323 auto vz_k = vy_k_op * std::sin(i_k) + y_k_op * i_k_dot * std::cos(i_k);
327 e_vel = Eigen::Vector3d{ vx_k, vy_k, vz_k };
335 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))
336 + 2 * vy_k * Omega_e_dot + x_k * std::pow(Omega_e_dot, 2);
338 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))
339 + 2 * vx_k * Omega_e_dot + y_k * std::pow(Omega_e_dot, 2);
341 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));
343 e_accel = Eigen::Vector3d{ ax_k, ay_k, az_k };
347 return { .e_pos = e_pos,
349 .e_accel = e_accel };
BDS Ephemeris information.
Utility class for logging to console and file.
#define LOG_DATA
All output which occurs repeatedly every time observations are received.
Structs identifying a unique satellite.
const double e
Eccentricity [-].
const double Cus
Amplitude of the sine harmonic correction term to the argument of latitude [rad].
const InsTime toe
Time of Ephemeris.
const std::array< double, 3 > a
const double delta_n
Mean motion difference from computed value [rad/s].
const double T_GD1
Equipment Group Delay Differential. B1/B3 [s].
const double svAccuracy
SV accuracy [m].
const uint8_t satH1
Autonomous Satellite Health flag.
double calcSatellitePositionVariance() const final
Calculates the Variance of the satellite position in [m^2].
PosVelAccel calcSatelliteData(const InsTime &transTime, Orbit::Calc calc) const final
Calculates position, velocity and acceleration of the satellite at transmission time.
const uint16_t satNum
Number of the satellite.
const double Crc
Amplitude of the cosine harmonic correction term to the orbit radius [m].
const double Omega_dot
Rate of change of right ascension [rad/s].
const double i_0
Inclination angle at reference time [rad].
const double Cuc
Amplitude of the cosine harmonic correction term to the argument of latitude [rad].
const double sqrt_A
Square root of the semi-major axis [m^1/2].
Corrections calcClockCorrections(const InsTime &recvTime, double dist, const Frequency &freq) const final
Calculates clock bias and drift of the satellite.
const double omega
Argument of perigee [rad].
const double Cis
Amplitude of the sine harmonic correction term to the angle of inclination [rad].
const double Omega_0
Longitude of the ascending node at reference time [rad].
const InsTime toc
Time of Clock.
const double M_0
Mean anomaly at reference time [rad].
const double Crs
Amplitude of the sine harmonic correction term to the orbit radius [m].
const double T_GD2
Equipment Group Delay Differential. B2/B3 [s].
const double i_dot
Rate of change of inclination [rad/s].
const double Cic
Amplitude of the cosine harmonic correction term to the angle of inclination [rad].
bool isHealthy() const final
Checks whether the signal is healthy.
const size_t AODC
Age of Data, Clock.
const size_t AODE
Age of Data, Ephemeris.
BDSEphemeris(const uint16_t &satNum, const InsTime &toc, const InsTime &toe, const size_t &AODE, const size_t &AODC, const std::array< double, 3 > &a, const double &sqrt_A, const double &e, const double &i_0, const double &Omega_0, const double &omega, const double &M_0, const double &delta_n, const double &Omega_dot, const double &i_dot, const double &Cus, const double &Cuc, const double &Cis, const double &Cic, const double &Crs, const double &Crc, const double &svAccuracy, uint8_t satH1, double T_GD1, double T_GD2)
Constructor.
Frequency definition for different satellite systems.
static constexpr double F
Relativistic constant F for clock corrections [s/√m] (-2*√µ/c²)
static constexpr double omega_ie
Earth angular velocity BeiDou (CGCS2000) [rad/s].
static constexpr double MU
Earth gravitational constant BeiDou (CGCS2000) [m³/s²].
static constexpr double R_E
Earth Equatorial Radius [m].
static constexpr double J2
Oblate Earth Gravity Coefficient [-].
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.
@ 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.
@ BeiDouEphemeris
BeiDou Broadcast Ephemeris.
Utility Namespace for Time related tasks.
@ B02
Beidou B1-2 (B1I) (1561.098 MHz).
@ B07
Beidou B2b (B2I) (1207.14 MHz).
constexpr auto deg2rad(const T °)
Convert Degree to Radians.
Satellite clock corrections.
Satellite Position, Velocity and Acceleration.
Identifies a satellite (satellite system and number)