Program Listing for File gnss_yaw_steering.h

Return to documentation for file (agents/gnss_yaw_steering.h)

#pragma once

#include "lupnt/core/definitions.h"

namespace lupnt {

  class GnssYawSteering {
  public:
    GnssYawSteering() = delete;

    // ---- Satellite-Sun-Earth geometry --------------------------------------

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

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

    static Real OrbitNoonAngle(Real mu);

    // ---- Nominal yaw-attitude model (Kouba, 2009), Eq. (1)-(2) --------------

    static Real NominalYawAngle(Real beta, Real mu);

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

    // ---- GPS Block IIF -------------------------------------------------------
    // (Kuang et al., 2017)

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

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

    // ---- GPS Block IIR -------------------------------------------------------
    // (Kouba, 2017)

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

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

    // ---- GPS Block III -------------------------------------------------------
    // (Montenbruck et al., 2026)
    //
    // No manufacturer-published yaw-steering model exists for GPS Block III;
    // IGS analysis centers currently substitute the nominal, GPS IIR, or
    // GPS IIF laws, none of which match the attitude quaternions distributed
    // by JPL (believed to reflect the true on-board model) particularly well.
    // Montenbruck et al. (2026) instead adapt the Galileo-IOV-type "smoothed
    // yaw steering" law (cf. `GalileoIovEclipseYawAngle`) to GPS III's wider
    // collinearity zone and lower peak yaw rate (~0.09 deg/s, vs. ~0.20 deg/s
    // for IIR and ~0.11 deg/s for IIF), finding it to give the closest overall
    // approximation (RMS yaw-angle error 1.9-3.5 deg) of the JPL quaternions
    // among the candidate models considered -- and recommend it as a
    // transitional standard for OD/PPP processing of GPS III satellites.

    static Vec3 Gps3SunVector(Real beta, Real mu);

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

    // ---- Galileo IOV ---------------------------------------------------------
    // (EGSC, 2017)

    static Vec3 GalileoSunVector(Real eta, Real beta);

    static Real GalileoIovNominalYawAngle(Real eta, Real beta);

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

    // ---- Galileo FOC ---------------------------------------------------------
    // (EGSC, 2017)

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

    // ---- BDS-3 CAST (WHU model) ----------------------------------------------
    // (Wang et al., 2018)

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

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

    // ---- BDS-3 SECM (CSNO / MCSNO models) ------------------------------------
    // (CSNO, 2019; Xia et al., 2018; Yang et al., 2023)

    static Real Bds3SecmCsnoYawAngle(Real beta, Real mu);

    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);

    // ---- FORTRAN-style helper -------------------------------------------------

    static Real Sign(Real a, Real b);

  private:
    static Real CosineTransitionYawAngle(Real t, Real ts, Real phi_s, double period_s);
  };

}  // namespace lupnt