Program Listing for File analytical_orbit_dynamics.cc¶

↰ Return to documentation for file (dynamics/analytical_orbit_dynamics.cc)

#include "lupnt/dynamics/analytical_orbit_dynamics.h"

#include <Eigen/QR>

#include "lupnt/conversions/anomaly_conversions.h"
#include "lupnt/core/constants.h"
#include "lupnt/numerics/math_utils.h"
#include "lupnt/states/state.h"

namespace lupnt {

  State AnalyticalDynamics::Propagate(const State& x0, Real t0, Real tf, const State* u) {
    return Propagate(x0, t0, tf, u, nullptr);
  }

  MatX AnalyticalDynamics::Propagate(const State& x0, const VecX& tfs, const State* u) {
    MatX xf = MatX6::Zero(tfs.size(), 6);
    // ProgressBar pbar(tf.size());
    xf.row(0) = x0;
#pragma omp parallel for
    for (int i = 1; i < tfs.size(); i++) {
      Real tf_i = tfs(i);
      Vec6 xf_i = Propagate(x0, tfs(0), tf_i, u);
      xf.row(i) = xf_i;
      // if (print_progress_) pbar.Update(i);
    }
    // if (print_progress_) pbar.Finish();
    return xf;
  }

  // ****************************************************************************
  // KeplerianDynamics
  // ****************************************************************************

  // Explicitly instantiate only the constructor
  template KeplerianDynamics<ClassicalOE>::KeplerianDynamics(Real);
  template KeplerianDynamics<QuasiNonsingularOE>::KeplerianDynamics(Real);
  template KeplerianDynamics<EquinoctialOE>::KeplerianDynamics(Real);

  // ClassicalOE
  template <> State KeplerianDynamics<ClassicalOE>::Propagate(const State& coe, Real t0, Real tf,
                                                              const State* u, MatXd* stm) {
    LUPNT_CHECK(coe.GetType() == ClassicalOE::TYPE || coe.GetType() == UNDEFINED,
                "Invalid state type", "KeplerianDynamics");
    (void)u;

    Real dt = tf - t0;
    if (abs(dt) < EPS) {
      if (stm != nullptr) *stm = Mat6d::Identity(6, 6);
      return coe;
    }
    Real n = sqrt(GM_ / pow(coe[0], 3));
    Real M = WrapToPi(coe[5] + n * dt);

    Vec6 coe_new = coe;
    coe_new[5] = M;

    if (stm != nullptr) {
      *stm = Mat6d::Identity(6, 6);
      (*stm)(5, 0) = -3. / 2. * (n / coe[0] * dt).val();
    }
    return State(coe, coe_new);
  }

  // QuasiNonsingularOE
  template <> State KeplerianDynamics<QuasiNonsingularOE>::Propagate(const State& qnsoe, Real t0,
                                                                     Real tf, const State* u_in,
                                                                     MatXd* stm) {
    (void)u_in;
    Real dt = tf - t0;
    Real n = sqrt(GM_ / pow(qnsoe[0], 3));
    Real u = qnsoe[1] + n * dt;

    Vec6 qnsoe_new = qnsoe;
    qnsoe_new[1] = u;

    if (stm != nullptr) throw std::runtime_error("Not implemented");
    return State(qnsoe, qnsoe_new);
  }

  // EquinoctialOE
  template <> State KeplerianDynamics<EquinoctialOE>::Propagate(const State& eqoe, Real t0, Real tf,
                                                                const State* u, MatXd* stm) {
    (void)u;
    Real dt = tf - t0;
    Real n = sqrt(GM_ / pow(eqoe[0], 3));
    Real lon = eqoe[5] + n * dt;

    Vec6 eqoe_new = eqoe;
    eqoe_new[5] = lon;

    if (stm != nullptr) throw std::runtime_error("Not implemented");
    return State(eqoe, eqoe_new);
  }

  /* ****************************************************************************
    ClohessyWiltshireDynamics
    ************************************************************************** */

  ClohessyWiltshireDynamics::ClohessyWiltshireDynamics(Real a, Real n) : a_(a), n_(n) {};

  State ClohessyWiltshireDynamics::Propagate(const State& x0, Real t0, Real tf, const State* u,
                                             MatXd* stm) {
    (void)u;
    if (abs(tf - t0) < EPS) {
      if (stm != nullptr) *stm = Mat6d::Identity(6, 6);
      return x0;
    }
    if (t0 != t0_) {
      MatX Phi = ComputeMat(t0);
      K_ = Phi.colPivHouseholderQr().solve(x0);
    }
    Mat6 Phi = ComputeMat(tf - t0);
    Vec6 xf = Phi * K_;
    if (stm != nullptr) *stm = Phi.cast<double>();
    return State(x0, xf);
  }

  Mat6 ClohessyWiltshireDynamics::ComputeMat(Real t) {
    Real sin_nt = sin(n_ * t);
    Real cos_nt = cos(n_ * t);

    Mat6 A = Mat6::Zero();
    A.block(0, 0, 3, 3) = a_ * Vec6d::Identity(3, 3);
    A.block(3, 3, 3, 3) = a_ * n_ * Vec6d::Identity(3, 3);

    Mat6 B = Mat6::Zero();
    B(0, 0) = 1.;
    B(0, 1) = sin_nt;
    B(0, 2) = cos_nt;

    B(1, 0) = -3. / 2. * n_ * t;
    B(1, 1) = 2. * cos_nt;
    B(1, 2) = -2. * sin_nt;
    B(1, 3) = 1.;

    B(2, 4) = sin_nt;
    B(2, 5) = cos_nt;

    B(3, 1) = cos_nt;
    B(3, 2) = -sin_nt;

    B(4, 0) = -3. / 2.;
    B(4, 1) = -2. * sin_nt;
    B(4, 2) = -2. * cos_nt;

    B(5, 4) = cos_nt;
    B(5, 5) = -sin_nt;

    Mat6 Phi = A * B;
    return Phi;
  }

  // ****************************************************************************
  // YamanakaAnkersenDynamics
  // ****************************************************************************

  YamanakaAnkersenDynamics::YamanakaAnkersenDynamics(const ClassicalOE& coe_c, const Cart6& rv_rtn,
                                                     Real GM_) {
    a_ = coe_c.a().val();
    n_ = sqrt(GM_ / pow(a_, 3.));
    e_ = coe_c.e().val();
    M0_ = coe_c.M().val();
    rv_rtn_ = rv_rtn;
  }

  State YamanakaAnkersenDynamics::Propagate(const State& x0, Real t0, Real tf, const State* u,
                                            MatXd* stm) {
    (void)u;
    if (abs(tf - t0) < EPS) {
      if (stm != nullptr) *stm = Mat6d::Identity(6, 6);
      return x0;
    }
    throw std::runtime_error("Not implemented");

    if (t0 != t0_) {
      MatX Phi = ComputeMat(t0);
      K_ = ComputeInverseMat(t0) * rv_rtn_;
      // K_ = Phi.colPivHouseholderQr().solve(x0);
    }
    Mat6 Phi = ComputeMat(tf - t0);
    Vec6 xf = Phi * K_;
    if (stm != nullptr) *stm = Phi.cast<double>();
    return State(x0, xf);
  }

  MatX YamanakaAnkersenDynamics::ComputeMat(Real t) {
    Real M = n_ * (t - t0_) + M0_;
    Real f = MeanToTrueAnomaly(M, e_);
    Real sin_f = sin(f);
    Real cos_f = cos(f);
    Real k = 1. + e_ * cos(f);
    Real kp = -e_ * sin(f);
    Real eta = sqrt(1. - e_ * e_);
    Real tau = n_ * t / pow(eta, 3.);

    MatX A = MatX::Zero(6, 6);
    A.block(0, 0, 3, 3) = a_ * eta * eta * Vec6d::Identity(3, 3);
    A.block(3, 3, 3, 3) = a_ * n_ / eta * Vec6d::Identity(3, 3);

    MatX B = MatX::Zero(6, 6);
    B(0, 0) = 1. / k + 3. / 2. * kp * tau;
    B(0, 1) = sin_f;
    B(0, 2) = cos_f;

    B(1, 0) = -3. / 2. * k * tau;
    B(1, 1) = (1. + 1. / k) * cos_f;
    B(1, 2) = -(1. + 1. / k) * sin_f;
    B(1, 3) = 1. / k;

    B(2, 4) = 1. / k * sin_f;
    B(2, 5) = 1. / k * cos_f;

    B(3, 0) = kp / 2. - 3. / 2. * k * k * (k - 1.) * tau;
    B(3, 1) = k * k * cos_f;
    B(3, 2) = -k * k * sin_f;

    B(4, 0) = -3. / 2. * (k + k * k * kp * tau);
    B(4, 1) = -(k * k + 1) * sin_f;
    B(4, 2) = -e_ - (k * k + 1) * cos_f;
    B(4, 3) = -kp;

    B(5, 4) = e_ + cos_f;
    B(5, 5) = -sin_f;

    MatX Phi = A * B;
    return Phi;
  }
  MatX YamanakaAnkersenDynamics::ComputeInverseMat(Real t) {
    Real M = n_ * (t - t0_) + M0_;
    Real f = MeanToTrueAnomaly(M, e_);
    Real sin_f = sin(f);
    Real cos_f = cos(f);
    Real k = 1. + e_ * cos(f);
    Real kp = -e_ * sin(f);
    Real eta = sqrt(1. - e_ * e_);
    Real tau = n_ * t / pow(eta, 3.);

    MatX A = MatX::Zero(6, 6);
    A.block(0, 0, 3, 3) = 1. / a_ / (eta * eta) * Vec6d::Identity(3, 3);
    A.block(3, 3, 3, 3) = eta / a_ / n_ * Vec6d::Identity(3, 3);

    MatX B = MatX::Zero(6, 6);
    B(0, 0) = 2. * (k * k) * (k + 1) / (eta * eta);
    B(0, 1) = 2. * (k * k) * kp / (eta * eta);
    B(0, 3) = -2. * kp / (eta * eta);
    B(0, 4) = 2. * k / (eta * eta);

    B(1, 0) = (1. - pow(k + 1, 2) / (eta * eta)) * sin_f
              + 3. * e_ * (k * k) * (k + 1) * tau / (eta * eta);
    B(1, 1) = -(k + 1) * kp * sin_f / (eta * eta) + 3. * e_ * (k * k) * kp * tau / (eta * eta);
    B(1, 3) = (1. / (eta * eta)) * (cos_f - 2. * e_ / k) - 3. * e_ * kp * tau / (eta * eta);
    B(1, 4) = -(1. / (eta * eta)) * (1. + 1. / k) * sin_f + 3. * e_ * k * tau / (eta * eta);

    B(2, 0) = -(k / (eta * eta)) * (2. * e_ + (k + 2) * cos_f);
    B(2, 1) = -(1. / (eta * eta)) * (e_ + (k + 1) * cos_f) * kp;
    B(2, 3) = -(1. / (eta * eta)) * sin_f;
    B(2, 4) = -(1. / (eta * eta)) * (e_ / k + (1. + 1. / k) * cos_f);

    B(3, 0) = (pow(k + 1, 2) / (eta * eta)) * kp + 3. * (k * k) * (k + 1) * tau / (eta * eta);
    B(3, 1) = (k / (eta * eta)) * (2. + k - (k * k)) - 1. + 3. * (k * k) * kp * tau / (eta * eta);
    B(3, 3) = (1. / (eta * eta)) * (k - 1. - 2. / k) - 3. * kp * tau / (eta * eta);
    B(3, 4) = (1. / (eta * eta)) * (1. + 1. / k) * kp + 3. * k * tau / (eta * eta);

    B(4, 2) = sin_f;
    B(4, 5) = (1. / k) * cos_f;

    B(5, 2) = e_ + cos_f;
    B(5, 5) = -(1. / k) * sin_f;

    MatX Phi = B * A;
    return Phi;
  }

  // ****************************************************************************
  // RoeGeometricMappingDynamics
  // ****************************************************************************

  RoeGeometricMappingDynamics::RoeGeometricMappingDynamics(const ClassicalOE coe_c,
                                                           const QuasiNonsingROE& roe, Real GM) {
    a_ = coe_c.a();
    e_ = coe_c.e();
    i_ = coe_c.i();
    w_ = coe_c.w();
    M0_ = coe_c.M();

    ex_ = coe_c.e() * cos(coe_c.w());
    ey_ = coe_c.e() * sin(coe_c.w());

    n_ = sqrt(GM / pow(coe_c.a(), 3));
    K_ = roe;
  }

  State RoeGeometricMappingDynamics::Propagate(const State& x0, Real t0, Real tf, const State* u,
                                               MatXd* stm) {
    (void)u;
    if (abs(tf - t0) < EPS) {
      if (stm != nullptr) *stm = Mat6d::Identity(6, 6);
      return x0;
    }
    throw std::runtime_error("Not implemented");

    if (t0 != t0_) {
      throw std::runtime_error("Not implemented");
    }

    MatX Phi = ComputeMat(tf - t0_);
    Vec6 xf = Phi * K_;
    if (stm != nullptr) *stm = Phi.cast<double>();
    return State(x0, xf);
  }

  MatX RoeGeometricMappingDynamics::ComputeMat(Real t) {
    Real M = n_ * (t - t0_) + M0_;
    Real f = MeanToTrueAnomaly(M, e_);
    Real u = f + w_;
    Real sin_u = sin(u);
    Real cos_u = cos(u);
    Real cot_i = 1. / tan(i_);
    Real k = 1. + ex_ * cos(u) + ey_ * sin(u);
    Real kp = -ex_ * sin(u) + ey_ * cos(u);
    Real eta = sqrt(1. - e_ * e_);

    MatX A = MatX::Zero(6, 6);
    A.block(0, 0, 3, 3) = a_ * eta * eta * Vec6d::Identity(3, 3);
    A.block(3, 3, 3, 3) = a_ * n_ / eta * Vec6d::Identity(3, 3);

    MatX B = MatX::Zero(6, 6);
    B(0, 0) = 1. / k + 3. / 2. * kp * n_ / pow(eta, 3) * t;
    B(0, 1) = -kp / pow(eta, 3);
    B(0, 2) = 1. / pow(eta, 3) * (ex_ * (k - 1.) / (1. + eta) - cos_u);
    B(0, 3) = 1. / pow(eta, 3) * (ey_ * (k - 1.) / (1. + eta) - sin_u);
    B(0, 5) = kp / pow(eta, 3) * cot_i;

    B(1, 0) = -3 / 2. * k * n_ / pow(eta, 3) * t;
    B(1, 1) = k / pow(eta, 3);
    B(1, 2) = 1. / pow(eta, 2) * ((1. + 1. / k) * sin_u + ey_ / k + k / eta * (ey_ / (1. + eta)));
    B(1, 3) = -1. / pow(eta, 2) * ((1. + 1. / k) * cos_u + ex_ / k + k / eta * (ex_ / (1. + eta)));
    B(1, 5) = (1. / k - k / pow(eta, 3)) * cot_i;

    B(2, 4) = 1. / k * sin_u;
    B(2, 5) = -1. / k * cos_u;

    B(3, 0) = kp / 2. + 3. / 2. * k * k * (1. - k) * n_ / pow(eta, 3) * t;
    B(3, 1) = k * k / pow(eta, 3) * (k - 1.);
    B(3, 2) = k * k / pow(eta, 3) * (eta * sin_u + ey_ * (k - 1.) / (1. + eta));
    B(3, 3) = -k * k / pow(eta, 3) * (eta * cos_u + ex_ * (k - 1.) / (1. + eta));
    B(3, 5) = -k * k / pow(eta, 3) * (k - 1.) * cot_i;

    B(4, 0) = -3 / 2. * k * (1. + k * kp * n_ / pow(eta, 3) * t);
    B(4, 1) = k * k / pow(eta, 3) * kp;
    B(4, 2) = (1. + k * k / pow(eta, 3)) * cos_u
              + ex_ * k / pow(eta, 2) * (1. + k / eta * (1. - k) / (1. + eta));
    B(4, 3) = (1. + k * k / pow(eta, 3)) * sin_u
              + ey_ * k / pow(eta, 2) * (1. + k / eta * (1. - k) / (1. + eta));
    B(4, 5) = -(1. + k * k / pow(eta, 3)) * kp * cot_i;

    B(5, 4) = cos_u + ex_;
    B(5, 5) = sin_u + ey_;

    MatX Phi = A * B;
    std::cout << A << std::endl << std::endl;
    std::cout << B << std::endl << std::endl;
    std::cout << Phi << std::endl;
    return Phi;
  }

}  // namespace lupnt