Example #1
0
    }  // findc2c3

    /// <summary>
    /// Determine the time of flight in physics time units (GE internal time) that it takes for the body
    /// in orbit to go from position r0 to position r1 in an orbit with parameter p.
    ///
    /// The angle between two 3D vectors cannot be greater than 180 degrees unless the orientation of the
    /// plane they define is also specified. The normal parameter is used for this. If an angle less than
    /// 180 is desired then the cross product of r0 and v0 can be used as the normal.
    /// Calling TOF via the OrbitUniversal wrapper will handle all that automatically.
    ///
    /// </summary>
    /// <param name="r0">from point (with respect to center)</param>
    /// <param name="r1">to point (with respect to center)</param>
    /// <param name="p">orbit semi-parameter</param>
    /// <param name="mu">centerbody mass</param>
    /// <param name="normal">normal to orital plane</param>
    /// <returns>time to travel from r0 to r1 in GE time</returns>
    public static double TimeOfFlight(Vector3d r0, Vector3d r1, double p, double mu, Vector3d normal)
    {
        // Vallado, Algorithm 11, p126
        double tof     = 0;
        double r0r1    = r0.magnitude * r1.magnitude;
        double cos_dnu = Vector3d.Dot(r0, r1) / r0r1;
        double sin_dnu = Vector3d.Cross(r0, r1).magnitude / r0r1;

        // use the normal to determine if angle is > 180
        if (Vector3d.Dot(Vector3d.Cross(r0, r1), normal) < 0.0)
        {
            sin_dnu *= -1.0;
        }
        // GE - precision issue at 180 degrees. Simply return 1/2 the orbit period.
        if (Mathd.Abs(1.0 + cos_dnu) < 1E-5)
        {
            double a180 = 0.5f * (r0.magnitude + r1.magnitude);
            return(Mathd.Sqrt(a180 * a180 * a180 / mu) * Mathd.PI);
        }
        // sin_nu: Need to use direction of flight to pick sign per Algorithm 53
        double k = r0r1 * (1.0 - cos_dnu);
        double l = r0.magnitude + r1.magnitude;
        double m = r0r1 * (1 + cos_dnu);
        double a = (m * k * p) / ((2.0 * m - l * l) * p * p + 2.0 * k * l * p - k * k);
        double f = 1.0 - (r1.magnitude / p) * (1.0 - cos_dnu);
        double g = r0r1 * sin_dnu / (Mathd.Sqrt(mu * p));

        double alpha = 1 / a;

        if (alpha > 1E-7)
        {
            // ellipse
            double delta_nu = Mathd.Atan2(sin_dnu, cos_dnu);
            double fdot     = Mathd.Sqrt(mu / p) * Mathd.Tan(0.5 * delta_nu) *
                              ((1 - cos_dnu) / p - (1 / r0.magnitude) - (1.0 / r1.magnitude));
            double cos_deltaE = 1 - r0.magnitude / a * (1.0 - f);
            double sin_deltaE = -r0r1 * fdot / (Mathd.Sqrt(mu * a));
            double deltaE     = Mathd.Atan2(sin_deltaE, cos_deltaE);
            tof = g + Mathd.Sqrt(a * a * a / mu) * (deltaE - sin_deltaE);
        }
        else if (alpha < -1E-7)
        {
            // hyperbola
            double cosh_deltaH = 1.0 + (f - 1.0) * r0.magnitude / a;
            double deltaH      = GEMath.Acosh(cosh_deltaH);
            tof = g + Mathd.Sqrt(-a * a * a / mu) * (GEMath.Sinh(deltaH) - deltaH);
        }
        else
        {
            // parabola
            double c = Mathd.Sqrt(r0.magnitude * r0.magnitude + r1.magnitude * r1.magnitude - 2.0 * r0r1 * cos_dnu);
            double s = 0.5 * (r0.magnitude + r1.magnitude + c);
            tof = 2 / 3 * Mathd.Sqrt(s * s * s / (2.0 * mu)) * (1 - Mathd.Pow(((s - c) / s), 1.5));
        }
        return(tof);
    }
Example #2
0
    /* -----------------------------------------------------------------------------
    *
    *                           function newtonnu
    *
    *  this function solves keplers equation when the true anomaly is known.
    *    the mean and eccentric, parabolic, or hyperbolic anomaly is also found.
    *    the parabolic limit at 168ΓΈ is arbitrary. the hyperbolic anomaly is also
    *    limited. the hyperbolic sine is used because it's not double valued.
    *
    *  author        : david vallado                  719-573-2600   27 may 2002
    *
    *  revisions
    *    vallado     - fix small                                     24 sep 2002
    *
    *  inputs          description                    range / units
    *    ecc         - eccentricity                   0.0  to
    *    nu          - true anomaly                   -2pi to 2pi rad
    *
    *  outputs       :
    *    e0          - eccentric anomaly              0.0  to 2pi rad       153.02 deg
    *    m           - mean anomaly                   0.0  to 2pi rad       151.7425 deg
    *
    *  locals        :
    *    e1          - eccentric anomaly, next value  rad
    *    sine        - sine of e
    *    cose        - cosine of e
    *    ktr         - index
    *
    *  coupling      :
    *    arcsinh     - arc hyperbolic sine
    *    sinh        - hyperbolic sine
    *
    *  references    :
    *    vallado       2013, 77, alg 5
    * --------------------------------------------------------------------------- */

    private static void NewtonNu(OrbitElements oe)
    {
        double small, sine, cose, cosnu, temp;

        double ecc = oe.ecc;
        double nu = oe.nu;
        double e0, m;

        // ---------------------  implementation   ---------------------
        e0    = 999999.9;
        m     = 999999.9;
        small = 0.00000001;

        // --------------------------- circular ------------------------
        if (Mathd.Abs(ecc) < small)
        {
            m  = nu;
            e0 = nu;
        }
        else
        // ---------------------- elliptical -----------------------
        if (ecc < 1.0 - small)
        {
            cosnu = Mathd.Cos(nu);
            temp  = 1.0 / (1.0 + ecc * cosnu);
            sine  = (Mathd.Sqrt(1.0 - ecc * ecc) * Mathd.Sin(nu)) * temp;
            cose  = (ecc + cosnu) * temp;
            e0    = Mathd.Atan2(sine, cose);
            m     = e0 - ecc * Mathd.Sin(e0);
        }
        else
        // -------------------- hyperbolic  --------------------
        if (ecc > 1.0 + small)
        {
            if ((ecc > 1.0) && (Mathd.Abs(nu) + 0.00001 < Mathd.PI - Mathd.Acos(Mathd.Clamp(1.0 / ecc, -1.0, 1.0))))
            {
                sine = (Mathd.Sqrt(ecc * ecc - 1.0) * Mathd.Sin(nu)) / (1.0 + ecc * Mathd.Cos(nu));
                e0   = GEMath.Asinh(sine);
                m    = ecc * GEMath.Sinh(e0) - e0;
            }
        }
        else
        // ----------------- parabolic ---------------------
        if (Mathd.Acos(Mathd.Clamp(nu, -1.0, 1.0)) < 168.0 * Mathd.PI / 180.0)
        {
            e0 = Mathd.Tan(nu * 0.5);
            m  = e0 + (e0 * e0 * e0) / 3.0;
        }

        if (ecc < 1.0)
        {
            m = System.Math.Truncate(m / (2.0 * Mathd.PI));
            if (m < 0.0)
            {
                m = m + 2.0 * Mathd.PI;
            }
            e0 = System.Math.Truncate(e0 / (2.0 * Mathd.PI));
        }
        oe.m       = m;
        oe.eccanom = e0;
    }  // newtonnu
Example #3
0
    }  // coe2rv

    public static void COEtoRVMirror(OrbitElements oe,
                                     NBody centerBody,
                                     ref Vector3d r,
                                     ref Vector3d v,
                                     bool relativePos)
    {
        double   temp, sinnu, cosnu;
        Vector3d rpqw, vpqw;

        double mu = GravityEngine.Instance().GetMass(centerBody);

        // --------------------  implementation   ----------------------
        //       determine what type of orbit is involved and set up the
        //       set up angles for the special cases.
        // -------------------------------------------------------------
        if (oe.ecc < small)
        {
            // ----------------  circular equatorial  ------------------
            if ((oe.incl < small) | (Mathd.Abs(oe.incl - Mathd.PI) < small))
            {
                oe.argp = 0.0;
                oe.raan = 0.0;
                oe.nu   = oe.truelon;
            }
            else
            {
                // --------------  circular inclined  ------------------
                oe.argp = 0.0;
                oe.nu   = oe.arglat;
            }
        }
        else
        {
            // ---------------  elliptical equatorial  -----------------
            if ((oe.incl < small) | (Mathd.Abs(oe.incl - Mathd.PI) < small))
            {
                oe.argp = oe.lonper;
                oe.raan = 0.0;
            }
        }

        // ----------  form pqw position and velocity vectors ----------
        cosnu = Mathd.Cos(oe.nu);
        sinnu = Mathd.Sin(oe.nu);
        temp  = oe.p / (1.0 + oe.ecc * cosnu);
        // flip Y
        rpqw = new Vector3d(temp * cosnu, -temp * sinnu, 0.0);
        if (Mathd.Abs(oe.p) < 0.00000001)
        {
            oe.p = 0.00000001;
        }

        // flip X (not Y)
        vpqw = new Vector3d(sinnu * Mathd.Sqrt(mu / oe.p),
                            (oe.ecc + cosnu) * Mathd.Sqrt(mu / oe.p),
                            0.0);

        // ----------------  perform transformation to ijk  ------------
        r = GEMath.Rot3(rpqw, -oe.argp);
        r = GEMath.Rot1(r, -oe.incl);
        r = GEMath.Rot3(r, -oe.raan);

        v = GEMath.Rot3(vpqw, -oe.argp);
        v = GEMath.Rot1(v, -oe.incl);
        v = GEMath.Rot3(v, -oe.raan);

        if (!relativePos)
        {
            r += GravityEngine.Instance().GetPositionDoubleV3(centerBody);
            v += GravityEngine.Instance().GetVelocityDoubleV3(centerBody);
        }
    }  // coe2rvMirror