public string SuicideBurnCountdown() { if (orbit.PeA > 0) { return("N/A"); } double angleFromHorizontal = 90 - Vector3d.Angle(-vesselState.velocityVesselSurface, vesselState.up); angleFromHorizontal = MuUtils.Clamp(angleFromHorizontal, 0, 90); double sine = Math.Sin(angleFromHorizontal * Math.PI / 180); double g = vesselState.localg; double T = vesselState.limitedMaxThrustAccel; double effectiveDecel = 0.5 * (-2 * g * sine + Math.Sqrt((2 * g * sine) * (2 * g * sine) + 4 * (T * T - g * g))); double decelTime = vesselState.speedSurface / effectiveDecel; Vector3d estimatedLandingSite = vesselState.CoM + 0.5 * decelTime * vesselState.velocityVesselSurface; double terrainRadius = mainBody.Radius + mainBody.TerrainAltitude(estimatedLandingSite); double impactTime = 0; try { impactTime = orbit.NextTimeOfRadius(vesselState.time, terrainRadius); } catch (ArgumentException) { return(GuiUtils.TimeToDHMS(0)); } return(GuiUtils.TimeToDHMS(impactTime - decelTime / 2 - vesselState.time)); }
public string TimeToImpact() { if (orbit.PeA > 0) { return("N/A"); } double impactTime = vesselState.time; try { for (int iter = 0; iter < 10; iter++) { Vector3d impactPosition = orbit.SwappedAbsolutePositionAtUT(impactTime); double terrainRadius = mainBody.Radius + mainBody.TerrainAltitude(impactPosition); impactTime = orbit.NextTimeOfRadius(vesselState.time, terrainRadius); } } catch (ArgumentException) { return(GuiUtils.TimeToDHMS(0)); } return(GuiUtils.TimeToDHMS(impactTime - vesselState.time)); }
public string TargetOrbitPeriod() { if (!core.target.NormalTargetExists) { return("N/A"); } return(GuiUtils.TimeToDHMS(core.target.TargetOrbit.period)); }
public string TargetEccentricity() { if (!core.target.NormalTargetExists) { return("N/A"); } return(GuiUtils.TimeToDHMS(core.target.TargetOrbit.eccentricity)); }
public string TargetOrbitTimeToPe() { if (!core.target.NormalTargetExists) { return("N/A"); } return(GuiUtils.TimeToDHMS(core.target.TargetOrbit.timeToPe)); }
public string TimeToManeuverNode() { if (!vessel.patchedConicsUnlocked() || !vessel.patchedConicSolver.maneuverNodes.Any()) { return("N/A"); } return(GuiUtils.TimeToDHMS(vessel.patchedConicSolver.maneuverNodes[0].UT - vesselState.time)); }
public string TimeToSOITransition() { if (orbit.patchEndTransition == Orbit.PatchTransitionType.FINAL) { return("N/A"); } return(GuiUtils.TimeToDHMS(orbit.EndUT - vesselState.time)); }
public string TimeToEquatorialDescendingNode() { if (!orbit.DescendingNodeEquatorialExists()) { return("N/A"); } return(GuiUtils.TimeToDHMS(orbit.TimeOfDescendingNodeEquatorial(vesselState.time) - vesselState.time)); }
public string SuicideBurnCountdown() { try { return(GuiUtils.TimeToDHMS(OrbitExtensions.SuicideBurnCountdown(orbit, vesselState, vessel))); } catch { return("N/A"); } }
public string NextNodeCountdown() { if (!vessel.patchedConicsUnlocked() || !vessel.patchedConicSolver.maneuverNodes.Any()) { return("-"); } ManeuverNode node = vessel.patchedConicSolver.maneuverNodes.First(); double dV = node.GetBurnVector(orbit).magnitude; return(GuiUtils.TimeToDHMS(node.UT - BurnTime(dV) * leadFraction - vesselState.time)); }
public string NextNodeBurnTime() { if (!vessel.patchedConicsUnlocked() || !vessel.patchedConicSolver.maneuverNodes.Any()) { return("-"); } ManeuverNode node = vessel.patchedConicSolver.maneuverNodes.First(); double dV = node.GetBurnVector(orbit).magnitude; return(GuiUtils.TimeToDHMS(BurnTime(dV))); }
public string NextManeuverNodeBurnTime() { if (!vessel.patchedConicsUnlocked() || !vessel.patchedConicSolver.maneuverNodes.Any()) { return("N/A"); } ManeuverNode node = vessel.patchedConicSolver.maneuverNodes.First(); double burnTime = node.GetBurnVector(node.patch).magnitude / vesselState.limitedMaxThrustAccel; return(GuiUtils.TimeToDHMS(burnTime)); }
public string TargetTimeToClosestApproach() { if (!core.target.NormalTargetExists) { return("N/A"); } if (core.target.Orbit.referenceBody != orbit.referenceBody) { return("N/A"); } return(GuiUtils.TimeToDHMS(orbit.NextClosestApproachTime(core.target.Orbit, vesselState.time) - vesselState.time)); }
public string SynodicPeriod() { if (!core.target.NormalTargetExists) { return("N/A"); } if (core.target.TargetOrbit.referenceBody != orbit.referenceBody) { return("N/A"); } return(GuiUtils.TimeToDHMS(orbit.SynodicPeriod(core.target.TargetOrbit))); }
public string NextNodeBurnTime() { if (!vessel.patchedConicsUnlocked() || vessel.patchedConicSolver.maneuverNodes.Count == 0) { return("-"); } ManeuverNode node = vessel.patchedConicSolver.maneuverNodes[0]; double dV = node.GetBurnVector(orbit).magnitude; double halfBurnTIme; return(GuiUtils.TimeToDHMS(BurnTime(dV, out halfBurnTIme))); }
override public void WindowGUI(int windowID) { base.preWindowGUI(windowID); base.WindowGUI(windowID); GUILayout.Label("Warp to: ", GUILayout.ExpandWidth(false)); warpTarget = (WarpTarget)GuiUtils.ComboBox.Box((int)warpTarget, warpTargetStrings, this); if (warpTarget == WarpTarget.Time) { GUILayout.Label("Warp for: ", GUILayout.ExpandWidth(true)); timeOffset.text = GUILayout.TextField(timeOffset.text, GUILayout.Width(100)); } else if (warpTarget == WarpTarget.PhaseAngleT) { // I wonder if I should check for target that don't make sense if (!core.target.NormalTargetExists) { GUILayout.Label("You need a target"); } else { GuiUtils.SimpleTextBox("Phase Angle:", phaseAngle, "º", 60); } } if (!warping) { GuiUtils.SimpleTextBox("Lead time: ", leadTime, ""); } if (warping) { if (GUILayout.Button("Abort")) { this.onAbord(); } } if (warping) { GUILayout.Label("Warping to " + (leadTime > 0 ? GuiUtils.TimeToDHMS(leadTime) + " before " : "") + warpTargetStrings[(int)warpTarget] + "."); } if (this.isStarted() && !this.isExecuted() && this.startTime > 0) { GUILayout.Label(" waiting " + this.spendTime + "s"); } base.postWindowGUI(windowID); }
public string NextNodeCountdown() { if (!vessel.patchedConicsUnlocked() || !vessel.patchedConicSolver.maneuverNodes.Any()) { return("-"); } ManeuverNode node = vessel.patchedConicSolver.maneuverNodes.First(); double dV = node.GetBurnVector(orbit).magnitude; double halfBurnTIme; double burnTIme = BurnTime(dV, out halfBurnTIme); if (double.IsInfinity(halfBurnTIme)) { halfBurnTIme = 0.0; } return(GuiUtils.TimeToDHMS(node.UT - halfBurnTIme - vesselState.time)); }
public string TimeToDescendingNodeWithTarget() { if (!core.target.NormalTargetExists) { return("N/A"); } if (core.target.TargetOrbit.referenceBody != orbit.referenceBody) { return("N/A"); } if (!orbit.DescendingNodeExists(core.target.TargetOrbit)) { return("N/A"); } return(GuiUtils.TimeToDHMS(orbit.TimeOfDescendingNode(core.target.TargetOrbit, vesselState.time) - vesselState.time)); }
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; } } }
protected override void WindowGUI(int windowID) { GUILayout.BeginVertical(); GUILayout.BeginHorizontal(); GUILayout.Label("Warp to: ", GUILayout.ExpandWidth(false)); warpTarget = (WarpTarget)GuiUtils.ArrowSelector((int)warpTarget, numWarpTargets, warpTargetStrings[(int)warpTarget]); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GuiUtils.SimpleTextBox("Lead time: ", leadTime, ""); if (warping) { if (GUILayout.Button("Abort")) { warping = false; core.warp.MinimumWarp(true); } } else { if (GUILayout.Button("Warp")) { warping = true; } } GUILayout.EndHorizontal(); if (warping) { GUILayout.Label("Warping to " + (leadTime > 0 ? GuiUtils.TimeToDHMS(leadTime) + " before " : "") + warpTargetStrings[(int)warpTarget] + "."); } GUILayout.EndVertical(); GUI.DragWindow(); }
public string TargetTimeToClosestApproach() { if (core.target.Target != null && vesselState.altitudeTrue < 1000.0) { return(GuiUtils.TimeToDHMS(GuiUtils.FromToETA(vessel.CoM, core.target.Transform.position))); } if (!core.target.NormalTargetExists) { return("N/A"); } if (vesselState.altitudeTrue < 1000.0) { double a = (vessel.mainBody.transform.position - vessel.transform.position).magnitude; double b = (vessel.mainBody.transform.position - core.target.Transform.position).magnitude; double c = Vector3d.Distance(vessel.transform.position, core.target.Position); double ang = Math.Acos(((a * a + b * b) - c * c) / (double)(2f * a * b)); return(GuiUtils.TimeToDHMS(ang * vessel.mainBody.Radius / vesselState.speedSurfaceHorizontal)); } if (!core.target.NormalTargetExists) { return("N/A"); } if (vesselState.altitudeTrue < 1000.0) { double a = (vessel.mainBody.transform.position - vessel.transform.position).magnitude; double b = (vessel.mainBody.transform.position - core.target.Transform.position).magnitude; double c = Vector3d.Distance(vessel.transform.position, core.target.Position); double ang = Math.Acos(((a * a + b * b) - c * c) / (double)(2f * a * b)); return(GuiUtils.TimeToDHMS(ang * vessel.mainBody.Radius / vesselState.speedSurfaceHorizontal)); } if (core.target.TargetOrbit.referenceBody != orbit.referenceBody) { return("N/A"); } return(GuiUtils.TimeToDHMS(orbit.NextClosestApproachTime(core.target.TargetOrbit, vesselState.time) - vesselState.time)); }
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 (!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); }
protected override void WindowGUI(int windowID) { if (btNormal == null) { btNormal = new GUIStyle(GUI.skin.button); btNormal.normal.textColor = btNormal.focused.textColor = Color.white; btNormal.hover.textColor = btNormal.active.textColor = Color.yellow; btNormal.onNormal.textColor = btNormal.onFocused.textColor = btNormal.onHover.textColor = btNormal.onActive.textColor = Color.green; btNormal.padding = new RectOffset(8, 8, 8, 8); btActive = new GUIStyle(btNormal); btActive.active = btActive.onActive; btActive.normal = btActive.onNormal; btActive.onFocused = btActive.focused; btActive.hover = btActive.onHover; } GUILayout.BeginVertical(); if (autopilot != null) { if (autopilot.enabled) { if (GUILayout.Button(Localizer.Format("#MechJeb_Ascent_button1")))//Disengage autopilot { autopilot.users.Remove(this); } } else { if (GUILayout.Button(Localizer.Format("#MechJeb_Ascent_button2")))//Engage autopilot { autopilot.users.Add(this); } } if (ascentPathIdx == ascentType.PVG) { if (GUILayout.Button(Localizer.Format("#MechJeb_Ascent_button3")))//Reset Guidance (DO NOT PRESS) { core.guidance.Reset(); } GUILayout.BeginHorizontal(); // EditorStyles.toolbar); if (GUILayout.Button(Localizer.Format("#MechJeb_Ascent_button4"), autopilot.showTargeting ? btActive : btNormal, GUILayout.ExpandWidth(true))) //"TARG" { autopilot.showTargeting = !autopilot.showTargeting; } if (GUILayout.Button(Localizer.Format("#MechJeb_Ascent_button5"), autopilot.showGuidanceSettings ? btActive : btNormal, GUILayout.ExpandWidth(true))) //GUID { autopilot.showGuidanceSettings = !autopilot.showGuidanceSettings; } if (GUILayout.Button(Localizer.Format("#MechJeb_Ascent_button6"), autopilot.showSettings ? btActive : btNormal, GUILayout.ExpandWidth(true))) //OPTS { autopilot.showSettings = !autopilot.showSettings; } if (GUILayout.Button(Localizer.Format("#MechJeb_Ascent_button7"), autopilot.showStatus ? btActive : btNormal, GUILayout.ExpandWidth(true))) //STATUS { autopilot.showStatus = !autopilot.showStatus; } GUILayout.EndHorizontal(); } else if (ascentPathIdx == ascentType.GRAVITYTURN) { GUILayout.BeginHorizontal(); // EditorStyles.toolbar); if (GUILayout.Button(Localizer.Format("#MechJeb_Ascent_button8"), autopilot.showTargeting ? btActive : btNormal, GUILayout.ExpandWidth(true))) //TARG { autopilot.showTargeting = !autopilot.showTargeting; } if (GUILayout.Button(Localizer.Format("#MechJeb_Ascent_button9"), autopilot.showGuidanceSettings ? btActive : btNormal, GUILayout.ExpandWidth(true))) //GUID { autopilot.showGuidanceSettings = !autopilot.showGuidanceSettings; } if (GUILayout.Button(Localizer.Format("#MechJeb_Ascent_button10"), autopilot.showSettings ? btActive : btNormal, GUILayout.ExpandWidth(true))) //OPTS { autopilot.showSettings = !autopilot.showSettings; } GUILayout.EndHorizontal(); } else if (ascentPathIdx == ascentType.BREATHING_GT) { GUILayout.BeginHorizontal(); // EditorStyles.toolbar); if (GUILayout.Button(Localizer.Format("#MechJeb_Ascent_button8"), autopilot.showTargeting ? btActive : btNormal, GUILayout.ExpandWidth(true))) //TARG { autopilot.showTargeting = !autopilot.showTargeting; } if (GUILayout.Button(Localizer.Format("#MechJeb_Ascent_button9"), autopilot.showGuidanceSettings ? btActive : btNormal, GUILayout.ExpandWidth(true)))//GUID { autopilot.showGuidanceSettings = !autopilot.showGuidanceSettings; } if (GUILayout.Button(Localizer.Format("#MechJeb_Ascent_button10"), autopilot.showSettings ? btActive : btNormal, GUILayout.ExpandWidth(true)))//OPTS { autopilot.showSettings = !autopilot.showSettings; } GUILayout.EndHorizontal(); } else if (ascentPathIdx == ascentType.CLASSIC) { GUILayout.BeginHorizontal(); // EditorStyles.toolbar); if (GUILayout.Button(Localizer.Format("#MechJeb_Ascent_button11"), autopilot.showTargeting ? btActive : btNormal, GUILayout.ExpandWidth(true))) //TARG { autopilot.showTargeting = !autopilot.showTargeting; } if (GUILayout.Button(Localizer.Format("#MechJeb_Ascent_button12"), autopilot.showSettings ? btActive : btNormal, GUILayout.ExpandWidth(true))) //OPTS { autopilot.showSettings = !autopilot.showSettings; } GUILayout.EndHorizontal(); } if (autopilot.showTargeting) { if (ascentPathIdx == ascentType.PVG) { GuiUtils.SimpleTextBox(Localizer.Format("#MechJeb_Ascent_label1"), autopilot.desiredOrbitAltitude, "km"); //Target Periapsis GuiUtils.SimpleTextBox(Localizer.Format("#MechJeb_Ascent_label2"), pvgascent.desiredApoapsis, "km"); //Target Apoapsis: if (pvgascent.desiredApoapsis >= 0 && pvgascent.desiredApoapsis < autopilot.desiredOrbitAltitude) { GUIStyle s = new GUIStyle(GUI.skin.label); s.normal.textColor = Color.yellow; GUILayout.Label(Localizer.Format("#MechJeb_Ascent_label3"), s);//Ap < Pe: circularizing orbit } if (pvgascent.desiredApoapsis < 0) { GUIStyle s = new GUIStyle(GUI.skin.label); s.normal.textColor = XKCDColors.Orange; GUILayout.Label(Localizer.Format("#MechJeb_Ascent_label4"), s);//Hyperbolic target orbit (neg Ap) } } else { GuiUtils.SimpleTextBox(Localizer.Format("#MechJeb_Ascent_label5"), autopilot.desiredOrbitAltitude, "km");//Orbit altitude } GUIStyle si = new GUIStyle(GUI.skin.label); if (Math.Abs(desiredInclination) < Math.Abs(vesselState.latitude) - 2.001) { si.onHover.textColor = si.onNormal.textColor = si.normal.textColor = XKCDColors.Orange; } GUILayout.BeginHorizontal(); GUILayout.Label(Localizer.Format("#MechJeb_Ascent_label6"), si, GUILayout.ExpandWidth(true));//Orbit inc. desiredInclination.text = GUILayout.TextField(desiredInclination.text, GUILayout.ExpandWidth(true), GUILayout.Width(100)); GUILayout.Label("º", GUILayout.ExpandWidth(false)); if (GUILayout.Button(Localizer.Format("#MechJeb_Ascent_button13")))//Current { desiredInclination.val = vesselState.latitude; } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); if (Math.Abs(desiredInclination) < Math.Abs(vesselState.latitude) - 2.001) { GUILayout.Label(Localizer.Format("#MechJeb_Ascent_label7", Math.Abs(vesselState.latitude) - Math.Abs(desiredInclination)), si);//inc {0:F1}º below current latitude } GUILayout.EndHorizontal(); autopilot.desiredInclination = desiredInclination; } if (autopilot.showGuidanceSettings) { if (ascentPathIdx == ascentType.GRAVITYTURN) { GUILayout.BeginVertical(); GuiUtils.SimpleTextBox(Localizer.Format("#MechJeb_Ascent_label8"), gtascent.turnStartAltitude, "km"); //Turn start altitude: GuiUtils.SimpleTextBox(Localizer.Format("#MechJeb_Ascent_label9"), gtascent.turnStartVelocity, "m/s"); //Turn start velocity: GuiUtils.SimpleTextBox(Localizer.Format("#MechJeb_Ascent_label10"), gtascent.turnStartPitch, "deg"); //Turn start pitch: GuiUtils.SimpleTextBox(Localizer.Format("#MechJeb_Ascent_label11"), gtascent.intermediateAltitude, "km"); //Intermediate altitude: GuiUtils.SimpleTextBox(Localizer.Format("#MechJeb_Ascent_label12"), gtascent.holdAPTime, "s"); //Hold AP Time: GUILayout.EndVertical(); } else if (ascentPathIdx == ascentType.BREATHING_GT) { GUILayout.BeginVertical(); //GuiUtils.SimpleTextBox(Localizer.Format("#MechJeb_Ascent_label8"), bgtascent.turnStartAltitude, "km");//Turn start altitude: GuiUtils.SimpleTextBox(Localizer.Format("#MechJeb_Ascent_label9"), bgtascent.turnStartVelocity, "m/s"); //Turn start velocity: GuiUtils.SimpleTextBox(Localizer.Format("#MechJeb_Ascent_label10"), bgtascent.turnStartPitch, "deg"); //Turn start pitch: GuiUtils.SimpleTextBox(Localizer.Format("speed for breathing mode:"), bgtascent.startBreathingSpeed, "m/s"); //speed for breathing mode: GuiUtils.SimpleTextBox(Localizer.Format("TWR to throttle other:"), bgtascent.minTWRthrottle, "s"); //TWR to throttle other: GUILayout.EndVertical(); } else if (ascentPathIdx == ascentType.PVG) { GUILayout.BeginVertical(); GuiUtils.SimpleTextBox(Localizer.Format("#MechJeb_Ascent_label13"), pvgascent.pitchStartVelocity, "m/s"); //Booster Pitch start: GuiUtils.SimpleTextBox(Localizer.Format("#MechJeb_Ascent_label14"), pvgascent.pitchRate, "°/s"); //Booster Pitch rate: GuiUtils.SimpleTextBox(Localizer.Format("#MechJeb_Ascent_label15"), core.guidance.pvgInterval, "s"); //Guidance Interval: if (core.guidance.pvgInterval < 1 || core.guidance.pvgInterval > 30) { GUIStyle s = new GUIStyle(GUI.skin.label); s.normal.textColor = Color.yellow; GUILayout.Label(Localizer.Format("#MechJeb_Ascent_label16"), s); //Guidance intervals are limited to between 1s and 30s } GuiUtils.SimpleTextBox(Localizer.Format("#MechJeb_Ascent_label17"), autopilot.limitQa, "Pa-rad"); //Qα limit if (autopilot.limitQa < 100 || autopilot.limitQa > 4000) { GUIStyle s = new GUIStyle(GUI.skin.label); s.normal.textColor = Color.yellow; if (autopilot.limitQa < 100) { GUILayout.Label(Localizer.Format("#MechJeb_Ascent_label18"), s);//Qα limit cannot be set to lower than 100 Pa-rad } else if (autopilot.limitQa > 10000) { GUILayout.Label(Localizer.Format("#MechJeb_Ascent_label19"), s);//Qα limit cannot be set to higher than 10000 Pa-rad } else { GUILayout.Label(Localizer.Format("#MechJeb_Ascent_label20"), s);//Qα limit is recommended to be 1000 to 4000 Pa-rad } } pvgascent.omitCoast = GUILayout.Toggle(pvgascent.omitCoast, Localizer.Format("#MechJeb_Ascent_checkbox1"));//Omit Coast GUILayout.EndVertical(); } } autopilot.limitQaEnabled = (ascentPathIdx == ascentType.PVG); // this is mandatory for PVG if (autopilot.showSettings) { ToggleAscentNavballGuidanceInfoItem(); if (ascentPathIdx != ascentType.PVG) { core.thrust.LimitToPreventOverheatsInfoItem(); //core.thrust.LimitToTerminalVelocityInfoItem(); core.thrust.LimitToMaxDynamicPressureInfoItem(); core.thrust.LimitAccelerationInfoItem(); core.thrust.LimitThrottleInfoItem(); core.thrust.LimiterMinThrottleInfoItem(); core.thrust.LimitElectricInfoItem(); } else { core.thrust.LimitToPreventOverheatsInfoItem(); //core.thrust.LimitToTerminalVelocityInfoItem(); core.thrust.LimitToMaxDynamicPressureInfoItem(); //core.thrust.LimitAccelerationInfoItem(); //core.thrust.LimitThrottleInfoItem(); core.thrust.LimiterMinThrottleInfoItem(); //core.thrust.LimitElectricInfoItem(); GUILayout.Label(Localizer.Format("#MechJeb_Ascent_label21")); //FIXME: g-limiter is down for maintenance core.thrust.limitAcceleration = false; core.thrust.limitThrottle = false; core.thrust.limitToTerminalVelocity = false; core.thrust.electricThrottle = false; } GUILayout.BeginHorizontal(); autopilot.forceRoll = GUILayout.Toggle(autopilot.forceRoll, Localizer.Format("#MechJeb_Ascent_checkbox2"));//Force Roll if (autopilot.forceRoll) { GuiUtils.SimpleTextBox(Localizer.Format("#MechJeb_Ascent_label22"), autopilot.verticalRoll, "º", 30f); //climb GuiUtils.SimpleTextBox(Localizer.Format("#MechJeb_Ascent_label23"), autopilot.turnRoll, "º", 30f); //turn } GUILayout.EndHorizontal(); if (ascentPathIdx != ascentType.PVG) { 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, Localizer.Format("#MechJeb_Ascent_checkbox3"), s, GUILayout.ExpandWidth(true));//Limit AoA to autopilot.maxAoA.text = GUILayout.TextField(autopilot.maxAoA.text, GUILayout.Width(30)); GUILayout.Label("º (" + autopilot.currentMaxAoA.ToString("F1") + "°)", GUILayout.ExpandWidth(true)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Space(25); if (autopilot.limitAoA) { GUIStyle sl = new GUIStyle(GUI.skin.label); if (autopilot.limitingAoA && vesselState.dynamicPressure < autopilot.aoALimitFadeoutPressure) { sl.normal.textColor = sl.hover.textColor = Color.green; } GuiUtils.SimpleTextBox(Localizer.Format("#MechJeb_Ascent_label24"), autopilot.aoALimitFadeoutPressure, "Pa", 50, sl);//Dynamic Pressure Fadeout } GUILayout.EndHorizontal(); autopilot.limitQaEnabled = false; // this is only for PVG } if (ascentPathIdx == ascentType.CLASSIC) { // corrective steering only applies to Classic GUILayout.BeginHorizontal(); autopilot.correctiveSteering = GUILayout.Toggle(autopilot.correctiveSteering, Localizer.Format("#MechJeb_Ascent_checkbox4"), GUILayout.ExpandWidth(false));//Corrective steering if (autopilot.correctiveSteering) { GUILayout.Label(Localizer.Format("#MechJeb_Ascent_label25"), GUILayout.ExpandWidth(false));//Gain autopilot.correctiveSteeringGain.text = GUILayout.TextField(autopilot.correctiveSteeringGain.text, GUILayout.Width(40)); } GUILayout.EndHorizontal(); } autopilot.autostage = GUILayout.Toggle(autopilot.autostage, Localizer.Format("#MechJeb_Ascent_checkbox5"));//Autostage if (autopilot.autostage) { core.staging.AutostageSettingsInfoItem(); } autopilot.autodeploySolarPanels = GUILayout.Toggle(autopilot.autodeploySolarPanels, Localizer.Format("#MechJeb_Ascent_checkbox6"));//Auto-deploy solar panels autopilot.autoDeployAntennas = GUILayout.Toggle(autopilot.autoDeployAntennas, Localizer.Format("#MechJeb_Ascent_checkbox7"));//Auto-deploy antennas GUILayout.BeginHorizontal(); core.node.autowarp = GUILayout.Toggle(core.node.autowarp, Localizer.Format("#MechJeb_Ascent_checkbox8"));//Auto-warp if (ascentPathIdx != ascentType.PVG) { autopilot.skipCircularization = GUILayout.Toggle(autopilot.skipCircularization, Localizer.Format("#MechJeb_Ascent_checkbox9"));//Skip Circularization } else { // skipCircularization is always true for Optimizer autopilot.skipCircularization = true; } GUILayout.EndHorizontal(); } if (autopilot.showStatus) { if (ascentPathIdx == ascentType.PVG) { if (core.guidance.solution != null) { for (int i = core.guidance.solution.num_segments; i > 0; i--) { GUILayout.Label(String.Format("{0}: {1}", i, core.guidance.solution.ArcString(vesselState.time, i - 1))); } } GUILayout.BeginHorizontal(); GUILayout.Label(String.Format("vgo: {0:F1}", core.guidance.vgo), GUILayout.Width(100)); GUILayout.Label(String.Format("heading: {0:F1}", core.guidance.heading), GUILayout.Width(100)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label(String.Format("tgo: {0:F3}", core.guidance.tgo), GUILayout.Width(100)); GUILayout.Label(String.Format("pitch: {0:F1}", core.guidance.pitch), GUILayout.Width(100)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUIStyle si = new GUIStyle(GUI.skin.label); if (core.guidance.isStable()) { si.onHover.textColor = si.onNormal.textColor = si.normal.textColor = XKCDColors.Green; } else if (core.guidance.isInitializing() || core.guidance.status == PVGStatus.FINISHED) { si.onHover.textColor = si.onNormal.textColor = si.normal.textColor = XKCDColors.Orange; } else { si.onHover.textColor = si.onNormal.textColor = si.normal.textColor = XKCDColors.Red; } GUILayout.Label(Localizer.Format("#MechJeb_Ascent_label26") + core.guidance.status, si);//Guidance Status: GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label(Localizer.Format("#MechJeb_Ascent_label27") + core.guidance.successful_converges, GUILayout.Width(100)); //converges: GUILayout.Label(Localizer.Format("#MechJeb_Ascent_label28") + core.guidance.last_lm_status, GUILayout.Width(100)); //status: GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label("n: " + core.guidance.last_lm_iteration_count + "(" + core.guidance.max_lm_iteration_count + ")", GUILayout.Width(100)); GUILayout.Label(Localizer.Format("#MechJeb_Ascent_label29") + GuiUtils.TimeToDHMS(core.guidance.staleness));//staleness: GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label(String.Format("znorm: {0:G5}", core.guidance.last_znorm)); GUILayout.EndHorizontal(); if (core.guidance.last_failure_cause != null) { GUIStyle s = new GUIStyle(GUI.skin.label); s.normal.textColor = Color.red; GUILayout.BeginHorizontal(); GUILayout.Label(Localizer.Format("#MechJeb_Ascent_label30") + core.guidance.last_failure_cause, s);//LAST FAILURE: GUILayout.EndHorizontal(); } if (vessel.situation != Vessel.Situations.LANDED && vessel.situation != Vessel.Situations.PRELAUNCH && vessel.situation != Vessel.Situations.SPLASHED) { double m0 = atmoStats[vessel.currentStage].startMass; double thrust = atmoStats[vessel.currentStage].startThrust; if (Math.Abs(vesselState.mass - m0) / m0 > 0.01) { GUIStyle s = new GUIStyle(GUI.skin.label); s.normal.textColor = Color.yellow; GUILayout.BeginHorizontal(); GUILayout.Label(String.Format(Localizer.Format("#MechJeb_Ascent_label31") + "{0:F1}%", (vesselState.mass - m0) / m0 * 100.0), s);//MASS IS OFF BY GUILayout.EndHorizontal(); } if (Math.Abs(vesselState.thrustCurrent - thrust) / thrust > 0.01) { GUIStyle s = new GUIStyle(GUI.skin.label); s.normal.textColor = Color.yellow; GUILayout.BeginHorizontal(); GUILayout.Label(String.Format(Localizer.Format("#MechJeb_Ascent_label32") + "{0:F1}%", (vesselState.thrustCurrent - thrust) / thrust * 100.0), s);//THRUST IS OFF BY GUILayout.EndHorizontal(); } } } } if (vessel.LandedOrSplashed) { if (core.target.NormalTargetExists) { if (core.node.autowarp) { GUILayout.BeginHorizontal(); GUILayout.Label(Localizer.Format("#MechJeb_Ascent_label33"), GUILayout.ExpandWidth(true)); //Launch countdown: autopilot.warpCountDown.text = GUILayout.TextField(autopilot.warpCountDown.text, GUILayout.Width(60)); GUILayout.Label("s", GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); } if (!launchingToPlane && !launchingToRendezvous && !launchingToInterplanetary) { // disable plane/rendezvous/interplanetary for now if (ascentPathIdx != ascentType.PVG) { GUILayout.BeginHorizontal(); if (GUILayout.Button(Localizer.Format("#MechJeb_Ascent_button14"), GUILayout.ExpandWidth(false))) //Launch to rendezvous: { launchingToRendezvous = true; autopilot.StartCountdown(vesselState.time + LaunchTiming.TimeToPhaseAngle(autopilot.launchPhaseAngle, mainBody, vesselState.longitude, core.target.TargetOrbit)); } autopilot.launchPhaseAngle.text = GUILayout.TextField(autopilot.launchPhaseAngle.text, GUILayout.Width(60)); GUILayout.Label("º", GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); } GUILayout.BeginHorizontal(); if (GUILayout.Button(Localizer.Format("#MechJeb_Ascent_button15"), GUILayout.ExpandWidth(false))) //Launch into plane of target { launchingToPlane = true; autopilot.StartCountdown(vesselState.time + LaunchTiming.TimeToPlane(autopilot.launchLANDifference, mainBody, vesselState.latitude, vesselState.longitude, core.target.TargetOrbit)); } autopilot.launchLANDifference.text = GUILayout.TextField( autopilot.launchLANDifference.text, GUILayout.Width(60)); GUILayout.Label("º", GUILayout.ExpandWidth(false)); GUILayout.EndHorizontal(); if (core.target.TargetOrbit.referenceBody == orbit.referenceBody.referenceBody) { if (GUILayout.Button(Localizer.Format("#MechJeb_Ascent_button16"))) //Launch at interplanetary window { launchingToInterplanetary = true; //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); autopilot.StartCountdown(interplanetaryWindowUT); } } } } else { launchingToInterplanetary = launchingToPlane = launchingToRendezvous = false; GUILayout.Label(Localizer.Format("#MechJeb_Ascent_label34")); //Select a target for a timed launch. } if (launchingToInterplanetary || launchingToPlane || launchingToRendezvous) { string message = ""; if (launchingToInterplanetary) { message = Localizer.Format("#MechJeb_Ascent_msg1"); //Launching at interplanetary window } else if (launchingToPlane) { desiredInclination = MuUtils.Clamp(core.target.TargetOrbit.inclination, Math.Abs(vesselState.latitude), 180 - Math.Abs(vesselState.latitude)); desiredInclination *= Math.Sign(Vector3d.Dot(core.target.TargetOrbit.SwappedOrbitNormal(), Vector3d.Cross(vesselState.CoM - mainBody.position, mainBody.transform.up))); message = Localizer.Format("#MechJeb_Ascent_msg2"); //Launching to target plane } else if (launchingToRendezvous) { message = "#MechJeb_Ascent_msg3"; //Launching to rendezvous } if (autopilot.tMinus > 3 * vesselState.deltaT) { message += ": T-" + GuiUtils.TimeToDHMS(autopilot.tMinus, 1); } GUILayout.Label(message); if (GUILayout.Button(Localizer.Format("#MechJeb_Ascent_button17")))//Abort { launchingToInterplanetary = launchingToPlane = launchingToRendezvous = autopilot.timedLaunch = false; } } } if (autopilot.enabled) { GUILayout.Label(Localizer.Format("#MechJeb_Ascent_label35") + autopilot.status);//Autopilot status: } if (core.DeactivateControl) { GUIStyle s = new GUIStyle(GUI.skin.label); s.normal.textColor = Color.red; GUILayout.Label(Localizer.Format("#MechJeb_Ascent_label36"), s);//CONTROL DISABLED (AVIONICS) } } if (!vessel.patchedConicsUnlocked() && ascentPathIdx != ascentType.PVG) { GUILayout.Label(Localizer.Format("#MechJeb_Ascent_label37"));//"Warning: MechJeb is unable to circularize without an upgraded Tracking Station." } GUILayout.BeginHorizontal(); autopilot.ascentPathIdxPublic = (ascentType)GuiUtils.ComboBox.Box((int)autopilot.ascentPathIdxPublic, autopilot.ascentPathList, this); GUILayout.EndHorizontal(); if (autopilot.ascentMenu != null) { autopilot.ascentMenu.enabled = GUILayout.Toggle(autopilot.ascentMenu.enabled, Localizer.Format("#MechJeb_Ascent_checkbox10")); //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.LimitToPreventOverheatsInfoItem(); core.thrust.LimitToTerminalVelocityInfoItem(); core.thrust.LimitAccelerationInfoItem(); core.thrust.LimitThrottleInfoItem(); GUILayout.BeginHorizontal(); autopilot.forceRoll = GUILayout.Toggle(autopilot.forceRoll, "Force Roll"); if (autopilot.forceRoll) { GuiUtils.SimpleTextBox("climb", autopilot.verticalRoll, "º", 30f); GuiUtils.SimpleTextBox("turn", autopilot.turnRoll, "º", 30f); } GUILayout.EndHorizontal(); 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 AoA to", s, GUILayout.ExpandWidth(true)); autopilot.maxAoA.text = GUILayout.TextField(autopilot.maxAoA.text, GUILayout.Width(30)); GUILayout.Label("º (" + autopilot.currentMaxAoA.ToString("F1") + "°)", GUILayout.ExpandWidth(true)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Space(25); if (autopilot.limitAoA) { GUIStyle sl = new GUIStyle(GUI.skin.label); if (autopilot.limitingAoA && vesselState.dynamicPressure < autopilot.aoALimitFadeoutPressure) { sl.normal.textColor = sl.hover.textColor = Color.green; } GuiUtils.SimpleTextBox("Dynamic Pressure Fadeout", autopilot.aoALimitFadeoutPressure, "pa", 50, sl); } GUILayout.EndHorizontal(); autopilot.correctiveSteering = GUILayout.Toggle(autopilot.correctiveSteering, "Corrective steering"); autopilot.autostage = GUILayout.Toggle(autopilot.autostage, "Autostage"); if (autopilot.autostage) { core.staging.AutostageSettingsInfoItem(); } autopilot.autodeploySolarPanels = GUILayout.Toggle(autopilot.autodeploySolarPanels, "Auto-deploy solar panels"); 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; autopilot.StartCountdown(vesselState.time + LaunchTiming.TimeToPhaseAngle(autopilot.launchPhaseAngle, mainBody, vesselState.longitude, core.target.TargetOrbit)); } 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; autopilot.StartCountdown(vesselState.time + LaunchTiming.TimeToPlane(mainBody, vesselState.latitude, vesselState.longitude, core.target.TargetOrbit)); } if (core.target.TargetOrbit.referenceBody == orbit.referenceBody.referenceBody) { if (GUILayout.Button("Launch at interplanetary window")) { launchingToInterplanetary = true; //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); autopilot.StartCountdown(interplanetaryWindowUT); } } } } else { launchingToInterplanetary = launchingToPlane = launchingToRendezvous = false; GUILayout.Label("Select a target for a timed launch."); } if (launchingToInterplanetary || launchingToPlane || launchingToRendezvous) { string message = ""; if (launchingToInterplanetary) { message = "Launching at interplanetary window"; } else if (launchingToPlane) { 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) { message = "Launching to rendezvous"; } if (autopilot.tMinus > 3 * vesselState.deltaT) { message += ": T-" + GuiUtils.TimeToDHMS(autopilot.tMinus, 1); } GUILayout.Label(message); if (GUILayout.Button("Abort")) { launchingToInterplanetary = launchingToPlane = launchingToRendezvous = autopilot.timedLaunch = false; } } } if (autopilot != null && autopilot.enabled) { GUILayout.Label("Autopilot status: " + autopilot.status); } if (!vessel.patchedConicsUnlocked()) { GUILayout.Label("Warning: MechJeb is unable to circularize without an upgraded Tracking Station."); } MechJebModuleAscentPathEditor editor = core.GetComputerModule <MechJebModuleAscentPathEditor>(); if (editor != null) { editor.enabled = GUILayout.Toggle(editor.enabled, "Edit ascent path"); } GUILayout.EndVertical(); base.WindowGUI(windowID); }
public EditableTime(double seconds) : base(seconds) { _text = GuiUtils.TimeToDHMS(seconds); }
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); }
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); }
private void DoPorkchopGui(Orbit o, double universalTime, MechJebModuleTargetController target) { // That mess is why you should not compute anything inside a GUI call // TODO : rewrite all that... if (worker == null) { if (Event.current.type == EventType.Layout) layoutSkipped = true; return; } if (Event.current.type == EventType.Layout) layoutSkipped = false; if (layoutSkipped) return; string dv = " - "; string departure = " - "; string duration = " - "; if (worker.Finished && worker.computed.GetLength(1) == porkchop_Height) { if (plot == null && Event.current.type == EventType.Layout) { int width = worker.computed.GetLength(0); int height = worker.computed.GetLength(1); if (texture != null && (texture.width != width || texture.height != height)) { Object.Destroy(texture); texture = null; } if (texture == null) texture = new Texture2D(width, height, TextureFormat.RGB24, false); Porkchop.RefreshTexture(worker.computed, texture); plot = new PlotArea( worker.minDepartureTime, worker.maxDepartureTime, worker.minTransferTime, worker.maxTransferTime, texture, (xmin, xmax, ymin, ymax) => { minDepartureTime = Math.Max(xmin, universalTime); maxDepartureTime = xmax; minTransferTime = Math.Max(ymin, 3600); maxTransferTime = ymax; GUI.changed = true; }); plot.selectedPoint = new int[]{worker.bestDate, worker.bestDuration}; } } if (plot != null) { var point = plot.selectedPoint; if (plot.hoveredPoint != null) point = plot.hoveredPoint; var p = worker.computed[point[0], point[1]]; if (p != null) { dv = MuUtils.ToSI(p.dV.magnitude) + "m/s"; if (worker.DateFromIndex(point[0]) < Planetarium.GetUniversalTime()) departure = "any time now"; else departure = GuiUtils.TimeToDHMS(worker.DateFromIndex(point[0]) - Planetarium.GetUniversalTime()); duration = GuiUtils.TimeToDHMS(worker.DurationFromIndex(point[1])); } plot.DoGUI(); if (!plot.draggable) _draggable = false; } else { GUIStyle progressStyle = new GUIStyle { font = GuiUtils.skin.font, fontSize = GuiUtils.skin.label.fontSize, fontStyle = GuiUtils.skin.label.fontStyle, normal = {textColor = GuiUtils.skin.label.normal.textColor} }; GUILayout.Box("Computing: " + worker.Progress + "%", progressStyle, new GUILayoutOption[] { GUILayout.Width(windowWidth), GUILayout.Height(porkchop_Height)}); } GUILayout.BeginHorizontal(); GUILayout.Label("ΔV: " + dv); GUILayout.FlexibleSpace(); if (GUILayout.Button("Reset", GuiUtils.yellowOnHover)) ComputeTimes(o, target.TargetOrbit, universalTime); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label("Select: "); GUILayout.FlexibleSpace(); if (GUILayout.Button("Lowest ΔV")) { plot.selectedPoint = new int[]{ worker.bestDate, worker.bestDuration }; GUI.changed = false; } if (GUILayout.Button("ASAP")) { int bestDuration = 0; for (int i = 1; i < worker.computed.GetLength(1); i++) { if (worker.computed[0, bestDuration].dV.sqrMagnitude > worker.computed[0, i].dV.sqrMagnitude) bestDuration = i; } plot.selectedPoint = new int[]{ 0, bestDuration }; GUI.changed = false; } GUILayout.EndHorizontal(); GUILayout.Label("Departure in " + departure); GUILayout.Label("Transit duration " + duration); }
protected override void WindowGUI(int windowID) { GUILayout.BeginVertical(); GUILayout.BeginHorizontal(); GUILayout.Label(Localizer.Format("#MechJeb_WarpHelper_label1"), GUILayout.ExpandWidth(false));//"Warp to: " warpTarget = (WarpTarget)GuiUtils.ComboBox.Box((int)warpTarget, warpTargetStrings, this); GUILayout.EndHorizontal(); if (warpTarget == WarpTarget.Time) { GUILayout.BeginHorizontal(); GUILayout.Label(Localizer.Format("#MechJeb_WarpHelper_label2"), GUILayout.ExpandWidth(true));//"Warp for: " timeOffset.text = GUILayout.TextField(timeOffset.text, GUILayout.Width(100)); GUILayout.EndHorizontal(); } else if (warpTarget == WarpTarget.PhaseAngleT) { // I wonder if I should check for target that don't make sense if (!core.target.NormalTargetExists) { GUILayout.Label(Localizer.Format("#MechJeb_WarpHelper_label3"));//"You need a target" } else { GuiUtils.SimpleTextBox(Localizer.Format("#MechJeb_WarpHelper_label4"), phaseAngle, "º", 60);//"Phase Angle:" } } GUILayout.BeginHorizontal(); GuiUtils.SimpleTextBox(Localizer.Format("#MechJeb_WarpHelper_label5"), leadTime, "");//"Lead time: " if (warping) { if (GUILayout.Button(Localizer.Format("#MechJeb_WarpHelper_button1")))//"Abort" { warping = false; core.warp.MinimumWarp(true); } } else { if (GUILayout.Button(Localizer.Format("#MechJeb_WarpHelper_button2")))//"Warp" { warping = true; switch (warpTarget) { case WarpTarget.Periapsis: targetUT = orbit.NextPeriapsisTime(vesselState.time); break; case WarpTarget.Apoapsis: if (orbit.eccentricity < 1) { targetUT = orbit.NextApoapsisTime(vesselState.time); } break; case WarpTarget.SoI: if (orbit.patchEndTransition != Orbit.PatchTransitionType.FINAL) { targetUT = orbit.EndUT; } break; case WarpTarget.Node: if (vessel.patchedConicsUnlocked() && vessel.patchedConicSolver.maneuverNodes.Any()) { targetUT = vessel.patchedConicSolver.maneuverNodes[0].UT; } break; case WarpTarget.Time: targetUT = vesselState.time + timeOffset; break; case WarpTarget.PhaseAngleT: if (core.target.NormalTargetExists) { Orbit reference; if (core.target.TargetOrbit.referenceBody == orbit.referenceBody) { reference = orbit; // we orbit arround the same body } else { reference = orbit.referenceBody.orbit; } // From Kerbal Alarm Clock double angleChangePerSec = (360 / core.target.TargetOrbit.period) - (360 / reference.period); double currentAngle = reference.PhaseAngle(core.target.TargetOrbit, vesselState.time); double angleDigff = currentAngle - phaseAngle; if (angleDigff > 0 && angleChangePerSec > 0) { angleDigff -= 360; } if (angleDigff < 0 && angleChangePerSec < 0) { angleDigff += 360; } double TimeToTarget = Math.Floor(Math.Abs(angleDigff / angleChangePerSec)); targetUT = vesselState.time + TimeToTarget; } break; case WarpTarget.AtmosphericEntry: try { targetUT = OrbitExtensions.NextTimeOfRadius(vessel.orbit, vesselState.time, vesselState.mainBody.Radius + vesselState.mainBody.RealMaxAtmosphereAltitude()); } catch { warping = false; } break; case WarpTarget.SuicideBurn: try { targetUT = OrbitExtensions.SuicideBurnCountdown(orbit, vesselState, vessel) + vesselState.time; } catch { warping = false; } break; default: targetUT = vesselState.time; break; } } } GUILayout.EndHorizontal(); core.warp.useQuickWarpInfoItem(); if (warping) { GUILayout.Label(Localizer.Format("#MechJeb_WarpHelper_label6") + (leadTime > 0 ? GuiUtils.TimeToDHMS(leadTime) + " before " : "") + warpTargetStrings[(int)warpTarget] + "."); //"Warping to " } core.warp.ControlWarpButton(); GUILayout.EndVertical(); base.WindowGUI(windowID); }