Ejemplo n.º 1
0
        //Computes the deltaV of the burn needed to set a given LAN at a given UT.
        public static Vector3d DeltaVToShiftLAN(Orbit o, double UT, double newLAN)
        {
            Vector3d pos = o.SwappedAbsolutePositionAtUT(UT);
            // Burn position in the same reference frame as LAN
            double burn_latitude  = o.referenceBody.GetLatitude(pos);
            double burn_longitude = o.referenceBody.GetLongitude(pos) + o.referenceBody.rotationAngle;

            const double target_latitude  = 0; // Equator
            double       target_longitude = 0; // Prime Meridian

            // Select the location of either the descending or ascending node.
            // If the descending node is closer than the ascending node, or there is no ascending node, target the reverse of the newLAN
            // Otherwise target the newLAN
            if (o.AscendingNodeEquatorialExists() && o.DescendingNodeEquatorialExists())
            {
                if (o.TimeOfDescendingNodeEquatorial(UT) < o.TimeOfAscendingNodeEquatorial(UT))
                {
                    // DN is closer than AN
                    // Burning for the AN would entail flipping the orbit around, and would be very expensive
                    // therefore, burn for the corresponding Longitude of the Descending Node
                    target_longitude = MuUtils.ClampDegrees360(newLAN + 180.0);
                }
                else
                {
                    // DN is closer than AN
                    target_longitude = MuUtils.ClampDegrees360(newLAN);
                }
            }
            else if (o.AscendingNodeEquatorialExists() && !o.DescendingNodeEquatorialExists())
            {
                // No DN
                target_longitude = MuUtils.ClampDegrees360(newLAN);
            }
            else if (!o.AscendingNodeEquatorialExists() && o.DescendingNodeEquatorialExists())
            {
                // No AN
                target_longitude = MuUtils.ClampDegrees360(newLAN + 180.0);
            }
            else
            {
                throw new ArgumentException("OrbitalManeuverCalculator.DeltaVToShiftLAN: No Equatorial Nodes");
            }
            double   desiredHeading            = MuUtils.ClampDegrees360(Heading(burn_latitude, burn_longitude, target_latitude, target_longitude));
            Vector3d actualHorizontalVelocity  = Vector3d.Exclude(o.Up(UT), o.SwappedOrbitalVelocityAtUT(UT));
            Vector3d eastComponent             = actualHorizontalVelocity.magnitude * Math.Sin(Math.PI / 180 * desiredHeading) * o.East(UT);
            Vector3d northComponent            = actualHorizontalVelocity.magnitude * Math.Cos(Math.PI / 180 * desiredHeading) * o.North(UT);
            Vector3d desiredHorizontalVelocity = eastComponent + northComponent;

            return(desiredHorizontalVelocity - actualHorizontalVelocity);
        }
Ejemplo n.º 2
0
        protected override void WindowGUI(int windowID)
        {
            if (vessel.patchedConicSolver.maneuverNodes.Count == 0)
            {
                GUILayout.Label(Localizer.Format("#MechJeb_NodeEd_Label1"));//"No maneuver nodes to edit."
                RelativityModeSelectUI();
                base.WindowGUI(windowID);
                return;
            }

            GUILayout.BeginVertical();

            ManeuverNode oldNode = node;

            if (vessel.patchedConicSolver.maneuverNodes.Count == 1)
            {
                node = vessel.patchedConicSolver.maneuverNodes[0];
            }
            else
            {
                if (!vessel.patchedConicSolver.maneuverNodes.Contains(node))
                {
                    node = vessel.patchedConicSolver.maneuverNodes[0];
                }

                int nodeIndex = vessel.patchedConicSolver.maneuverNodes.IndexOf(node);
                int numNodes  = vessel.patchedConicSolver.maneuverNodes.Count;

                nodeIndex = GuiUtils.ArrowSelector(nodeIndex, numNodes, "Maneuver node #" + (nodeIndex + 1));

                node = vessel.patchedConicSolver.maneuverNodes[nodeIndex];
                if (nodeIndex < (numNodes - 1) && GUILayout.Button(Localizer.Format("#MechJeb_NodeEd_button1")))
                {
                    MergeNext(nodeIndex);                                                                                           //"Merge next node"
                }
            }

            if (node != oldNode)
            {
                prograde   = node.DeltaV.z;
                radialPlus = node.DeltaV.x;
                normalPlus = node.DeltaV.y;
            }

            if (gizmo != node.attachedGizmo)
            {
                if (gizmo != null)
                {
                    gizmo.OnGizmoUpdated -= GizmoUpdateHandler;
                }
                gizmo = node.attachedGizmo;
                if (gizmo != null)
                {
                    gizmo.OnGizmoUpdated += GizmoUpdateHandler;
                }
            }


            GUILayout.BeginHorizontal();
            GuiUtils.SimpleTextBox(Localizer.Format("#MechJeb_NodeEd_Label2"), prograde, "m/s", 60);//"Prograde:"
            if (LimitedRepeatButtoon("-"))
            {
                prograde -= progradeDelta;
                node.UpdateNode(new Vector3d(radialPlus, normalPlus, prograde), node.UT);
            }
            progradeDelta.text = GUILayout.TextField(progradeDelta.text, GUILayout.Width(50));
            if (LimitedRepeatButtoon("+"))
            {
                prograde += progradeDelta;
                node.UpdateNode(new Vector3d(radialPlus, normalPlus, prograde), node.UT);
            }
            GUILayout.Label("m/s", GUILayout.ExpandWidth(false));
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GuiUtils.SimpleTextBox(Localizer.Format("#MechJeb_NodeEd_Label3"), radialPlus, "m/s", 60);//"Radial+:"
            if (LimitedRepeatButtoon("-"))
            {
                radialPlus -= radialPlusDelta;
                node.UpdateNode(new Vector3d(radialPlus, normalPlus, prograde), node.UT);
            }
            radialPlusDelta.text = GUILayout.TextField(radialPlusDelta.text, GUILayout.Width(50));
            if (LimitedRepeatButtoon("+"))
            {
                radialPlus += radialPlusDelta;
                node.UpdateNode(new Vector3d(radialPlus, normalPlus, prograde), node.UT);
            }
            GUILayout.Label("m/s", GUILayout.ExpandWidth(false));
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GuiUtils.SimpleTextBox(Localizer.Format("#MechJeb_NodeEd_Label4"), normalPlus, "m/s", 60);//"Normal+:"
            if (LimitedRepeatButtoon("-"))
            {
                normalPlus -= normalPlusDelta;
                node.UpdateNode(new Vector3d(radialPlus, normalPlus, prograde), node.UT);
            }
            normalPlusDelta.text = GUILayout.TextField(normalPlusDelta.text, GUILayout.Width(50));
            if (LimitedRepeatButtoon("+"))
            {
                normalPlus += normalPlusDelta;
                node.UpdateNode(new Vector3d(radialPlus, normalPlus, prograde), node.UT);
            }
            GUILayout.Label("m/s", GUILayout.ExpandWidth(false));
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GUILayout.Label(Localizer.Format("#MechJeb_NodeEd_Label5"), GUILayout.ExpandWidth(true));//"Set delta to:"
            if (GUILayout.Button("0.01", GUILayout.ExpandWidth(true)))
            {
                progradeDelta = radialPlusDelta = normalPlusDelta = 0.01;
            }
            if (GUILayout.Button("0.1", GUILayout.ExpandWidth(true)))
            {
                progradeDelta = radialPlusDelta = normalPlusDelta = 0.1;
            }
            if (GUILayout.Button("1", GUILayout.ExpandWidth(true)))
            {
                progradeDelta = radialPlusDelta = normalPlusDelta = 1;
            }
            if (GUILayout.Button("10", GUILayout.ExpandWidth(true)))
            {
                progradeDelta = radialPlusDelta = normalPlusDelta = 10;
            }
            if (GUILayout.Button("100", GUILayout.ExpandWidth(true)))
            {
                progradeDelta = radialPlusDelta = normalPlusDelta = 100;
            }
            GUILayout.EndHorizontal();

            if (GUILayout.Button(Localizer.Format("#MechJeb_NodeEd_button2")))
            {
                node.UpdateNode(new Vector3d(radialPlus, normalPlus, prograde), node.UT);                                                               //"Update"
            }
            GUILayout.BeginHorizontal();
            GUILayout.Label(Localizer.Format("#MechJeb_NodeEd_Label6"), GUILayout.ExpandWidth(true));//"Shift time"
            if (GUILayout.Button("-o", GUILayout.ExpandWidth(false)))
            {
                node.UpdateNode(node.DeltaV, node.UT - node.patch.period);
            }
            if (GUILayout.Button("-", GUILayout.ExpandWidth(false)))
            {
                node.UpdateNode(node.DeltaV, node.UT - timeOffset);
            }
            timeOffset.text = GUILayout.TextField(timeOffset.text, GUILayout.Width(100));
            if (GUILayout.Button("+", GUILayout.ExpandWidth(false)))
            {
                node.UpdateNode(node.DeltaV, node.UT + timeOffset);
            }
            if (GUILayout.Button("+o", GUILayout.ExpandWidth(false)))
            {
                node.UpdateNode(node.DeltaV, node.UT + node.patch.period);
            }
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            if (GUILayout.Button(Localizer.Format("#MechJeb_NodeEd_button3"), GUILayout.ExpandWidth(true)))//"Snap node to"
            {
                Orbit  o  = node.patch;
                double UT = node.UT;
                switch (snap)
                {
                case Snap.PERIAPSIS:
                    UT = o.NextPeriapsisTime(o.eccentricity < 1 ? UT - o.period / 2 : UT);
                    break;

                case Snap.APOAPSIS:
                    if (o.eccentricity < 1)
                    {
                        UT = o.NextApoapsisTime(UT - o.period / 2);
                    }
                    break;

                case Snap.EQ_ASCENDING:
                    if (o.AscendingNodeEquatorialExists())
                    {
                        UT = o.TimeOfAscendingNodeEquatorial(UT - o.period / 2);
                    }
                    break;

                case Snap.EQ_DESCENDING:
                    if (o.DescendingNodeEquatorialExists())
                    {
                        UT = o.TimeOfDescendingNodeEquatorial(UT - o.period / 2);
                    }
                    break;

                case Snap.REL_ASCENDING:
                    if (core.target.NormalTargetExists && core.target.TargetOrbit.referenceBody == o.referenceBody)
                    {
                        if (o.AscendingNodeExists(core.target.TargetOrbit))
                        {
                            UT = o.TimeOfAscendingNode(core.target.TargetOrbit, UT - o.period / 2);
                        }
                    }
                    break;

                case Snap.REL_DESCENDING:
                    if (core.target.NormalTargetExists && core.target.TargetOrbit.referenceBody == o.referenceBody)
                    {
                        if (o.DescendingNodeExists(core.target.TargetOrbit))
                        {
                            UT = o.TimeOfDescendingNode(core.target.TargetOrbit, UT - o.period / 2);
                        }
                    }
                    break;
                }
                node.UpdateNode(node.DeltaV, UT);
            }

            snap = (Snap)GuiUtils.ArrowSelector((int)snap, numSnaps, snapStrings[(int)snap]);

            GUILayout.EndHorizontal();

            RelativityModeSelectUI();


            if (core.node != null)
            {
                if (vessel.patchedConicSolver.maneuverNodes.Count > 0 && !core.node.enabled)
                {
                    if (GUILayout.Button(Localizer.Format("#MechJeb_NodeEd_button4")))//"Execute next node"
                    {
                        core.node.ExecuteOneNode(this);
                    }

                    if (MechJebModuleGuidanceController.isLoadedPrincipia && GUILayout.Button(Localizer.Format("#MechJeb_NodeEd_button7")))//Execute next Principia node
                    {
                        core.node.ExecuteOnePNode(this);
                    }

                    if (vessel.patchedConicSolver.maneuverNodes.Count > 1)
                    {
                        if (GUILayout.Button(Localizer.Format("#MechJeb_NodeEd_button5")))//"Execute all nodes"
                        {
                            core.node.ExecuteAllNodes(this);
                        }
                    }
                }
                else if (core.node.enabled)
                {
                    if (GUILayout.Button(Localizer.Format("#MechJeb_NodeEd_button6")))//"Abort node execution"
                    {
                        core.node.Abort();
                    }
                }

                GUILayout.BeginHorizontal();
                core.node.autowarp = GUILayout.Toggle(core.node.autowarp, Localizer.Format("#MechJeb_NodeEd_checkbox1"), GUILayout.ExpandWidth(true)); //"Auto-warp"
                GUILayout.Label(Localizer.Format("#MechJeb_NodeEd_Label7"), GUILayout.ExpandWidth(false));                                             //"Tolerance:"
                core.node.tolerance.text = GUILayout.TextField(core.node.tolerance.text, GUILayout.Width(35), GUILayout.ExpandWidth(false));
                GUILayout.Label("m/s", GUILayout.ExpandWidth(false));
                GUILayout.EndHorizontal();
            }

            GUILayout.EndVertical();

            base.WindowGUI(windowID);
        }
Ejemplo n.º 3
0
        public double ComputeManeuverTime(Orbit o, double UT, MechJebModuleTargetController target)
        {
            switch (allowedTimeRef[currentTimeRef])
            {
            case TimeReference.X_FROM_NOW:
                UT += leadTime.val;
                break;

            case TimeReference.APOAPSIS:
                if (o.eccentricity < 1)
                {
                    UT = o.NextApoapsisTime(UT);
                }
                else
                {
                    throw new OperationException("Warning: orbit is hyperbolic, so apoapsis doesn't exist.");
                }
                break;

            case TimeReference.PERIAPSIS:
                UT = o.NextPeriapsisTime(UT);
                break;

            case TimeReference.CLOSEST_APPROACH:
                if (target.NormalTargetExists)
                {
                    UT = o.NextClosestApproachTime(target.TargetOrbit, UT);
                }
                else
                {
                    throw new OperationException("Warning: no target selected.");
                }
                break;

            case TimeReference.ALTITUDE:
                if (circularizeAltitude > o.PeA && (circularizeAltitude < o.ApA || o.eccentricity >= 1))
                {
                    UT = o.NextTimeOfRadius(UT, o.referenceBody.Radius + circularizeAltitude);
                }
                else
                {
                    throw new OperationException("Warning: can't circularize at this altitude, since current orbit does not reach it.");
                }
                break;

            case TimeReference.EQ_ASCENDING:
                if (o.AscendingNodeEquatorialExists())
                {
                    UT = o.TimeOfAscendingNodeEquatorial(UT);
                }
                else
                {
                    throw new OperationException("Warning: equatorial ascending node doesn't exist.");
                }
                break;

            case TimeReference.EQ_DESCENDING:
                if (o.DescendingNodeEquatorialExists())
                {
                    UT = o.TimeOfDescendingNodeEquatorial(UT);
                }
                else
                {
                    throw new OperationException("Warning: equatorial descending node doesn't exist.");
                }
                break;

            case TimeReference.EQ_NEAREST_AD:
                if (o.AscendingNodeEquatorialExists())
                {
                    UT = o.DescendingNodeEquatorialExists()
                        ? System.Math.Min(o.TimeOfAscendingNodeEquatorial(UT), o.TimeOfDescendingNodeEquatorial(UT))
                        : o.TimeOfAscendingNodeEquatorial(UT);
                }
                else if (o.DescendingNodeEquatorialExists())
                {
                    UT = o.TimeOfDescendingNodeEquatorial(UT);
                }
                else
                {
                    throw new OperationException("Warning: neither ascending nor descending node exists.");
                }
                break;

            case TimeReference.EQ_HIGHEST_AD:
                if (o.AscendingNodeEquatorialExists())
                {
                    if (o.DescendingNodeEquatorialExists())
                    {
                        var anTime = o.TimeOfAscendingNodeEquatorial(UT);
                        var dnTime = o.TimeOfDescendingNodeEquatorial(UT);
                        UT = o.getOrbitalVelocityAtUT(anTime).magnitude <= o.getOrbitalVelocityAtUT(dnTime).magnitude
                            ? anTime
                            : dnTime;
                    }
                    else
                    {
                        UT = o.TimeOfAscendingNodeEquatorial(UT);
                    }
                }
                else if (o.DescendingNodeEquatorialExists())
                {
                    UT = o.TimeOfDescendingNodeEquatorial(UT);
                }
                else
                {
                    throw new OperationException("Warning: neither ascending nor descending node exists.");
                }
                break;
            }

            universalTime = UT;
            return(universalTime);
        }
Ejemplo n.º 4
0
        protected override void WindowGUI(int windowID)
        {
            if (vessel.patchedConicSolver.maneuverNodes.Count == 0)
            {
                GUILayout.Label("No maneuver nodes to edit.");
                RelativityModeSelectUI();
                base.WindowGUI(windowID);
                return;
            }

            GUILayout.BeginVertical();

            ManeuverNode oldNode = node;

            if (vessel.patchedConicSolver.maneuverNodes.Count == 1)
            {
                node = vessel.patchedConicSolver.maneuverNodes[0];
            }
            else
            {
                if (!vessel.patchedConicSolver.maneuverNodes.Contains(node))
                {
                    node = vessel.patchedConicSolver.maneuverNodes[0];
                }

                int nodeIndex = vessel.patchedConicSolver.maneuverNodes.IndexOf(node);
                int numNodes  = vessel.patchedConicSolver.maneuverNodes.Count;

                nodeIndex = GuiUtils.ArrowSelector(nodeIndex, numNodes, "Maneuver node #" + (nodeIndex + 1));

                node = vessel.patchedConicSolver.maneuverNodes[nodeIndex];
            }

            if (node != oldNode)
            {
                prograde   = node.DeltaV.z;
                radialPlus = node.DeltaV.x;
                normalPlus = node.DeltaV.y;
            }

            if (gizmo != node.attachedGizmo)
            {
                if (gizmo != null)
                {
                    gizmo.OnGizmoUpdated -= GizmoUpdateHandler;
                }
                gizmo = node.attachedGizmo;
                if (gizmo != null)
                {
                    gizmo.OnGizmoUpdated += GizmoUpdateHandler;
                }
            }


            GUILayout.BeginHorizontal();
            GuiUtils.SimpleTextBox("Prograde:", prograde, "m/s", 60);
            if (GUILayout.Button("-", GUILayout.ExpandWidth(false)))
            {
                prograde -= progradeDelta;
                node.OnGizmoUpdated(new Vector3d(radialPlus, normalPlus, prograde), node.UT);
            }
            progradeDelta.text = GUILayout.TextField(progradeDelta.text, GUILayout.Width(50));
            if (GUILayout.Button("+", GUILayout.ExpandWidth(false)))
            {
                prograde += progradeDelta;
                node.OnGizmoUpdated(new Vector3d(radialPlus, normalPlus, prograde), node.UT);
            }
            GUILayout.Label("m/s", GUILayout.ExpandWidth(false));
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GuiUtils.SimpleTextBox("Radial+:", radialPlus, "m/s", 60);
            if (GUILayout.Button("-", GUILayout.ExpandWidth(false)))
            {
                radialPlus -= radialPlusDelta;
                node.OnGizmoUpdated(new Vector3d(radialPlus, normalPlus, prograde), node.UT);
            }
            radialPlusDelta.text = GUILayout.TextField(radialPlusDelta.text, GUILayout.Width(50));
            if (GUILayout.Button("+", GUILayout.ExpandWidth(false)))
            {
                radialPlus += radialPlusDelta;
                node.OnGizmoUpdated(new Vector3d(radialPlus, normalPlus, prograde), node.UT);
            }
            GUILayout.Label("m/s", GUILayout.ExpandWidth(false));
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GuiUtils.SimpleTextBox("Normal+:", normalPlus, "m/s", 60);
            if (GUILayout.Button("-", GUILayout.ExpandWidth(false)))
            {
                normalPlus -= normalPlusDelta;
                node.OnGizmoUpdated(new Vector3d(radialPlus, normalPlus, prograde), node.UT);
            }
            normalPlusDelta.text = GUILayout.TextField(normalPlusDelta.text, GUILayout.Width(50));
            if (GUILayout.Button("+", GUILayout.ExpandWidth(false)))
            {
                normalPlus += normalPlusDelta;
                node.OnGizmoUpdated(new Vector3d(radialPlus, normalPlus, prograde), node.UT);
            }
            GUILayout.Label("m/s", GUILayout.ExpandWidth(false));
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GUILayout.Label("Set delta to:", GUILayout.ExpandWidth(true));
            if (GUILayout.Button("0.01", GUILayout.ExpandWidth(true)))
            {
                progradeDelta = radialPlusDelta = normalPlusDelta = 0.01;
            }
            if (GUILayout.Button("0.1", GUILayout.ExpandWidth(true)))
            {
                progradeDelta = radialPlusDelta = normalPlusDelta = 0.1;
            }
            if (GUILayout.Button("1", GUILayout.ExpandWidth(true)))
            {
                progradeDelta = radialPlusDelta = normalPlusDelta = 1;
            }
            if (GUILayout.Button("10", GUILayout.ExpandWidth(true)))
            {
                progradeDelta = radialPlusDelta = normalPlusDelta = 10;
            }
            if (GUILayout.Button("100", GUILayout.ExpandWidth(true)))
            {
                progradeDelta = radialPlusDelta = normalPlusDelta = 100;
            }
            GUILayout.EndHorizontal();

            if (GUILayout.Button("Update"))
            {
                node.OnGizmoUpdated(new Vector3d(radialPlus, normalPlus, prograde), node.UT);
            }

            GUILayout.BeginHorizontal();
            GUILayout.Label("Shift time", GUILayout.ExpandWidth(true));
            if (GUILayout.Button("-", GUILayout.ExpandWidth(false)))
            {
                node.OnGizmoUpdated(node.DeltaV, node.UT - timeOffset);
            }
            timeOffset.text = GUILayout.TextField(timeOffset.text, GUILayout.Width(100));
            if (GUILayout.Button("+", GUILayout.ExpandWidth(false)))
            {
                node.OnGizmoUpdated(node.DeltaV, node.UT + timeOffset);
            }
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            if (GUILayout.Button("Snap node to", GUILayout.ExpandWidth(true)))
            {
                Orbit  o  = node.patch;
                double UT = node.UT;
                switch (snap)
                {
                case Snap.PERIAPSIS:
                    UT = o.NextPeriapsisTime(UT - o.period / 2);     //period is who-knows-what for e > 1, but this should still work
                    break;

                case Snap.APOAPSIS:
                    if (o.eccentricity < 1)
                    {
                        UT = o.NextApoapsisTime(UT - o.period / 2);
                    }
                    break;

                case Snap.EQ_ASCENDING:
                    if (o.AscendingNodeEquatorialExists())
                    {
                        UT = o.TimeOfAscendingNodeEquatorial(UT - o.period / 2);
                    }
                    break;

                case Snap.EQ_DESCENDING:
                    if (o.DescendingNodeEquatorialExists())
                    {
                        UT = o.TimeOfDescendingNodeEquatorial(UT - o.period / 2);
                    }
                    break;

                case Snap.REL_ASCENDING:
                    if (core.target.NormalTargetExists && core.target.TargetOrbit.referenceBody == o.referenceBody)
                    {
                        if (o.AscendingNodeExists(core.target.TargetOrbit))
                        {
                            UT = o.TimeOfAscendingNode(core.target.TargetOrbit, UT - o.period / 2);
                        }
                    }
                    break;

                case Snap.REL_DESCENDING:
                    if (core.target.NormalTargetExists && core.target.TargetOrbit.referenceBody == o.referenceBody)
                    {
                        if (o.DescendingNodeExists(core.target.TargetOrbit))
                        {
                            UT = o.TimeOfDescendingNode(core.target.TargetOrbit, UT - o.period / 2);
                        }
                    }
                    break;
                }
                node.OnGizmoUpdated(node.DeltaV, UT);
            }

            snap = (Snap)GuiUtils.ArrowSelector((int)snap, numSnaps, snapStrings[(int)snap]);

            GUILayout.EndHorizontal();

            RelativityModeSelectUI();


            if (core.node != null)
            {
                if (vessel.patchedConicSolver.maneuverNodes.Count > 0 && !core.node.enabled)
                {
                    if (GUILayout.Button("Execute next node"))
                    {
                        core.node.ExecuteOneNode(this);
                    }

                    if (vessel.patchedConicSolver.maneuverNodes.Count > 1)
                    {
                        if (GUILayout.Button("Execute all nodes"))
                        {
                            core.node.ExecuteAllNodes(this);
                        }
                    }
                }
                else if (core.node.enabled)
                {
                    if (GUILayout.Button("Abort node execution"))
                    {
                        core.node.Abort();
                    }
                }

                GUILayout.BeginHorizontal();
                core.node.autowarp = GUILayout.Toggle(core.node.autowarp, "Auto-warp", GUILayout.ExpandWidth(true));
                GUILayout.Label("Tolerance:", GUILayout.ExpandWidth(false));
                core.node.tolerance.text = GUILayout.TextField(core.node.tolerance.text, GUILayout.Width(35), GUILayout.ExpandWidth(false));
                GUILayout.Label("m/s", GUILayout.ExpandWidth(false));
                GUILayout.EndHorizontal();
            }

            GUILayout.EndVertical();

            base.WindowGUI(windowID);
        }
        //Computes the deltaV of the burn needed to set a given LAN at a given UT.
        public static Vector3d DeltaVToShiftLAN(Orbit o, double UT, double newLAN)
        {
            Vector3d pos = o.SwappedAbsolutePositionAtUT(UT);
            // Burn position in the same reference frame as LAN
            double burn_latitude = o.referenceBody.GetLatitude(pos);
            double burn_longitude = o.referenceBody.GetLongitude(pos) + o.referenceBody.rotationAngle;

            const double target_latitude = 0; // Equator
            double target_longitude = 0; // Prime Meridian

            // Select the location of either the descending or ascending node.
            // If the descending node is closer than the ascending node, or there is no ascending node, target the reverse of the newLAN
            // Otherwise target the newLAN
            if (o.AscendingNodeEquatorialExists() && o.DescendingNodeEquatorialExists())
            {
                if (o.TimeOfDescendingNodeEquatorial(UT) < o.TimeOfAscendingNodeEquatorial(UT))
                {
                    // DN is closer than AN
                    // Burning for the AN would entail flipping the orbit around, and would be very expensive
                    // therefore, burn for the corresponding Longitude of the Descending Node
                    target_longitude = MuUtils.ClampDegrees360(newLAN + 180.0);
                }
                else
                {
                    // DN is closer than AN
                    target_longitude = MuUtils.ClampDegrees360(newLAN);
                }
            }
            else if (o.AscendingNodeEquatorialExists() && !o.DescendingNodeEquatorialExists())
            {
                // No DN
                target_longitude = MuUtils.ClampDegrees360(newLAN);
            }
            else if (!o.AscendingNodeEquatorialExists() && o.DescendingNodeEquatorialExists())
            {
                // No AN
                target_longitude = MuUtils.ClampDegrees360(newLAN + 180.0);
            }
            else
            {
                throw new ArgumentException("OrbitalManeuverCalculator.DeltaVToShiftLAN: No Equatorial Nodes");
            }
            double desiredHeading = MuUtils.ClampDegrees360(Heading(burn_latitude, burn_longitude, target_latitude, target_longitude));
            Vector3d actualHorizontalVelocity = Vector3d.Exclude(o.Up(UT), o.SwappedOrbitalVelocityAtUT(UT));
            Vector3d eastComponent = actualHorizontalVelocity.magnitude * Math.Sin(Math.PI / 180 * desiredHeading) * o.East(UT);
            Vector3d northComponent = actualHorizontalVelocity.magnitude * Math.Cos(Math.PI / 180 * desiredHeading) * o.North(UT);
            Vector3d desiredHorizontalVelocity = eastComponent + northComponent;
            return desiredHorizontalVelocity - actualHorizontalVelocity;
        }
Ejemplo n.º 6
0
        public double ComputeManeuverTime(Orbit o, double UT, MechJebModuleTargetController target)
        {
            switch (allowedTimeRef[currentTimeRef])
            {
            case TimeReference.X_FROM_NOW:
                UT += leadTime.val;
                break;

            case TimeReference.APOAPSIS:
                if (o.eccentricity < 1)
                {
                    UT = o.NextApoapsisTime(UT);
                }
                else
                {
                    throw new OperationException("Warning: orbit is hyperbolic, so apoapsis doesn't exist.");
                }
                break;

            case TimeReference.PERIAPSIS:
                UT = o.NextPeriapsisTime(UT);
                break;

            case TimeReference.CLOSEST_APPROACH:
                if (target.NormalTargetExists)
                {
                    UT = o.NextClosestApproachTime(target.TargetOrbit, UT);
                }
                else
                {
                    throw new OperationException("Warning: no target selected.");
                }
                break;

            case TimeReference.ALTITUDE:
                if (circularizeAltitude > o.PeA && (circularizeAltitude < o.ApA || o.eccentricity >= 1))
                {
                    UT = o.NextTimeOfRadius(UT, o.referenceBody.Radius + circularizeAltitude);
                }
                else
                {
                    throw new OperationException("Warning: can't circularize at this altitude, since current orbit does not reach it.");
                }
                break;

            case TimeReference.EQ_ASCENDING:
                if (o.AscendingNodeEquatorialExists())
                {
                    UT = o.TimeOfAscendingNodeEquatorial(UT);
                }
                else
                {
                    throw new OperationException("Warning: equatorial ascending node doesn't exist.");
                }
                break;

            case TimeReference.EQ_DESCENDING:
                if (o.DescendingNodeEquatorialExists())
                {
                    UT = o.TimeOfDescendingNodeEquatorial(UT);
                }
                else
                {
                    throw new OperationException("Warning: equatorial descending node doesn't exist.");
                }
                break;
            
            case TimeReference.EQ_NEAREST_AD:
                if(o.AscendingNodeEquatorialExists())
                {
                    UT = o.DescendingNodeEquatorialExists()
                        ? System.Math.Min(o.TimeOfAscendingNodeEquatorial(UT), o.TimeOfDescendingNodeEquatorial(UT))
                        : o.TimeOfAscendingNodeEquatorial(UT);
                }
                else if(o.DescendingNodeEquatorialExists())
                {
                    UT = o.TimeOfDescendingNodeEquatorial(UT);
                }
                else
                {
                    throw new OperationException("Warning: neither ascending nor descending node exists.");
                }
                break;

            case TimeReference.EQ_HIGHEST_AD:
                if(o.AscendingNodeEquatorialExists())
                {
                    if(o.DescendingNodeEquatorialExists())
                    {
                        var anTime = o.TimeOfAscendingNodeEquatorial(UT);
                        var dnTime = o.TimeOfDescendingNodeEquatorial(UT);
                        UT = o.getOrbitalVelocityAtUT(anTime).magnitude <= o.getOrbitalVelocityAtUT(dnTime).magnitude
                            ? anTime
                            : dnTime;
                    }
                    else
                    {
                        UT = o.TimeOfAscendingNodeEquatorial(UT);
                    }
                }
                else if(o.DescendingNodeEquatorialExists())
                {
                    UT = o.TimeOfDescendingNodeEquatorial(UT);
                }
                else
                {
                    throw new OperationException("Warning: neither ascending nor descending node exists.");
                }
                break;
            }

            universalTime = UT;
            return universalTime;
        }
Ejemplo n.º 7
0
        double DoChooseTimeGUI()
        {
            Dictionary <Operation, TimeReference[]> references = new Dictionary <Operation, TimeReference[]>();

            references[Operation.CIRCULARIZE]             = new TimeReference[] { TimeReference.APOAPSIS, TimeReference.PERIAPSIS, TimeReference.ALTITUDE, TimeReference.X_FROM_NOW };
            references[Operation.PERIAPSIS]               = new TimeReference[] { TimeReference.X_FROM_NOW, TimeReference.APOAPSIS, TimeReference.PERIAPSIS };
            references[Operation.APOAPSIS]                = new TimeReference[] { TimeReference.X_FROM_NOW, TimeReference.APOAPSIS, TimeReference.PERIAPSIS };
            references[Operation.ELLIPTICIZE]             = new TimeReference[] { TimeReference.X_FROM_NOW };
            references[Operation.INCLINATION]             = new TimeReference[] { TimeReference.EQ_ASCENDING, TimeReference.EQ_DESCENDING, TimeReference.X_FROM_NOW };
            references[Operation.PLANE]                   = new TimeReference[] { TimeReference.REL_ASCENDING, TimeReference.REL_DESCENDING };
            references[Operation.TRANSFER]                = new TimeReference[] { TimeReference.COMPUTED };
            references[Operation.MOON_RETURN]             = new TimeReference[] { TimeReference.COMPUTED };
            references[Operation.INTERPLANETARY_TRANSFER] = new TimeReference[] { TimeReference.COMPUTED };
            references[Operation.COURSE_CORRECTION]       = new TimeReference[] { TimeReference.COMPUTED };
            references[Operation.LAMBERT]                 = new TimeReference[] { TimeReference.X_FROM_NOW };
            references[Operation.KILL_RELVEL]             = new TimeReference[] { TimeReference.CLOSEST_APPROACH, TimeReference.X_FROM_NOW };

            TimeReference[] allowedReferences = references[operation];

            int referenceIndex = 0;

            if (allowedReferences.Contains(timeReference))
            {
                referenceIndex = Array.IndexOf(allowedReferences, timeReference);
            }

            referenceIndex = GuiUtils.ArrowSelector(referenceIndex, allowedReferences.Length, () =>
            {
                switch (timeReference)
                {
                case TimeReference.APOAPSIS: GUILayout.Label("at the next apoapsis"); break;

                case TimeReference.CLOSEST_APPROACH: GUILayout.Label("at closest approach to target"); break;

                case TimeReference.EQ_ASCENDING: GUILayout.Label("at the equatorial AN"); break;

                case TimeReference.EQ_DESCENDING: GUILayout.Label("at the equatorial DN"); break;

                case TimeReference.PERIAPSIS: GUILayout.Label("at the next periapsis"); break;

                case TimeReference.REL_ASCENDING: GUILayout.Label("at the next AN with the target."); break;

                case TimeReference.REL_DESCENDING: GUILayout.Label("at the next DN with the target."); break;

                case TimeReference.X_FROM_NOW:
                    leadTime.text = GUILayout.TextField(leadTime.text, GUILayout.Width(50));
                    GUILayout.Label(" from now");
                    break;

                case TimeReference.ALTITUDE:
                    GuiUtils.SimpleTextBox("at an altitude of", circularizeAltitude, "km");
                    break;
                }
            });

            timeReference = allowedReferences[referenceIndex];

            bool   error            = false;
            string timeErrorMessage = "";

            double UT = vesselState.time;

            Orbit o = orbit;

            List <ManeuverNode> maneuverNodes = GetManeuverNodes();

            if (maneuverNodes.Count() > 0)
            {
                GUILayout.Label("after the last maneuver node.");
                ManeuverNode last = maneuverNodes.Last();
                UT = last.UT;
                o  = last.nextPatch;
            }

            switch (timeReference)
            {
            case TimeReference.X_FROM_NOW:
                UT += leadTime;
                break;

            case TimeReference.APOAPSIS:
                if (o.eccentricity < 1)
                {
                    UT = o.NextApoapsisTime(UT);
                }
                else
                {
                    error            = true;
                    timeErrorMessage = "Warning: orbit is hyperbolic, so apoapsis doesn't exist.";
                }
                break;

            case TimeReference.PERIAPSIS:
                UT = o.NextPeriapsisTime(UT);
                break;

            case TimeReference.CLOSEST_APPROACH:
                if (core.target.NormalTargetExists)
                {
                    UT = o.NextClosestApproachTime(core.target.Orbit, UT);
                }
                else
                {
                    error            = true;
                    timeErrorMessage = "Warning: no target selected.";
                }
                break;

            case TimeReference.ALTITUDE:
                if (circularizeAltitude > o.PeA && circularizeAltitude < o.ApA)
                {
                    UT = o.NextTimeOfRadius(UT, o.referenceBody.Radius + circularizeAltitude);
                }
                else
                {
                    error            = true;
                    timeErrorMessage = "Warning: can't circularize at this altitude, since current orbit does not reach it.";
                }
                break;

            case TimeReference.EQ_ASCENDING:
                if (o.AscendingNodeEquatorialExists())
                {
                    UT = o.TimeOfAscendingNodeEquatorial(UT);
                }
                else
                {
                    error            = true;
                    timeErrorMessage = "Warning: equatorial ascending node doesn't exist.";
                }
                break;

            case TimeReference.EQ_DESCENDING:
                if (o.DescendingNodeEquatorialExists())
                {
                    UT = o.TimeOfDescendingNodeEquatorial(UT);
                }
                else
                {
                    error            = true;
                    timeErrorMessage = "Warning: equatorial descending node doesn't exist.";
                }
                break;
            }

            if (operation == Operation.COURSE_CORRECTION && core.target.NormalTargetExists)
            {
                Orbit correctionPatch = o;
                while (correctionPatch != null)
                {
                    if (correctionPatch.referenceBody == core.target.Orbit.referenceBody)
                    {
                        o  = correctionPatch;
                        UT = correctionPatch.StartUT;
                        break;
                    }
                    correctionPatch = vessel.GetNextPatch(correctionPatch);
                }
            }

            if (error)
            {
                GUIStyle s = new GUIStyle(GUI.skin.label);
                s.normal.textColor = Color.yellow;
                GUILayout.Label(timeErrorMessage, s);
            }

            return(UT);
        }
Ejemplo n.º 8
0
        double DoChooseTimeGUI(Operation op, TimeReference timeRef, out string timeErrorMessage, bool InvolveGUI = true, double leadingTime = 0)
        {
            if (InvolveGUI)
            {
                TimeReference[] allowedReferences = references[op];

                int referenceIndex = 0;
                if (allowedReferences.Contains(timeReference))
                {
                    referenceIndex = Array.IndexOf(allowedReferences, timeReference);
                }

                referenceIndex = GuiUtils.ArrowSelector(referenceIndex, allowedReferences.Length, () =>
                {
                    switch (timeReference)
                    {
                    case TimeReference.APOAPSIS: GUILayout.Label("at the next apoapsis"); break;

                    case TimeReference.CLOSEST_APPROACH: GUILayout.Label("at closest approach to target"); break;

                    case TimeReference.EQ_ASCENDING: GUILayout.Label("at the equatorial AN"); break;

                    case TimeReference.EQ_DESCENDING: GUILayout.Label("at the equatorial DN"); break;

                    case TimeReference.PERIAPSIS: GUILayout.Label("at the next periapsis"); break;

                    case TimeReference.REL_ASCENDING: GUILayout.Label("at the next AN with the target."); break;

                    case TimeReference.REL_DESCENDING: GUILayout.Label("at the next DN with the target."); break;

                    case TimeReference.X_FROM_NOW:
                        leadTime.text = GUILayout.TextField(leadTime.text, GUILayout.Width(50));
                        GUILayout.Label(" from now");
                        break;

                    case TimeReference.ALTITUDE:
                        GuiUtils.SimpleTextBox("at an altitude of", circularizeAltitude, "km");
                        break;
                    }
                });

                timeReference = allowedReferences[referenceIndex];
            }

            timeErrorMessage = "";

            bool error = false;

            double UT = vesselState.time;

            Orbit o = orbit;

            List <ManeuverNode> maneuverNodes = GetManeuverNodes();

            if (maneuverNodes.Any())
            {
                if (InvolveGUI)
                {
                    GUILayout.Label("after the last maneuver node.");
                }
                ManeuverNode last = maneuverNodes.Last();
                UT = last.UT;
                o  = last.nextPatch;
            }

            switch (InvolveGUI ? timeReference : timeRef)
            {
            case TimeReference.X_FROM_NOW:
                UT += (InvolveGUI ? leadTime.val : leadingTime);
                break;

            case TimeReference.APOAPSIS:
                if (o.eccentricity < 1)
                {
                    UT = o.NextApoapsisTime(UT);
                }
                else
                {
                    error            = true;
                    timeErrorMessage = "Warning: orbit is hyperbolic, so apoapsis doesn't exist.";
                }
                break;

            case TimeReference.PERIAPSIS:
                UT = o.NextPeriapsisTime(UT);
                break;

            case TimeReference.CLOSEST_APPROACH:
                if (core.target.NormalTargetExists)
                {
                    UT = o.NextClosestApproachTime(core.target.TargetOrbit, UT);
                }
                else
                {
                    error            = true;
                    timeErrorMessage = "Warning: no target selected.";
                }
                break;

            case TimeReference.ALTITUDE:
                if (circularizeAltitude > o.PeA && (circularizeAltitude < o.ApA || o.eccentricity >= 1))
                {
                    UT = o.NextTimeOfRadius(UT, o.referenceBody.Radius + circularizeAltitude);
                }
                else
                {
                    error            = true;
                    timeErrorMessage = "Warning: can't circularize at this altitude, since current orbit does not reach it.";
                }
                break;

            case TimeReference.EQ_ASCENDING:
                if (o.AscendingNodeEquatorialExists())
                {
                    UT = o.TimeOfAscendingNodeEquatorial(UT);
                }
                else
                {
                    error            = true;
                    timeErrorMessage = "Warning: equatorial ascending node doesn't exist.";
                }
                break;

            case TimeReference.EQ_DESCENDING:
                if (o.DescendingNodeEquatorialExists())
                {
                    UT = o.TimeOfDescendingNodeEquatorial(UT);
                }
                else
                {
                    error            = true;
                    timeErrorMessage = "Warning: equatorial descending node doesn't exist.";
                }
                break;
            }

            if (op == Operation.COURSE_CORRECTION && core.target.NormalTargetExists)
            {
                Orbit correctionPatch = o;
                while (correctionPatch != null)
                {
                    if (correctionPatch.referenceBody == core.target.TargetOrbit.referenceBody)
                    {
                        o  = correctionPatch;
                        UT = correctionPatch.StartUT;
                        break;
                    }
                    correctionPatch = vessel.GetNextPatch(correctionPatch);
                }
            }

            if (error && InvolveGUI)
            {
                GUIStyle s = new GUIStyle(GUI.skin.label);
                s.normal.textColor = Color.yellow;
                GUILayout.Label(timeErrorMessage, s);
            }

            return(UT);
        }