public void RCSBalancerInfoItem() { GUILayout.BeginVertical(); GuiUtils.SimpleLabel("Calculation time", (solverThread.calculationTime * 1000).ToString("F0") + " ms"); GuiUtils.SimpleLabelInt("Pending tasks", solverThread.taskCount); GuiUtils.SimpleLabelInt("Cache size", solverThread.cacheSize); GuiUtils.SimpleLabelInt("Cache hits", solverThread.cacheHits); GuiUtils.SimpleLabelInt("Cache misses", solverThread.cacheMisses); GuiUtils.SimpleLabel("CoM shift", MuUtils.ToSI(solverThread.comError) + "m"); GuiUtils.SimpleLabel("CoM recalc", MuUtils.ToSI(solverThread.comErrorThreshold) + "m"); GuiUtils.SimpleLabel("Max CoM shift", MuUtils.ToSI(solverThread.maxComError) + "m"); GuiUtils.SimpleLabel("Status", solverThread.statusString); string error = solverThread.errorString; if (!string.IsNullOrEmpty(error)) { GUILayout.Label(error, GUILayout.ExpandWidth(true)); } GUILayout.EndVertical(); }
public string TargetSMA() { if (!core.target.NormalTargetExists) { return("N/A"); } return(MuUtils.ToSI(core.target.TargetOrbit.semiMajorAxis, 2) + "m"); }
public string TargetOrbitSpeed() { if (!core.target.NormalTargetExists) { return("N/A"); } return(MuUtils.ToSI(core.target.TargetOrbit.GetVel().magnitude) + "m/s"); }
public string TargetPeriapsis() { if (!core.target.NormalTargetExists) { return("N/A"); } return(MuUtils.ToSI(core.target.TargetOrbit.PeA, 2) + "m"); }
public string TargetRelativeVelocity() { if (!core.target.NormalTargetExists) { return("N/A"); } return(MuUtils.ToSI(core.target.RelativeVelocity.magnitude) + "m/s"); }
public string TargetDistance() { if (core.target.Target == null) { return("N/A"); } return(MuUtils.ToSI(core.target.Distance, -1) + "m"); }
public string TargetApoapsis() { if (!core.target.NormalTargetExists) { return("N/A"); } return(MuUtils.ToSI(core.target.Orbit.ApA, 2) + "m"); }
protected override void WindowGUI(int windowID) { GUILayout.BeginVertical(); GUIStyle s = new GUIStyle(GUI.skin.label); s.alignment = TextAnchor.MiddleCenter; List <Runway> availableRunways = MechJebModuleSpaceplaneAutopilot.runways.Where(p => p.body == mainBody).ToList(); if (runwayIndex > availableRunways.Count) { runwayIndex = 0; } if (availableRunways.Any()) { GUILayout.Label(Localizer.Format("#MechJeb_ApproAndLand_label1"), s);//Landing runwayIndex = GuiUtils.ComboBox.Box(runwayIndex, availableRunways.Select(p => p.name).ToArray(), this); autoland.runway = availableRunways[runwayIndex]; GUILayout.Label(Localizer.Format("#MechJeb_ApproAndLand_label2") + MuUtils.ToSI(Vector3d.Distance(vesselState.CoM, autoland.runway.Start()), 0) + "m"); //Distance to runway: showLandingTarget = GUILayout.Toggle(showLandingTarget, Localizer.Format("#MechJeb_ApproAndLand_label3")); //Show landing navball guidance if (GUILayout.Button(Localizer.Format("#MechJeb_ApproAndLan_button1"))) //Autoland { autoland.Autoland(this); } if (autoland.enabled && GUILayout.Button(Localizer.Format("#MechJeb_ApproAndLan_button2")))//Abort { autoland.AutopilotOff(); } GuiUtils.SimpleTextBox(Localizer.Format("#MechJeb_ApproAndLand_label14"), autoland.glideslope, "°"); //Autoland glideslope: GuiUtils.SimpleTextBox(Localizer.Format("#MechJeb_ApproAndLand_label4"), autoland.approachSpeed, "m/s"); //Approach speed: GuiUtils.SimpleTextBox(Localizer.Format("#MechJeb_ApproAndLand_label5"), autoland.touchdownSpeed, "m/s"); //Touchdown speed: autoland.bEngageReverseIfAvailable = GUILayout.Toggle(autoland.bEngageReverseIfAvailable, Localizer.Format("#MechJeb_ApproAndLand_label6")); //Reverse thrust upon touchdown autoland.bBreakAsSoonAsLanded = GUILayout.Toggle(autoland.bBreakAsSoonAsLanded, Localizer.Format("#MechJeb_ApproAndLand_label7")); //Brake as soon as landed if (autoland.enabled) { GUILayout.Label(Localizer.Format("#MechJeb_ApproAndLand_label8") + autoland.AutolandApproachStateToHumanReadableDescription()); //State: GUILayout.Label(Localizer.Format("#MechJeb_ApproAndLand_label9", Math.Round(autoland.GetAutolandLateralDistanceToNextWaypoint(), 0))); //Distance to waypoint: {0}m //GUILayout.Label(string.Format("Distance to waypoint: {0} m", Math.Round(autoland.GetAutolandLateralDistanceToNextWaypoint(), 0))); GUILayout.Label(Localizer.Format("#MechJeb_ApproAndLand_label10", Math.Round(autoland.Autopilot.SpeedTarget, 1))); //Target speed: {0} m/s GUILayout.Label(Localizer.Format("#MechJeb_ApproAndLand_label11", Math.Round(autoland.GetAutolandTargetAltitude(autoland.GetAutolandTargetVector()), 0))); //Target altitude: {0} m GUILayout.Label(Localizer.Format("#MechJeb_ApproAndLand_label12", Math.Round(autoland.Autopilot.VertSpeedTarget, 1))); //Target vertical speed: {0} m/s GUILayout.Label(Localizer.Format("#MechJeb_ApproAndLand_label13", Math.Round(autoland.Autopilot.HeadingTarget, 0))); //Target heading: {0}º } } GUILayout.EndVertical(); base.WindowGUI(windowID); }
public string NextManeuverNodeDeltaV() { if (!vessel.patchedConicsUnlocked() || !vessel.patchedConicSolver.maneuverNodes.Any()) { return("N/A"); } return(MuUtils.ToSI(vessel.patchedConicSolver.maneuverNodes[0].GetBurnVector(orbit).magnitude, -1) + "m/s"); }
protected override void WindowGUI(int windowID) { GUILayout.BeginVertical(); GUIStyle s = new GUIStyle(GUI.skin.label); s.alignment = TextAnchor.MiddleCenter; List <Runway> availableRunways = MechJebModuleSpaceplaneAutopilot.runways.Where(p => p.body == mainBody).ToList(); if (runwayIndex > availableRunways.Count) { runwayIndex = 0; } if (availableRunways.Any()) { GUILayout.Label("Landing", s); runwayIndex = GuiUtils.ComboBox.Box(runwayIndex, availableRunways.Select(p => p.name).ToArray(), this); autoland.runway = availableRunways[runwayIndex]; GUILayout.Label("Distance to runway: " + MuUtils.ToSI(Vector3d.Distance(vesselState.CoM, autoland.runway.Start()), 0) + "m"); showLandingTarget = GUILayout.Toggle(showLandingTarget, "Show landing navball guidance"); if (GUILayout.Button("Autoland")) { autoland.Autoland(this); } if (autoland.enabled && GUILayout.Button("Abort")) { autoland.AutopilotOff(); } GuiUtils.SimpleTextBox("Autoland glideslope:", autoland.glideslope); GuiUtils.SimpleTextBox("Approach speed:", autoland.approachSpeed); GuiUtils.SimpleTextBox("Touchdown speed:", autoland.touchdownSpeed); autoland.bEngageReverseIfAvailable = GUILayout.Toggle(autoland.bEngageReverseIfAvailable, "Reverse thrust upon touchdown"); autoland.bBreakAsSoonAsLanded = GUILayout.Toggle(autoland.bBreakAsSoonAsLanded, "Break As Soon As Landed"); if (autoland.enabled) { GUILayout.Label("State: " + autoland.AutolandApproachStateToHumanReadableDescription()); GUILayout.Label(string.Format("Distance to waypoint: {0} m", Math.Round(autoland.GetAutolandLateralDistanceToNextWaypoint(), 0))); GUILayout.Label(string.Format("Target speed: {0} m/s", Math.Round(autoland.Autopilot.SpeedTarget, 1))); GUILayout.Label(string.Format("Target altitude: {0} m", Math.Round(autoland.GetAutolandTargetAltitude(autoland.GetAutolandTargetVector()), 0))); GUILayout.Label(string.Format("Target vertical speed: {0} m/s", Math.Round(autoland.Autopilot.VertSpeedTarget, 1))); GUILayout.Label(string.Format("Target heading: {0}º", Math.Round(autoland.Autopilot.HeadingTarget, 0))); } } GUILayout.EndVertical(); base.WindowGUI(windowID); }
protected override void WindowGUI(int windowID) { GUILayout.BeginVertical(); GUIStyle s = new GUIStyle(GUI.skin.label); s.alignment = TextAnchor.MiddleCenter; GUILayout.Label("Landing", s); Runway[] runways = MechJebModuleSpaceplaneAutopilot.runways; int runwayIndex = Array.IndexOf(runways, autopilot.runway); runwayIndex = GuiUtils.ArrowSelector(runwayIndex, runways.Length, autopilot.runway.name); autopilot.runway = runways[runwayIndex]; GUILayout.Label("Distance to runway: " + MuUtils.ToSI(Vector3d.Distance(vesselState.CoM, autopilot.runway.Start(vesselState.CoM)), 0) + "m"); showLandingTarget = GUILayout.Toggle(showLandingTarget, "Show landing navball guidance"); if (GUILayout.Button("Autoland")) { autopilot.Autoland(this); } if (autopilot.enabled && autopilot.mode == MechJebModuleSpaceplaneAutopilot.Mode.AUTOLAND && GUILayout.Button("Abort")) { autopilot.AutopilotOff(); } GuiUtils.SimpleTextBox("Autoland glideslope:", autopilot.glideslope, "º"); GUILayout.Label("Hold", s); GUILayout.BeginHorizontal(); if (GUILayout.Button("Initiate hold:")) { autopilot.HoldHeadingAndAltitude(this); } GUILayout.Label("Heading:"); autopilot.targetHeading.text = GUILayout.TextField(autopilot.targetHeading.text, GUILayout.Width(40)); GUILayout.Label("º Altitude:"); autopilot.targetAltitude.text = GUILayout.TextField(autopilot.targetAltitude.text, GUILayout.Width(40)); GUILayout.Label("m"); GUILayout.EndHorizontal(); if (autopilot.enabled && autopilot.mode == MechJebModuleSpaceplaneAutopilot.Mode.HOLD && GUILayout.Button("Abort")) { autopilot.AutopilotOff(); } GUILayout.EndVertical(); base.WindowGUI(windowID); }
public string OrbitSummary(Orbit o) { if (o.eccentricity > 1) { return("hyperbolic, Pe = " + MuUtils.ToSI(o.PeA, 2) + "m"); } else { return(MuUtils.ToSI(o.PeA, 2) + "m x " + MuUtils.ToSI(o.ApA, 2) + "m"); } }
public string TargetClosestApproachDistance() { if (!core.target.NormalTargetExists) { return("N/A"); } if (core.target.Orbit.referenceBody != orbit.referenceBody) { return("N/A"); } return(MuUtils.ToSI(orbit.NextClosestApproachDistance(core.target.Orbit, vesselState.time), -1) + "m"); }
public override ManeuverParameters MakeNodeImpl(Orbit o, double universalTime, MechJebModuleTargetController target) { double UT = timeSelector.ComputeManeuverTime(o, universalTime, target); if (o.referenceBody.Radius + newApA < o.Radius(UT)) { string burnAltitude = MuUtils.ToSI(o.Radius(UT) - o.referenceBody.Radius) + "m"; throw new OperationException(Localizer.Format("#MechJeb_Ap_Exception", burnAltitude));//new apoapsis cannot be lower than the altitude of the burn (<<1>>) } return(new ManeuverParameters(OrbitalManeuverCalculator.DeltaVToChangeApoapsis(o, UT, newApA + o.referenceBody.Radius), UT)); }
public string TargetClosestApproachRelativeVelocity() { if (!core.target.NormalTargetExists) { return("N/A"); } if (core.target.Orbit.referenceBody != orbit.referenceBody) { return("N/A"); } double UT = orbit.NextClosestApproachTime(core.target.Orbit, vesselState.time); double relVel = (orbit.SwappedOrbitalVelocityAtUT(UT) - core.target.Orbit.SwappedOrbitalVelocityAtUT(UT)).magnitude; return(MuUtils.ToSI(relVel, -1) + "m/s"); }
public override ManeuverParameters MakeNodeImpl(Orbit o, double universalTime, MechJebModuleTargetController target) { double UT = timeSelector.ComputeManeuverTime(o, universalTime, target); if (o.referenceBody.Radius + newPeA > o.Radius(UT)) { string burnAltitude = MuUtils.ToSI(o.Radius(UT) - o.referenceBody.Radius) + "m"; throw new Exception("new periapsis cannot be higher than the altitude of the burn (" + burnAltitude + ")"); } else if (newPeA < -o.referenceBody.Radius) { throw new Exception("new periapsis cannot be lower than minus the radius of " + o.referenceBody.theName + "(-" + MuUtils.ToSI(o.referenceBody.Radius, 3) + "m)"); } return(new ManeuverParameters(OrbitalManeuverCalculator.DeltaVToChangePeriapsis(o, UT, newPeA + o.referenceBody.Radius), UT)); }
void DrawGUIPrediction() { ReentrySimulation.Result result = predictor.Result; if (result != null) { switch (result.outcome) { case ReentrySimulation.Outcome.LANDED: GUILayout.Label("Landing Predictions:"); GUILayout.Label(Coordinates.ToStringDMS(result.endPosition.latitude, result.endPosition.longitude) + "\nASL:" + MuUtils.ToSI(result.endASL, -1, 4) + "m"); GUILayout.Label(result.body.GetExperimentBiomeSafe(result.endPosition.latitude, result.endPosition.longitude)); double error = Vector3d.Distance(mainBody.GetWorldSurfacePosition(result.endPosition.latitude, result.endPosition.longitude, 0) - mainBody.position, mainBody.GetWorldSurfacePosition(core.target.targetLatitude, core.target.targetLongitude, 0) - mainBody.position); GUILayout.Label("Target difference = " + MuUtils.ToSI(error, 0) + "m" + "\nMax drag: " + result.maxDragGees.ToString("F1") + "g" + "\nDelta-v needed: " + result.deltaVExpended.ToString("F1") + "m/s" + "\nTime to land: " + (vessel.Landed ? "0.0s" : GuiUtils.TimeToDHMS(result.endUT - Planetarium.GetUniversalTime(), 1))); break; case ReentrySimulation.Outcome.AEROBRAKED: GUILayout.Label("Predicted orbit after aerobraking:"); Orbit o = result.AeroBrakeOrbit(); if (o.eccentricity > 1) { GUILayout.Label("Hyperbolic, eccentricity = " + o.eccentricity.ToString("F2")); } else { GUILayout.Label(MuUtils.ToSI(o.PeA, 3) + "m x " + MuUtils.ToSI(o.ApA, 3) + "m"); } GUILayout.Label("Max drag: " + result.maxDragGees.ToString("F1") + "g" + "\nExit atmosphere in: " + GuiUtils.TimeToDHMS(result.aeroBrakeUT - Planetarium.GetUniversalTime(), 1)); break; case ReentrySimulation.Outcome.NO_REENTRY: GUILayout.Label("Orbit does not reenter:\n" + MuUtils.ToSI(orbit.PeA, 3) + "m Pe > " + MuUtils.ToSI(mainBody.RealMaxAtmosphereAltitude(), 3) + (mainBody.atmosphere ? "m atmosphere height" : "m ground")); break; case ReentrySimulation.Outcome.TIMED_OUT: GUILayout.Label("Reentry simulation timed out."); break; } } }
void DrawGUIPrediction() { ReentrySimulation.Result result = predictor.GetResult(); if (result != null) { switch (result.outcome) { case ReentrySimulation.Outcome.LANDED: GUILayout.Label("Predicted landing site:"); GUILayout.Label(Coordinates.ToStringDMS(result.endPosition.latitude, result.endPosition.longitude)); double error = Vector3d.Distance(mainBody.GetRelSurfacePosition(result.endPosition.latitude, result.endPosition.longitude, 0), mainBody.GetRelSurfacePosition(core.target.targetLatitude, core.target.targetLongitude, 0)); GUILayout.Label("Difference from target = " + MuUtils.ToSI(error, 0) + "m"); if (result.maxDragGees > 0) { GUILayout.Label("Predicted max drag gees: " + result.maxDragGees.ToString("F1")); } break; case ReentrySimulation.Outcome.AEROBRAKED: GUILayout.Label("Predicted orbit after aerobraking:"); Orbit o = result.EndOrbit(); if (o.eccentricity > 1) { GUILayout.Label("Hyperbolic, eccentricity = " + o.eccentricity.ToString("F2")); } else { GUILayout.Label(MuUtils.ToSI(o.PeA, 3) + "m x " + MuUtils.ToSI(o.ApA, 3) + "m"); } break; case ReentrySimulation.Outcome.NO_REENTRY: GUILayout.Label("Orbit does not reenter:"); GUILayout.Label(MuUtils.ToSI(orbit.PeA, 3) + "m Pe > " + MuUtils.ToSI(mainBody.RealMaxAtmosphereAltitude(), 3) + "m atmosphere height"); break; case ReentrySimulation.Outcome.TIMED_OUT: GUILayout.Label("Reentry simulation timed out."); break; } } }
public override List <ManeuverParameters> MakeNodesImpl(Orbit o, double universalTime, MechJebModuleTargetController target) { double UT = timeSelector.ComputeManeuverTime(o, universalTime, target); if (o.referenceBody.Radius + newPeA > o.Radius(UT)) { string burnAltitude = MuUtils.ToSI(o.Radius(UT) - o.referenceBody.Radius) + "m"; throw new OperationException(Localizer.Format("#MechJeb_Pe_Exception1") + " (" + burnAltitude + ")");//new periapsis cannot be higher than the altitude of the burn } else if (newPeA < -o.referenceBody.Radius) { throw new OperationException(Localizer.Format("#MechJeb_Pe_Exception2", o.referenceBody.displayName) + "(-" + MuUtils.ToSI(o.referenceBody.Radius, 3) + "m)");//new periapsis cannot be lower than minus the radius of <<1>> } List <ManeuverParameters> NodeList = new List <ManeuverParameters>(); NodeList.Add(new ManeuverParameters(OrbitalManeuverCalculator.DeltaVToChangePeriapsis(o, UT, newPeA + o.referenceBody.Radius), UT)); return(NodeList); }
public override ManeuverParameters MakeNodeImpl(Orbit o, double universalTime, MechJebModuleTargetController target) { double UT = timeSelector.ComputeManeuverTime(o, universalTime, target); string burnAltitude = MuUtils.ToSI(o.Radius(UT) - o.referenceBody.Radius) + "m"; if (o.referenceBody.Radius + newPeA > o.Radius(UT)) { throw new OperationException(Localizer.Format("#MechJeb_both_Exception1", burnAltitude));//new periapsis cannot be higher than the altitude of the burn (<<1>>) } else if (o.referenceBody.Radius + newApA < o.Radius(UT)) { throw new OperationException(Localizer.Format("#MechJeb_both_Exception2") + "(" + burnAltitude + ")");//new apoapsis cannot be lower than the altitude of the burn } else if (newPeA < -o.referenceBody.Radius) { throw new OperationException(Localizer.Format("#MechJeb_both_Exception3") + o.referenceBody.displayName + "(-" + MuUtils.ToSI(o.referenceBody.Radius, 3) + "m)");//"new periapsis cannot be lower than minus the radius of " } return(new ManeuverParameters(OrbitalManeuverCalculator.DeltaVToEllipticize(o, UT, newPeA + o.referenceBody.Radius, newApA + o.referenceBody.Radius), UT)); }
protected override void WindowGUI(int windowID) { if (!core.target.NormalTargetExists) { GUILayout.Label("Select a target to rendezvous with."); base.WindowGUI(windowID); return; } if (core.target.Orbit.referenceBody != orbit.referenceBody) { GUILayout.Label("Rendezvous target must be in the same sphere of influence."); base.WindowGUI(windowID); return; } GUILayout.BeginVertical(); //Information readouts: GuiUtils.SimpleLabel("Rendezvous target", core.target.Name); double leadTime = 30; GuiUtils.SimpleLabel("Target orbit", MuUtils.ToSI(core.target.Orbit.PeA, 3) + "m x " + MuUtils.ToSI(core.target.Orbit.ApA, 3) + "m"); GuiUtils.SimpleLabel("Current orbit", MuUtils.ToSI(orbit.PeA, 3) + "m x " + MuUtils.ToSI(orbit.ApA, 3) + "m"); GuiUtils.SimpleLabel("Relative inclination", orbit.RelativeInclination(core.target.Orbit).ToString("F2") + "º"); double closestApproachTime = orbit.NextClosestApproachTime(core.target.Orbit, vesselState.time); GuiUtils.SimpleLabel("Time until closest approach", GuiUtils.TimeToDHMS(closestApproachTime - vesselState.time)); GuiUtils.SimpleLabel("Separation at closest approach", MuUtils.ToSI(orbit.Separation(core.target.Orbit, closestApproachTime), 0) + "m"); //Maneuver planning buttons: if (GUILayout.Button("Align Planes")) { double UT; Vector3d dV; if (orbit.AscendingNodeExists(core.target.Orbit)) { dV = OrbitalManeuverCalculator.DeltaVAndTimeToMatchPlanesAscending(orbit, core.target.Orbit, vesselState.time, out UT); } else { dV = OrbitalManeuverCalculator.DeltaVAndTimeToMatchPlanesDescending(orbit, core.target.Orbit, vesselState.time, out UT); } vessel.RemoveAllManeuverNodes(); vessel.PlaceManeuverNode(orbit, dV, UT); } GUILayout.BeginHorizontal(); if (GUILayout.Button("Establish new orbit at")) { double phasingOrbitRadius = phasingOrbitAltitude + mainBody.Radius; vessel.RemoveAllManeuverNodes(); if (orbit.ApR < phasingOrbitRadius) { double UT1 = vesselState.time + leadTime; Vector3d dV1 = OrbitalManeuverCalculator.DeltaVToChangeApoapsis(orbit, UT1, phasingOrbitRadius); vessel.PlaceManeuverNode(orbit, dV1, UT1); Orbit transferOrbit = vessel.patchedConicSolver.maneuverNodes[0].nextPatch; double UT2 = transferOrbit.NextApoapsisTime(UT1); Vector3d dV2 = OrbitalManeuverCalculator.DeltaVToCircularize(transferOrbit, UT2); vessel.PlaceManeuverNode(transferOrbit, dV2, UT2); } else if (orbit.PeR > phasingOrbitRadius) { double UT1 = vesselState.time + leadTime; Vector3d dV1 = OrbitalManeuverCalculator.DeltaVToChangePeriapsis(orbit, UT1, phasingOrbitRadius); vessel.PlaceManeuverNode(orbit, dV1, UT1); Orbit transferOrbit = vessel.patchedConicSolver.maneuverNodes[0].nextPatch; double UT2 = transferOrbit.NextPeriapsisTime(UT1); Vector3d dV2 = OrbitalManeuverCalculator.DeltaVToCircularize(transferOrbit, UT2); vessel.PlaceManeuverNode(transferOrbit, dV2, UT2); } else { double UT = orbit.NextTimeOfRadius(vesselState.time, phasingOrbitRadius); Vector3d dV = OrbitalManeuverCalculator.DeltaVToCircularize(orbit, UT); vessel.PlaceManeuverNode(orbit, dV, UT); } } phasingOrbitAltitude.text = GUILayout.TextField(phasingOrbitAltitude.text, GUILayout.Width(70)); GUILayout.Label("km", GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); if (GUILayout.Button("Intercept with Hohmann transfer")) { double UT; Vector3d dV = OrbitalManeuverCalculator.DeltaVAndTimeForHohmannTransfer(orbit, core.target.Orbit, vesselState.time, out UT); vessel.RemoveAllManeuverNodes(); vessel.PlaceManeuverNode(orbit, dV, UT); } if (GUILayout.Button("Match velocities at closest approach")) { double UT = closestApproachTime; Vector3d dV = OrbitalManeuverCalculator.DeltaVToMatchVelocities(orbit, UT, core.target.Orbit); vessel.RemoveAllManeuverNodes(); vessel.PlaceManeuverNode(orbit, dV, UT); } if (GUILayout.Button("Get closer")) { double UT = vesselState.time; double interceptUT = UT + 100; Vector3d dV = OrbitalManeuverCalculator.DeltaVToInterceptAtTime(orbit, UT, core.target.Orbit, interceptUT, 10); vessel.RemoveAllManeuverNodes(); vessel.PlaceManeuverNode(orbit, dV, UT); } GUILayout.EndVertical(); base.WindowGUI(windowID); }
string GetStringValue(object value) { if (value == null) { return("null"); } if (value is string) { return((string)value + " " + units); } if (value is int) { return(((int)value).ToString() + " " + units); } double doubleValue = -999; if (value is double) { doubleValue = (double)value; } else if (value is float) { doubleValue = (float)value; } else if (value is MovingAverage) { doubleValue = (MovingAverage)value; } else if (value is Vector3d) { doubleValue = ((Vector3d)value).magnitude; } else if (value is Vector3) { doubleValue = ((Vector3)value).magnitude; } else if (value is EditableDouble) { doubleValue = (EditableDouble)value; } if (format == TIME) { return(GuiUtils.TimeToDHMS(doubleValue, timeDecimalPlaces)); } else if (format == ANGLE) { return(Coordinates.AngleToDMS(doubleValue)); } else if (format == ANGLE_NS) { return(Coordinates.AngleToDMS(doubleValue) + " " + (doubleValue > 0 ? "N" : "S")); } else if (format == ANGLE_EW) { return(Coordinates.AngleToDMS(doubleValue) + " " + (doubleValue > 0 ? "E" : "W")); } else if (format == SI) { return(MuUtils.ToSI(doubleValue, siMaxPrecision, siSigFigs) + units); } else { return(doubleValue.ToString(format) + " " + units); } }
protected override void WindowGUI(int windowID) { if (path == null) { GUILayout.Label("Path is null!!!1!!1!1!1111!11eleven"); base.WindowGUI(windowID); } GUILayout.BeginVertical(); double oldTurnStartAltitude = path.turnStartAltitude; double oldTurnEndAltitude = path.turnEndAltitude; double oldTurnShapeExponent = path.turnShapeExponent; double oldTurnEndAngle = path.turnEndAngle; GUILayout.BeginHorizontal(); path.autoPath = GUILayout.Toggle(path.autoPath, "Automatic Altitude Turn", GUILayout.ExpandWidth(false)); if (path.autoPath) { path.autoTurnPerc = Mathf.Floor(GUILayout.HorizontalSlider(path.autoTurnPerc, 0.01f, 1.05f) * 200f + 0.5f) / 200f; } GUILayout.EndHorizontal(); if (path.autoPath) { GUILayout.BeginHorizontal(); GUILayout.Label("Turn start altitude: "); GUILayout.Label(MuUtils.ToSI(path.autoTurnStartAltitude, -1, 2) + "m", new GUIStyle(GUI.skin.label) { alignment = TextAnchor.MiddleRight }, GUILayout.ExpandWidth(true)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label("Turn end altitude: "); GUILayout.Label(MuUtils.ToSI(path.autoTurnEndAltitude, -1, 2) + "m", new GUIStyle(GUI.skin.label) { alignment = TextAnchor.MiddleRight }, GUILayout.ExpandWidth(true)); GUILayout.EndHorizontal(); } else { GuiUtils.SimpleTextBox("Turn start altitude:", path.turnStartAltitude, "km"); GuiUtils.SimpleTextBox("Turn end altitude:", path.turnEndAltitude, "km"); } GuiUtils.SimpleTextBox("Final flight path angle:", path.turnEndAngle, "°"); GuiUtils.SimpleTextBox("Turn shape:", path.turnShapeExponent, "%"); // Round the slider's value (0..1) to sliderPrecision decimal places. int sliderPrecision = 3; double sliderTurnShapeExponent = GUILayout.HorizontalSlider((float)path.turnShapeExponent, 0.0F, 1.0F); if (Math.Round(Math.Abs(sliderTurnShapeExponent - oldTurnShapeExponent), sliderPrecision) > 0) { path.turnShapeExponent = new EditableDoubleMult(Math.Round(sliderTurnShapeExponent, sliderPrecision), 0.01); } GUILayout.Box(pathTexture); GUILayout.EndVertical(); if (path.turnStartAltitude != oldTurnStartAltitude || path.turnEndAltitude != oldTurnEndAltitude || path.turnShapeExponent != oldTurnShapeExponent || path.turnEndAngle != oldTurnEndAngle || !pathTextureDrawnBefore) { UpdatePathTexture(); } base.WindowGUI(windowID); }
protected override void WindowGUI(int windowID) { GUILayout.BeginVertical(); if (core.target.PositionTargetExists) { var ASL = core.vessel.mainBody.TerrainAltitude(core.target.targetLatitude, core.target.targetLongitude); GUILayout.Label("Target coordinates:"); GUILayout.BeginHorizontal(); core.target.targetLatitude.DrawEditGUI(EditableAngle.Direction.NS); if (GUILayout.Button("▲")) { moveByMeter(ref core.target.targetLatitude, 10, ASL); } GUILayout.Label("10m"); if (GUILayout.Button("▼")) { moveByMeter(ref core.target.targetLatitude, -10, ASL); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); core.target.targetLongitude.DrawEditGUI(EditableAngle.Direction.EW); if (GUILayout.Button("◄")) { moveByMeter(ref core.target.targetLongitude, -10, ASL); } GUILayout.Label("10m"); if (GUILayout.Button("►")) { moveByMeter(ref core.target.targetLongitude, 10, ASL); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label("ASL: " + MuUtils.ToSI(ASL, -1, 4) + "m"); GUILayout.Label(core.target.targetBody.GetExperimentBiomeSafe(core.target.targetLatitude, core.target.targetLongitude)); GUILayout.EndHorizontal(); } else { if (GUILayout.Button("Enter target coordinates")) { core.target.SetPositionTarget(mainBody, core.target.targetLatitude, core.target.targetLongitude); } } if (GUILayout.Button("Pick target on map")) { core.target.PickPositionTargetOnMap(); } List <LandingSite> availableLandingSites = landingSites.Where(p => p.body == mainBody).ToList(); if (availableLandingSites.Any()) { GUILayout.BeginHorizontal(); landingSiteIdx = GuiUtils.ComboBox.Box(landingSiteIdx, availableLandingSites.Select(p => p.name).ToArray(), this); if (GUILayout.Button("Set", GUILayout.ExpandWidth(false))) { core.target.SetPositionTarget(mainBody, availableLandingSites[landingSiteIdx].latitude, availableLandingSites[landingSiteIdx].longitude); } GUILayout.EndHorizontal(); } DrawGUITogglePredictions(); if (core.landing != null) { GUILayout.Label("Autopilot:"); predictor.maxOrbits = core.landing.enabled ? 0.5 : 4; predictor.noSkipToFreefall = !core.landing.enabled; if (core.landing.enabled) { if (GUILayout.Button("Abort autoland")) { core.landing.StopLanding(); } } else { GUILayout.BeginHorizontal(); if (!core.target.PositionTargetExists || vessel.LandedOrSplashed) { GUI.enabled = false; } if (GUILayout.Button("Land at target")) { core.landing.LandAtPositionTarget(this); } GUI.enabled = !vessel.LandedOrSplashed; if (GUILayout.Button("Land somewhere")) { core.landing.LandUntargeted(this); } GUI.enabled = true; GUILayout.EndHorizontal(); } GuiUtils.SimpleTextBox("Touchdown speed:", core.landing.touchdownSpeed, "m/s", 35); if (core.landing != null) { core.node.autowarp = GUILayout.Toggle(core.node.autowarp, "Auto-warp"); } core.landing.deployGears = GUILayout.Toggle(core.landing.deployGears, "Deploy Landing Gear"); GuiUtils.SimpleTextBox("Stage Limit:", core.landing.limitGearsStage, "", 35); core.landing.deployChutes = GUILayout.Toggle(core.landing.deployChutes, "Deploy Parachutes"); predictor.deployChutes = core.landing.deployChutes; GuiUtils.SimpleTextBox("Stage Limit:", core.landing.limitChutesStage, "", 35); predictor.limitChutesStage = core.landing.limitChutesStage; core.landing.rcsAdjustment = GUILayout.Toggle(core.landing.rcsAdjustment, "Use RCS for small adjustment"); if (core.landing.enabled) { GUILayout.Label("Status: " + core.landing.status); GUILayout.Label("Step: " + (core.landing.CurrentStep != null ? core.landing.CurrentStep.GetType().Name : "N/A")); GUILayout.Label("Mode " + (core.landing.descentSpeedPolicy != null ? core.landing.descentSpeedPolicy.GetType().Name : "N/A") + " (" + core.landing.UseAtmosphereToBrake().ToString() + ")"); //GUILayout.Label("DecEndAlt: " + core.landing.DecelerationEndAltitude().ToString("F2")); //var dragLength = mainBody.DragLength(core.landing.LandingAltitude, core.landing.vesselAverageDrag, vesselState.mass); //GUILayout.Label("Drag Length: " + ( dragLength < double.MaxValue ? dragLength.ToString("F2") : "infinite")); // //string parachuteInfo = core.landing.ParachuteControlInfo; //if (null != parachuteInfo) //{ // GUILayout.Label(parachuteInfo); //} } } GUILayout.EndVertical(); base.WindowGUI(windowID); }
protected override void WindowGUI(int windowID) { if (!core.target.NormalTargetExists) { GUILayout.Label("Select a target to rendezvous with."); base.WindowGUI(windowID); return; } if (core.target.Orbit.referenceBody != orbit.referenceBody) { GUILayout.Label("Rendezvous target must be in the same sphere of influence."); base.WindowGUI(windowID); return; } GUILayout.BeginVertical(); step = (Step)GuiUtils.ArrowSelector((int)step, numSteps, stepStrings[(int)step]); double leadTime = 30; switch (step) { case Step.AlignPlanes: GUILayout.Label("First, bring your relative inclination to zero by aligning your orbital plane with the target's orbital plane:"); GUILayout.Label("Relative inclination: " + orbit.RelativeInclination(core.target.Orbit).ToString("F2") + "º"); if (GUILayout.Button("Align Planes")) { double UT; Vector3d dV; if (orbit.AscendingNodeExists(core.target.Orbit)) { dV = OrbitalManeuverCalculator.DeltaVAndTimeToMatchPlanesAscending(orbit, core.target.Orbit, vesselState.time, out UT); } else { dV = OrbitalManeuverCalculator.DeltaVAndTimeToMatchPlanesDescending(orbit, core.target.Orbit, vesselState.time, out UT); } vessel.PlaceManeuverNode(orbit, dV, UT); } break; case Step.PhasingOrbit: double phasingOrbitRadius = 0.9 * core.target.Orbit.PeR; if (phasingOrbitRadius < orbit.referenceBody.Radius + orbit.referenceBody.RealMaxAtmosphereAltitude()) { phasingOrbitRadius = 1.1 * core.target.Orbit.ApR; } double phasingOrbitAltitude = phasingOrbitRadius - mainBody.Radius; GUILayout.Label("Next, establish a circular phasing orbit close to the target orbit."); GUILayout.Label("Target orbit: " + MuUtils.ToSI(core.target.Orbit.PeA, 3) + "m x " + MuUtils.ToSI(core.target.Orbit.ApA, 3) + "m"); GUILayout.Label("Suggested phasing orbit: " + MuUtils.ToSI(phasingOrbitAltitude, 3) + "m x " + MuUtils.ToSI(phasingOrbitAltitude, 3) + "m"); GUILayout.Label("Current orbit: " + MuUtils.ToSI(orbit.PeA, 3) + "m x " + MuUtils.ToSI(orbit.ApA, 3) + "m"); if (GUILayout.Button("Establish Phasing Orbit")) { if (orbit.ApR < phasingOrbitRadius) { double UT1 = vesselState.time + leadTime; Vector3d dV1 = OrbitalManeuverCalculator.DeltaVToChangeApoapsis(orbit, UT1, phasingOrbitRadius); vessel.PlaceManeuverNode(orbit, dV1, UT1); Orbit transferOrbit = vessel.patchedConicSolver.maneuverNodes[0].nextPatch; double UT2 = transferOrbit.NextApoapsisTime(UT1); Vector3d dV2 = OrbitalManeuverCalculator.DeltaVToCircularize(transferOrbit, UT2); vessel.PlaceManeuverNode(transferOrbit, dV2, UT2); } else if (orbit.PeR > phasingOrbitRadius) { double UT1 = vesselState.time + leadTime; Vector3d dV1 = OrbitalManeuverCalculator.DeltaVToChangePeriapsis(orbit, UT1, phasingOrbitRadius); vessel.PlaceManeuverNode(orbit, dV1, UT1); Orbit transferOrbit = vessel.patchedConicSolver.maneuverNodes[0].nextPatch; double UT2 = transferOrbit.NextPeriapsisTime(UT1); Vector3d dV2 = OrbitalManeuverCalculator.DeltaVToCircularize(transferOrbit, UT2); vessel.PlaceManeuverNode(transferOrbit, dV2, UT2); } else { double UT = orbit.NextTimeOfRadius(vesselState.time, phasingOrbitRadius); Vector3d dV = OrbitalManeuverCalculator.DeltaVToCircularize(orbit, UT); vessel.PlaceManeuverNode(orbit, dV, UT); } } break; case Step.Transfer: GUILayout.Label("Once in the phasing orbit, transfer to the target orbit at just the right time to intercept the target:"); if (GUILayout.Button("Intercept with Hohmann transfer")) { double UT; Vector3d dV = OrbitalManeuverCalculator.DeltaVAndTimeForHohmannTransfer(orbit, core.target.Orbit, vesselState.time, out UT); vessel.PlaceManeuverNode(orbit, dV, UT); } double closestApproachTime = orbit.NextClosestApproachTime(core.target.Orbit, vesselState.time); GUILayout.Label("Once on a transfer trajectory, match velocities at closest approach:"); GUILayout.Label("Time until closest approach: " + GuiUtils.TimeToDHMS(closestApproachTime - vesselState.time)); GUILayout.Label("Separation at closest approach: " + MuUtils.ToSI(orbit.Separation(core.target.Orbit, closestApproachTime), 0) + "m"); if (GUILayout.Button("Match velocities at closest approach")) { double UT = closestApproachTime; Vector3d dV = OrbitalManeuverCalculator.DeltaVToMatchVelocities(orbit, UT, core.target.Orbit); vessel.PlaceManeuverNode(orbit, dV, UT); } break; case Step.GetCloser: GUILayout.Label("If you aren't close enough after matching velocities, thrust gently toward the target:"); if (GUILayout.Button("Get closer")) { double UT = vesselState.time; double interceptUT = UT + 100; Vector3d dV = OrbitalManeuverCalculator.DeltaVToInterceptAtTime(orbit, UT, core.target.Orbit, interceptUT, 10); vessel.PlaceManeuverNode(orbit, dV, UT); } GUILayout.Label("Then match velocities again at closest approach"); break; } GUILayout.EndVertical(); MechJebModuleRendezvousAutopilot autopilot = core.GetComputerModule <MechJebModuleRendezvousAutopilot>(); if (autopilot != null) { bool active = GUILayout.Toggle(autopilot.enabled, "Autopilot enable"); if (autopilot.enabled != active) { if (active) { autopilot.users.Add(this); } else { autopilot.users.Remove(this); } } if (autopilot.enabled) { GUILayout.Label("Status: " + autopilot.status); } } base.WindowGUI(windowID); }
public override List <ManeuverParameters> MakeNodesImpl(Orbit o, double universalTime, MechJebModuleTargetController target) { double UT = timeSelector.ComputeManeuverTime(o, universalTime, target); if (2 * newSMA > o.Radius(UT) + o.referenceBody.sphereOfInfluence) { errorMessage = Localizer.Format("#MechJeb_Sa_errormsg");//Warning: new Semi-Major Axis is very large, and may result in a hyberbolic orbit } if (o.Radius(UT) > 2 * newSMA) { throw new OperationException(Localizer.Format("#MechJeb_Sa_Exception", o.referenceBody.displayName) + "(" + MuUtils.ToSI(o.referenceBody.Radius, 3) + "m)");//cannot make Semi-Major Axis less than twice the burn altitude plus the radius of <<1>> } List <ManeuverParameters> NodeList = new List <ManeuverParameters>(); NodeList.Add(new ManeuverParameters(OrbitalManeuverCalculator.DeltaVForSemiMajorAxis(o, UT, newSMA), UT)); return(NodeList); }
protected override void WindowGUI(int windowID) { GUILayout.BeginVertical(); bool showingGuidance = (core.target.Target != null && core.target.Name == TARGET_NAME); if (showingGuidance) { GUILayout.Label("The purple circle on the navball points along the ascent path."); if (GUILayout.Button("Stop showing navball guidance")) { core.target.Unset(); } } else if (GUILayout.Button("Show navball ascent path guidance")) { core.target.SetDirectionTarget(TARGET_NAME); } if (autopilot != null) { if (autopilot.enabled) { if (GUILayout.Button("Disengage autopilot")) { autopilot.users.Remove(this); } } else { if (GUILayout.Button("Engage autopilot")) { autopilot.users.Add(this); } } ascentPath = autopilot.ascentPath; GuiUtils.SimpleTextBox("Orbit altitude", autopilot.desiredOrbitAltitude, "km"); autopilot.desiredInclination = desiredInclination; } GuiUtils.SimpleTextBox("Orbit inclination", desiredInclination, "º"); core.thrust.LimitToPreventOverheatsInfoItem(); core.thrust.LimitToTerminalVelocityInfoItem(); core.thrust.LimitAccelerationInfoItem(); core.thrust.LimitThrottleInfoItem(); autopilot.forceRoll = GUILayout.Toggle(autopilot.forceRoll, "Force Roll"); GUILayout.BeginHorizontal(); GUIStyle s = new GUIStyle(GUI.skin.toggle); if (autopilot.limitingAoA) { s.onHover.textColor = s.onNormal.textColor = Color.green; } autopilot.limitAoA = GUILayout.Toggle(autopilot.limitAoA, "Limit angle of attack to", s, GUILayout.Width(150)); autopilot.maxAoA.text = GUILayout.TextField(autopilot.maxAoA.text, GUILayout.Width(30)); GUILayout.Label("º", GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); if (autopilot.limitAoA) { GuiUtils.SimpleTextBox("Dynamic Pressure Fadeout", autopilot.aoALimitFadeoutPressure, "", 50); } autopilot.correctiveSteering = GUILayout.Toggle(autopilot.correctiveSteering, "Corrective steering"); autopilot.autostage = GUILayout.Toggle(autopilot.autostage, "Autostage"); if (autopilot.autostage) { core.staging.AutostageSettingsInfoItem(); } core.node.autowarp = GUILayout.Toggle(core.node.autowarp, "Auto-warp"); if (autopilot != null && vessel.LandedOrSplashed) { if (core.target.NormalTargetExists) { if (core.node.autowarp) { GUILayout.BeginHorizontal(); GUILayout.Label("Launch countdown:", GUILayout.ExpandWidth(true)); autopilot.warpCountDown.text = GUILayout.TextField(autopilot.warpCountDown.text, GUILayout.Width(60)); GUILayout.Label("s", GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); } if (!launchingToPlane && !launchingToRendezvous && !launchingToInterplanetary) { GUILayout.BeginHorizontal(); if (GUILayout.Button("Launch to rendezvous:", GUILayout.ExpandWidth(false))) { launchingToRendezvous = true; lastTMinus = 999; } autopilot.launchPhaseAngle.text = GUILayout.TextField(autopilot.launchPhaseAngle.text, GUILayout.Width(60)); GUILayout.Label("º", GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); if (GUILayout.Button("Launch into plane of target")) { launchingToPlane = true; lastTMinus = 999; } if (core.target.TargetOrbit.referenceBody == orbit.referenceBody.referenceBody) { if (GUILayout.Button("Launch at interplanetary window")) { launchingToInterplanetary = true; lastTMinus = 999; //compute the desired launch date OrbitalManeuverCalculator.DeltaVAndTimeForHohmannTransfer(mainBody.orbit, core.target.TargetOrbit, vesselState.time, out interplanetaryWindowUT); double desiredOrbitPeriod = 2 * Math.PI * Math.Sqrt(Math.Pow(mainBody.Radius + autopilot.desiredOrbitAltitude, 3) / mainBody.gravParameter); //launch just before the window, but don't try to launch in the past interplanetaryWindowUT -= 3 * desiredOrbitPeriod; interplanetaryWindowUT = Math.Max(vesselState.time + autopilot.warpCountDown, interplanetaryWindowUT); } } } } else { launchingToInterplanetary = launchingToPlane = launchingToRendezvous = false; GUILayout.Label("Select a target for a timed launch."); } if (launchingToInterplanetary || launchingToPlane || launchingToRendezvous) { double tMinus = 0; string message = ""; if (launchingToInterplanetary) { tMinus = interplanetaryWindowUT - vesselState.time; message = "Launching at interplanetary window"; } else if (launchingToPlane) { tMinus = LaunchTiming.TimeToPlane(mainBody, vesselState.latitude, vesselState.longitude, core.target.TargetOrbit); desiredInclination = core.target.TargetOrbit.inclination; desiredInclination *= Math.Sign(Vector3d.Dot(core.target.TargetOrbit.SwappedOrbitNormal(), Vector3d.Cross(vesselState.CoM - mainBody.position, mainBody.transform.up))); message = "Launching to target plane"; } else if (launchingToRendezvous) { tMinus = LaunchTiming.TimeToPhaseAngle(autopilot.launchPhaseAngle, mainBody, vesselState.longitude, core.target.TargetOrbit); message = "Launching to rendezvous"; } double launchTime = vesselState.time + tMinus; if (tMinus < 3 * vesselState.deltaT || (tMinus > 10.0 && lastTMinus < 1.0)) { if (autopilot.enabled) { Staging.ActivateNextStage(); } launchingToInterplanetary = launchingToPlane = launchingToRendezvous = false; } else { message += ": T-" + MuUtils.ToSI(tMinus, 0) + "s"; if (autopilot.enabled && core.node.autowarp) { core.warp.WarpToUT(launchTime - autopilot.warpCountDown); } } GUILayout.Label(message); lastTMinus = tMinus; if (GUILayout.Button("Abort")) { launchingToInterplanetary = launchingToPlane = launchingToRendezvous = false; } } } if (autopilot != null && autopilot.enabled) { GUILayout.Label("Autopilot status: " + autopilot.status); } MechJebModuleAscentPathEditor editor = core.GetComputerModule <MechJebModuleAscentPathEditor>(); if (editor != null) { editor.enabled = GUILayout.Toggle(editor.enabled, "Edit ascent path"); } GUILayout.EndVertical(); base.WindowGUI(windowID); }
protected override void WindowGUI(int windowID) { GUILayout.BeginVertical(); bool showingGuidance = (core.target.Target != null && core.target.Name == TARGET_NAME); if (showingGuidance) { GUILayout.Label("The purple circle on the navball points along the ascent path."); if (GUILayout.Button("Stop showing navball guidance")) { core.target.Unset(); } } else if (GUILayout.Button("Show navball ascent path guidance")) { core.target.SetDirectionTarget(TARGET_NAME); } if (autopilot != null) { if (autopilot.enabled) { if (GUILayout.Button("Disengage autopilot")) { autopilot.users.Remove(this); } } else { if (GUILayout.Button("Engage autopilot")) { autopilot.users.Add(this); } } ascentPath = autopilot.ascentPath; GuiUtils.SimpleTextBox("Orbit altitude", autopilot.desiredOrbitAltitude, "km"); autopilot.desiredInclination = desiredInclination; } GuiUtils.SimpleTextBox("Orbit inclination", desiredInclination, "º"); core.thrust.limitToPreventOverheats = GUILayout.Toggle(core.thrust.limitToPreventOverheats, "Prevent overheats"); core.thrust.limitToTerminalVelocity = GUILayout.Toggle(core.thrust.limitToTerminalVelocity, "Limit to terminal velocity"); GUILayout.BeginHorizontal(); core.thrust.limitAcceleration = GUILayout.Toggle(core.thrust.limitAcceleration, "Limit acceleration to", GUILayout.ExpandWidth(false)); core.thrust.maxAcceleration.text = GUILayout.TextField(core.thrust.maxAcceleration.text, GUILayout.ExpandWidth(true)); GUILayout.Label("m/s²", GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); autopilot.correctiveSteering = GUILayout.Toggle(autopilot.correctiveSteering, "Corrective steering"); core.staging.AutostageInfoItem(); core.node.autowarp = GUILayout.Toggle(core.node.autowarp, "Auto-warp"); if (autopilot != null && vessel.LandedOrSplashed) { if (core.target.NormalTargetExists) { if (!launchingToPlane && !launchingToRendezvous) { GUILayout.BeginHorizontal(); if (GUILayout.Button("Launch to rendezvous:", GUILayout.ExpandWidth(false))) { launchingToRendezvous = true; } autopilot.launchPhaseAngle.text = GUILayout.TextField(autopilot.launchPhaseAngle.text, GUILayout.Width(60)); GUILayout.Label("º", GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); } if (!launchingToPlane && !launchingToRendezvous && GUILayout.Button("Launch into plane of target")) { launchingToPlane = true; } } else { launchingToPlane = launchingToRendezvous = false; GUILayout.Label("Select a target for a timed launch."); } if (launchingToPlane || launchingToRendezvous) { double tMinus; if (launchingToPlane) { tMinus = LaunchTiming.TimeToPlane(mainBody, vesselState.latitude, vesselState.longitude, core.target.Orbit); } else { tMinus = LaunchTiming.TimeToPhaseAngle(autopilot.launchPhaseAngle, mainBody, vesselState.longitude, core.target.Orbit); } double launchTime = vesselState.time + tMinus; core.warp.WarpToUT(launchTime); if (launchingToPlane) { desiredInclination = core.target.Orbit.inclination; desiredInclination *= Math.Sign(Vector3d.Dot(core.target.Orbit.SwappedOrbitNormal(), Vector3d.Cross(vesselState.CoM - mainBody.position, mainBody.transform.up))); } if (autopilot.enabled) { core.warp.WarpToUT(launchTime); } GUILayout.Label("Launching to " + (launchingToPlane ? "target plane" : "rendezvous") + ": T-" + MuUtils.ToSI(tMinus, 0) + "s"); if (tMinus < 3 * vesselState.deltaT) { if (autopilot.enabled) { Staging.ActivateNextStage(); } launchingToPlane = launchingToRendezvous = false; } if (GUILayout.Button("Abort")) { launchingToPlane = launchingToRendezvous = false; } } if (autopilot.enabled) { GUILayout.Label("Autopilot status: " + autopilot.status); } } MechJebModuleAscentPathEditor editor = core.GetComputerModule <MechJebModuleAscentPathEditor>(); if (editor != null) { editor.enabled = GUILayout.Toggle(editor.enabled, "Edit ascent path"); } GUILayout.EndVertical(); base.WindowGUI(windowID); }
public override void Drive(FlightCtrlState s) { if (!core.target.NormalTargetExists) { users.Clear(); return; } core.node.autowarp = core.target.Distance > 1000; //don't warp when close to target, because warping introduces small perturbations //If we get within the target distance and then next maneuver node is still //far in the future, delete it and we will create a new one to match velocities immediately. //This can often happen because the target vessel's orbit shifts slightly when it is unpacked. if (core.target.Distance < desiredDistance && vessel.patchedConicSolver.maneuverNodes.Count > 0 && vessel.patchedConicSolver.maneuverNodes[0].UT > vesselState.time + 1) { vessel.RemoveAllManeuverNodes(); } if (vessel.patchedConicSolver.maneuverNodes.Count > 0) { //If we have plotted a maneuver, execute it. if (!core.node.enabled) { core.node.ExecuteAllNodes(this); } } else if (core.target.Distance < desiredDistance * 1.05 + 2 && core.target.RelativeVelocity.magnitude < 1) { //finished users.Clear(); core.thrust.ThrustOff(); status = "Successful rendezvous"; } else if (core.target.Distance < desiredDistance * 1.05 + 2) { //We are within the target distance: match velocities double UT = vesselState.time; Vector3d dV = OrbitalManeuverCalculator.DeltaVToMatchVelocities(orbit, UT, core.target.Orbit); vessel.PlaceManeuverNode(orbit, dV, UT); status = "Within " + desiredDistance.ToString() + "m: matching velocities."; } else if (core.target.Distance < vesselState.radius / 25) { if (orbit.NextClosestApproachDistance(core.target.Orbit, vesselState.time) < desiredDistance && orbit.NextClosestApproachTime(core.target.Orbit, vesselState.time) < vesselState.time + 150) { //We're close to the target, and on a course that will take us closer. Kill relvel at closest approach double UT = orbit.NextClosestApproachTime(core.target.Orbit, vesselState.time); Vector3d dV = OrbitalManeuverCalculator.DeltaVToMatchVelocities(orbit, UT, core.target.Orbit); //adjust burn time so as to come to rest at the desired distance from the target: double approachDistance = orbit.Separation(core.target.Orbit, UT); double approachSpeed = (orbit.SwappedOrbitalVelocityAtUT(UT) - core.target.Orbit.SwappedOrbitalVelocityAtUT(UT)).magnitude; if (approachDistance < desiredDistance) { UT -= Math.Sqrt(Math.Abs(desiredDistance * desiredDistance - approachDistance * approachDistance)) / approachSpeed; } //if coming in hot, stop early to avoid crashing: if (approachSpeed > 10) { UT -= 1; } vessel.PlaceManeuverNode(orbit, dV, UT); status = "Planning to match velocities at closest approach."; } else { //We're not far from the target. Close the distance double closingSpeed = core.target.Distance / 100; if (closingSpeed > 100) { closingSpeed = 100; } double closingTime = core.target.Distance / closingSpeed; double UT = vesselState.time + 15; double interceptUT = UT + closingTime; Vector3d dV = OrbitalManeuverCalculator.DeltaVToInterceptAtTime(orbit, UT, core.target.Orbit, interceptUT, 0); vessel.PlaceManeuverNode(orbit, dV, UT); status = "Close to target: plotting intercept"; } } else if (orbit.NextClosestApproachDistance(core.target.Orbit, vesselState.time) < core.target.Orbit.semiMajorAxis / 25) { //We're not close to the target, but we're on an approximate intercept course. //Kill relative velocities at closest approach double UT = orbit.NextClosestApproachTime(core.target.Orbit, vesselState.time); Vector3d dV = OrbitalManeuverCalculator.DeltaVToMatchVelocities(orbit, UT, core.target.Orbit); //adjust burn time so as to come to rest at the desired distance from the target: double approachDistance = (orbit.SwappedAbsolutePositionAtUT(UT) - core.target.Orbit.SwappedAbsolutePositionAtUT(UT)).magnitude; double approachSpeed = (orbit.SwappedOrbitalVelocityAtUT(UT) - core.target.Orbit.SwappedOrbitalVelocityAtUT(UT)).magnitude; if (approachDistance < desiredDistance) { UT -= Math.Sqrt(Math.Abs(desiredDistance * desiredDistance - approachDistance * approachDistance)) / approachSpeed; } //if coming in hot, stop early to avoid crashing: if (approachSpeed > 10) { UT -= 1; } vessel.PlaceManeuverNode(orbit, dV, UT); status = "On intercept course. Planning to match velocities at closest approach."; } else if (orbit.RelativeInclination(core.target.Orbit) < 0.05 && orbit.eccentricity < 0.05 && orbit.SynodicPeriod(core.target.Orbit) < 5 * orbit.period) { //We're not on an intercept course, but we have a circular orbit in the right plane. //Also we are phasing quickly enough that it won't be too long until an intercept window //Plot a Hohmann transfer intercept. double UT; Vector3d dV = OrbitalManeuverCalculator.DeltaVAndTimeForHohmannTransfer(orbit, core.target.Orbit, vesselState.time, out UT); vessel.PlaceManeuverNode(orbit, dV, UT); status = "Planning Hohmann transfer for intercept."; } else if (orbit.RelativeInclination(core.target.Orbit) < 0.05 && orbit.eccentricity < 0.05) { //We are in a circular orbit in the right plane, but we aren't phasing quickly enough. Move to a better phasing orbit double lowPhasingRadius = core.target.Orbit.semiMajorAxis / 1.16; double highPhasingRadius = core.target.Orbit.semiMajorAxis * 1.16; bool useLowPhasingRadius = (lowPhasingRadius > mainBody.RealMaxAtmosphereAltitude() + 3000 && orbit.semiMajorAxis < core.target.orbit.semiMajorAxis); double phasingOrbitRadius = (useLowPhasingRadius ? lowPhasingRadius : highPhasingRadius); if (orbit.ApR < phasingOrbitRadius) { double UT1 = vesselState.time + 15; Vector3d dV1 = OrbitalManeuverCalculator.DeltaVToChangeApoapsis(orbit, UT1, phasingOrbitRadius); vessel.PlaceManeuverNode(orbit, dV1, UT1); Orbit transferOrbit = vessel.patchedConicSolver.maneuverNodes[0].nextPatch; double UT2 = transferOrbit.NextApoapsisTime(UT1); Vector3d dV2 = OrbitalManeuverCalculator.DeltaVToCircularize(transferOrbit, UT2); vessel.PlaceManeuverNode(transferOrbit, dV2, UT2); } else if (orbit.PeR > phasingOrbitRadius) { double UT1 = vesselState.time + 15; Vector3d dV1 = OrbitalManeuverCalculator.DeltaVToChangePeriapsis(orbit, UT1, phasingOrbitRadius); vessel.PlaceManeuverNode(orbit, dV1, UT1); Orbit transferOrbit = vessel.patchedConicSolver.maneuverNodes[0].nextPatch; double UT2 = transferOrbit.NextPeriapsisTime(UT1); Vector3d dV2 = OrbitalManeuverCalculator.DeltaVToCircularize(transferOrbit, UT2); vessel.PlaceManeuverNode(transferOrbit, dV2, UT2); } else { double UT = orbit.NextTimeOfRadius(vesselState.time, phasingOrbitRadius); Vector3d dV = OrbitalManeuverCalculator.DeltaVToCircularize(orbit, UT); vessel.PlaceManeuverNode(orbit, dV, UT); } status = "Increasing phasing rate by establishing new phasing orbit at " + MuUtils.ToSI(phasingOrbitRadius - mainBody.Radius, 0) + "m"; } else if (orbit.RelativeInclination(core.target.Orbit) < 0.05) { //We're not on an intercept course. We're in the right plane, but our orbit isn't circular. Circularize. bool circularizeAtPe; if (orbit.eccentricity > 1) { circularizeAtPe = true; } else { circularizeAtPe = Math.Abs(orbit.PeR - core.target.Orbit.semiMajorAxis) < Math.Abs(orbit.ApR - core.target.Orbit.semiMajorAxis); } double UT; if (circularizeAtPe) { UT = Math.Max(vesselState.time, orbit.NextPeriapsisTime(vesselState.time)); } else { UT = orbit.NextApoapsisTime(vesselState.time); } Vector3d dV = OrbitalManeuverCalculator.DeltaVToCircularize(orbit, UT); vessel.PlaceManeuverNode(orbit, dV, UT); status = "Circularizing."; } else { //We're not on an intercept course, and we're not in the right plane. Match planes bool ascending; if (orbit.eccentricity < 1) { if (orbit.TimeOfAscendingNode(core.target.Orbit, vesselState.time) < orbit.TimeOfDescendingNode(core.target.Orbit, vesselState.time)) { ascending = true; } else { ascending = false; } } else { if (orbit.AscendingNodeExists(core.target.Orbit)) { ascending = true; } else { ascending = false; } } double UT; Vector3d dV; if (ascending) { dV = OrbitalManeuverCalculator.DeltaVAndTimeToMatchPlanesAscending(orbit, core.target.Orbit, vesselState.time, out UT); } else { dV = OrbitalManeuverCalculator.DeltaVAndTimeToMatchPlanesDescending(orbit, core.target.Orbit, vesselState.time, out UT); } vessel.PlaceManeuverNode(orbit, dV, UT); status = "Matching planes."; } }
protected override void WindowGUI(int windowID) { if (!core.target.NormalTargetExists) { GUILayout.Label(Localizer.Format("#MechJeb_RZplan_label1"));//"Select a target to rendezvous with." base.WindowGUI(windowID); return; } if (core.target.TargetOrbit.referenceBody != orbit.referenceBody) { GUILayout.Label(Localizer.Format("#MechJeb_RZplan_label2"));//"Rendezvous target must be in the same sphere of influence." base.WindowGUI(windowID); return; } GUILayout.BeginVertical(); //Information readouts: GuiUtils.SimpleLabel(Localizer.Format("#MechJeb_RZplan_label3"), core.target.Name);//"Rendezvous target" const double leadTime = 30; GuiUtils.SimpleLabel(Localizer.Format("#MechJeb_RZplan_label4"), MuUtils.ToSI(core.target.TargetOrbit.PeA, 3) + "m x " + MuUtils.ToSI(core.target.TargetOrbit.ApA, 3) + "m"); //"Target orbit" GuiUtils.SimpleLabel(Localizer.Format("#MechJeb_RZplan_label5"), MuUtils.ToSI(orbit.PeA, 3) + "m x " + MuUtils.ToSI(orbit.ApA, 3) + "m"); //"Current orbit" GuiUtils.SimpleLabel(Localizer.Format("#MechJeb_RZplan_label6"), orbit.RelativeInclination(core.target.TargetOrbit).ToString("F2") + "º"); //"Relative inclination" double closestApproachTime = orbit.NextClosestApproachTime(core.target.TargetOrbit, vesselState.time); GuiUtils.SimpleLabel(Localizer.Format("#MechJeb_RZplan_label7"), GuiUtils.TimeToDHMS(closestApproachTime - vesselState.time)); //"Time until closest approach" GuiUtils.SimpleLabel(Localizer.Format("#MechJeb_RZplan_label8"), MuUtils.ToSI(orbit.Separation(core.target.TargetOrbit, closestApproachTime), 0) + "m"); //"Separation at closest approach" //Maneuver planning buttons: if (GUILayout.Button(Localizer.Format("#MechJeb_RZplan_button1")))//"Align Planes" { double UT; Vector3d dV; if (orbit.AscendingNodeExists(core.target.TargetOrbit)) { dV = OrbitalManeuverCalculator.DeltaVAndTimeToMatchPlanesAscending(orbit, core.target.TargetOrbit, vesselState.time, out UT); } else { dV = OrbitalManeuverCalculator.DeltaVAndTimeToMatchPlanesDescending(orbit, core.target.TargetOrbit, vesselState.time, out UT); } vessel.RemoveAllManeuverNodes(); vessel.PlaceManeuverNode(orbit, dV, UT); } GUILayout.BeginHorizontal(); if (GUILayout.Button(Localizer.Format("#MechJeb_RZplan_button2")))//"Establish new orbit at" { double phasingOrbitRadius = phasingOrbitAltitude + mainBody.Radius; vessel.RemoveAllManeuverNodes(); if (orbit.ApR < phasingOrbitRadius) { double UT1 = vesselState.time + leadTime; Vector3d dV1 = OrbitalManeuverCalculator.DeltaVToChangeApoapsis(orbit, UT1, phasingOrbitRadius); vessel.PlaceManeuverNode(orbit, dV1, UT1); Orbit transferOrbit = vessel.patchedConicSolver.maneuverNodes[0].nextPatch; double UT2 = transferOrbit.NextApoapsisTime(UT1); Vector3d dV2 = OrbitalManeuverCalculator.DeltaVToCircularize(transferOrbit, UT2); vessel.PlaceManeuverNode(transferOrbit, dV2, UT2); } else if (orbit.PeR > phasingOrbitRadius) { double UT1 = vesselState.time + leadTime; Vector3d dV1 = OrbitalManeuverCalculator.DeltaVToChangePeriapsis(orbit, UT1, phasingOrbitRadius); vessel.PlaceManeuverNode(orbit, dV1, UT1); Orbit transferOrbit = vessel.patchedConicSolver.maneuverNodes[0].nextPatch; double UT2 = transferOrbit.NextPeriapsisTime(UT1); Vector3d dV2 = OrbitalManeuverCalculator.DeltaVToCircularize(transferOrbit, UT2); vessel.PlaceManeuverNode(transferOrbit, dV2, UT2); } else { double UT = orbit.NextTimeOfRadius(vesselState.time, phasingOrbitRadius); Vector3d dV = OrbitalManeuverCalculator.DeltaVToCircularize(orbit, UT); vessel.PlaceManeuverNode(orbit, dV, UT); } } phasingOrbitAltitude.text = GUILayout.TextField(phasingOrbitAltitude.text, GUILayout.Width(70)); GUILayout.Label("km", GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); if (GUILayout.Button(Localizer.Format("#MechJeb_RZplan_button3")))//"Intercept with Hohmann transfer" { double UT; Vector3d dV = OrbitalManeuverCalculator.DeltaVAndTimeForHohmannTransfer(orbit, core.target.TargetOrbit, vesselState.time, out UT); vessel.RemoveAllManeuverNodes(); vessel.PlaceManeuverNode(orbit, dV, UT); } if (GUILayout.Button(Localizer.Format("#MechJeb_RZplan_button4")))//"Match velocities at closest approach" { double UT = closestApproachTime; Vector3d dV = OrbitalManeuverCalculator.DeltaVToMatchVelocities(orbit, UT, core.target.TargetOrbit); vessel.RemoveAllManeuverNodes(); vessel.PlaceManeuverNode(orbit, dV, UT); } if (GUILayout.Button(Localizer.Format("#MechJeb_RZplan_button5")))//"Get closer" { double UT = vesselState.time; Vector3d dV = OrbitalManeuverCalculator.DeltaVToInterceptAtTime(orbit, UT, core.target.TargetOrbit, 100, 10); vessel.RemoveAllManeuverNodes(); vessel.PlaceManeuverNode(orbit, dV, UT); } if (core.node != null) { if (vessel.patchedConicSolver.maneuverNodes.Any() && !core.node.enabled) { if (GUILayout.Button(Localizer.Format("#MechJeb_RZplan_button6")))//"Execute next node" { core.node.ExecuteOneNode(this); } if (vessel.patchedConicSolver.maneuverNodes.Count > 1) { if (GUILayout.Button(Localizer.Format("#MechJeb_RZplan_button7")))//"Execute all nodes" { core.node.ExecuteAllNodes(this); } } } else if (core.node.enabled) { if (GUILayout.Button(Localizer.Format("#MechJeb_RZplan_button8")))//"Abort node execution" { core.node.Abort(); } } GUILayout.BeginHorizontal(); core.node.autowarp = GUILayout.Toggle(core.node.autowarp, Localizer.Format("#MechJeb_RZplan_checkbox"), GUILayout.ExpandWidth(true)); //"Auto-warp" GUILayout.Label(Localizer.Format("#MechJeb_RZplan_label9"), GUILayout.ExpandWidth(false)); //"Tolerance:" core.node.tolerance.text = GUILayout.TextField(core.node.tolerance.text, GUILayout.Width(35), GUILayout.ExpandWidth(false)); if (GUILayout.Button("+", GUILayout.ExpandWidth(false))) { core.node.tolerance.val += 0.1; } if (GUILayout.Button("-", GUILayout.ExpandWidth(false))) { core.node.tolerance.val -= core.node.tolerance.val > 0.1 ? 0.1 : 0.0; } if (GUILayout.Button("R", GUILayout.ExpandWidth(false))) { core.node.tolerance.val = 0.1; } GUILayout.Label("m/s", GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); } GUILayout.EndVertical(); base.WindowGUI(windowID); }