/// <summary> /// Callback to compute the launch transfer times and display them in the scene. /// </summary> public void Compute() { int itemNo = destDropdown.value; NBody toNbody = destinations[itemNo].GetComponent <NBody>(); OrbitData fromOrbit = new OrbitData(); fromOrbit.SetOrbit(fromNbody, centerNbody); OrbitData toOrbit = new OrbitData(); toOrbit.SetOrbit(toNbody, centerNbody); HohmannXfer hohmannXfer = new HohmannXfer(fromOrbit, toOrbit, true); // Find launch windows double[] times = hohmannXfer.LaunchTimes(numWindows); List <Dropdown.OptionData> items = new List <Dropdown.OptionData>(); foreach (double t in times) { Dropdown.OptionData item = new Dropdown.OptionData(); item.text = GravityScaler.GetWorldTimeFormatted(t, GravityScaler.Units.SOLAR); items.Add(item); } launchTimes.ClearOptions(); launchTimes.AddOptions(items); }
public string ApproachPrediction(string moonName) { // @TODO: Too much C&P! // Step 1: Determine the patched conic xfer OrbitData shipOrbit = new OrbitData(); NBody shipNbody = spaceshipCtrl.GetNBody(); shipOrbit.SetOrbit(shipNbody, centralMass); OrbitData moonOrbit = new OrbitData(); NBody moonNbody = GetTargetByName(moonName); moonOrbit.SetOrbit(moonNbody, centralMass); //Make a copy of the universe state and evolve forward to find min distance to // moon. GravityEngine ge = GravityEngine.Instance(); GravityState gs = ge.GetGravityStateCopy(); // run a simulation and find the closest approach (Expensive!) LunarCourseCorrection lcc = new LunarCourseCorrection(shipNbody, moonNbody); // want to be within 10% of Earth-Moon distance, before start checking courseCorrectionData = new LunarCourseCorrection.CorrectionData(); courseCorrectionData.gravityState = gs; courseCorrectionData.approachDistance = 0.1f * moonOrbit.a;; courseCorrectionData.correction = 0; courseCorrectionData.maxPhysTime = time_to_moon_phys; lcc.ClosestApproachAsync(courseCorrectionData, MoonPreviewCompleted); return("Calculation started...\n"); }
public List <OrbitTransfer> FindTransfers() { // find orbit parameters for each body. OrbitData shipOrbit = new OrbitData(); shipOrbit.SetOrbit(ship, centralMass); OrbitData targetOrbit = new OrbitData(); targetOrbit.SetOrbit(target, centralMass); //Debug.Log("ship:" + shipOrbit.LogString()); //Debug.Log("target:" + targetOrbit.LogString()); List <OrbitTransfer> transfers = new List <OrbitTransfer>(); if ((shipOrbit.ecc < 1f) && (targetOrbit.ecc < 1f)) { // both ellipses if (shipOrbit.ecc >= DELTA_ECC) { // add option to circularize our orbit (independent of target) // TODO: need more general ellipse tuning transfers.Add(new CircularizeXfer(shipOrbit)); } if ((shipOrbit.ecc < DELTA_ECC) && (targetOrbit.ecc < DELTA_ECC)) { // both circular - can use Hohmann if (Mathf.Abs(shipOrbit.inclination - targetOrbit.inclination) > DELTA_INCL) { // change in inclination // DEBUG hack // transfers.Add(new CircularPlaneChange(shipOrbit, targetOrbit)); } else { transfers.Add(new HohmannXfer(shipOrbit, targetOrbit)); if (BiellipticXfer.HasLowerDv(shipOrbit, targetOrbit)) { // need to pick (or let user select) the xfer radius - could show a curve? // Test code - just pick 1.5x dest as xfer radius // TODO: Make transfer radius selectable transfers.Add(new BiellipticXfer(shipOrbit, targetOrbit, targetOrbit.a * 1.5f)); } } } else { Debug.Log("TODO: Transfer between co-planar ellipses."); } } else { Debug.Log("Not transfer between ellipses."); } return(transfers); }
/// <summary> /// Initiate a transfer of the spaceship to the moon. The name of the targets[] entry that is the moon /// is provided as a string argument. /// /// Typically called by the GEConsole. /// </summary> public string MoonTransfer(string moonName, float angle) { // Find xfer choices and present to user OrbitData shipOrbit = new OrbitData(); shipOrbit.SetOrbit(spaceshipCtrl.GetNBody(), centralMass); OrbitData targetOrbit = new OrbitData(); targetOrbit.SetOrbit(GetTargetByName(moonName), centralMass); OrbitTransfer xfer = new PatchedConicXfer(shipOrbit, targetOrbit, angle); spaceshipCtrl.SetTransfer(xfer); SetState(State.MANEUVER); // display the maneuver in the console (will only be one for patched conic) return(xfer.GetManeuvers()[0].LogString() + "\n"); }
/// <summary> /// Determine the correction required to establish the desired distance to the moon (i.e. that which /// was predicted by the preview) /// </summary> /// <param name="moonName"></param> /// <returns></returns> public string LunarCourseCorrection(string moonName) { NBody moon = GetTargetByName(moonName); OrbitData moonOrbit = new OrbitData(); NBody moonNbody = GetTargetByName(moonName); moonOrbit.SetOrbit(moonNbody, centralMass); GravityEngine.Instance().SetEvolve(false); lcc = new LunarCourseCorrection(spaceshipCtrl.GetNBody(), moon); float approachDistance = 0.1f * moonOrbit.a; double targetDistance = predictedDistance; double targetAccuracy = 0; // Does not matter for closest string result = lcc.CorrectionCalcAsync(targetDistance, targetAccuracy, approachDistance, time_to_moon_phys, CorrectionCalcCompleted); // GravityEngine.Instance().SetEvolve(true); return(result); }
private void SetMarkers() { if (shipOrbitData == null) { // Cannot rely on controller start after GE start, so instead of forcing // start order, do a lazy init here shipOrbitData = new OrbitData(); shipOrbitData.SetOrbit(spaceshipNBody, shipOrbit.centerNbody); } // skip scaling since we are in dimensionless units Vector3 pos = shipOrbitData.GetPhysicsPositionforEllipse(fromPhase); fromMarker.transform.position = pos; pos = shipOrbitData.GetPhysicsPositionforEllipse(toPhase); toMarker.transform.position = pos; }
public string MoonPreview(string moonName, float lambda1, bool async) { // Step 1: Determine the patched conic xfer OrbitData shipOrbit = new OrbitData(); NBody shipNbody = spaceshipCtrl.GetNBody(); shipOrbit.SetOrbit(shipNbody, centralMass); OrbitData moonOrbit = new OrbitData(); NBody moonNbody = GetTargetByName(moonName); moonOrbit.SetOrbit(moonNbody, centralMass); OrbitTransfer xfer = new PatchedConicXfer(shipOrbit, moonOrbit, lambda1); // Step 2: Make a copy of the universe state and evolve forward to find min distance to // moon. GravityEngine ge = GravityEngine.Instance(); GravityState gs = ge.GetGravityStateCopy(); // there is only one maneuver to add gs.maneuverMgr.Add(xfer.GetManeuvers()[0]); // run a simulation and find the closest approach (Expensive!) LunarCourseCorrection lcc = new LunarCourseCorrection(shipNbody, moonNbody); // want to be within 10% of Earth-Moon distance, before start checking courseCorrectionData = new LunarCourseCorrection.CorrectionData(); courseCorrectionData.gravityState = gs; courseCorrectionData.approachDistance = 0.1f * moonOrbit.a;; courseCorrectionData.correction = 0; courseCorrectionData.maxPhysTime = time_to_moon_phys; // Direct (unthreaded) calculation if (async) { lcc.ClosestApproachAsync(courseCorrectionData, MoonPreviewCompleted); return("Calculation started...\n"); } else { predictedDistance = lcc.ClosestApproach(courseCorrectionData); return(string.Format("Patched Conic with lambda={0} => approach={1}\n", lambda1, predictedDistance)); } }
public List <OrbitTransfer> FindTransfers(bool rendezvous) { // find orbit parameters for each body. OrbitData shipOrbit = new OrbitData(); shipOrbit.SetOrbit(ship, centralMass); //shipOrbit.SetOrbitForVelocity(ship, centralMass); OrbitData targetOrbit = new OrbitData(); targetOrbit.SetOrbit(target, centralMass); //targetOrbit.SetOrbitForVelocity(target, centralMass); //Debug.Log("ship:" + shipOrbit.LogString()); //Debug.Log("target:" + targetOrbit.LogString()); List <OrbitTransfer> transfers = new List <OrbitTransfer>(); if ((shipOrbit.ecc < 1f) && (targetOrbit.ecc < 1f)) { // both ellipses if (shipOrbit.ecc >= DELTA_ECC) { // add option to circularize our orbit (independent of target) // TODO: need more general ellipse tuning transfers.Add(new CircularizeXfer(shipOrbit)); } if ((shipOrbit.ecc < DELTA_ECC) && (targetOrbit.ecc < DELTA_ECC)) { // both circular - can use Hohmann if (Mathf.Abs(shipOrbit.inclination - targetOrbit.inclination) > DELTA_INCL) { // Change in inclination // If same radius can use CircularInclinationAndAN() if (Mathf.Abs(shipOrbit.a - targetOrbit.a) < DELTA_RADIUS) { transfers.Add(new CircularInclinationAndAN(shipOrbit, targetOrbit)); } else { Debug.Log("TODO: transfer between non-coplaner circles"); } } else { // Same inclination transfers.Add(new HohmannXfer(shipOrbit, targetOrbit, true)); // If the target is a moon (mass > 0) then consider a patched conic transfer if (target.mass > 0) { // Need to let user pick the angle of arrival transfers.Add(new PatchedConicXfer(shipOrbit, targetOrbit, PatchedConicXfer.LAMBDA1_DEFAULT)); } if (BiellipticXfer.HasLowerDv(shipOrbit, targetOrbit)) { // Pick 50% excess for orbit (UI can re-adjust as needed) transfers.Add(new BiellipticXfer(shipOrbit, targetOrbit, 50f)); } } } else { Debug.Log("TODO: Transfer between co-planar ellipses."); } } else { Debug.Log("Not transfer between ellipses."); } return(transfers); }