/// <summary>
    /// Set up a KeplerSeqeunce to do the three phases of the transfer as Kepler mode conics.
    ///
    /// Add all the ghost orbits with the required times
    /// </summary>
    /// <param name="transferTime"></param>
    private void TransferOnRails()
    {
        // the ship needs to have a KeplerSequence
        KeplerSequence kseq = spaceship.GetComponent <KeplerSequence>();

        if (kseq == null)
        {
            Debug.LogError("Could not find a KeplerSequence on " + spaceship.name);
            return;
        }
        // Ellipse 1: shipPos/shipvel already phased by the caller.
        double t_start = ge.GetPhysicalTime();
        double t_toSoi = timeHohmann * tflightFactor;

        KeplerSequence.ElementStarted noCallback = null;
        Vector3d r0    = new Vector3d();
        Vector3d v0    = new Vector3d();
        double   time0 = 0;

        ghostShipOrbit[TO_MOON].GetRVT(ref r0, ref v0, ref time0);
        kseq.AppendElementRVT(r0, v0, t_start, true, spaceship, planet, noCallback);

        // Hyperbola: start at t + transferTime
        // Need to add wrt to ghostMoon (relative=true), then for actual Kepler motion want it around moon
        ghostShipOrbit[SOI_HYPER].GetRVT(ref r0, ref v0, ref time0);
        OrbitUniversal hyperObit = kseq.AppendElementRVT(r0, v0, t_start + t_toSoi, true, spaceship, ghostMoon[MOON_SOI_ENTER], EnterMoonSoi);

        hyperObit.centerNbody = moonBody;

        // Ellipse 2:
        ghostShipOrbit[EXIT_SOI].GetRVT(ref r0, ref v0, ref time0);
        kseq.AppendElementRVT(r0, v0, t_soiExit, true, spaceship, planet, ExitMoonSoi);
    }
 /// <summary>
 /// Raise a circular orbit by the specified percent
 /// - only on-rail is implemented
 /// </summary>
 /// <param name="percentRaise"></param>
 private void NewCircularOrbit(float percentRaise)
 {
     if (onRails)
     {
         KeplerSequence keplerSeq = spaceship.GetComponent <KeplerSequence>();
         OrbitUniversal orbitU    = keplerSeq.GetCurrentOrbit();
         // check orbit is circular
         if (orbitU.eccentricity < 1E-2)
         {
             // circular, ok to proceed
             OrbitData fromOrbit = new OrbitData(orbitU);
             OrbitData toOrbit   = new OrbitData(fromOrbit);
             toOrbit.a = percentRaise * fromOrbit.a;
             const bool    rendezvous  = false;
             OrbitTransfer hohmannXfer = new HohmannXfer(fromOrbit, toOrbit, rendezvous);
             keplerSeq.RemoveFutureSegments();
             keplerSeq.AddManeuvers(hohmannXfer.GetManeuvers());
         }
     }
     else
     {
         // assume we're in orbit around the moon
         OrbitData orbitData = new OrbitData();
         orbitData.SetOrbitForVelocity(spaceship, moonBody);
         OrbitData toOrbit = new OrbitData(orbitData);
         toOrbit.a = percentRaise * orbitData.a;
         const bool    rendezvous  = false;
         OrbitTransfer hohmannXfer = new HohmannXfer(orbitData, toOrbit, rendezvous);
         ge.AddManeuvers(hohmannXfer.GetManeuvers());
     }
 }
Exemple #3
0
    /// <summary>
    /// The spaceship has a fixed orbit that is on rails (must be an OrbitUniversal).
    ///
    /// To allow for setting of specific times and forward/backward motion implement the transfer as a
    /// KeplerSequence of three OrbitUniversals:
    /// - initial orbit when t less then now
    /// - transfer ellipse when t between now and (now + transfer_time)
    /// - destination orbit when t greater than (now + transfer_time)
    ///
    /// </summary>
    private void TransferOnRails()
    {
        // initial orbit - needs to be OrbitUniversal (could morph an OrbitEllipse, but keep things simple)
        OrbitUniversal initialOrbit = spaceshipNBody.GetComponent <OrbitUniversal>();

        if (initialOrbit == null)
        {
            Debug.LogError("script assumes ship orbit will be OrbitUniversal");
            return;
        }

        KeplerSequence keplerSeq = spaceshipNBody.GetComponent <KeplerSequence>();

        if (keplerSeq == null)
        {
            Debug.LogError("Cannot do on-rails transfer. Ship does not have a KeplerSequence");
            return;
        }

        // Kepler sequence already has the initial orbit.
        // transfer orbit
        Vector3d xfer_r0 = lambertU.GetTransferPositionDouble();
        Vector3d xfer_v0 = lambertU.GetTransferVelocityDouble();
        double   xfer_t  = ge.GetPhysicalTimeDouble();

        keplerSeq.AppendElementRVT(xfer_r0, xfer_v0, xfer_t, false, spaceshipNBody, starNBody, null);
        // destination orbit
        double   dest_t = xfer_t + transferTime;
        Vector3d dest_v = new Vector3d(targetData.GetPhysicsVelocityForEllipse(targetData.phase));
        Vector3d dest_r = new Vector3d(targetData.GetPhysicsPositionforEllipse(targetData.phase));

        keplerSeq.AppendElementRVT(dest_r, dest_v, dest_t, false, spaceshipNBody, starNBody, SequenceDoneCallback);
    }
 /// <summary>
 /// Circularize around Moon
 /// - currently only onRails is implemented
 /// </summary>
 private void CircularizeAroundMoon()
 {
     // check ship is on segment where it near Moon
     if (onRails)
     {
         KeplerSequence keplerSeq = spaceship.GetComponent <KeplerSequence>();
         OrbitUniversal orbitU    = keplerSeq.GetCurrentOrbit();
         if (orbitU.centerNbody == moonBody)
         {
             // in orbit around the moon - do circularization
             OrbitData     orbitData       = new OrbitData(orbitU);
             OrbitTransfer circularizeXfer = new CircularizeXfer(orbitData);
             keplerSeq.RemoveFutureSegments();
             keplerSeq.AddManeuvers(circularizeXfer.GetManeuvers());
         }
     }
     else
     {
         // assume we're in orbit around the moon
         OrbitData orbitData = new OrbitData();
         orbitData.SetOrbitForVelocity(spaceship, moonBody);
         OrbitTransfer circularizeXfer = new CircularizeXfer(orbitData);
         ge.AddManeuvers(circularizeXfer.GetManeuvers());
     }
 }
    public override void OnInspectorGUI()
    {
        KeplerSequence keplerSeq = (KeplerSequence)target;

        OrbitUniversal orbitU = keplerSeq.GetComponent <OrbitUniversal>();

        if (orbitU.evolveMode == OrbitUniversal.EvolveMode.GRAVITY_ENGINE)
        {
            EditorGUILayout.LabelField("Base orbit is in GRAVITY MODE. Kepler sequence will be ignored!");
            return;
        }
        if (EditorApplication.isPlaying)
        {
            EditorGUILayout.LabelField("Dump of Kepler Sequence Elements");
            EditorGUILayout.LabelField(string.Format("time={0} current={1}",
                                                     GravityEngine.Instance().GetPhysicalTime(), keplerSeq.GetCurrentOrbitIndex()));
            string[] info = keplerSeq.DumpInfo().Split('\n');
            foreach (string s in info)
            {
                EditorGUILayout.LabelField(s);
            }
            EditorGUILayout.LabelField("Tip: GetCurrentOrbit() returns the active element.");
        }
        else
        {
            EditorGUILayout.LabelField("Inspector will show active elements when playing");
        }
    }
Exemple #6
0
    /// <summary>
    /// Used to determine the initial physics position of an NBody (initialPhysPosition).
    ///
    /// Used in two contexts:
    /// (1) When a body is added to GE (either at setup or when a body is dynamically added at run-time).
    /// (2) In the editor DrawGizmo calls when the orbit path is being show in a scene that is not running.
    ///     In the case of orbit gizmos the orbit parameters will MOVE the object to the correct position in the
    ///     orbit based on the position calculated here.
    ///
    /// If the NBody game object has an INBodyInit component (e.g from an OrbitEllipse) then
    /// this is used to determine it's position. There is a potential for recursion here, since that
    /// orbit ellipse may be on a NBody that is in turn positioned by an orbit ellipse e.g. moon/planet/sun.
    ///
    /// If the NBody has an engine ref (i.e. GE has taken charge) then update with the position from GE.
    /// /// </summary>
    /// <param name="ge"></param>
    public void InitPosition(GravityEngine ge)
    {
        // Not ideal that NBody knows so much about methods to run setup. Be better to delegate this eventually.

        // check for initial condition setup (e.g. initial conditions for elliptical orbit/binary pair)
        if (engineRef != null)
        {
            initialPhysPosition = ge.GetPhysicsPosition(this);
        }
        else
        {
            // If there is a Kepler sequence, use that instead of e.g. the first OrbitU
            INbodyInit     initNbody;
            KeplerSequence keplerSeq = GetComponent <KeplerSequence>();
            if (keplerSeq != null)
            {
                initNbody = (INbodyInit)keplerSeq;
            }
            else
            {
                initNbody = gameObject.GetComponent <INbodyInit>();
            }
            if (initNbody != null)
            {
                initNbody.InitNBody(ge.physToWorldFactor, ge.massScale);
            }
            else
            {
                // binary pair
                if (transform.parent != null)
                {
                    BinaryPair bp = transform.parent.GetComponent <BinaryPair>();
                    if (bp != null)
                    {
                        bp.SetupBodies();
                        return;
                    }
                }
                if (ge.units != GravityScaler.Units.DIMENSIONLESS)
                {
                    // value in scaled systems is taken from the NBody scaled position and not the transform
                    initialPhysPosition = initialPos;
                }
                else
                {
                    // value is taken from the transform object
                    initialPhysPosition = transform.position;
                }
            }
        }
    }
 private void WarnAboutKeplerSeq(OrbitUniversal orbitU)
 {
     // when playing warn user if OrbitU attached to NBody is being used or not
     if (EditorApplication.isPlaying)
     {
         KeplerSequence ks = orbitU.GetComponent <KeplerSequence>();
         if (ks != null)
         {
             if (ks.GetCurrentOrbit() != orbitU)
             {
                 EditorGUILayout.LabelField("OrbitUniversal is not current orbit in Kepler sequence!",
                                            EditorStyles.boldLabel);
             }
         }
     }
 }
    /// <summary>
    /// Raise a circular orbit by the specified percent
    /// - only on-rail is implemented
    /// </summary>
    /// <param name="percentRaise"></param>
    private void NewCircularOrbit(float percentRaise)
    {
        KeplerSequence keplerSeq = spaceship.GetComponent <KeplerSequence>();
        OrbitUniversal orbitU    = keplerSeq.GetCurrentOrbit();

        // check orbit is circular
        if (orbitU.eccentricity < 1E-2)
        {
            // circular, ok to proceed
            OrbitData fromOrbit = new OrbitData(orbitU);
            OrbitData toOrbit   = new OrbitData(fromOrbit);
            toOrbit.a = percentRaise * fromOrbit.a;
            const bool    rendezvous  = false;
            OrbitTransfer hohmannXfer = new HohmannXfer(fromOrbit, toOrbit, rendezvous);
            keplerSeq.RemoveFutureSegments();
            keplerSeq.AddManeuvers(hohmannXfer.GetManeuvers());
        }
    }
 public void Awake()
 {
     orbitU    = GetComponent <OrbitUniversal>();
     keplerSeq = GetComponent <KeplerSequence>();
 }
    /// <summary>
    /// Set up a KeplerSeqeunce to do the three phases of the transfer as Kepler mode conics.
    ///
    /// Leave the existing ship orbit as the first
    /// </summary>
    /// <param name="transferTime"></param>
    private void TransferOnRails(double transferTime, Vector3 shipPos, Vector3 shipVel, float moonOmega)
    {
        // the ship needs to have a KeplerSequence
        KeplerSequence kseq = spaceship.GetComponent <KeplerSequence>();

        if (kseq == null)
        {
            Debug.LogError("Could not find a KeplerSequence on " + spaceship.name);
            return;
        }
        float      moonPhaseDeg = moonOmega * (float)transferTime * Mathf.Rad2Deg;
        Quaternion moonPhaseRot = Quaternion.AngleAxis(moonPhaseDeg, Vector3.forward);

        // Ellipse 1: shipPos/shipvel already phased by the caller.
        double t = ge.GetPhysicalTime();

        KeplerSequence.ElementStarted noCallback = null;
        kseq.AppendElementRVT(new Vector3d(shipPos), new Vector3d(shipVel), t, false, spaceship, planet, noCallback);

        // Hyperbola: start at t + transferTime
        // have targetPoint and final velocity from LambertTransfer. Need to make these wrt moon at this time
        // targetPoint is w.r.t current moon position, but need to rotate around SOI by amount moon will shift
        // as ship transits to moon
        Vector3 targetPos    = targetPoint.ToVector3();
        Vector3 moonPosAtSoi = moonPhaseRot * ge.GetPhysicsPosition(moonBody);
        Vector3 moonVelAtSoi = moonPhaseRot * ge.GetVelocity(moonBody);
        // get the relative positions (i.e. as if moon at the origin with v=0)
        Vector3 adjustedTarget = moonPhaseRot * targetPos - moonPosAtSoi;
        Vector3 adjustedVel    = moonPhaseRot * lambertU.GetFinalVelocity() - moonVelAtSoi;

        // Create moon hyperbola at the moon position after flight to moon. This means the init cannot make reference
        // to the CURRENT moon position.
        Vector3d       soiEnterR  = new Vector3d(adjustedTarget);
        Vector3d       soiEnterV  = new Vector3d(adjustedVel);
        OrbitUniversal hyperOrbit = kseq.AppendElementRVT(soiEnterR,
                                                          soiEnterV,
                                                          t + transferTime,
                                                          true,
                                                          spaceship,
                                                          moonBody,
                                                          EnterMoonSoi);

        // Find the hyperbola exit SOI position/vel
        OrbitUtils.OrbitElements oe = OrbitUtils.RVtoCOE(soiEnterR, soiEnterV, moonBody, true);
        Vector3d soiExitR           = new Vector3d();
        Vector3d soiExitV           = new Vector3d();

        Debug.Log("oe=" + oe);
        // Gives position and velocity in relative position
        OrbitUtils.COEtoRVMirror(oe, moonBody, ref soiExitR, ref soiExitV, true);

        // Determine hyperbola transit time to the soiExit position
        double hyperTOF = hyperOrbit.TimeOfFlight(soiEnterR, soiExitR);

        //Debug.LogFormat("Hyper TOF={0} r0={1} r1={2} p={3}", hyperTOF, adjustedTarget, soiExitR,
        //    hyperOrbit.p);

        // Ellipse 2:
        // Adjust phase to allow for moon travel during hyperbola transit
        // Need to set position and vel relative to the planet using position relative to moon at 0
        moonPhaseDeg = moonOmega * (float)hyperTOF * Mathf.Rad2Deg;
        Quaternion moonHyperRot     = Quaternion.AngleAxis(moonPhaseDeg, Vector3.forward);
        Vector3    moonAtExit       = moonHyperRot * moonPosAtSoi;
        Vector3    moonVelAtExit    = moonHyperRot * moonVelAtSoi;
        Vector3    soiExitwrtPlanet = soiExitR.ToVector3() + moonAtExit;
        // soiexitV is relative to moon at (0,0,0) BUT frame of hyperbola does not rotate
        Vector3 soiExitVelwrtPlanet = moonHyperRot * soiExitV.ToVector3() + moonVelAtExit;

        Debug.LogFormat("Ellipse2: soiExitV={0} moonV={1} net={2}", soiExitV, moonVelAtExit, soiExitVelwrtPlanet);

        kseq.AppendElementRVT(new Vector3d(soiExitwrtPlanet),
                              new Vector3d(soiExitVelwrtPlanet),
                              t + transferTime + hyperTOF,
                              true,
                              spaceship,
                              planet,
                              ExitMoonSoi);
        running = true;
    }
 // Use this for initialization
 void Start()
 {
     keplerSeq = shipNbody.GetComponent <KeplerSequence>();
     markers   = new List <GameObject>();
 }
 // Use this for initialization
 void Start()
 {
     keplerSeq = shipNbody.GetComponent <KeplerSequence>();
 }