示例#1
0
            // find orbit round with min normalDiff to target, makes only sense if we are in inclined orbit
            bool minOrbit()
            {
                ManeuverNode plannedNode = vessel.patchedConicSolver.maneuverNodes[0];

                if (Math.Abs(orbit.inclination) < 5)
                {
                    return(true);
                }
                Debug.Log(String.Format("Current deorbit round at t={0:F0} has normalDiff={1:F1}", plannedNode.UT - Planetarium.GetUniversalTime(), targetInfo.normalDifference));
                if (iteration == 0 || Math.Abs(targetInfo.normalDifference) < minDiff)
                {
                    Debug.Log(String.Format("Found new optimum deorbit round at t={0:F0} for normalDiff={1:F1} ", plannedNode.UT - Planetarium.GetUniversalTime(), targetInfo.normalDifference));
                    minDiff = Math.Abs(targetInfo.normalDifference);
                    minUT   = plannedNode.UT;
                }
                iteration++;
                if (iteration > maxIterations)
                {
                    plannedNode.RemoveSelf();
                    vessel.PlaceManeuverNode(vessel.orbit, OrbitalManeuverCalculator.DeltaVToChangePeriapsis(orbit, minUT, mainBody.Radius + core.landing.reentryTargetHeight), minUT);
                    targetInfo.invalidateCalculation();
                    return(true);
                }
                // factor accounts for ground movement during orbit round
                double nextRound = plannedNode.UT + orbit.period * vessel.mainBody.rotationPeriod / (vessel.mainBody.rotationPeriod - orbit.period);

                plannedNode.RemoveSelf();
                vessel.PlaceManeuverNode(vessel.orbit, OrbitalManeuverCalculator.DeltaVToChangePeriapsis(orbit, nextRound, mainBody.Radius + core.landing.reentryTargetHeight), nextRound);
                targetInfo.invalidateCalculation();
                return(false);
            }
示例#2
0
 protected override void Update()
 {
     if (!VSL.HasManeuverNode ||
         Node != Solver.maneuverNodes[0] ||
         NodeCB != Node.patch.referenceBody)
     {
         Message("Maneuver has been interrupted.");
         Disable();
         return;
     }
     if (!VSL.Engines.HaveThrusters && !VSL.Engines.HaveNextStageEngines)
     {
         Message("Out of fuel");
         Disable();
         return;
     }
     //update the node
     NodeDeltaV = (TargetOrbit.GetFrameVelAtUT(NodeUT) - VSL.orbit.GetFrameVelAtUT(NodeUT)).xzy;
     Executor.ThrustWhenAligned = ThrustWhenAligned;
     ThrustWhenAligned          = true;
     if (Executor.Execute(NodeDeltaV, MinDeltaV, StartCondition))
     {
         return;
     }
     ManeuverStage = Stage.FINISHED;
     Node.RemoveSelf();
     Disable();
 }
示例#3
0
        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;
        }
 internal void DeleteNode()
 {
     if (currentNode != null)
     {
         currentNode.RemoveSelf();
         currentNode = null;
         UpdateCurrentNode();
     }
 }
示例#5
0
 internal void deleteNode()
 {
     if (_currentNode != null)
     {
         _currentNode.RemoveSelf();
         _currentNode = null;
         updateCurrentNode();
     }
 }
示例#6
0
            bool optimizeDeorbit()
            {
                //Debug.Log(String.Format("Autoland: currentImpactRadialVector={0} currentTargetRadialVector={1} differenceTarget={2}", targetInfo.currentImpactRadialVector, targetInfo.currentTargetRadialVector, targetInfo.differenceTarget));
                //Debug.Log(String.Format("Autoland: orbitClosestToTarget={0} orbitNormal={1} targetForward={2} ", targetInfo.orbitClosestToTarget, orbit.SwappedOrbitNormal(), targetForward.ToString("F3")));
                //Debug.Log(String.Format("Autoland: normalDiff={0:F1}, backwardDiff={1:F1}", targetInfo.normalDifference, targetInfo.backwardDifference));

                if (Math.Abs(targetInfo.targetAheadAngle) < 0.5 && Math.Abs(targetInfo.backwardDifference) < deorbitprecision)
                {
                    return(true); // execute plannedNode
                }
                else
                {
                    //move Node
                    ManeuverNode plannedNode = vessel.patchedConicSolver.maneuverNodes[0];
                    double       deorbitTime = plannedNode.UT;
                    double       timedelta;

                    if (Math.Abs(targetInfo.targetAheadAngle) < 0.5) // for small changes use tangential calculation, otherwise angluar
                    {
                        timedelta = targetInfo.backwardDifference / vesselState.speedSurfaceHorizontal;
                    }
                    else
                    {
                        timedelta = targetInfo.targetAheadAngle * orbit.period / 360f;
                    }

                    if (timedelta < 0) // asymetric to avoid jumping between two points without improvement. Observed with inclined trajectory.
                    {
                        deorbitTime -= timedelta;
                    }
                    else
                    {
                        deorbitTime -= 0.5 * timedelta;
                    }

                    if (deorbitTime < vesselState.time)
                    {
                        deorbitTime += orbit.period;
                    }
                    if (deorbitTime > vesselState.time + 1.5 * orbit.period)
                    {
                        deorbitTime -= orbit.period;
                    }

                    status = String.Format("Optimizing deorbit time based on trajectory prediction, shift by {0:F4} degree, {1:F0} m equals {2:F1} seconds", targetInfo.targetAheadAngle, targetInfo.backwardDifference, deorbitTime - plannedNode.UT);
                    Debug.Log("Autoland: " + status);

                    // deltaV needs to rotate
                    plannedNode.RemoveSelf();
                    vessel.PlaceManeuverNode(vessel.orbit, OrbitalManeuverCalculator.DeltaVToChangePeriapsis(orbit, deorbitTime, mainBody.Radius + core.landing.reentryTargetHeight), deorbitTime);
                    targetInfo.invalidateCalculation();
                    iteration++;
                }

                return(false);
            }
示例#7
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="computer">FlightComputer instance of the computer of the vessel.</param>
 private void AbortManeuver(FlightComputer computer)
 {
     RTUtil.ScreenMessage("[Flight Computer]: Maneuver removed");
     if (computer.Vessel.patchedConicSolver != null)
     {
         Node.RemoveSelf();
     }
     // enqueue kill rot
     computer.Enqueue(AttitudeCommand.KillRot(), true, true, true);
 }
示例#8
0
        void MergeNext(int index)
        {
            ManeuverNode cur  = vessel.patchedConicSolver.maneuverNodes[index];
            ManeuverNode next = vessel.patchedConicSolver.maneuverNodes[index + 1];

            double newUT = (cur.UT + next.UT) / 2;

            cur.UpdateNode(cur.patch.DeltaVToManeuverNodeCoordinates(newUT, cur.WorldDeltaV() + next.WorldDeltaV()), newUT);
            next.RemoveSelf();
        }
示例#9
0
            public override AutopilotStep OnFixedUpdate()
            {
                if (!vessel.patchedConicsUnlocked() || vessel.patchedConicSolver.maneuverNodes.Count == 0)
                {
                    return(doAfterExecution);
                }

                node = vessel.patchedConicSolver.maneuverNodes[0];
                double dVLeft = node.GetBurnVector(orbit).magnitude;

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

                    node.RemoveSelf();

                    return(this); // we are done for this frame, continue in next
                }

                double halfBurnTime;
                double burnTime = core.node.BurnTime(dVLeft, out halfBurnTime);

                double timeToNode = node.UT - vesselState.time;

                status = "Moving to node";

                if ((!double.IsInfinity(halfBurnTime) && halfBurnTime > 0 && timeToNode < halfBurnTime) || timeToNode < 0)
                {
                    burnTriggered = true;
                    status        = "Executing node";
                    if (!MuUtils.PhysicsRunning())
                    {
                        core.warp.MinimumWarp();
                    }
                }

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

                return(this);
            }
 private void remove_maneuver_node()
 {
     if (Node.solver != null)
     {
         Node.RemoveSelf();
     }
     else if (Solver != null &&
              Solver.maneuverNodes.Count > 0 &&
              Math.Abs(Solver.maneuverNodes[0].UT - Node.UT) < 1e-6)
     {
         Solver.maneuverNodes[0].RemoveSelf();
     }
     Node = null;
 }
示例#11
0
 protected override void Update()
 {
     if (!IsActive)
     {
         return;
     }
     if (!VSL.HasManeuverNode || Node != Solver.maneuverNodes[0])
     {
         reset(); return;
     }
     if (Executor.Execute(Node.GetBurnVector(VSL.orbit), MinDeltaV, StartCondition))
     {
         return;
     }
     Node.RemoveSelf();
     reset();
 }
示例#12
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="computer">FlightComputer instance of the computer of the vessel.</param>
        private void AbortManeuver(FlightComputer computer)
        {
            RTUtil.ScreenMessage("[Flight Computer]: Maneuver removed");
            if (computer.Vessel.patchedConicSolver != null)
            {
                Node.RemoveSelf();
            }

            // Flight Computer mode after execution based on settings
            if (RTSettings.Instance.FCOffAfterExecute)
            {
                computer.Enqueue(AttitudeCommand.Off(), true, true, true);
            }
            if (!RTSettings.Instance.FCOffAfterExecute)
            {
                computer.Enqueue(AttitudeCommand.KillRot(), true, true, true);
            }
        }
示例#13
0
        protected override void Update()
        {
            if (!IsActive)
            {
                return;
            }
            if (!VSL.HasManeuverNode || Node != Solver.maneuverNodes[0])
            {
                reset(); return;
            }
            NodeDeltaV = Node.GetBurnVector(VSL.orbit);
//            Log("Node.dV {}", NodeDeltaV);//debug
            if (Executor.Execute(NodeDeltaV, MinDeltaV, StartCondition))
            {
                within_threshold |= Executor.RemainingDeltaV < ThresholdDeltaV;
                if (within_threshold)
                {
                    VSL.Controls.GimbalLimit = 0;
                    var dV = Executor.RemainingDeltaV;
                    if (dV < min_deltaV)
                    {
                        min_deltaV = dV; return;
                    }
                    if (dV - min_deltaV < GLB.THR.MinDeltaV)
                    {
                        return;
                    }
                }
                else
                {
                    return;
                }
            }
            Node.RemoveSelf();
            reset();
        }
示例#14
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();
        }
        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;
                    }
                }
            }
        }
示例#16
0
        public override void OnFixedUpdate()
        {
            throttle.target = 0.0;

            if (vessel.patchedConicSolver.maneuverNodes.Count == 0)
            {
                Debug.Log("NodeExecutor: no maneuver node to execute");
                Disable();
                return;
            }

            ManeuverNode node   = vessel.patchedConicSolver.maneuverNodes[0];
            double       dVLeft = node.GetBurnVector(orbit).magnitude;

            if (dVLeft < tolerance && attitude.AngleFromTarget() > 5)
            {
                Debug.Log("NodeExecutor: done with node, removing it");
                node.RemoveSelf();
                Disable();
                return;
            }

            attitude.attitudeTo(Vector3d.forward, AttitudeReference.MANEUVER_NODE);
            double BurnUT = node.UT - BurnTime(dVLeft) / 2.0;

            if (vesselState.time < (BurnUT - 300))
            {
                /* way before the burn */
                if (attitude.AngleFromTarget() < 1 && CheckAngularVelocity(ref checkOneStart))
                {
                    warp.WarpToUT(this, BurnUT - leadTime);
                }
            }
            else if (vesselState.time < (BurnUT - leadTime))
            {
                /* before the burn */
                if (attitude.AngleFromTarget() < 1 && CheckAngularVelocity(ref checkTwoStart))
                {
                    warp.WarpToUT(this, BurnUT - leadTime);
                }
                if (attitude.AngleFromTarget() > 5)
                {
                    warp.MinimumWarp(this);
                }
            }
            else if (vesselState.time < BurnUT)
            {
                /* settling time */
                warp.MinimumWarp(this);
            }
            else
            {
                /* feeling the burn */
                warp.MinimumWarp(this);
                throttle.target = 0.0;

                if (attitude.AngleFromTarget() > 5)
                {
                    seeking = true;
                }
                else if (attitude.AngleFromTarget() < 1 || !seeking)
                {
                    double thrustToMass = vesselState.thrustMaximum / vesselState.mass;
                    throttle.target = Utils.Clamp(dVLeft / thrustToMass / 2.0, 0.01, 1.0);
                    seeking         = false;
                }
            }
        }
示例#17
0
        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())
                    {
                        aerobrakeNode.RemoveSelf();
                        aerobrakeNode = null;
                    }
                }

                //Update or create node if necessary:
                ReentrySimulation.Result r = Result;
                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.WorldAeroBrakePosition(), r.WorldAeroBrakeVelocity(), r.body, r.aeroBrakeUT);

                    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.UpdateNode(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))
                    {
                        aerobrakeNode.RemoveSelf();
                    }
                }
            }
            else
            {
                //Remove aerobrake node when it is turned off:
                if (aerobrakeNode != null && vessel.patchedConicSolver.maneuverNodes.Contains(aerobrakeNode))
                {
                    aerobrakeNode.RemoveSelf();
                }
            }
        }