Пример #1
0
bool cOrbit::TrueAnomalyAtRadius(double r, double timeOfStart, double &tAOut) const
{
    double e = Eccentricity();
    double a = SemiMajorAxis();
    bool status = false;

    double arg = (a - a*e*e - r)/(e*r);

    if(-1 <= arg && arg <= 1)
    {
        double tA = TrueAnomalyAt(timeOfStart, status);

        tAOut = acos(arg);

        tAOut = min(
            fmod(tAOut - tA + 4*M_PI, 2*M_PI),
            fmod(-tAOut - tA + 4*M_PI, 2*M_PI)
            ) + tA;

        return status;
    }
    else
    {
        return false;
    }
}
Пример #2
0
double cOrbit::EccentricAnomalyAtTrueAnomaly(double tA) const
{
    double e = Eccentricity();
    if (IsHyperbolic()) {
        double cosTrueAnomaly = std::cos(tA);
        double H = acosh((e + cosTrueAnomaly) / (1.0 + e * cosTrueAnomaly));
        if (tA < 0) 
        {
            return -H;
        } 
        else 
        {
            return H;
        }
    } else {
        double E = 2 * std::atan(std::tan(tA / 2) / std::sqrt((1 + e) / (1 - e)));
        if (E < 0) 
        {
            return E + TWO_PI;
        } 
        else 
        {
            return E;
        }
    }
}
Пример #3
0
double cOrbit::TrueAnomalyAt(double t, bool &status)  const
{
    double e = Eccentricity();
    if (IsHyperbolic())
    {
        double H = EccentricAnomalyAt(t, status);
        double tA = std::acos((e - std::cosh(H)) / (std::cosh(H) * e - 1.0));

        if (H < 0) 
        { 
            return -tA; 
        } 
        else 
        { 
            return tA; 
        }
    }
    else
    {
        double E = EccentricAnomalyAt(t, status);
        double tA = 2 * std::atan2(std::sqrt(1.0 + e) * std::sin(E / 2.0), std::sqrt(1.0 - e) * std::cos(E / 2.0));

        if (tA < 0) 
        {
            return tA + TWO_PI; 
        }
        else 
        {
            return tA;
        }
    }
}
Пример #4
0
double cOrbit::EccentricAnomalyAt(double t, bool &status) const
{
    ECC_ANOMALY_T params;
    params.e = Eccentricity();
    params.M = MeanAnomalyAt(t);
    double EccentricAnomaly = params.M;

    // to prevent sinh/cosh overflow
    if(EccentricAnomaly < -10.0) 
    { 
        EccentricAnomaly = -10.0; 
    }
    if(EccentricAnomaly >  10.0) 
    { 
        EccentricAnomaly =  10.0; 
    }

    if (IsHyperbolic())
    {
        status = cTools::NewtonMethod<double, ECC_ANOMALY_T>(EccentricAnomaly, params, eccAnomalyFunction1, eccAnomalyDFunction1);
    }
    else
    {
        status = cTools::NewtonMethod<double, ECC_ANOMALY_T>(EccentricAnomaly, params, eccAnomalyFunction2, eccAnomalyDFunction2);
    }

    return EccentricAnomaly;
}
Пример #5
0
cOrbit::cOrbit(const cTle &tle) :
   m_tle(tle),
   m_pNoradModel(NULL)
{
   InitializeCachingVars();

   int    epochYear = (int)m_tle.GetField(cTle::FLD_EPOCHYEAR);
   double epochDay  =      m_tle.GetField(cTle::FLD_EPOCHDAY );

   if (epochYear < 57)
   {
      epochYear += 2000;
   }
   else
   {
      epochYear += 1900;
   }

   m_jdEpoch = cJulian(epochYear, epochDay);

   m_secPeriod = -1.0;

   // Recover the original mean motion and semimajor axis from the
   // input elements.
   double mm     = MeanMotionTle();
   double rpmin  = mm * TWOPI / MIN_PER_DAY;   // rads per minute

   double a1     = pow(XKE / rpmin, 2.0 / 3.0);
   double e      = Eccentricity();
   double i      = Inclination();
   double temp   = (1.5 * CK2 * (3.0 * sqr(cos(i)) - 1.0) / 
                   pow(1.0 - e * e, 1.5));   
   double delta1 = temp / (a1 * a1);
   double a0     = a1 * 
                   (1.0 - delta1 * 
                   ((1.0 / 3.0) + delta1 * 
                   (1.0 + 134.0 / 81.0 * delta1)));

   double delta0 = temp / (a0 * a0);

   m_rmMeanMotionRec    = rpmin / (1.0 + delta0);
   m_aeAxisSemiMajorRec = a0 / (1.0 - delta0);
   m_aeAxisSemiMinorRec = m_aeAxisSemiMajorRec * sqrt(1.0 - (e * e));
   m_kmPerigeeRec       = XKMPER_WGS72 * (m_aeAxisSemiMajorRec * (1.0 - e) - AE);
   m_kmApogeeRec        = XKMPER_WGS72 * (m_aeAxisSemiMajorRec * (1.0 + e) - AE);

   if (TWOPI / m_rmMeanMotionRec >= 225.0)
   {
      // SDP4 - period >= 225 minutes.
      m_pNoradModel = new cNoradSDP4(*this);
   }
   else
   {
      // SGP4 - period < 225 minutes
      m_pNoradModel = new cNoradSGP4(*this);
   }
}
Пример #6
0
OrbitalElements::OrbitalElements(const Tle& tle)
{
    /*
     * extract and format tle data
     */
    mean_anomoly_ = tle.MeanAnomaly(false);
    ascending_node_ = tle.RightAscendingNode(false);
    argument_perigee_ = tle.ArgumentPerigee(false);
    eccentricity_ = tle.Eccentricity();
    inclination_ = tle.Inclination(false);
    mean_motion_ = tle.MeanMotion() * kTWOPI / kMINUTES_PER_DAY;
    bstar_ = tle.BStar();
    epoch_ = tle.Epoch();

    /*
     * recover original mean motion (xnodp) and semimajor axis (aodp)
     * from input elements
     */
    const double a1 = pow(kXKE / MeanMotion(), kTWOTHIRD);
    const double cosio = cos(Inclination());
    const double theta2 = cosio * cosio;
    const double x3thm1 = 3.0 * theta2 - 1.0;
    const double eosq = Eccentricity() * Eccentricity();
    const double betao2 = 1.0 - eosq;
    const double betao = sqrt(betao2);
    const double temp = (1.5 * kCK2) * x3thm1 / (betao * betao2);
    const double del1 = temp / (a1 * a1);
    const double a0 = a1 * (1.0 - del1 * (1.0 / 3.0 + del1 * (1.0 + del1 * 134.0 / 81.0)));
    const double del0 = temp / (a0 * a0);

    recovered_mean_motion_ = MeanMotion() / (1.0 + del0);
    /*
     * alternative way to calculate
     * doesnt affect final results
     * recovered_semi_major_axis_ = pow(XKE / RecoveredMeanMotion(), TWOTHIRD);
     */
    recovered_semi_major_axis_ = a0 / (1.0 - del0);

    /*
     * find perigee and period
     */
    perigee_ = (RecoveredSemiMajorAxis() * (1.0 - Eccentricity()) - kAE) * kXKMPER;
    period_ = kTWOPI / RecoveredMeanMotion();
}
Пример #7
0
double cOrbit::MeanAnomalyAtTrueAnomaly(double tA) const
{
    double e = Eccentricity();
    if (IsHyperbolic()) {
        double H = EccentricAnomalyAtTrueAnomaly(tA);
        return e * sinh(H) - H;
    } else {
        double E = EccentricAnomalyAtTrueAnomaly(tA);
        return E - e * std::sin(E);
    }
}
Пример #8
0
Vector3d cOrbit::VelocityAtTrueAnomaly(double tA) const
{
    double mu = ReferenceBody().GravitationalParameter();
    double e = Eccentricity();
    double h = std::sqrt(mu * SemiMajorAxis() * (1.0 - e * e));
    double r = RadiusAtTrueAnomaly(tA);
    double sin = std::sin(tA);
    double cos = std::cos(tA);
    double vr = mu * e * sin / h;
    double vtA = h / r;
    return RotationToReferenceFrame()._transformVector(Vector3d(vr * cos - vtA * sin, vr * sin + vtA * cos, 0)); 
}
Пример #9
0
 /**
  * Constructs a TransverseMercator object
  *
  * @param label This argument must be a Label containing the proper mapping
  *              information as indicated in the Projection class. Additionally,
  *              the transversemercator projection requires the center longitude
  *              to be defined in the keyword CenterLongitude, and the scale
  *              factor to be defined in the keyword ScaleFactor.
  *
  * @param allowDefaults If set to false the constructor expects that a keyword
  *                      of CenterLongitude and ScaleFactor will be in the label.
  *                      Otherwise it will attempt to compute the center
  *                      longitude using the middle of the longitude range
  *                      specified in the label, and the scale factor will
  *                      default to 1.0. Defaults to false.
  *
  * @throws Isis::iException::Io
  */
  TransverseMercator::TransverseMercator(Isis::Pvl &label, bool allowDefaults) :
    Isis::Projection::Projection (label) {
    try {
      // Try to read the mapping group
      Isis::PvlGroup &mapGroup = label.FindGroup ("Mapping",Isis::Pvl::Traverse);

      // Compute and write the default center longitude if allowed and
      // necessary
      if ((allowDefaults) && (!mapGroup.HasKeyword("CenterLongitude"))) {
        double lon = (p_minimumLongitude + p_maximumLongitude) / 2.0;
        mapGroup += Isis::PvlKeyword("CenterLongitude",lon);
      }

      // Compute and write the default center latitude if allowed and
      // necessary
      if ((allowDefaults) && (!mapGroup.HasKeyword("CenterLatitude"))) {
        double lat = (p_minimumLatitude + p_maximumLatitude) / 2.0;
        mapGroup += Isis::PvlKeyword("CenterLatitude",lat);
      }

      // Get the center longitude  & latitude
      p_centerLongitude = mapGroup["CenterLongitude"];
      p_centerLatitude = mapGroup["CenterLatitude"];

      // make sure the center latitude value is valid
      if (fabs(p_centerLatitude) >= 90.0) {
        string msg = "Invalid Center Latitude Value. Must be between -90 and 90";
        throw Isis::iException::Message(Isis::iException::Io,msg,_FILEINFO_);
      }

      // make sure the center longitude value is valid
      if (fabs(p_centerLongitude) > 360.0) {
        string msg = "Invalid Center Longitude Value. Must be between -360 and 360";
        throw Isis::iException::Message(Isis::iException::Io,msg,_FILEINFO_);
      }

      // convert latitude to planetographic if it is planetocentric
      if (this->IsPlanetocentric()) {
        p_centerLatitude = this->ToPlanetographic(p_centerLatitude);
      }

      // convert to radians and adjust for longitude direction
      if (p_longitudeDirection == PositiveWest) p_centerLongitude *= -1.0;
      p_centerLatitude *= Isis::PI / 180.0;
      p_centerLongitude *= Isis::PI / 180.0;

      // Compute other necessary variables
      p_eccsq = Eccentricity()*Eccentricity();
      p_esp = p_eccsq;
      p_e0 = 1.0 - 0.25 * p_eccsq * (1.0 + p_eccsq / 16.0 * (3.0 + 1.25 *p_eccsq));
      p_e1 = 0.375 * p_eccsq * (1.0 + 0.25 * p_eccsq * ( 1.0 + 0.468750 * p_eccsq));
      p_e2 = 0.058593750 * p_eccsq * p_eccsq * (1.0 + 0.750 * p_eccsq);
      p_e3 = p_eccsq * p_eccsq * p_eccsq * (35.0 / 3072.0);
      p_ml0 = p_equatorialRadius * (p_e0 * p_centerLatitude - p_e1 * sin(2.0 * p_centerLatitude) +
                p_e2 * sin(4.0 * p_centerLatitude) - p_e3 * sin(6.0 * p_centerLatitude));

      // Set flag for sphere or ellipsiod
      p_sph = true; // Sphere
      if (Eccentricity() >= .00001) {
        p_sph = false; // Ellipsoid
        p_esp = p_eccsq / (1.0 - p_eccsq);
      }

      // Get the scale factor
      if ((allowDefaults) && (!mapGroup.HasKeyword("ScaleFactor"))) {
        mapGroup += Isis::PvlKeyword("ScaleFactor",1.0);
      }
      p_scalefactor = mapGroup["ScaleFactor"];
    }
    catch (Isis::iException &e) {
      string message = "Invalid label group [Mapping]";
      throw Isis::iException::Message(Isis::iException::Io,message,_FILEINFO_);
    }
  }
Пример #10
0
  /**
   * Constructs a TransverseMercator object
   *
   * @param label This argument must be a Label containing the proper mapping
   *              information as indicated in the Projection class. Additionally,
   *              the transversemercator projection requires the center longitude
   *              to be defined in the keyword CenterLongitude, and the scale
   *              factor to be defined in the keyword ScaleFactor.
   *
   * @param allowDefaults If set to false the constructor expects that a keyword
   *                      of CenterLongitude and ScaleFactor will be in the label.
   *                      Otherwise it will attempt to compute the center
   *                      longitude using the middle of the longitude range
   *                      specified in the label, and the scale factor will
   *                      default to 1.0. Defaults to false.
   *
   * @throws IException
   */
  TransverseMercator::TransverseMercator(Pvl &label, bool allowDefaults) :
      TProjection::TProjection(label) {
    try {
      // Try to read the mapping group
      PvlGroup &mapGroup = label.findGroup("Mapping", Pvl::Traverse);

      // Compute and write the default center longitude if allowed and
      // necessary
      if ((allowDefaults) && (!mapGroup.hasKeyword("CenterLongitude"))) {
        double lon = (m_minimumLongitude + m_maximumLongitude) / 2.0;
        mapGroup += PvlKeyword("CenterLongitude", toString(lon));
      }

      // Compute and write the default center latitude if allowed and
      // necessary
      if ((allowDefaults) && (!mapGroup.hasKeyword("CenterLatitude"))) {
        double lat = (m_minimumLatitude + m_maximumLatitude) / 2.0;
        mapGroup += PvlKeyword("CenterLatitude", toString(lat));
      }

      // Get the center longitude  & latitude
      m_centerLongitude = mapGroup["CenterLongitude"];
      m_centerLatitude = mapGroup["CenterLatitude"];

      // make sure the center latitude value is valid
      if (fabs(m_centerLatitude) >= 90.0) {
        string msg = "Invalid Center Latitude Value. Must be between -90 and 90";
        throw IException(IException::Io, msg, _FILEINFO_);
      }

      // make sure the center longitude value is valid
      if (fabs(m_centerLongitude) > 360.0) {
        string msg = "Invalid Center Longitude Value. Must be between -360 and 360";
        throw IException(IException::Io, msg, _FILEINFO_);
      }

      // convert latitude to planetographic if it is planetocentric
      if (IsPlanetocentric()) {
        m_centerLatitude = ToPlanetographic(m_centerLatitude);
      }

      // convert to radians and adjust for longitude direction
      if (m_longitudeDirection == PositiveWest) m_centerLongitude *= -1.0;
      m_centerLatitude *= PI / 180.0;
      m_centerLongitude *= PI / 180.0;

      // Compute other necessary variables. See Snyder, page 61
      m_eccsq = Eccentricity() * Eccentricity();
      m_esp = m_eccsq;
      m_e0 = 1.0 - 0.25 * m_eccsq * (1.0 + m_eccsq / 16.0 * (3.0 + 1.25 * m_eccsq));
      m_e1 = 0.375 * m_eccsq * (1.0 + 0.25 * m_eccsq * (1.0 + 0.468750 * m_eccsq));
      m_e2 = 0.058593750 * m_eccsq * m_eccsq * (1.0 + 0.750 * m_eccsq);
      m_e3 = m_eccsq * m_eccsq * m_eccsq * (35.0 / 3072.0);
      m_ml0 = m_equatorialRadius * (m_e0 * m_centerLatitude - m_e1 * sin(2.0 * m_centerLatitude) +
                                    m_e2 * sin(4.0 * m_centerLatitude) - m_e3 * sin(6.0 * m_centerLatitude));

      // Set flag for sphere or ellipsiod
      m_sph = true; // Sphere
      if (Eccentricity() >= .00001) {
        m_sph = false; // Ellipsoid
        m_esp = m_eccsq / (1.0 - m_eccsq);
      }

      // Get the scale factor
      if ((allowDefaults) && (!mapGroup.hasKeyword("ScaleFactor"))) {
        mapGroup += PvlKeyword("ScaleFactor", toString(1.0));
      }
      m_scalefactor = mapGroup["ScaleFactor"];
    }
    catch(IException &e) {
      string message = "Invalid label group [Mapping]";
      throw IException(e, IException::Io, message, _FILEINFO_);
    }
  }
Пример #11
0
double cOrbit::RadiusAtTrueAnomaly(double tA) const
{
    double e = Eccentricity();

    return SemiMajorAxis() * (1 - e * e) / (1 + e * std::cos(tA));
}