Example #1
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>
    /// 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>
    /// 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;
    }