public ManeuverNodeStorage FromManeuverNode(ManeuverNode ManNodeToStore)
 {
     this.DeltaV = ManNodeToStore.DeltaV;
     this.NodeRotation = ManNodeToStore.nodeRotation;
     this.UT = ManNodeToStore.UT;
     return this;
 }
示例#2
0
        public static ManeuverCommand WithNode(ManeuverNode node, FlightComputer f)
        {
            double thrust = FlightCore.GetTotalThrust(f.Vessel);
            double advance = f.Delay;

            if (thrust > 0) {
                advance += (node.DeltaV.magnitude / (thrust / f.Vessel.GetTotalMass())) / 2;
            }

            var newNode = new ManeuverCommand()
            {
                Node = new ManeuverNode()
                {
                    DeltaV = node.DeltaV,
                    patch = node.patch,
                    solver = node.solver,
                    scaledSpaceTarget = node.scaledSpaceTarget,
                    nextPatch = node.nextPatch,
                    UT = node.UT,
                    nodeRotation = node.nodeRotation,
                },
                TimeStamp = node.UT - advance,
            };
            return newNode;
        }
示例#3
0
 internal bool compare(ManeuverNode m)
 {
     if (deltaV.x != m.DeltaV.x || deltaV.y != m.DeltaV.y || deltaV.z != m.DeltaV.z || UT != m.UT) {
         return false;
     }
     return true;
 }
        protected override void AdjustNode(
            ManeuverNode originalNode, Maneuver original, double originalPeriod, double originalMagnitude, ManeuverNode node, double value, double splitDv)
        {
            double fraction;
            double minFraction = 0;
            double maxFraction = 1;

            double targetPeriod = value * 60;

            for(int iteration = 0; iteration < MNSSettings.Instance.splitByPeriodIterations; iteration += 1)
            {
                fraction = (minFraction + maxFraction) / 2;
                Vector3d dv = original.DeltaV * fraction;
                if(node != originalNode)
                {
                    RotateDeltaV(originalNode, node, ref dv);
                }
                node.DeltaV = dv;
                node.solver.UpdateFlightPlan();

                if(node.nextPatch.ApA > 0 && node.nextPatch.period < targetPeriod)
                    minFraction = fraction;
                else
                    maxFraction = fraction;
            }
        }
 public ManeuverNode ToManeuverNode()
 {
     ManeuverNode retManNode = new ManeuverNode();
     retManNode.DeltaV = DeltaV;
     retManNode.nodeRotation = NodeRotation;
     retManNode.UT = UT;
     return retManNode;
 }
示例#6
0
文件: Node.cs 项目: niomaster/KOS
        public Node(Vessel v, ManeuverNode existingNode)
        {
            nodeRef = existingNode;
            vesselRef = v;
            NodeLookup.Add(existingNode, this);

            UpdateValues();
        }
示例#7
0
文件: Node.cs 项目: KSP-KOS/KOS
        private Node(Vessel v, ManeuverNode existingNode, SharedObjects shareObj)
            : this(shareObj)
        {
            nodeRef = existingNode;
            vesselRef = v;

            nodeLookup.Add(existingNode, this);

            FromNodeRef();
        }
示例#8
0
        internal NodeManager(ManeuverNode n)
        {
            curState = new NodeState(n);
            curNodeState = new NodeState();
            node = n;
            updateCurrentNodeState();

            if (n.findNextEncounter() != null) {
                encounter = true;
            }
        }
示例#9
0
        public NodeManager(ManeuverNode n)
        {
            curState = new NodeState(n);
            curNodeState = new NodeState();
            node = n;
            updateCurrentNodeState();

            if(NodeTools.findNextEncounter(n) != null) {
                encounter = true;
            }
        }
 protected override void AdjustNode(
     ManeuverNode originalNode, Maneuver original, double originalPeriod, double originalMagnitude, ManeuverNode node, double value, double splitDv)
 {
     Vector3d dv = original.DeltaV * (value / originalMagnitude);
     if(node != originalNode)
     {
         RotateDeltaV(originalNode, node, ref dv);
     }
     node.DeltaV = dv;
     node.solver.UpdateFlightPlan();
 }
 protected override bool ValidateInput(ManeuverNode originalNode, List<double> inputValues)
 {
     foreach(double input in inputValues)
     {
         if(input <= 0)
         {
             ScreenMessages.PostScreenMessage("Delta-V values must be greater than zero", 6f, ScreenMessageStyle.UPPER_CENTER);
             return false;
         }
     }
     return true;
 }
示例#12
0
文件: Node.cs 项目: niomaster/KOS
        public void AddToVessel(Vessel v)
        {
            if (nodeRef != null) throw new kOSException("Node has already been added");

            vesselRef = v;
            nodeRef = v.patchedConicSolver.AddManeuverNode(Time);

            UpdateNodeDeltaV();

            v.patchedConicSolver.UpdateFlightPlan();

            NodeLookup.Add(nodeRef, this);
        }
示例#13
0
 public static ManeuverCommand WithNode(ManeuverNode node)
 {
     var newNode = new ManeuverCommand()
     {
         Node = new ManeuverNode()
         {
             DeltaV = node.DeltaV,
             patch = node.patch,
             solver = node.solver,
             scaledSpaceTarget = node.scaledSpaceTarget,
             nextPatch = node.nextPatch,
             UT = node.UT,
             nodeRotation = node.nodeRotation,
         },
         TimeStamp = node.UT,
     };
     return newNode;
 }
        public static ManeuverCommand WithNode(int nodeIndex, FlightComputer f)
        {
            double       thrust  = FlightCore.GetTotalThrust(f.Vessel);
            ManeuverNode node    = f.Vessel.patchedConicSolver.maneuverNodes[nodeIndex];
            double       advance = f.Delay;

            if (thrust > 0)
            {
                advance += (node.DeltaV.magnitude / (thrust / f.Vessel.GetTotalMass())) / 2;
                // add 1 second for the throttle down time @ the end of the burn
                advance += 1;
            }

            var newNode = new ManeuverCommand()
            {
                Node      = node,
                TimeStamp = node.UT - advance,
            };

            return(newNode);
        }
示例#15
0
        public override bool Pop(FlightComputer f)
        {
            if (f.Vessel.patchedConicSolver == null)
            {
                f.Vessel.AttachPatchedConicsSolver();
                f.Vessel.patchedConicSolver.Update();
            }

            if (this.Node.solver == null) // need to repair (due to the scenario of 2 vessels within phyical range)
            {
                this.Node = f.Vessel.patchedConicSolver.maneuverNodes.Find(x => x.UT == this.Node.UT);
            }

            var burn = f.ActiveCommands.FirstOrDefault(c => c is BurnCommand);

            if (burn != null)
            {
                f.Remove(burn);
            }

            OriginalDelta        = Node.DeltaV.magnitude;
            RemainingDelta       = this.getRemainingDeltaV(f);
            this.EngineActivated = true;

            double thrustToMass = FlightCore.GetTotalThrust(f.Vessel) / f.Vessel.GetTotalMass();

            if (thrustToMass == 0.0)
            {
                this.EngineActivated = false;
                RTUtil.ScreenMessage("[Flight Computer]: No engine to carry out the maneuver.");
            }
            else
            {
                RemainingTime = RemainingDelta / thrustToMass;
            }

            f.PIDController.setPIDParameters(FlightComputer.PIDKp, FlightComputer.PIDKi, FlightComputer.PIDKd);

            return(true);
        }
        private void UpdateIntuitiveManeuverHandlersList()
        {
            PatchedConicSolver solver = NodeTools.getSolver();

            if (solver != curSolver)
            {
                this.maneuverGizmoHandlers.Clear();
                curSolver = solver;
                if (solver != null)
                {
                    List <ManeuverNode> nodes = solver.maneuverNodes;
                    for (int i = 0; i < nodes.Count; i++)
                    {
                        ManeuverNode node = nodes[i];
                        if ((node.attachedGizmo != null) && !isHandled(node))
                        {
                            this.maneuverGizmoHandlers.Add(new IntuitiveNodeGizmoHandler(this, node, options));
                        }
                    }
                }
            }
        }
示例#17
0
        protected override bool ValidateInput(ManeuverNode originalNode, List <double> inputValues)
        {
            double period = originalNode.patch.period;
            double prior  = period;

            foreach (double input in inputValues)
            {
                if (input * 60 < period)
                {
                    ScreenMessages.PostScreenMessage("Periods must be greater than the current orbital period", 6f, ScreenMessageStyle.UPPER_CENTER);
                    return(false);
                }
                if (!(input * 60 > prior))
                {
                    ScreenMessages.PostScreenMessage("Periods must be listed in increasing order", 6f, ScreenMessageStyle.UPPER_CENTER);
                    return(false);
                }
                prior = input * 60;
            }

            return(true);
        }
示例#18
0
 protected override void reset()
 {
     base.reset();
     if (Working)
     {
         THR.Throttle = 0;
     }
     if (CFG.AT[Attitude.ManeuverNode])
     {
         CFG.AT.On(Attitude.KillRotation);
     }
     CFG.AP1.OffIfOn(Autopilot1.Maneuver);
     Executor.Reset();
     NodeDeltaV         = Vector3d.zero;
     MinDeltaV          = GLB.THR.MinDeltaV;
     min_deltaV         = double.MaxValue;
     within_threshold   = false;
     VSL.Info.Countdown = 0;
     VSL.Info.TTB       = 0;
     Working            = false;
     Node = null;
 }
        protected override bool ValidateInput(ManeuverNode originalNode, List<double> inputValues)
        {
            double apoapsis = originalNode.patch.ApA;
            double prior = apoapsis;

            foreach(double input in inputValues)
            {
                if(input * 1000 < apoapsis)
                {
                    ScreenMessages.PostScreenMessage("Apoapsis values must be greater than the current apoapsis", 6f, ScreenMessageStyle.UPPER_CENTER);
                    return false;
                }
                if(!(input * 1000 > prior))
                {
                    ScreenMessages.PostScreenMessage("Apoapsis values must be listed in increasing order", 6f, ScreenMessageStyle.UPPER_CENTER);
                    return false;
                }
                prior = input * 1000;
            }

            return true;
        }
示例#20
0
        internal static void copyToClipboard(Orbit o, ManeuverNode node)
        {
            string message = "Precise Maneuver Information\r\n";

            message += String.Format("Depart at:      {0}\r\n", convertUTtoHumanTime(node.UT));
            message += String.Format("       UT:      {0:0}\r\n", node.UT);
            double eang = o.getEjectionAngle(node);

            if (!double.IsNaN(eang))
            {
                string e = String.Format("{0:0.00° to prograde;0.00° to retrograde}", o.getEjectionAngle(node));
                message += String.Format("Ejection Angle: {0}\r\n", e);
                e        = String.Format("{0:0.00}°", o.getEjectionInclination(node));
                message += String.Format("Ejection Inc.:  {0}\r\n", e);
            }
            message += String.Format("Prograde Δv:    {0:0.0} m/s\r\n", node.DeltaV.z);
            message += String.Format("Normal Δv:      {0:0.0} m/s\r\n", node.DeltaV.y);
            message += String.Format("Radial Δv:      {0:0.0} m/s\r\n", node.DeltaV.x);
            message += String.Format("Total Δv:       {0:0} m/s", node.DeltaV.magnitude);

            GUIUtility.systemCopyBuffer = message;
        }
        protected override bool ValidateInput(ManeuverNode originalNode, List<double> inputValues)
        {
            double period = originalNode.patch.period;
            double prior = period;

            foreach(double input in inputValues)
            {
                if(input * 60 < period)
                {
                    ScreenMessages.PostScreenMessage("Periods must be greater than the current orbital period", 6f, ScreenMessageStyle.UPPER_CENTER);
                    return false;
                }
                if(!(input * 60 > prior))
                {
                    ScreenMessages.PostScreenMessage("Periods must be listed in increasing order", 6f, ScreenMessageStyle.UPPER_CENTER);
                    return false;
                }
                prior = input * 60;
            }

            return true;
        }
示例#22
0
        protected override bool ValidateInput(ManeuverNode originalNode, List <double> inputValues)
        {
            double apoapsis = originalNode.patch.ApA;
            double prior    = apoapsis;

            foreach (double input in inputValues)
            {
                if (input * 1000 < apoapsis)
                {
                    ScreenMessages.PostScreenMessage("Apoapsis values must be greater than the current apoapsis", 6f, ScreenMessageStyle.UPPER_CENTER);
                    return(false);
                }
                if (!(input * 1000 > prior))
                {
                    ScreenMessages.PostScreenMessage("Apoapsis values must be listed in increasing order", 6f, ScreenMessageStyle.UPPER_CENTER);
                    return(false);
                }
                prior = input * 1000;
            }

            return(true);
        }
示例#23
0
        //If there is a maneuver node on this patch, returns the patch that follows that maneuver node
        //Otherwise, if this patch ends in an SOI transition, returns the patch that follows that transition
        //Otherwise, returns null
        public static Orbit GetNextPatch(this Vessel vessel, Orbit patch, ManeuverNode ignoreNode = null)
        {
            if (patch == null)
            {
                return(null);
            }

            //Determine whether this patch ends in an SOI transition or if it's the final one:
            bool finalPatch = (patch.patchEndTransition == Orbit.PatchTransitionType.FINAL);


            if (vessel.patchedConicSolver == null)
            {
                vessel.patchedConicSolver = vessel.gameObject.AddComponent <PatchedConicSolver>();
                vessel.patchedConicSolver.Load(vessel.flightPlanNode);
            }

            //See if any maneuver nodes occur during this patch. If there is one
            //return the patch that follows it
            var nodes = vessel.patchedConicSolver.maneuverNodes.Slinq().Where((n, p) => n.patch == p && n != ignoreNode, patch);
            // Slinq is nice but you can only enumerate it once
            var first = nodes.FirstOrDefault();

            if (first != null)
            {
                return(first.nextPatch);
            }

            //return the next patch, or null if there isn't one:
            if (!finalPatch)
            {
                return(patch.nextPatch);
            }
            else
            {
                return(null);
            }
        }
示例#24
0
        public void UpdateManeuverNodes(PatchedConicSolver solver)
        {
            if (solver == null)
            {
                return;
            }

            // Avoid flickering by not overwriting nodes where possible

            var maneuversLength = this.Maneuvers == null ? 0 : this.Maneuvers.Length;
            int commonLength    = Math.Min(solver.maneuverNodes.Count, maneuversLength);

            // update the common ones
            for (int i = 0; i < commonLength; i++)
            {
                var node       = solver.maneuverNodes[i];
                var nodeUpdate = this.Maneuvers[i];
                node.UT     = nodeUpdate.UniversalTime;
                node.DeltaV = nodeUpdate.DeltaV;
                node.OnGizmoUpdated(node.DeltaV, node.UT);
            }

            // remove any extra ones
            for (int i = solver.maneuverNodes.Count; i > maneuversLength; i--)
            {
                var node = solver.maneuverNodes[i - 1];
                solver.RemoveManeuverNode(node);
            }

            // add any new ones
            for (int i = solver.maneuverNodes.Count; i < maneuversLength; i++)
            {
                var          maneuver = this.Maneuvers[i];
                ManeuverNode node     = solver.AddManeuverNode(maneuver.UniversalTime);
                node.DeltaV = maneuver.DeltaV;
                node.OnGizmoUpdated(node.DeltaV, node.UT);
            }
        }
示例#25
0
        public void AddToVessel(Vessel v)
        {
            if (nodeRef != null)
            {
                throw new Exception("Node has already been added");
            }

            string careerReason;

            if (!Career.CanMakeNodes(out careerReason))
            {
                throw new KOSLowTechException("use maneuver nodes", careerReason);
            }

            vesselRef = v;
            nodeRef   = v.patchedConicSolver.AddManeuverNode(time);

            UpdateNodeDeltaV();

            v.patchedConicSolver.UpdateFlightPlan();

            nodeLookup.Add(nodeRef, this);
        }
示例#26
0
文件: Node.cs 项目: KSP-KOS/KOS
        public void AddToVessel(Vessel v)
        {
            if (nodeRef != null) throw new Exception("Node has already been added");

            string careerReason;
            if (! Career.CanMakeNodes(out careerReason))
                throw new KOSLowTechException("use maneuver nodes", careerReason);

            vesselRef = v;

            if (v.patchedConicSolver == null)
                throw new KOSSituationallyInvalidException(
                    "A KSP limitation makes it impossible to access the manuever nodes of this vessel at this time. " +
                    "(perhaps it's not the active vessel?)");

            nodeRef = v.patchedConicSolver.AddManeuverNode(time);

            UpdateNodeDeltaV();

            v.patchedConicSolver.UpdateFlightPlan();

            nodeLookup.Add(nodeRef, this);
        }
示例#27
0
        protected void UpdateWidgetColorForCurrentTime(TrackingStationWidget widget)
        {
            ManeuverNode node = this.NextManeuverNodeForVessel(widget.vessel);

            if (node == null)
            {
                return;
            }

            double maneuverTime = node.UT;

            // if the maneuver node is less than 15mins away - yellow
            if (maneuverTime < Planetarium.GetUniversalTime() + ManeuverQueue.minimumManeuverDeltaT)
            {
                this.ApplyColorToVesselWidget(widget, this.nodeWarningColor);
            }

            // if the maneuver nodes is in the past - red
            if (maneuverTime < Planetarium.GetUniversalTime())
            {
                this.ApplyColorToVesselWidget(widget, this.nodePassedColor);
            }
        }
        internal void SearchNewGizmo()
        {
            var solver  = FlightGlobals.ActiveVessel.patchedConicSolver;
            var curList = solver.maneuverNodes.Where(a => a.attachedGizmo != null);
            var tmp     = curList.ToList();

            /* let's see if user is hovering a mouse *
            * over any gizmo. That would be a hint. */
            if (curList.Count(a => a.attachedGizmo.MouseOverGizmo) == 1)
            {
                var node = curList.First(a => a.attachedGizmo.MouseOverGizmo);
                if (node != currentNode)
                {
                    currentNode = node;
                    NotifyNodeChanged();
                }
            }
            else
            {
                /* then, let's see if we can find any     *
                * new gizmos that were created recently. */
                if (prevGizmos != null)
                {
                    curList = curList.Except(prevGizmos);
                }
                if (curList.Count() == 1)
                {
                    var node = curList.First();
                    if (node != currentNode)
                    {
                        currentNode = node;
                        NotifyNodeChanged();
                    }
                }
            }
            prevGizmos = tmp;
        }
        public static ManeuverNode PlaceManeuverNode(Vessel vessel, Orbit patch, Vector3d dV, double UT)
        {
            if (vessel.patchedConicsUnlocked())
            {
                //placing a maneuver node with bad dV values can really mess up the game, so try to protect against that
                //and log an exception if we get a bad dV vector:
                for (int i = 0; i < 3; i++)
                {
                    if (double.IsNaN(dV[i]) || double.IsInfinity(dV[i]))
                    {
                        throw new Exception("VesselExtensions.PlaceManeuverNode: bad dV: " + dV);
                    }
                }

                if (double.IsNaN(UT) || double.IsInfinity(UT))
                {
                    throw new Exception("VesselExtensions.PlaceManeuverNode: bad UT: " + UT);
                }

                //It seems that sometimes the game can freak out if you place a maneuver node in the past, so this
                //protects against that.
                UT = Math.Max(UT, Planetarium.GetUniversalTime());

                //convert a dV in world coordinates into the coordinate system of the maneuver node,
                //which uses (x, y, z) = (radial+, normal-, prograde)
                Vector3d nodeDV = patch.DeltaVToManeuverNodeCoordinates(UT, dV);

                ManeuverNode mn = vessel.patchedConicSolver.AddManeuverNode(UT);
                mn.DeltaV = nodeDV;
                vessel.patchedConicSolver.UpdateFlightPlan();
                return(mn);
            }
            else
            {
                return(null);
            }
        }
 private bool update_maneuver_node()
 {
     Node        = null;
     NodeCB      = null;
     TargetOrbit = null;
     if (Solver != null)
     {
         if (Solver.maneuverNodes.Count <= 0)
         {
             return(false);
         }
         Node = Solver.maneuverNodes[0];
     }
     else
     {
         if (VSL.vessel.flightPlanNode.nodes.Count <= 0)
         {
             return(false);
         }
         var node = VSL.vessel.flightPlanNode.nodes[0];
         Node = new ManeuverNode();
         Node.Load(node);
         Node.patch     = new Orbit(VSL.orbit);
         Node.nextPatch =
             TrajectoryCalculator.NewOrbit(VSL.orbit, Utils.Node2OrbitalDeltaV(Node), Node.UT);
         VSL.vessel.flightPlanNode.RemoveNode(node);
     }
     NodeCB      = Node.patch.referenceBody;
     TargetOrbit = Node.nextPatch;
     update_node_deltaV();
     if (VSL.Engines.MaxDeltaV < Node.DeltaV.magnitude)
     {
         Status(Colors.Warning,
                "WARNING: there may be not enough propellant for the maneuver");
     }
     return(true);
 }
示例#31
0
 ReferenceFrame(
     ReferenceFrameType type, global::CelestialBody body = null, global::Vessel vessel = null,
     ManeuverNode node             = null, Part part             = null, ModuleDockingNode dockingPort = null,
     Thruster thruster             = null, ReferenceFrame parent = null,
     ReferenceFrame hybridPosition = null, ReferenceFrame hybridRotation        = null,
     ReferenceFrame hybridVelocity = null, ReferenceFrame hybridAngularVelocity = null)
 {
     this.type = type;
     this.body = body;
     vesselId  = vessel != null ? vessel.id : Guid.Empty;
     this.node = node;
     //TODO: is it safe to use a part id of 0 to mean no part?
     if (part != null)
     {
         partId = part.flightID;
     }
     this.dockingPort           = dockingPort;
     this.thruster              = thruster;
     this.parent                = parent;
     this.hybridPosition        = hybridPosition;
     this.hybridRotation        = hybridRotation;
     this.hybridVelocity        = hybridVelocity;
     this.hybridAngularVelocity = hybridAngularVelocity;
 }
示例#32
0
        //Draws the gauge textures to the screen
        private void PaintGauge(ManeuverNode node)
        {
            //Draw the face (background)
            GUI.DrawTextureWithTexCoords(new Rect(0f, 0f, 400f * Scale, 407f * Scale), texture, new Rect(0f, 0f, 0.5f, 0.499f));
            //PatchedConicSolver PCS = FlightGlobals.ActiveVessel.patchedConicSolver;
            //Draw the dV needle
            drawNeedle();
            //Draw  the digital readouts
            drawNumbers(node);

            //Draw the bezel, if selected
            if (SteamGauges.drawBezels)
            {
                GUI.DrawTextureWithTexCoords(new Rect(0f, 0f, 400f * Scale, 407f * Scale), texture, new Rect(0f, 0.5f, 0.5f, 0.5f));
            }
            //Draw the casing (foreground)
            GUI.DrawTextureWithTexCoords(new Rect(0f, 0f, 400f * Scale, 407f * Scale), texture, new Rect(0.5f, 0.5f, 0.5f, 0.5f));

            //Draw the buttons
            if (autoBurn)
            {
                GUI.DrawTextureWithTexCoords(burn_toggle, texture, new Rect(0.5800f, 0.3649f, 0.08625f, 0.0553f));  //Green Burn
            }
            else
            {
                GUI.DrawTextureWithTexCoords(burn_toggle, texture, new Rect(0.6713f, 0.3649f, 0.08625f, 0.0553f));  //Grey Burn
            }
            if (autoShutdown)
            {
                GUI.DrawTextureWithTexCoords(shutdown_toggle, texture, new Rect(0.7625f, 0.3649f, 0.08625f, 0.0553f));  //Green Stop
            }
            else
            {
                GUI.DrawTextureWithTexCoords(shutdown_toggle, texture, new Rect(0.8563f, 0.3649f, 0.08625f, 0.0553f));  //Grey Stop
            }
        }
示例#33
0
        void UpdateManeuverNode()
        {
            if (vessel.patchedConicSolver != null)
            {
                node = vessel.patchedConicSolver.maneuverNodes.Count > 0 ? vessel.patchedConicSolver.maneuverNodes[0] : null;

                if (node != null)
                {
                    nodeOrbit = node.nextPatch;
                }
                else
                {
                    nodeOrbit = null;
                }
            }
            else
            {
                node      = null;
                nodeOrbit = null;
            }
            nodeDV         = -1.0;
            maneuverVector = Vector3d.zero;
            maneuverNodeComponentVector = Vector3d.zero;
        }
示例#34
0
        //If there is a maneuver node on this patch, returns the patch that follows that maneuver node
        //Otherwise, if this patch ends in an SOI transition, returns the patch that follows that transition
        //Otherwise, returns null
        public static Orbit GetNextPatch(this Vessel vessel, Orbit patch, ManeuverNode ignoreNode = null)
        {
            //Determine whether this patch ends in an SOI transition or if it's the final one:
            bool finalPatch = (patch.patchEndTransition == Orbit.PatchTransitionType.FINAL);

            //See if any maneuver nodes occur during this patch. If there is one
            //return the patch that follows it
            var nodes = vessel.patchedConicSolver.maneuverNodes.Where(n => (n.patch == patch && n != ignoreNode));

            if (nodes.Count() > 0)
            {
                return(nodes.First().nextPatch);
            }

            //return the next patch, or null if there isn't one:
            if (!finalPatch)
            {
                return(patch.nextPatch);
            }
            else
            {
                return(null);
            }
        }
示例#35
0
        /// <summary>
        /// Gets the ejection angle of the current maneuver node.
        /// </summary>
        /// <returns>The ejection angle in degrees.  Positive results are the angle from prograde, negative results are the angle from retrograde.</returns>
        /// <param name="nodeUT">Kerbal Space Program Universal Time.</param>
        internal static double getEjectionAngle(this Orbit o, ManeuverNode node)
        {
            if (node.nextPatch.patchEndTransition == Orbit.PatchTransitionType.ESCAPE)
            {
                CelestialBody body = o.referenceBody;

                // Calculate the angle between the node's position and the reference body's velocity at nodeUT
                Vector3d prograde = body.orbit.getOrbitalVelocityAtUT(node.UT);
                Vector3d position = o.getRelativePositionAtUT(node.UT);
                double   eangle   = ((Math.Atan2(prograde.y, prograde.x) - Math.Atan2(position.y, position.x)) * 180.0 / Math.PI).Angle360();

                // Correct to angle from retrograde if needed.
                if (eangle > 180)
                {
                    eangle = 180 - eangle;
                }

                return(eangle);
            }
            else
            {
                return(double.NaN);
            }
        }
        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("-o", GUILayout.ExpandWidth(false)))
            {
                node.OnGizmoUpdated(node.DeltaV, node.UT - node.patch.period);
            }
            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);
            }
            if (GUILayout.Button("+o", GUILayout.ExpandWidth(false)))
            {
                node.OnGizmoUpdated(node.DeltaV, node.UT + node.patch.period);
            }
            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);
        }
示例#37
0
 /// <summary>
 /// Remove a maneuver node from the flight plane.
 /// </summary>
 /// <param name="node">The maneuver node to be removed.</param>
 public extern void RemoveManeuverNode(ManeuverNode node);
 protected void LogNode(string message, ManeuverNode node)
 {
     #if DEBUG
     //Quaternion rot = node.nodeRotation;
     //Vector3 angles = rot.eulerAngles;
     Orbit orbit = node.nextPatch;
     Debug.Log(string.Format("{0} Node dv:{1} ut:{2} next per:{3} per:{4}", message, node.DeltaV.magnitude, node.UT, node.nextPatch.period, node.patch.period));
     //Debug.Log(string.Format("{0} Quat w:{1} x:{2} y:{3} z:{4}", message, rot.w, rot.x, rot.y, rot.z));
     //Debug.Log(string.Format("{0} Euler x:{1} y:{2} z:{3}", message, angles.x, angles.y, angles.z));
     Debug.Log(string.Format("{0} Orbit inc:{1} ecc:{2} sma:{3} end:{4}", message, orbit.inclination, orbit.eccentricity, orbit.semiMajorAxis, orbit.patchEndTransition));
     #endif
 }
示例#39
0
文件: Node.cs 项目: niomaster/KOS
 public static Node FromExisting(Vessel v, ManeuverNode existingNode)
 {
     return NodeLookup.ContainsKey(existingNode) ? NodeLookup[existingNode] : new Node(v, existingNode);
 }
示例#40
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);
        }
示例#41
0
 internal NodeState(ManeuverNode m)
 {
     deltaV = new Vector3d(m.DeltaV.x, m.DeltaV.y, m.DeltaV.z);
     UT     = m.UT;
 }
        protected void MaintainAerobrakeNode()
        {
            if (makeAerobrakeNodes)
            {
                //Remove node after finishing aerobraking:
                if (aerobrakeNode != null && vessel.patchedConicSolver.maneuverNodes.Contains(aerobrakeNode))
                {
                    if (aerobrakeNode.UT < vesselState.time && vesselState.altitudeASL > mainBody.RealMaxAtmosphereAltitude())
                    {
                        vessel.patchedConicSolver.RemoveManeuverNode(aerobrakeNode);
                        aerobrakeNode = null;
                    }
                }

                //Update or create node if necessary:
                ReentrySimulation.Result r = GetResult();
                if (r != null && r.outcome == ReentrySimulation.Outcome.AEROBRAKED)
                {
                    //Compute the node dV:
                    Orbit preAerobrakeOrbit = GetReenteringPatch();

                    //Put the node at periapsis, unless we're past periapsis. In that case put the node at the current time.
                    double UT;
                    if (preAerobrakeOrbit == orbit &&
                        vesselState.altitudeASL < mainBody.RealMaxAtmosphereAltitude() && vesselState.speedVertical > 0)
                    {
                        UT = vesselState.time;
                    }
                    else
                    {
                        UT = preAerobrakeOrbit.NextPeriapsisTime(preAerobrakeOrbit.StartUT);
                    }

                    Orbit postAerobrakeOrbit = MuUtils.OrbitFromStateVectors(r.WorldEndPosition(), r.WorldEndVelocity(), r.body, r.endUT);

                    Vector3d dV = OrbitalManeuverCalculator.DeltaVToChangeApoapsis(preAerobrakeOrbit, UT, postAerobrakeOrbit.ApR);

                    if (aerobrakeNode != null && vessel.patchedConicSolver.maneuverNodes.Contains(aerobrakeNode))
                    {
                        //update the existing node
                        Vector3d nodeDV = preAerobrakeOrbit.DeltaVToManeuverNodeCoordinates(UT, dV);
                        aerobrakeNode.OnGizmoUpdated(nodeDV, UT);
                    }
                    else
                    {
                        //place a new node
                        aerobrakeNode = vessel.PlaceManeuverNode(preAerobrakeOrbit, dV, UT);
                    }
                }
                else
                {
                    //no aerobraking, remove the node:
                    if (aerobrakeNode != null && vessel.patchedConicSolver.maneuverNodes.Contains(aerobrakeNode))
                    {
                        vessel.patchedConicSolver.RemoveManeuverNode(aerobrakeNode);
                    }
                }
            }
            else
            {
                //Remove aerobrake node when it is turned off:
                if (aerobrakeNode != null && vessel.patchedConicSolver.maneuverNodes.Contains(aerobrakeNode))
                {
                    vessel.patchedConicSolver.RemoveManeuverNode(aerobrakeNode);
                }
            }
        }
示例#43
0
 internal static double getEjectionInclination(this Orbit o, ManeuverNode node)
 {
     if (node.nextPatch.patchEndTransition == Orbit.PatchTransitionType.ESCAPE) {
         CelestialBody body = o.referenceBody;
         Orbit bodyOrbit = body.orbit;
         Orbit orbitAfterEscape = node.nextPatch.nextPatch;
         return bodyOrbit.getRelativeInclination(orbitAfterEscape);
     } else {
         return double.NaN;
     }
 }
        // Analysis disable once UnusedParameter
        public bool RenderOrbit(RenderTexture screen, float cameraAspect)
        {
            if (!startupComplete || HighLogic.LoadedSceneIsEditor)
            {
                return(false);
            }
            // Make sure the parameters fit on the screen.
            Vector4 displayPosition = orbitDisplayPosition;

            displayPosition.z = Mathf.Min(screen.width - displayPosition.x, displayPosition.z);
            displayPosition.w = Mathf.Min(screen.height - displayPosition.y, displayPosition.w);

            // Here is our pixel budget in each direction:
            double horizPixelSize = displayPosition.z - iconPixelSize;
            double vertPixelSize  = displayPosition.w - iconPixelSize;

            // Find a basis for transforming values into the framework of
            // vessel.orbit.  The rendering framework assumes the periapsis
            // is drawn directly to the right of the mainBody center of mass.
            // It assumes the orbit's prograde direction is "up" (screen
            // relative) at the periapsis, providing a counter-clockwise
            // motion for vessel.
            // Once we have the basic transform, we will add in scalars
            // that will ultimately transform an arbitrary point (relative to
            // the planet's center) into screen space.
            Matrix4x4 screenTransform = Matrix4x4.identity;
            double    now             = Planetarium.GetUniversalTime();
            double    timeAtPe        = vessel.orbit.NextPeriapsisTime(now);

            // Get the 3 direction vectors, based on Pe being on the right of the screen
            // OrbitExtensions provides handy utilities to get these.
            Vector3d right   = vessel.orbit.Up(timeAtPe);
            Vector3d forward = vessel.orbit.SwappedOrbitNormal();
            // MOARdV: OrbitExtensions.Horizontal is unstable.  I've seen it
            // become (0, 0, 0) intermittently in flight.  Instead, use the
            // cross product of the other two.
            // We flip the sign of this vector because we are using an inverted
            // y coordinate system to keep the icons right-side up.
            Vector3d up = -Vector3d.Cross(forward, right);

            //Vector3d up = -vessel.orbit.Horizontal(timeAtPe);

            screenTransform.SetRow(0, new Vector4d(right.x, right.y, right.z, 0.0));
            screenTransform.SetRow(1, new Vector4d(up.x, up.y, up.z, 0.0));
            screenTransform.SetRow(2, new Vector4d(forward.x, forward.y, forward.z, 0.0));

            // Figure out our bounds.  First, make sure the entire planet
            // fits on the screen.  We define the center of the vessel.mainBody
            // as the origin of our coodinate system.
            double maxX = vessel.mainBody.Radius;
            double minX = -maxX;
            double maxY = maxX;
            double minY = -maxX;

            if (vessel.mainBody.atmosphere)
            {
                maxX += vessel.mainBody.maxAtmosphereAltitude;
                minX  = -maxX;
                maxY  = maxX;
                minY  = -maxX;
            }

            // Now make sure the entire orbit fits on the screen.
            Vector3 vesselPos;

            // The PeR, ApR, and semiMinorAxis are all one dimensional, so we
            // can just apply them directly to these values.
            maxX = Math.Max(maxX, vessel.orbit.PeR);
            if (vessel.orbit.eccentricity < 1.0)
            {
                minX = Math.Min(minX, -vessel.orbit.ApR);

                maxY = Math.Max(maxY, vessel.orbit.semiMinorAxis);
                minY = Math.Min(minY, -vessel.orbit.semiMinorAxis);
            }
            else if (vessel.orbit.EndUT > 0.0)
            {
                // If we're hyperbolic, let's get the SoI transition
                vesselPos = screenTransform.MultiplyPoint3x4(vessel.orbit.SwappedRelativePositionAtUT(vessel.orbit.EndUT));
                maxX      = Math.Max(maxX, vesselPos.x);
                minX      = Math.Min(minX, vesselPos.x);
                maxY      = Math.Max(maxY, vesselPos.y);
                minY      = Math.Min(minY, vesselPos.y);
            }

            // Make sure the vessel shows up on-screen.  Since a hyperbolic
            // orbit doesn't have a meaningful ApR, we use this as a proxy for
            // how far we need to extend the bounds to show the vessel.
            vesselPos = screenTransform.MultiplyPoint3x4(vessel.orbit.SwappedRelativePositionAtUT(now));
            maxX      = Math.Max(maxX, vesselPos.x);
            minX      = Math.Min(minX, vesselPos.x);
            maxY      = Math.Max(maxY, vesselPos.y);
            minY      = Math.Min(minY, vesselPos.y);

            // Account for a target vessel
            var targetBody   = FlightGlobals.fetch.VesselTarget as CelestialBody;
            var targetVessel = FlightGlobals.fetch.VesselTarget as Vessel;

            if (targetVessel != null && targetVessel.mainBody != vessel.mainBody)
            {
                // We only care about tgtVessel if it is in the same SoI.
                targetVessel = null;
            }
            if (targetVessel != null && !targetVessel.LandedOrSplashed)
            {
                if (targetVessel.mainBody == vessel.mainBody)
                {
                    double tgtPe = targetVessel.orbit.NextPeriapsisTime(now);

                    vesselPos = screenTransform.MultiplyPoint3x4(targetVessel.orbit.SwappedRelativePositionAtUT(tgtPe));
                    maxX      = Math.Max(maxX, vesselPos.x);
                    minX      = Math.Min(minX, vesselPos.x);
                    maxY      = Math.Max(maxY, vesselPos.y);
                    minY      = Math.Min(minY, vesselPos.y);

                    if (targetVessel.orbit.eccentricity < 1.0)
                    {
                        vesselPos = screenTransform.MultiplyPoint3x4(targetVessel.orbit.SwappedRelativePositionAtUT(targetVessel.orbit.NextApoapsisTime(now)));
                        maxX      = Math.Max(maxX, vesselPos.x);
                        minX      = Math.Min(minX, vesselPos.x);
                        maxY      = Math.Max(maxY, vesselPos.y);
                        minY      = Math.Min(minY, vesselPos.y);
                    }

                    vesselPos = screenTransform.MultiplyPoint3x4(targetVessel.orbit.SwappedRelativePositionAtUT(now));
                    maxX      = Math.Max(maxX, vesselPos.x);
                    minX      = Math.Min(minX, vesselPos.x);
                    maxY      = Math.Max(maxY, vesselPos.y);
                    minY      = Math.Min(minY, vesselPos.y);
                }
            }

            if (targetBody != null)
            {
                // Validate some values up front, so we don't need to test them later.
                if (targetBody.GetOrbit() == null)
                {
                    targetBody = null;
                }
                else if (targetBody.orbit.referenceBody == vessel.orbit.referenceBody)
                {
                    // If the target body orbits our current world, let's at
                    // least make sure the body's location is visible.
                    vesselPos = screenTransform.MultiplyPoint3x4(targetBody.GetOrbit().SwappedRelativePositionAtUT(now));
                    maxX      = Math.Max(maxX, vesselPos.x);
                    minX      = Math.Min(minX, vesselPos.x);
                    maxY      = Math.Max(maxY, vesselPos.y);
                    minY      = Math.Min(minY, vesselPos.y);
                }
            }

            ManeuverNode node = (vessel.patchedConicSolver.maneuverNodes.Count > 0) ? vessel.patchedConicSolver.maneuverNodes[0] : null;

            if (node != null)
            {
                double nodePe = node.nextPatch.NextPeriapsisTime(now);
                vesselPos = screenTransform.MultiplyPoint3x4(node.nextPatch.SwappedRelativePositionAtUT(nodePe));
                maxX      = Math.Max(maxX, vesselPos.x);
                minX      = Math.Min(minX, vesselPos.x);
                maxY      = Math.Max(maxY, vesselPos.y);
                minY      = Math.Min(minY, vesselPos.y);

                if (node.nextPatch.eccentricity < 1.0)
                {
                    double nodeAp = node.nextPatch.NextApoapsisTime(now);
                    vesselPos = screenTransform.MultiplyPoint3x4(node.nextPatch.SwappedRelativePositionAtUT(nodeAp));
                    maxX      = Math.Max(maxX, vesselPos.x);
                    minX      = Math.Min(minX, vesselPos.x);
                    maxY      = Math.Max(maxY, vesselPos.y);
                    minY      = Math.Min(minY, vesselPos.y);
                }
                else if (node.nextPatch.EndUT > 0.0)
                {
                    // If the next patch is hyperbolic, include the endpoint.
                    vesselPos = screenTransform.MultiplyPoint3x4(vessel.orbit.SwappedRelativePositionAtUT(node.nextPatch.EndUT));
                    maxX      = Math.Max(maxX, vesselPos.x);
                    minX      = Math.Min(minX, vesselPos.x);
                    maxY      = Math.Max(maxY, vesselPos.y);
                    minY      = Math.Min(minY, vesselPos.y);
                }
            }

            // Add translation.  This will ensure that all of the features
            // under consideration above will be displayed.
            screenTransform[0, 3] = -0.5f * (float)(maxX + minX);
            screenTransform[1, 3] = -0.5f * (float)(maxY + minY);

            double neededWidth  = maxX - minX;
            double neededHeight = maxY - minY;

            // Pick a scalar that will fit the bounding box we just created.
            float pixelScalar = (float)Math.Min(horizPixelSize / neededWidth, vertPixelSize / neededHeight);

            screenTransform = Matrix4x4.Scale(new Vector3(pixelScalar, pixelScalar, pixelScalar)) * screenTransform;

            GL.Clear(true, true, backgroundColorValue);
            GL.PushMatrix();
            GL.LoadPixelMatrix(-displayPosition.z * 0.5f, displayPosition.z * 0.5f, displayPosition.w * 0.5f, -displayPosition.w * 0.5f);
            GL.Viewport(new Rect(displayPosition.x, screen.height - displayPosition.y - displayPosition.w, displayPosition.z, displayPosition.w));

            lineMaterial.SetPass(0);
            GL.Begin(GL.LINES);

            // Draw the planet:
            Vector3 focusCenter = screenTransform.MultiplyPoint3x4(new Vector3(0.0f, 0.0f, 0.0f));

            // orbitDriver is null on the sun, so we'll just use white instead.
            GL.Color((vessel.mainBody.orbitDriver == null) ? new Color(1.0f, 1.0f, 1.0f) : vessel.mainBody.orbitDriver.orbitColor);
            DrawCircle(focusCenter.x, focusCenter.y, (float)(vessel.mainBody.Radius * pixelScalar), orbitPoints);
            if (vessel.mainBody.atmosphere)
            {
                // Use the atmospheric ambient to color the atmosphere circle.
                GL.Color(vessel.mainBody.atmosphericAmbientColor);

                DrawCircle(focusCenter.x, focusCenter.y, (float)((vessel.mainBody.Radius + vessel.mainBody.maxAtmosphereAltitude) * pixelScalar), orbitPoints);
            }

            if (targetVessel != null && !targetVessel.LandedOrSplashed)
            {
                GL.Color(iconColorTargetValue);
                if (!targetVessel.orbit.activePatch && targetVessel.orbit.eccentricity < 1.0 && targetVessel.orbit.referenceBody == vessel.orbit.referenceBody)
                {
                    // For some reason, activePatch is false for targetVessel.
                    // If we have a stable orbit for the target, use a fallback
                    // rendering method:
                    ReallyDrawOrbit(targetVessel.orbit, vessel.orbit.referenceBody, screenTransform, orbitPoints);
                }
                else
                {
                    DrawOrbit(targetVessel.orbit, vessel.orbit.referenceBody, screenTransform, orbitPoints);
                }
            }

            foreach (CelestialBody moon in vessel.orbit.referenceBody.orbitingBodies)
            {
                if (moon != targetBody)
                {
                    GL.Color(moon.orbitDriver.orbitColor);
                    ReallyDrawOrbit(moon.GetOrbit(), vessel.orbit.referenceBody, screenTransform, orbitPoints);
                }
            }

            if (targetBody != null)
            {
                GL.Color(iconColorTargetValue);
                ReallyDrawOrbit(targetBody.GetOrbit(), vessel.orbit.referenceBody, screenTransform, orbitPoints);
            }

            if (node != null)
            {
                GL.Color(orbitColorNextNodeValue);
                DrawOrbit(node.nextPatch, vessel.orbit.referenceBody, screenTransform, orbitPoints);
            }

            if (vessel.orbit.nextPatch != null && vessel.orbit.nextPatch.activePatch)
            {
                GL.Color(orbitColorNextNodeValue);
                DrawOrbit(vessel.orbit.nextPatch, vessel.orbit.referenceBody, screenTransform, orbitPoints);
            }

            // Draw the vessel orbit
            GL.Color(orbitColorSelfValue);
            DrawOrbit(vessel.orbit, vessel.orbit.referenceBody, screenTransform, orbitPoints);

            // Done drawing lines.  Reset color to white, so we don't mess up anyone else.
            GL.Color(Color.white);
            GL.End();

            // Draw target vessel icons.
            Vector3 transformedPosition;

            foreach (CelestialBody moon in vessel.orbit.referenceBody.orbitingBodies)
            {
                if (moon != targetBody)
                {
                    transformedPosition = screenTransform.MultiplyPoint3x4(moon.getTruePositionAtUT(now) - vessel.orbit.referenceBody.getTruePositionAtUT(now));
                    DrawIcon(transformedPosition.x, transformedPosition.y, VesselType.Unknown, moon.orbitDriver.orbitColor, MapIcons.OtherIcon.PLANET);
                }
            }

            if (targetVessel != null || targetBody != null)
            {
                var orbit = (targetVessel != null) ? targetVessel.GetOrbit() : targetBody.GetOrbit();

                double tClosestApproach, dClosestApproach;

                if (targetVessel != null && targetVessel.LandedOrSplashed)
                {
                    orbit = JUtil.ClosestApproachSrfOrbit(vessel.orbit, targetVessel, out tClosestApproach, out dClosestApproach);
                }
                else
                {
                    dClosestApproach = JUtil.GetClosestApproach(vessel.orbit, orbit, out tClosestApproach);

                    DrawNextPe(orbit, vessel.orbit.referenceBody, now, iconColorTargetValue, screenTransform);
                    DrawNextAp(orbit, vessel.orbit.referenceBody, now, iconColorTargetValue, screenTransform);
                }

                if (targetBody != null)
                {
                    transformedPosition = screenTransform.MultiplyPoint3x4(targetBody.getTruePositionAtUT(now) - vessel.orbit.referenceBody.getTruePositionAtUT(now));
                    DrawIcon(transformedPosition.x, transformedPosition.y, VesselType.Unknown, iconColorTargetValue, MapIcons.OtherIcon.PLANET);
                }
                else
                {
                    transformedPosition = screenTransform.MultiplyPoint3x4(orbit.SwappedRelativePositionAtUT(now));
                    DrawIcon(transformedPosition.x, transformedPosition.y, targetVessel.vesselType, iconColorTargetValue);
                }

                if (vessel.orbit.AscendingNodeExists(orbit))
                {
                    double anTime = vessel.orbit.TimeOfAscendingNode(orbit, now);
                    if (anTime < vessel.orbit.EndUT || (vessel.orbit.patchEndTransition != Orbit.PatchTransitionType.ESCAPE && vessel.orbit.patchEndTransition != Orbit.PatchTransitionType.ENCOUNTER))
                    {
                        transformedPosition = screenTransform.MultiplyPoint3x4(vessel.orbit.SwappedRelativePositionAtUT(anTime));
                        DrawIcon(transformedPosition.x, transformedPosition.y, VesselType.Unknown, orbitColorSelfValue, MapIcons.OtherIcon.AN);
                    }
                }
                if (vessel.orbit.DescendingNodeExists(orbit))
                {
                    double dnTime = vessel.orbit.TimeOfDescendingNode(orbit, now);
                    if (dnTime < vessel.orbit.EndUT || (vessel.orbit.patchEndTransition != Orbit.PatchTransitionType.ESCAPE && vessel.orbit.patchEndTransition != Orbit.PatchTransitionType.ENCOUNTER))
                    {
                        transformedPosition = screenTransform.MultiplyPoint3x4(vessel.orbit.SwappedRelativePositionAtUT(dnTime));
                        DrawIcon(transformedPosition.x, transformedPosition.y, VesselType.Unknown, orbitColorSelfValue, MapIcons.OtherIcon.DN);
                    }
                }

                Orbit o = GetPatchAtUT(vessel.orbit, tClosestApproach);
                if (o != null)
                {
                    Vector3d encounterPosition = o.SwappedRelativePositionAtUT(tClosestApproach) + o.referenceBody.getTruePositionAtUT(tClosestApproach) - vessel.orbit.referenceBody.getTruePositionAtUT(tClosestApproach);
                    transformedPosition = screenTransform.MultiplyPoint3x4(encounterPosition);
                    DrawIcon(transformedPosition.x, transformedPosition.y, VesselType.Unknown, iconColorClosestApproachValue, MapIcons.OtherIcon.SHIPATINTERCEPT);
                }

                // Unconditionally try to draw the closest approach point on
                // the target orbit.
                transformedPosition = screenTransform.MultiplyPoint3x4(orbit.SwappedRelativePositionAtUT(tClosestApproach));
                DrawIcon(transformedPosition.x, transformedPosition.y, VesselType.Unknown, iconColorClosestApproachValue, MapIcons.OtherIcon.TGTATINTERCEPT);
            }
            else
            {
                if (vessel.orbit.AscendingNodeEquatorialExists())
                {
                    double anTime = vessel.orbit.TimeOfAscendingNodeEquatorial(now);
                    if (anTime < vessel.orbit.EndUT || (vessel.orbit.patchEndTransition != Orbit.PatchTransitionType.ESCAPE && vessel.orbit.patchEndTransition != Orbit.PatchTransitionType.ENCOUNTER))
                    {
                        transformedPosition = screenTransform.MultiplyPoint3x4(vessel.orbit.SwappedRelativePositionAtUT(anTime));
                        DrawIcon(transformedPosition.x, transformedPosition.y, VesselType.Unknown, orbitColorSelfValue, MapIcons.OtherIcon.AN);
                    }
                }
                if (vessel.orbit.DescendingNodeEquatorialExists())
                {
                    double dnTime = vessel.orbit.TimeOfDescendingNodeEquatorial(now);
                    if (dnTime < vessel.orbit.EndUT || (vessel.orbit.patchEndTransition != Orbit.PatchTransitionType.ESCAPE && vessel.orbit.patchEndTransition != Orbit.PatchTransitionType.ENCOUNTER))
                    {
                        transformedPosition = screenTransform.MultiplyPoint3x4(vessel.orbit.SwappedRelativePositionAtUT(dnTime));
                        DrawIcon(transformedPosition.x, transformedPosition.y, VesselType.Unknown, orbitColorSelfValue, MapIcons.OtherIcon.DN);
                    }
                }
            }

            // Draw orbital features
            DrawNextPe(vessel.orbit, vessel.orbit.referenceBody, now, iconColorPEValue, screenTransform);

            DrawNextAp(vessel.orbit, vessel.orbit.referenceBody, now, iconColorAPValue, screenTransform);

            if (vessel.orbit.nextPatch != null && vessel.orbit.nextPatch.activePatch)
            {
                transformedPosition = screenTransform.MultiplyPoint3x4(vessel.orbit.SwappedRelativePositionAtUT(vessel.orbit.EndUT));
                DrawIcon(transformedPosition.x, transformedPosition.y, VesselType.Unknown, orbitColorSelfValue, MapIcons.OtherIcon.EXITSOI);

                Orbit nextPatch = vessel.orbit.nextPatch.nextPatch;
                if (nextPatch != null && nextPatch.activePatch)
                {
                    transformedPosition = screenTransform.MultiplyPoint3x4(nextPatch.SwappedRelativePositionAtUT(nextPatch.EndUT) + nextPatch.referenceBody.getTruePositionAtUT(nextPatch.EndUT) - vessel.orbit.referenceBody.getTruePositionAtUT(nextPatch.EndUT));
                    DrawIcon(transformedPosition.x, transformedPosition.y, VesselType.Unknown, orbitColorNextNodeValue, MapIcons.OtherIcon.EXITSOI);
                }
            }

            if (node != null && node.nextPatch.activePatch)
            {
                DrawNextPe(node.nextPatch, vessel.orbit.referenceBody, now, orbitColorNextNodeValue, screenTransform);

                DrawNextAp(node.nextPatch, vessel.orbit.referenceBody, now, orbitColorNextNodeValue, screenTransform);

                transformedPosition = screenTransform.MultiplyPoint3x4(vessel.orbit.SwappedRelativePositionAtUT(node.UT));
                DrawIcon(transformedPosition.x, transformedPosition.y, VesselType.Unknown, orbitColorNextNodeValue, MapIcons.OtherIcon.NODE);
            }

            // Draw ownship icon
            transformedPosition = screenTransform.MultiplyPoint3x4(vessel.orbit.SwappedRelativePositionAtUT(now));
            DrawIcon(transformedPosition.x, transformedPosition.y, vessel.vesselType, iconColorSelfValue);

            GL.PopMatrix();
            GL.Viewport(new Rect(0, 0, screen.width, screen.height));

            return(true);
        }
示例#45
0
 public static Node FromExisting(Vessel v, ManeuverNode existingNode, SharedObjects shared)
 {
     return(nodeLookup.ContainsKey(existingNode) ? nodeLookup[existingNode] : new Node(v, existingNode, shared));
 }
示例#46
0
        protected override void AdjustNode(
            ManeuverNode originalNode, Maneuver original, double originalPeriod, double originalMagnitude, ManeuverNode node, double value, double splitDv)
        {
            double fraction;
            double minFraction = 0;
            double maxFraction = 1;

            double targetApo = value * 1000;

            for (int iteration = 0; iteration < HighLogic.CurrentGame.Parameters.CustomParams <MNS>().splitByApoIterations; iteration += 1)
            {
                fraction = (minFraction + maxFraction) / 2;
                Vector3d dv = original.DeltaV * fraction;
                if (node != originalNode)
                {
                    RotateDeltaV(originalNode, node, ref dv);
                }
                node.DeltaV = dv;
                node.solver.UpdateFlightPlan();

                if (node.nextPatch.ApA > 0 && node.nextPatch.ApA < targetApo)
                {
                    minFraction = fraction;
                }
                else
                {
                    maxFraction = fraction;
                }
            }
        }
 /// <summary>
 /// Remove a maneuver node from the flight plane.
 /// </summary>
 /// <param name="node">The maneuver node to be removed.</param>
 public extern void RemoveManeuverNode(ManeuverNode node);
示例#48
0
        internal void createManeuverNode(PatchedConicSolver p)
        {
            ManeuverNode newnode = p.AddManeuverNode(UT);

            newnode.OnGizmoUpdated(deltaV, UT);
        }
        public override void OnFixedUpdate()
        {
            if (!vessel.patchedConicsUnlocked() || !vessel.patchedConicSolver.maneuverNodes.Any())
            {
                Abort();
                return;
            }

            //check if we've finished a node:
            ManeuverNode node   = vessel.patchedConicSolver.maneuverNodes.First();
            double       dVLeft = node.GetBurnVector(orbit).magnitude;

            if (dVLeft < tolerance && core.attitude.attitudeAngleFromTarget() > 5)
            {
                burnTriggered = false;

                node.RemoveSelf();

                if (mode == Mode.ONE_NODE)
                {
                    Abort();
                    return;
                }
                else if (mode == Mode.ALL_NODES)
                {
                    if (!vessel.patchedConicSolver.maneuverNodes.Any())
                    {
                        Abort();
                        return;
                    }
                    else
                    {
                        node = vessel.patchedConicSolver.maneuverNodes.First();
                    }
                }
            }

            //aim along the node
            core.attitude.attitudeTo(Vector3d.forward, AttitudeReference.MANEUVER_NODE, this);

            double halfBurnTime;
            double burnTime = BurnTime(dVLeft, out halfBurnTime);

            double timeToNode = node.UT - vesselState.time;

            if (timeToNode < halfBurnTime)
            {
                burnTriggered = true;
                if (!MuUtils.PhysicsRunning())
                {
                    core.warp.MinimumWarp();
                }
            }

            //autowarp, but only if we're already aligned with the node
            if (autowarp && !burnTriggered)
            {
                if (core.attitude.attitudeAngleFromTarget() < 1 || (core.attitude.attitudeAngleFromTarget() < 10 && !MuUtils.PhysicsRunning()))
                {
                    core.warp.WarpToUT(node.UT - halfBurnTime - leadTime);
                }
                else if (!MuUtils.PhysicsRunning() && core.attitude.attitudeAngleFromTarget() > 10 && timeToNode < 600)
                {
                    //realign
                    core.warp.MinimumWarp();
                }
            }

            core.thrust.targetThrottle = 0;

            if (burnTriggered)
            {
                if (alignedForBurn)
                {
                    if (core.attitude.attitudeAngleFromTarget() < 90)
                    {
                        double timeConstant = (dVLeft > 10 || vesselState.minThrustAccel > 0.25 * vesselState.maxThrustAccel ? 0.5 : 2);
                        core.thrust.ThrustForDV(dVLeft + tolerance, timeConstant);
                    }
                    else
                    {
                        alignedForBurn = false;
                    }
                }
                else
                {
                    if (core.attitude.attitudeAngleFromTarget() < 2)
                    {
                        alignedForBurn = true;
                    }
                }
            }
        }
 public void RestoreManeuverNode(ManeuverNode newManNode)
 {
     ManeuverNode tmpNode = FlightGlobals.ActiveVessel.patchedConicSolver.AddManeuverNode(newManNode.UT);
     tmpNode.DeltaV = newManNode.DeltaV;
     tmpNode.nodeRotation = newManNode.nodeRotation;
     FlightGlobals.ActiveVessel.patchedConicSolver.UpdateFlightPlan();
 }
示例#51
0
        protected override void WindowGUI(int windowID)
        {
            if (vessel.patchedConicSolver.maneuverNodes.Count == 0)
            {
                GUILayout.Label("No maneuver nodes to edit.");
                GUI.DragWindow();
                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("Add", GUILayout.ExpandWidth(false)))
            {
                prograde += progradeDelta;
                node.OnGizmoUpdated(new Vector3d(radialPlus, normalPlus, prograde), node.UT);
            }
            progradeDelta.text = GUILayout.TextField(progradeDelta.text, GUILayout.Width(50));
            GUILayout.Label("m/s", GUILayout.ExpandWidth(false));
            GUILayout.EndHorizontal();

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

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

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

            GUILayout.BeginHorizontal();
            if (GUILayout.Button("Shift time by", GUILayout.ExpandWidth(true)))
            {
                node.OnGizmoUpdated(node.DeltaV, node.UT + timeOffset);
            }
            timeOffset.text = GUILayout.TextField(timeOffset.text, GUILayout.Width(100));
            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.Orbit.referenceBody == o.referenceBody)
                        {
                            if (o.AscendingNodeExists(core.target.Orbit)) UT = o.TimeOfAscendingNode(core.target.Orbit, UT - o.period / 2);
                        }
                        break;

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

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

            GUILayout.EndHorizontal();

            GUILayout.EndVertical();

            GUI.DragWindow();
        }
示例#52
0
文件: Node.cs 项目: niomaster/KOS
        public void Remove()
        {
            if (nodeRef == null) return;

            NodeLookup.Remove(nodeRef);

            vesselRef.patchedConicSolver.RemoveManeuverNode(nodeRef);

            nodeRef = null;
            vesselRef = null;
        }
示例#53
0
        /// <summary>
        /// Draw the main window.
        /// </summary>
        /// <param name="windowId">Window identifier.</param>
        void OnWindow(int windowId)
        {
            if (FlightGlobals.ActiveVessel == null)
            {
                return;
            }
            PatchedConicSolver solver = FlightGlobals.ActiveVessel.patchedConicSolver;

            GUILayout.BeginVertical(GUILayout.Width(320.0f));
            GUILayout.BeginHorizontal();
            if (GUILayout.Button("New") && IsAllowed())
            {
                _maneuver = solver.AddManeuverNode(Planetarium.GetUniversalTime() + (10.0 * 60.0));
                _mindex   = solver.maneuverNodes.IndexOf(_maneuver);
            }
            if (GUILayout.Button("Delete") && _maneuver != null)
            {
                _maneuver.RemoveSelf();
            }
            if (GUILayout.Button("Delete All") && _maneuver != null)
            {
                DeleteAll();
            }
            if (GUILayout.Button("Store") && solver.maneuverNodes.Count > 0)
            {
                StoredManeuver start = null;
                StoredManeuver prev  = null;
                foreach (ManeuverNode node in solver.maneuverNodes)
                {
                    StoredManeuver temp = new StoredManeuver(node.DeltaV, node.UT);
                    if (start == null)
                    {
                        start = temp;
                    }
                    if (prev != null)
                    {
                        prev.Next = temp;
                    }
                    prev = temp;
                }
                _stored.Add(start);
            }
            if (GUILayout.Button("Close"))
            {
                ToggleWindow();
            }
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GUILayout.Label("Warp");
            if (GUILayout.Button("+10m"))
            {
                // Cancel any existing warp.
                TimeWarp.SetRate(0, true);
                // Warp to the maneuver.
                TimeWarp.fetch.WarpTo(Planetarium.GetUniversalTime() + 10.0 * Format.ONE_KMIN);
            }
            if (GUILayout.Button("+1h"))
            {
                // Cancel any existing warp.
                TimeWarp.SetRate(0, true);
                // Warp to the maneuver.
                TimeWarp.fetch.WarpTo(Planetarium.GetUniversalTime() + Format.ONE_KHOUR);
            }
            if (GUILayout.Button("+1d"))
            {
                // Cancel any existing warp.
                TimeWarp.SetRate(0, true);
                // Warp to the maneuver.
                TimeWarp.fetch.WarpTo(Planetarium.GetUniversalTime() + Format.ONE_KDAY);
            }
            if (GUILayout.Button("+10d"))
            {
                // Cancel any existing warp.
                TimeWarp.SetRate(0, true);
                // Warp to the maneuver.
                TimeWarp.fetch.WarpTo(Planetarium.GetUniversalTime() + 10.0 * Format.ONE_KDAY);
            }
            if (FlightGlobals.ActiveVessel.orbit.patchEndTransition != Orbit.PatchTransitionType.FINAL)
            {
                if (GUILayout.Button("Transition"))
                {
                    // Cancel any existing warp.
                    TimeWarp.SetRate(0, true);
                    // Warp to the maneuver.
                    TimeWarp.fetch.WarpTo(FlightGlobals.ActiveVessel.orbit.EndUT - Format.ONE_KMIN);
                }
            }
            GUILayout.EndHorizontal();

            if (solver.maneuverNodes.Count > 0)
            {
                if (_maneuver == null || _mvessel != FlightGlobals.ActiveVessel ||
                    !solver.maneuverNodes.Contains(_maneuver))
                {
                    _maneuver = solver.maneuverNodes [0];
                    _mvessel  = FlightGlobals.ActiveVessel;
                    _mindex   = 0;
                }
                GUILayout.BeginHorizontal();
                GUILayout.Label("Maneuver:" + (_mindex + 1) + " of " +
                                solver.maneuverNodes.Count);
                if (GUILayout.Button("Prev"))
                {
                    _mindex--;
                    if (_mindex < 0)
                    {
                        _mindex = solver.maneuverNodes.Count - 1;
                    }
                    _maneuver = solver.maneuverNodes [_mindex];
                    _mvessel  = FlightGlobals.ActiveVessel;
                }
                if (GUILayout.Button("Next"))
                {
                    _mindex++;
                    if (_mindex >= solver.maneuverNodes.Count)
                    {
                        _mindex = 0;
                    }
                    _maneuver = solver.maneuverNodes [_mindex];
                    _mvessel  = FlightGlobals.ActiveVessel;
                }
                GUILayout.EndHorizontal();
                if (_maneuver != null)
                {
                    double timeToNode = Planetarium.GetUniversalTime() - _maneuver.UT;
                    if (_mindex == 0)
                    {
                        GUILayout.BeginHorizontal();
                        GUILayout.Label("Warp To Maneuver");
                        if (GUILayout.Button("-1m") && -timeToNode > Format.ONE_KMIN)
                        {
                            // Cancel any existing warp.
                            TimeWarp.SetRate(0, true);
                            // Warp to the maneuver.
                            TimeWarp.fetch.WarpTo(_maneuver.UT - Format.ONE_KMIN);
                        }
                        if (GUILayout.Button("-10m") && -timeToNode > 10.0 * Format.ONE_KMIN)
                        {
                            // Cancel any existing warp.
                            TimeWarp.SetRate(0, true);
                            // Warp to the maneuver.
                            TimeWarp.fetch.WarpTo(_maneuver.UT - 10.0 * Format.ONE_KMIN);
                        }
                        if (GUILayout.Button("-1h") && -timeToNode > Format.ONE_KHOUR)
                        {
                            // Cancel any existing warp.
                            TimeWarp.SetRate(0, true);
                            // Warp to the maneuver.
                            TimeWarp.fetch.WarpTo(_maneuver.UT - Format.ONE_KHOUR);
                        }
                        GUILayout.EndHorizontal();
                    }
                    else
                    {
                        GUILayout.Label("Warp To Maneuver - Switch to first maneuver");
                    }
                    GUILayout.Label("Time:" + KSPUtil.dateTimeFormatter.PrintDateDeltaCompact(timeToNode, true, true, true));
                    GUILayout.Label("Δv:" + Format.GetNumberString(_maneuver.DeltaV.magnitude) + "m/s");

                    GUILayout.BeginHorizontal();
                    _menuSelection = GUILayout.SelectionGrid(_menuSelection,
                                                             new string [] { ".01 m/s", ".1 m/s", "1 m/s", "10 m/s", "100 m/s", "1000 m/s" }, 3,
                                                             GUILayout.MinWidth(300.0f));
                    if (_menuSelection == 0)
                    {
                        _increment = 0.01d;
                    }
                    else if (_menuSelection == 1)
                    {
                        _increment = 0.1d;
                    }
                    else if (_menuSelection == 2)
                    {
                        _increment = 1.0d;
                    }
                    else if (_menuSelection == 3)
                    {
                        _increment = 10.0d;
                    }
                    else if (_menuSelection == 4)
                    {
                        _increment = 100.0d;
                    }
                    else if (_menuSelection == 5)
                    {
                        _increment = 1000.0d;
                    }
                    GUILayout.EndHorizontal();

                    GUILayout.BeginHorizontal();
                    GUILayout.Label("Prograde:" + Format.GetNumberString(_maneuver.DeltaV.z) + "m/s",
                                    GUILayout.MinWidth(200.0f));
                    if (GUILayout.Button("-"))
                    {
                        Vector3d dv = _maneuver.DeltaV;
                        dv.z -= _increment;
                        _maneuver.OnGizmoUpdated(dv, _maneuver.UT);
                    }
                    if (GUILayout.Button("0"))
                    {
                        Vector3d dv = _maneuver.DeltaV;
                        dv.z = 0.0d;
                        _maneuver.OnGizmoUpdated(dv, _maneuver.UT);
                    }
                    if (GUILayout.Button("+"))
                    {
                        Vector3d dv = _maneuver.DeltaV;
                        dv.z += _increment;
                        _maneuver.OnGizmoUpdated(dv, _maneuver.UT);
                    }
                    GUILayout.EndHorizontal();

                    GUILayout.BeginHorizontal();
                    GUILayout.Label("Normal  :" + Format.GetNumberString(_maneuver.DeltaV.y) + "m/s",
                                    GUILayout.MinWidth(200.0f));
                    if (GUILayout.Button("-"))
                    {
                        Vector3d dv = _maneuver.DeltaV;
                        dv.y -= _increment;
                        _maneuver.OnGizmoUpdated(dv, _maneuver.UT);
                    }
                    if (GUILayout.Button("0"))
                    {
                        Vector3d dv = _maneuver.DeltaV;
                        dv.y = 0.0d;
                        _maneuver.OnGizmoUpdated(dv, _maneuver.UT);
                    }
                    if (GUILayout.Button("+"))
                    {
                        Vector3d dv = _maneuver.DeltaV;
                        dv.y += _increment;
                        _maneuver.OnGizmoUpdated(dv, _maneuver.UT);
                    }
                    GUILayout.EndHorizontal();

                    GUILayout.BeginHorizontal();
                    GUILayout.Label("Radial  :" + Format.GetNumberString(_maneuver.DeltaV.x) + "m/s",
                                    GUILayout.MinWidth(200.0f));
                    if (GUILayout.Button("-"))
                    {
                        Vector3d dv = _maneuver.DeltaV;
                        dv.x -= _increment;
                        _maneuver.OnGizmoUpdated(dv, _maneuver.UT);
                    }
                    if (GUILayout.Button("0"))
                    {
                        Vector3d dv = _maneuver.DeltaV;
                        dv.x = 0.0d;
                        _maneuver.OnGizmoUpdated(dv, _maneuver.UT);
                    }
                    if (GUILayout.Button("+"))
                    {
                        Vector3d dv = _maneuver.DeltaV;
                        dv.x += _increment;
                        _maneuver.OnGizmoUpdated(dv, _maneuver.UT);
                    }
                    GUILayout.EndHorizontal();

                    double ut       = _maneuver.UT;
                    double utUpdate = _timeControl.TimeGUI(ut, FlightGlobals.ActiveVessel);
                    if (utUpdate != ut)
                    {
                        _maneuver.OnGizmoUpdated(_maneuver.DeltaV, utUpdate);
                    }

                    GUILayout.BeginHorizontal();
                    if (GUILayout.Button("=10min"))
                    {
                        _maneuver.OnGizmoUpdated(_maneuver.DeltaV, Planetarium.GetUniversalTime() + (10.0 * 60.0));
                    }
                    double period = _maneuver.patch.period;
                    if (GUILayout.Button("-10 Orbit") && period > 0 && -timeToNode > 10.0 * period)
                    {
                        _maneuver.OnGizmoUpdated(_maneuver.DeltaV, _maneuver.UT - (10.0 * period));
                    }
                    if (GUILayout.Button("-1 Orbit") && period > 0 && -timeToNode > period)
                    {
                        _maneuver.OnGizmoUpdated(_maneuver.DeltaV, _maneuver.UT - period);
                    }
                    if (GUILayout.Button("+1 Orbit") && period > 0)
                    {
                        _maneuver.OnGizmoUpdated(_maneuver.DeltaV, _maneuver.UT + period);
                    }
                    if (GUILayout.Button("+10 Orbit") && period > 0)
                    {
                        _maneuver.OnGizmoUpdated(_maneuver.DeltaV, _maneuver.UT + (10.0 * period));
                    }
                    GUILayout.EndHorizontal();
                }
                else
                {
                    _windowPos.height = 0;
                }
            }
            else if (_maneuver != null)
            {
                _maneuver         = null;
                _windowPos.height = 0;
            }

            GUILayout.EndVertical();
            GUI.DragWindow();
        }
 private static ManeuverNode ManNodeDeserialize(String strInput)
 {
     ManeuverNode mReturn =  new ManeuverNode();
     String[] manparts = strInput.Split(",".ToCharArray());
     mReturn.UT = Convert.ToDouble(manparts[0]);
     mReturn.DeltaV = new Vector3d(Convert.ToDouble(manparts[1]),
                                 Convert.ToDouble(manparts[2]),
                                 Convert.ToDouble(manparts[3])
             );
     mReturn.nodeRotation = new Quaternion(Convert.ToSingle(manparts[4]),
                                         Convert.ToSingle(manparts[5]),
                                         Convert.ToSingle(manparts[6]),
                                         Convert.ToSingle(manparts[7])
             );
     return mReturn;
 }
示例#55
0
文件: Node.cs 项目: KSP-KOS/KOS
 public static Node FromExisting(Vessel v, ManeuverNode existingNode, SharedObjects shared)
 {
     return nodeLookup.ContainsKey(existingNode) ? nodeLookup[existingNode] : new Node(v, existingNode, shared);
 }
示例#56
0
        protected override void AdjustNode(
            ManeuverNode originalNode, Maneuver original, double originalPeriod, double originalMagnitude, ManeuverNode node, double value, double splitDv)
        {
            double fraction;
            double minFraction = 0;
            double maxFraction = 1;

            IBurnCalculator calculator = GetAvailableCalculator();

            for (int iteration = 0; iteration < HighLogic.CurrentGame.Parameters.CustomParams <MNS>().splitByBurnTimeIterations; iteration += 1)
            {
                fraction = (minFraction + maxFraction) / 2;
                Vector3d dv = original.DeltaV * fraction;
                if (node != originalNode)
                {
                    RotateDeltaV(originalNode, node, ref dv);
                }
                node.DeltaV = dv;
                node.solver.UpdateFlightPlan();

                double burnTime = calculator.CalculateBurnTime(dv.magnitude, splitDv);

                if (node.nextPatch.ApA > 0 && burnTime < value)
                {
                    minFraction = fraction;
                }
                else
                {
                    maxFraction = fraction;
                }
            }
        }
示例#57
0
 // calculation function for mergeNodeDown
 private static Vector3d mergeBurnVectors(double UT, ManeuverNode first, Orbit projOrbit)
 {
     Orbit curOrbit = first.findPreviousOrbit();
     return difference(curOrbit.getOrbitalVelocityAtUT(UT), projOrbit.getOrbitalVelocityAtUT(UT));
 }
 /* Nodes after the first will be in a different orbital plane if the maneuver is
  * not purely a prograde burn, so they must be rotated since the dV is specified
  * relative to the orbit at the point of the maneuver node
  */
 protected void RotateDeltaV(ManeuverNode original, ManeuverNode node, ref Vector3d dv)
 {
     DebugLog("dV before {0},{1},{2}", dv.x, dv.y, dv.z);
     dv = Quaternion.Inverse(node.nodeRotation) * original.nodeRotation * dv;
     DebugLog("dV after {0},{1},{2}", dv.x, dv.y, dv.z);
 }
示例#59
0
文件: Node.cs 项目: KSP-KOS/KOS
        public void Remove()
        {
            if (nodeRef == null) return;

            string careerReason;
            if (! Career.CanMakeNodes(out careerReason))
                throw new KOSLowTechException("use maneuver nodes", careerReason);

            nodeLookup.Remove(nodeRef);

            if (vesselRef.patchedConicSolver == null)
                throw new KOSSituationallyInvalidException(
                    "A KSP limitation makes it impossible to access the manuever nodes of this vessel at this time. " +
                    "(perhaps it's not the active vessel?)");

            nodeRef.RemoveSelf();

            nodeRef = null;
            vesselRef = null;
        }
示例#60
0
        // calculation function for mergeNodeDown
        private static Vector3d mergeBurnVectors(double UT, ManeuverNode first, Orbit projOrbit)
        {
            Orbit curOrbit = first.findPreviousOrbit();

            return(difference(curOrbit.getOrbitalVelocityAtUT(UT), projOrbit.getOrbitalVelocityAtUT(UT)));
        }