Class GnssYawSteering

Class Documentation

class GnssYawSteering

GNSS satellite yaw-attitude steering laws (Cheng et al., 2025).

All angles are in radians and all angular rates are in rad/s, in keeping with the rest of lupnt (the empirical constants from the paper, e.g. 0.11 deg/s, 3 deg, are converted internally via RAD). All functions are stateless static members; the class exists purely to namespace the laws (mirroring GnssAttitude/AntexLoader).

Public Functions

GnssYawSteering() = delete

Public Static Functions

static Real BetaAngle(const Vec3 &r_sat, const Vec3 &v_sat, const Vec3 &r_sun)

Sun elevation angle beta above the orbital plane [rad]. beta = asin(n . s_hat), where n = (r x v)/|r x v| is the orbit normal (angular-momentum direction) and s_hat = r_sun/|r_sun|.

Step 1 of the yaw-steering pipeline described above: called by GnssAttitude::Compute(r_sat_eci, v_sat_eci, r_sun_eci, ...) to derive the satellite-Sun-Earth geometry needed to evaluate NominalYawAngle.

Parameters:
  • r_satSatellite position (ECI or any inertial frame) [m]

  • v_satSatellite velocity, in the same frame as r_sat [m/s]

  • r_sun – Sun position, in the same frame as r_sat [m]

static Real OrbitAngle(const Vec3 &r_sat, const Vec3 &v_sat, const Vec3 &r_sun)

Orbit angle mu [rad]: the geocentric angle, in the orbital plane and in the direction of motion, from the orbit “midnight point” to the satellite (mu = 0 at the midnight point, mu = +/-pi at the “noon point”, mu increases in the direction of orbital motion).

Step 1 of the yaw-steering pipeline described above: called alongside BetaAngle by GnssAttitude::Compute(r_sat_eci, v_sat_eci, r_sun_eci, / ...) to derive the satellite-Sun-Earth geometry needed to evaluate NominalYawAngle.

Parameters:
  • r_satSatellite position (ECI or any inertial frame) [m]

  • v_satSatellite velocity, in the same frame as r_sat [m/s]

  • r_sun – Sun position, in the same frame as r_sat [m]

static Real OrbitNoonAngle(Real mu)

Convert a midnight-point-referenced orbit angle mu to the noon-point-referenced orbit angle eta used in Eq. (9): the noon point is diametrically opposite ( +/- pi ) the midnight point along the orbit, so eta = WrapToPi(mu - pi).

Bridges OrbitAngle’s midnight-referenced mu (used by NominalYawAngle/GnssAttitude) to the noon-referenced eta convention used by the Galileo IOV laws below (GalileoSunVector/GalileoIovNominalYawAngle/GalileoIovEclipseYawAngle).

Parameters:

mu – Orbit angle from the midnight point [rad]

Returns:

Orbit angle from the noon point [rad]

static Real NominalYawAngle(Real beta, Real mu)

Nominal yaw angle [Eq. 1] phi(t) = ATAN2(-tan(beta), sin(mu)) Eq. (1) shows that the sign of the nominal yaw angle is always opposite to that of beta.

Step 2 of the yaw-steering pipeline described above: evaluated by GnssAttitude::Compute(r_sat_eci, v_sat_eci, r_sun_eci, ...) from the beta/mu computed via BetaAngle/OrbitAngle, then passed to GnssAttitude::ComputeFromYawAngle to build the Sun-pointing nominal body frame.

static Real NominalYawRate(Real beta, Real mu, Real mu_dot)

Nominal yaw rate [Eq. 2] phi_dot = mu_dot * tan(beta) * cos(mu) / (sin(mu)^2 + tan(beta)^2) where mu_dot is the (average) orbital angular rate.

Provided as a low-level building block for maneuver-window detection (step 3 of the yaw-steering pipeline described above); not currently called elsewhere in LuPNT, since no maneuver-window state machine is implemented yet.

static Real GpsIIFShadowYawAngle(Real t, Real ts, Real te, Real phi_ts, Real phi_te)

Constant-yaw-rate model for GPS Block IIF satellites while crossing the Earth’s shadow [Eq. 3-4] The satellite maintains a constant yaw rate phi_dot_star = (phi(t_e) - phi(t_s)) / (t_e - t_s) from the shadow-entry epoch t_s to the shadow-exit epoch t_e, so phi(t) = phi(t_s) + phi_dot_star * (t - t_s).

Parameters:
  • t – Evaluation epoch (TAI seconds, or any consistent time base)

  • ts – Shadow entry epoch

  • te – Shadow exit epoch

  • phi_ts – Nominal yaw angle at ts [rad]

  • phi_te – Nominal yaw angle at te [rad]

static Real GpsIIFNoonTurnYawAngle(Real t, Real ts, Real phi_ts, Real beta)

Noon-turn maneuver model for GPS Block IIF satellites [Eq. 5] phi(t) = phi(t_s) - SIGN(R, beta + 0.7 deg) * (t - t_s) with maximum hardware yaw rate R = 0.11 deg/s (Kouba, 2013; Liu et al., 2018). The 0.7 deg bias avoids reverse yaw maneuvers when beta falls in [-0.7, 0] deg (Kuang et al., 2017).

Parameters:
  • t – Evaluation epoch

  • ts – Noon-turn start epoch

  • phi_ts – Nominal yaw angle at ts [rad]

  • beta – Sun elevation angle above the orbital plane [rad]

static Real GpsIIRMidnightTurnYawAngle(Real t, Real ts, Real phi_ts, Real beta)

Midnight-turn maneuver model for GPS Block IIR satellites [Eq. 6] phi(t) = phi(t_s) + SIGN(R, beta) * (t - t_s), R = 0.20 deg/s. GPS Block IIR satellites are not affected by Earth’s shadow, but undergo a short (~15 min) midnight-turn maneuver near the orbit midnight point, limited by the maximum hardware yaw rate R.

Parameters:
  • t – Evaluation epoch

  • ts – Midnight-turn start epoch

  • phi_ts – Nominal yaw angle at ts [rad]

  • beta – Sun elevation angle above the orbital plane [rad]

static Real GpsIIRNoonTurnYawAngle(Real t, Real ts, Real phi_ts, Real beta)

Noon-turn maneuver model for GPS Block IIR satellites [Eq. 7] phi(t) = phi(t_s) - SIGN(R, beta) * (t - t_s), R = 0.20 deg/s.

Parameters:
  • t – Evaluation epoch

  • ts – Noon-turn start epoch

  • phi_ts – Nominal yaw angle at ts [rad]

  • beta – Sun elevation angle above the orbital plane [rad]

static Vec3 Gps3SunVector(Real beta, Real mu)

Sun direction unit vector in the orbital reference frame, using the (along-track, orbit-normal, Earth-direction) axis convention and the midnight-referenced orbit angle mu directly (no detour through the noon-referenced eta), as introduced for the GPS III attitude model of Montenbruck et al. (2026) [Eq. 11] s = (cos(beta)*sin(mu), -sin(beta), cos(beta)*cos(mu))^T Algebraically, s == -GalileoSunVector(OrbitNoonAngle(mu), beta) component-wise (the two papers’ orbital-frame conventions differ by an overall sign), but both parameterizations yield the same nominal yaw angle: ATAN2(s_y, s_x) == ATAN2(-S_y, -S_x) == NominalYawAngle(beta, mu) (dividing both ATAN2 arguments by cos(beta) > 0 collapses either expression to ATAN2(-tan(beta), sin(mu)), i.e. Eq. (1)/Eq. (12)).

Parameters:
  • beta – Sun elevation angle above the orbital plane [rad]

  • mu – Orbit angle from the midnight point [rad]

static Real Gps3EclipseYawAngle(Real beta, Real mu, Real phi_nom)

Improved, rate-limited yaw-steering law for GPS Block III satellites during eclipse-season noon/midnight-turn maneuvers, per the GPS-III-adapted Galileo-IOV-type “smoothed yaw steering” model of Montenbruck et al. (2026) [Eq. 11-13, 17-18] phi(t) = ATAN2(s_y*, s_x) [Eq. 13] with the modified Sun-vector y-component s_y* = 0.5*(1+g)*SIGN(1,phi_nom)*gamma_y + 0.5*(1-g)*s_y [Eq. 18] and IOV-type cosine weighting g = cos(pi*|s_x| / gamma_x) [Eq. 17] SIGN(1, phi_nom) stands in for sign(s_{y,0}) &#8212; the sign of the Sun-vector y-component upon entry into the rectangular collinearity region |s_x| < gamma_x, |s_y| < gamma_y &#8212; which is essentially constant over the short maneuver and shares the sign of phi_nom (Eq. 1 shows phi_nom and beta &#8212; and hence s_y = -sin(beta) &#8212; always have opposite signs, so SIGN(1,phi_nom) = sign(-beta) = / sign(s_y)). The collinearity-zone half-widths are GPS-III-specific (substantially wider than Galileo IOV’s gamma_x = sin(15deg), gamma_y = sin(2deg), reflecting GPS III’s lower peak yaw rate): gamma_x = sin(15 deg), gamma_y = sin(5.8 deg)

Parameters:
  • beta – Sun elevation angle above the orbital plane [rad]

  • mu – Orbit angle from the midnight point [rad]

  • phi_nom – Nominal yaw angle at the current epoch [rad] (NominalYawAngle(beta, mu), used only for its sign)

static Vec3 GalileoSunVector(Real eta, Real beta)

Sun reference vector in the orbital reference frame [Eq. 9] S = (sin(eta)*cos(beta), sin(beta), cos(eta)*cos(beta))^T where eta is the geocentric angle between the satellite and the orbit noon point (see OrbitNoonAngle): eta = OrbitNoonAngle(mu).

Parameters:
  • eta – Orbit angle from the noon point [rad]

  • beta – Sun elevation angle above the orbital plane [rad]

static Real GalileoIovNominalYawAngle(Real eta, Real beta)

Nominal yaw angle for Galileo IOV satellites [Eq. 8] phi(t) = ATAN2(-S_y/sqrt(1-S_z^2), -S_x/sqrt(1-S_z^2)) Algebraically identical to Eq. (1)/NominalYawAngle(beta, mu) once eta = OrbitNoonAngle(mu) is substituted via Eq. (9): with sin(eta) = -sin(mu), -S_x = -sin(eta)*cos(beta) = sin(mu)*cos(beta) and -S_y = -sin(beta), so ATAN2(-S_y, -S_x) = ATAN2(-sin(beta), / sin(mu)*cos(beta)) = ATAN2(-tan(beta), sin(mu)).

Parameters:
  • eta – Orbit angle from the noon point [rad]

  • beta – Sun elevation angle above the orbital plane [rad]

static Real GalileoIovEclipseYawAngle(Real eta, Real beta, Real phi_nom)

Modeled (precise) yaw angle for Galileo IOV satellites during Earth’s-shadow / noon-turn maneuvers [Eq. 10-11] phi(t) = ATAN2(-S_y/sqrt(1-S_z^2), -S_x/sqrt(1-S_z^2)) with the modified Sun-vectory-component S_y’ = [sin(2deg)*SIGN(1,phi_nom) + S_y]/2 + [sin(2deg)*SIGN(1,phi_nom) - S_y]/2 * cos(pi*|S_x|/sin(15deg)) Triggered when|beta| < 4.1 degand the orbit anglemuis within ~10 deg of the midnight/noon point. @param eta Orbit angle from the noon point [rad] @param beta Sun elevation angle above the orbital plane [rad] @param phi_nom Nominal yaw angle at the current epoch [rad] (NominalYawAngle(beta, mu)`, used only for its sign)

static Real GalileoFocYawAngle(Real t, Real ts, Real phi_s)

Yaw-steering law for Galileo FOC satellites during yaw maneuvers (Earth’s shadow / noon-turn) [Eq. 12] phi(t) = 90deg*SIGN(1,phi_s) + (phi_s - 90deg*SIGN(1,phi_s)) * cos(2*pi/5656 * (t - t_s)) 5656 [s] is the maximum yaw-maneuver time constant. Triggered when |beta| < 4.1 deg and the orbit angle mu is within ~10 deg of the midnight/noon point.

Parameters:
  • t – Evaluation epoch

  • ts – Maneuver start (eclipsing) epoch

  • phi_s – Nominal yaw angle at ts [rad]

static Real Bds3CastIgsoYawAngle(Real t, Real ts, Real phi_s)

WHU yaw-steering model for BDS-3 CAST IGSO satellites [Eq. 13] Same functional form as GalileoFocYawAngle (Eq. 12) with maximum yaw-maneuver time 5740 [s] (maximum hardware yaw rate ~0.20 deg/s, midnight/noon turn lasting up to ~96 min).

Parameters:
  • t – Evaluation epoch

  • ts – Maneuver start (eclipsing) epoch

  • phi_s – Nominal yaw angle at ts [rad]

static Real Bds3CastMeoYawAngle(Real t, Real ts, Real phi_s)

WHU yaw-steering model for BDS-3 CAST MEO satellites [Eq. 14] Same functional form as GalileoFocYawAngle (Eq. 12) with maximum yaw-maneuver time 3090 [s] (midnight/noon turn lasting ~52 min).

Parameters:
  • t – Evaluation epoch

  • ts – Maneuver start (eclipsing) epoch

  • phi_s – Nominal yaw angle at ts [rad]

static Real Bds3SecmCsnoYawAngle(Real beta, Real mu)

CSNO model for BDS-3 SECM MEO satellites near zero-beta [Eq. 15] phi(t) = ATAN2(-tan(3deg), sin(mu)) for 0 < beta <= 3 deg phi(t) = ATAN2( tan(3deg), sin(mu)) for -3 deg <= beta < 0 (beta == 0 is treated as the beta < 0 branch; this discontinuity at beta = 0 is the “reverse yaw maneuver near zero beta-angle” reported by Xie et al. (2022) and is what Bds3SecmMcsnoYawAngle (the modified CSNO / “MCSNO” model) corrects).

Parameters:
  • beta – Sun elevation angle above the orbital plane [rad] (model is only meaningful for |beta| <= 3 deg)

  • mu – Orbit angle from the midnight point [rad]

static Real Bds3SecmMcsnoYawAngle(Real t, Real t0, Real ts, Real te, Real beta, Real beta_dot, Real mu, Real mu_ts, Real mu_dot, Real phi_ts)

Modified-CSNO (“MCSNO”) model for BDS-3 SECM MEO satellites, which replaces the CSNO model’s discontinuous sign flip at beta = 0 with a smooth linear transition of the yaw angle [Eq. 16].

phi(t) = ATAN2(-tan(3deg), sin(mu)) for t < t0, beta > 0 phi(t) = ATAN2( tan(3deg), sin(mu)) for t < t0, beta < 0 phi(t) = ATAN2(tan(SIGN(3deg, beta_dot)), sin(mu)) for t0 <= t < ts phi(t) = phi(ts) - SIGN(0.055deg/s, beta_dot) * (mu - mu_ts) / mu_dot for ts <= t < te phi(t) = ATAN2(-tan(SIGN(3deg, beta_dot)), sin(mu)) for t > te

where t0 is the epoch at which beta crosses zero, beta_dot is the rate of beta, mu_dot is the rate of mu, and [ts, te) is the ~3-minute linear-transition window during which the yaw angle ramps at the fixed rate 0.055 deg/s (Yang et al., 2023) &#8212; the transition begins at t0 if the orbit angle mu at t0 exceeds 36.8 deg, and at ts (with mu(ts) ~ 36.8 deg) otherwise.

Parameters:
  • t – Evaluation epoch

  • t0 – Epoch at which beta = 0

  • ts – Linear-transition start epoch

  • te – Linear-transition end epoch

  • beta – Sun elevation angle above the orbital plane [rad]

  • beta_dot – Rate of beta [rad/s]

  • mu – Orbit angle from the midnight point at t [rad]

  • mu_ts – Orbit angle from the midnight point at ts [rad]

  • mu_dot – Rate of mu (orbital angular rate) [rad/s]

  • phi_ts – Yaw angle at the transition-start epoch ts [rad]

static Real Sign(Real a, Real b)

FORTRAN SIGN(A, B) intrinsic: the magnitude of a with the sign of b (+|a| if b >= 0, else -|a|). Used throughout the reference’s yaw-steering laws to select the maneuver direction from the sign of beta (or phi_nom, phi_s, beta_dot).

Parameters:
  • a – Value whose magnitude is used

  • b – Value whose sign is used

Returns:

+|a| if b >= 0, else -|a|