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();
        }
Example #2
0
 public string TargetSMA()
 {
     if (!core.target.NormalTargetExists)
     {
         return("N/A");
     }
     return(MuUtils.ToSI(core.target.TargetOrbit.semiMajorAxis, 2) + "m");
 }
Example #3
0
 public string TargetOrbitSpeed()
 {
     if (!core.target.NormalTargetExists)
     {
         return("N/A");
     }
     return(MuUtils.ToSI(core.target.TargetOrbit.GetVel().magnitude) + "m/s");
 }
Example #4
0
 public string TargetPeriapsis()
 {
     if (!core.target.NormalTargetExists)
     {
         return("N/A");
     }
     return(MuUtils.ToSI(core.target.TargetOrbit.PeA, 2) + "m");
 }
Example #5
0
 public string TargetRelativeVelocity()
 {
     if (!core.target.NormalTargetExists)
     {
         return("N/A");
     }
     return(MuUtils.ToSI(core.target.RelativeVelocity.magnitude) + "m/s");
 }
Example #6
0
 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");
 }
Example #8
0
        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);
        }
Example #9
0
        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);
        }
Example #11
0
        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);
        }
Example #12
0
 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");
 }
Example #14
0
        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");
        }
Example #16
0
        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));
        }
Example #17
0
        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;
                }
            }
        }
Example #19
0
        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);
        }
Example #20
0
        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));
        }
Example #21
0
        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);
            }
        }
Example #23
0
        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);
        }
Example #24
0
        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);
        }
Example #26
0
        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);
        }
Example #27
0
        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);
        }
Example #28
0
        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);
        }
Example #29
0
        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);
        }