Program Listing for File dynamics.h¶

↰ Return to documentation for file (include/lupnt/dynamics/dynamics.h)

#pragma once

#include "lupnt/dynamics/propagator.h"
#include "lupnt/numerics/integrator.h"
#include "lupnt/physics/body.h"
#include "lupnt/physics/orbit_state.h"
#include "lupnt/physics/state.h"

namespace lupnt {

  // ****************************************************************************
  // Base Dyanmics Classes
  // ****************************************************************************

  // Dynamics Interface
  class IDynamics {
  public:
    virtual ~IDynamics() = default;

    // Interface
    virtual Ptr<IState> PropagateState(const Ptr<IState> &state, Real t0, Real tf,
                                       MatXd *stm = nullptr)
        = 0;
    virtual VecX Propagate(const VecX &x0, Real t0, Real tf, MatXd *stm = nullptr) = 0;
  };

  // Orbit Dynamics Interface
  class IOrbitDynamics : public IDynamics {
  public:
    virtual ~IOrbitDynamics() = default;

    // Overrides
    Ptr<IState> PropagateState(const Ptr<IState> &state, Real t0, Real tf,
                               MatXd *stm = nullptr) override;
    VecX Propagate(const VecX &x0, Real t0, Real tf, MatXd *stm = nullptr) override;

    // Interface
    virtual OrbitState PropagateState(const OrbitState &state, Real t0, Real tf,
                                      Mat6d *stm = nullptr)
        = 0;
    virtual Vec6 Propagate(const Vec6 &x0, Real t0, Real tf, Mat6d *stm = nullptr) = 0;
    virtual MatX6 Propagate(const Vec6 &x0, Real t0, const VecX &tf, bool progress = false) = 0;

    // Implementations
    MatX6 Propagate(const MatX6 &x0, Real t0, Real tf);
  };

  // Analytical Orbit Dynamics Interface
  class IAnalyticalOrbitDynamics : public IOrbitDynamics {
  public:
    virtual ~IAnalyticalOrbitDynamics() = default;

    // Overrides
    using IOrbitDynamics::Propagate;
    MatX6 Propagate(const Vec6 &x0, Real t0, const VecX &tf, bool progress = false) override;

    // Interface
    virtual OrbitState PropagateState(const OrbitState &state, Real t0, Real tf,
                                      Mat6d *stm = nullptr) override
        = 0;
    virtual Vec6 Propagate(const Vec6 &x0, Real t0, Real tf, Mat6d *stm = nullptr) override = 0;
  };

  class NumericalOrbitDynamics : public IOrbitDynamics {
  private:
    ODE odefunc_;
    NumericalPropagator propagator_;
    Real dt_ = 10.0;

  public:
    NumericalOrbitDynamics(ODE odefunc = nullptr, IntegratorType integ = default_integrator);
    void SetTimeStep(Real dt);
    Real GetTimeStep() const;
    void SetODEFunction(ODE odefunc);
    void SetIntegratorParams(IntegratorParams params) {
      propagator_.integrator->SetIntegratorParams(params);
    }

    // Overrides
    using IOrbitDynamics::Propagate;
    Vec6 Propagate(const Vec6 &x0, Real t0, Real tf, Mat6d *stm = nullptr) override;
    MatX6 Propagate(const Vec6 &x0, Real t0, const VecX &tf, bool progress = false) override;

    // Interface
    virtual Vec6 ComputeRates(Real t, const Vec6 &x) const = 0;
    virtual OrbitState PropagateState(const OrbitState &state, Real t0, Real tf,
                                      Mat6d *stm = nullptr) override
        = 0;
  };

  // ****************************************************************************
  // Analytical Dynamics Classes
  // ****************************************************************************

  // Keplerian Dynamics
  class KeplerianDynamics : public IAnalyticalOrbitDynamics {
  private:
    Real GM_;

  public:
    KeplerianDynamics(Real GM);
    Vec6 PropagateClassicalOE(const Vec6 &coe, Real t0, Real tf, Mat6d *stm = nullptr);
    Vec6 PropagateQuasiNonsingOE(const Vec6 &qnsoe, Real t0, Real tf, Mat6d *stm = nullptr);
    Vec6 PropagateEquinoctialOE(const Vec6 &eqoe, Real t0, Real tf, Mat6d *stm = nullptr);

    using IAnalyticalOrbitDynamics::Propagate;
    Vec6 Propagate(const Vec6 &x0, Real t0, Real tf, Mat6d *stm = nullptr) override;
    OrbitState PropagateState(const OrbitState &state, Real t0, Real tf,
                              Mat6d *stm = nullptr) override;
  };

  // Clohessy-Wiltshire Dynamics
  class ClohessyWiltshireDynamics : public IAnalyticalOrbitDynamics {
  private:
    Real a_, n_;
    Vec6 K_;
    Real t0_;

  public:
    ClohessyWiltshireDynamics(Real a, Real n);
    Mat6 ComputeMat(Real tf);

    using IAnalyticalOrbitDynamics::Propagate;
    Vec6 Propagate(const Vec6 &x0, Real t0, Real tf, Mat6d *stm = nullptr) override;
    OrbitState PropagateState(const OrbitState &state, Real t0, Real tf,
                              Mat6d *stm = nullptr) override;
  };

  // Yamanaka-Ankersen Dynamics
  class YamanakaAnkersenDynamics : public IAnalyticalOrbitDynamics {
  private:
    Real a_, n_, e_, M0_;
    Vec6 K_;
    Real t0_;
    Vec6 rv_rtn_;

  public:
    YamanakaAnkersenDynamics(const ClassicalOE &coe_c, const CartesianOrbitState &rv_rtn, Real GM_);
    MatX ComputeMat(Real t);
    MatX ComputeInverseMat(Real t);

    using IAnalyticalOrbitDynamics::Propagate;
    Vec6 Propagate(const Vec6 &x0, Real t0, Real tf, Mat6d *stm = nullptr) override;
    OrbitState PropagateState(const OrbitState &state, Real t0, Real tf,
                              Mat6d *stm = nullptr) override;
  };

  // Roe Geometric Mapping Dynamics
  class RoeGeometricMappingDynamics : public IAnalyticalOrbitDynamics {
  private:
    Real a_, e_, i_, w_, M0_;
    Real ex_, ey_, n_;
    Vec6 K_;
    Real t0_;

  public:
    RoeGeometricMappingDynamics(const ClassicalOE coe_c, const QuasiNonsingROE &roe, Real GM);
    MatX ComputeMat(Real t);

    using IAnalyticalOrbitDynamics::Propagate;
    Vec6 Propagate(const Vec6 &x0, Real t0, Real tf, Mat6d *stm = nullptr) override;
    OrbitState PropagateState(const OrbitState &state, Real t0, Real tf,
                              Mat6d *stm = nullptr) override;
  };

  // ****************************************************************************
  // Numerical Dynamics Classes
  // ****************************************************************************

  // Cartesian Two-Body Dynamics
  class CartesianTwoBodyDynamics : public NumericalOrbitDynamics {
  private:
    Real GM_;

  public:
    CartesianTwoBodyDynamics(Real GM, IntegratorType integ = default_integrator);
    Vec6 ComputeRates(Real t, const Vec6 &x) const override;
    OrbitState PropagateState(const OrbitState &state, Real t0, Real tf,
                              Mat6d *stm = nullptr) override;
  };

  // J2 Cartesian Two-Body Dynamics
  class J2CartTwoBodyDynamics : public NumericalOrbitDynamics {
  private:
    Real GM_, J2_, R_body_;

  public:
    J2CartTwoBodyDynamics(Real GM, Real J2, Real R_body, IntegratorType integ = default_integrator);
    Vec6 ComputeRates(Real t, const Vec6 &x) const override;
    OrbitState PropagateState(const OrbitState &state, Real t0, Real tf,
                              Mat6d *stm = nullptr) override;
  };

  class J2KeplerianDynamics : public NumericalOrbitDynamics {
  private:
    Real GM_, J2_, R_body_;

  public:
    J2KeplerianDynamics(Real GM, Real J2, Real R_body, IntegratorType integ = default_integrator);
    Vec6 ComputeRates(Real t, const Vec6 &x) const override;
    OrbitState PropagateState(const OrbitState &state, Real t0, Real tf,
                              Mat6d *stm = nullptr) override;
  };

  class MoonMeanDynamics : public NumericalOrbitDynamics {
  private:
    const double n3_ = 2.66e-6;
    const double J2_ = 2.03e-4;
    const double k_ = 0.98785;

  public:
    MoonMeanDynamics(IntegratorType integ = default_integrator);
    Vec6 ComputeRates(Real t, const Vec6 &x) const override;
    OrbitState PropagateState(const OrbitState &state, Real t0, Real tf,
                              Mat6d *stm = nullptr) override;
  };

  struct NBodyDynamicsParams {
    Real mass;  // [kg] Spacecraft mass
    Real area;  // [m^2] Cross-sectional area
    Real CR;    // [-] Radiation pressure coefficient
    Real CD;    // [-] Drag coefficient
    bool use_srp = false;
    bool use_drag = false;
  };

  template <typename T = double> class NBodyDynamics : public NumericalOrbitDynamics {
  private:
    Frame frame_ = Frame::NONE;
    std::vector<BodyT<T>> bodies_;
    NumericalPropagator propagator;
    ODE odefunc;
    bool use_srp_ = false;
    bool use_drag_ = false;

    Real mass_;  // [kg] Spacecraft mass
    Real area_;  // [m^2] Cross-sectional area
    Real CR_;    // [-] Radiation pressure coefficient
    Real CD_;    // [-] Drag coefficient

  public:
    NBodyDynamics(IntegratorType integ = default_integrator);
    Vec6 ComputeRates(Real epoch, const Vec6 &x) const override;
    OrbitState PropagateState(const OrbitState &state, Real t0, Real tf,
                              Mat6d *stm = nullptr) override;

    void AddBody(const BodyT<T> &body) {
      for (auto &b : bodies_) {
        if (b.id == body.id) throw std::runtime_error("Body already added");
      }
      bodies_.push_back(body);
    }

    std::vector<BodyT<T>> GetBodies() { return bodies_; }

    void RemoveBody(const BodyT<T> &body) {
      for (auto it = bodies_.begin(); it != bodies_.end(); ++it) {
        if (it->id == body.id) {
          bodies_.erase(it);
          break;
        }
      }
    }

    void SetFrame(Frame frame) { frame_ = frame; }
    void GetFrame(Frame &frame) { frame = frame_; }

    void SetMass(Real mass) { mass_ = mass; }
    void SetArea(Real area) { area_ = area; }
    void SetSrpCoeff(Real CR) { CR_ = CR; }
    void SetDragCoeff(Real CD) { CD_ = CD; }

    void SetUseSrp(bool use_srp) { use_srp_ = use_srp; }
    void SetUseDrag(bool use_drag) { use_drag_ = use_drag; }
  };

}  // namespace lupnt