/// <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; }