Пример #1
0
        public override void OnFixedUpdate()
        {
            if (markUT == 0)
            {
                Mark();
            }

            timeSinceMark = vesselState.time - markUT;

            if (vessel.situation == Vessel.Situations.PRELAUNCH)
            {
                Mark(); //keep resetting stats until we launch
                return;
            }

            gravityLosses += vesselState.deltaT * Vector3d.Dot(-vessel.srf_velocity.normalized, vesselState.gravityForce);
            gravityLosses -= vesselState.deltaT * Vector3d.Dot(vessel.srf_velocity.normalized, vesselState.up * vesselState.radius * Math.Pow(2 * Math.PI / part.vessel.mainBody.rotationPeriod, 2));
            double dragAccel = mainBody.DragAccel(vesselState.CoM, vessel.obt_velocity, vesselState.massDrag / vesselState.mass).magnitude;

            dragLosses += vesselState.deltaT * dragAccel;

            maxDragGees = Math.Max(maxDragGees, dragAccel / 9.81);

            double circularPeriod = 2 * Math.PI * vesselState.radius / OrbitalManeuverCalculator.CircularOrbitSpeed(mainBody, vesselState.radius);
            double angleTraversed = (vesselState.longitude - markLongitude) + 360 * (vesselState.time - markUT) / part.vessel.mainBody.rotationPeriod;

            phaseAngleFromMark = MuUtils.ClampDegrees360(360 * (vesselState.time - markUT) / circularPeriod - angleTraversed);
        }
Пример #2
0
        public override ManeuverParameters MakeNodeImpl(Orbit o, double universalTime, MechJebModuleTargetController target)
        {
            double UT = timeSelector.ComputeManeuverTime(o, universalTime, target);
            var    dV = OrbitalManeuverCalculator.DeltaVToShiftNodeLongitude(o, UT, target.targetLongitude);

            return(new ManeuverParameters(dV, UT));
        }
Пример #3
0
        void DriveCircularizationBurn(FlightCtrlState s)
        {
            if (!vessel.patchedConicsUnlocked() || skipCircularization)
            {
                this.users.Clear();
                return;
            }

            DriveDeployableComponents(s);

            if (placedCircularizeNode)
            {
                if (vessel.patchedConicSolver.maneuverNodes.Count == 0)
                {
                    MechJebModuleFlightRecorder recorder = core.GetComputerModule <MechJebModuleFlightRecorder>();
                    if (recorder != null)
                    {
                        launchPhaseAngle = recorder.phaseAngleFromMark;
                    }
                    if (recorder != null)
                    {
                        launchLANDifference = vesselState.orbitLAN - recorder.markLAN;
                    }

                    //finished circularize
                    this.users.Clear();
                    return;
                }
            }
            else
            {
                //place circularization node
                vessel.RemoveAllManeuverNodes();
                double UT = orbit.NextApoapsisTime(vesselState.time);
                //During the circularization burn, try to correct any inclination errors because it's better to combine the two burns.
                //  For example, if you're about to do a 1500 m/s circularization burn, if you combine a 200 m/s inclination correction
                //  into it, you actually only spend 1513 m/s to execute combined manuver.  Mechjeb should also do correction burns before
                //  this if possible, and this can't correct all errors... but it's better then nothing.
                //   (A better version of this should try to match inclination & LAN if target is specified)
                // FIXME? this inclination correction is unlikely to be at tha AN/DN and will throw the LAN off with anything other than high
                // TWR launches from equatorial launch sites -- should probably be made optional (or clip it if the correction is too large).
                Vector3d inclinationCorrection = OrbitalManeuverCalculator.DeltaVToChangeInclination(orbit, UT, Math.Abs(desiredInclination));
                Vector3d smaCorrection         = OrbitalManeuverCalculator.DeltaVForSemiMajorAxis(orbit.PerturbedOrbit(UT, inclinationCorrection), UT,
                                                                                                  desiredOrbitAltitude + mainBody.Radius);
                Vector3d dV = inclinationCorrection + smaCorrection;
                vessel.PlaceManeuverNode(orbit, dV, UT);
                placedCircularizeNode = true;

                core.node.ExecuteOneNode(this);
            }

            if (core.node.burnTriggered)
            {
                status = Localizer.Format("#MechJeb_Ascent_status7");                         //"Circularizing"
            }
            else
            {
                status = Localizer.Format("#MechJeb_Ascent_status8"); //"Coasting to circularization burn"
            }
        }
Пример #4
0
        public override ManeuverParameters MakeNodeImpl(Orbit o, double UT, MechJebModuleTargetController target)
        {
            if (!target.NormalTargetExists)
            {
                throw new Exception("must select a target for the Hohmann transfer.");
            }
            else if (o.referenceBody != target.TargetOrbit.referenceBody)
            {
                throw new Exception("target for Hohmann transfer must be in the same sphere of influence.");
            }
            else if (o.eccentricity > 1)
            {
                throw new Exception("starting orbit for Hohmann transfer must not be hyperbolic.");
            }
            else if (target.TargetOrbit.eccentricity > 1)
            {
                throw new Exception("target orbit for Hohmann transfer must not be hyperbolic.");
            }
            else if (o.RelativeInclination(target.TargetOrbit) > 30 && o.RelativeInclination(target.TargetOrbit) < 150)
            {
                errorMessage = "Warning: target's orbital plane is at a " + o.RelativeInclination(target.TargetOrbit).ToString("F0") + "º angle to starting orbit's plane (recommend at most 30º). Planned transfer may not intercept target properly.";
            }
            else if (o.eccentricity > 0.2)
            {
                errorMessage = "Warning: Recommend starting Hohmann transfers from a near-circular orbit (eccentricity < 0.2). Planned transfer is starting from an orbit with eccentricity " + o.eccentricity.ToString("F2") + " and so may not intercept target properly.";
            }

            Vector3d dV = OrbitalManeuverCalculator.DeltaVAndTimeForHohmannTransfer(o, target.TargetOrbit, UT, out UT);

            return(new ManeuverParameters(dV, UT));
        }
Пример #5
0
        public override ManeuverParameters MakeNodeImpl(Orbit o, double universalTime, MechJebModuleTargetController target)
        {
            double UT = timeSelector.ComputeManeuverTime(o, universalTime, target);

            if (!target.NormalTargetExists)
            {
                throw new Exception("must select a target to match planes with.");
            }
            else if (o.referenceBody != target.TargetOrbit.referenceBody)
            {
                throw new Exception("can only match planes with an object in the same sphere of influence.");
            }
            else if (timeSelector.timeReference == TimeReference.REL_ASCENDING)
            {
                if (!o.AscendingNodeExists(target.TargetOrbit))
                {
                    throw new Exception("ascending node with target doesn't exist.");
                }
            }
            else
            {
                if (!o.DescendingNodeExists(target.TargetOrbit))
                {
                    throw new Exception("descending node with target doesn't exist.");
                }
            }

            Vector3d dV = (timeSelector.timeReference == TimeReference.REL_ASCENDING) ?
                          OrbitalManeuverCalculator.DeltaVAndTimeToMatchPlanesAscending(o, target.TargetOrbit, UT, out UT):
                          OrbitalManeuverCalculator.DeltaVAndTimeToMatchPlanesDescending(o, target.TargetOrbit, UT, out UT);

            return(new ManeuverParameters(dV, UT));
        }
Пример #6
0
        public override ManeuverParameters MakeNodeImpl(Orbit o, double universalTime, MechJebModuleTargetController target)
        {
            double UT = timeSelector.ComputeManeuverTime(o, universalTime, target);
            var    dV = OrbitalManeuverCalculator.DeltaVToResonantOrbit(o, UT, (double)resonanceNumerator.val / resonanceDenominator.val);

            return(new ManeuverParameters(dV, UT));
        }
Пример #7
0
        public override List <ManeuverParameters> MakeNodesImpl(Orbit o, double universalTime, MechJebModuleTargetController target)
        {
            double UT = timeSelector.ComputeManeuverTime(o, universalTime, target);
            List <ManeuverParameters> NodeList = new List <ManeuverParameters>();

            NodeList.Add(new ManeuverParameters(OrbitalManeuverCalculator.DeltaVToCircularize(o, UT), UT));
            return(NodeList);
        }
        public override void OnFixedUpdate()
        {
            if (markUT == 0)
            {
                Mark();
            }

            timeSinceMark = vesselState.time - markUT;

            if (vessel.situation == Vessel.Situations.PRELAUNCH)
            {
                Mark(); //keep resetting stats until we launch
                return;
            }

            if (vesselState.currentThrustAccel > 0)
            {
                gravityLosses += vesselState.deltaT * Vector3d.Dot(-vesselState.orbitalVelocity.normalized, vesselState.gravityForce);
            }
            dragLosses     += vesselState.deltaT * vesselState.drag;
            deltaVExpended += vesselState.deltaT * vesselState.currentThrustAccel;
            steeringLosses += vesselState.deltaT * vesselState.currentThrustAccel * (1 - Vector3d.Dot(vesselState.orbitalVelocity.normalized, vesselState.forward));

            maxDragGees = Math.Max(maxDragGees, vesselState.drag / 9.81);

            double circularPeriod = 2 * Math.PI * vesselState.radius / OrbitalManeuverCalculator.CircularOrbitSpeed(mainBody, vesselState.radius);
            double angleTraversed = (vesselState.longitude - markLongitude) + 360 * (vesselState.time - markUT) / part.vessel.mainBody.rotationPeriod;

            phaseAngleFromMark = MuUtils.ClampDegrees360(360 * (vesselState.time - markUT) / circularPeriod - angleTraversed);

            if (paused)
            {
                return;
            }

            //int oldHistoryIdx = historyIdx;

            //historyIdx = Mathf.Min(Mathf.FloorToInt((float)(timeSinceMark / precision)), history.Length - 1);

            if (vesselState.time >= (lastRecordTime + precision) && historyIdx < history.Length - 1)
            {
                lastRecordTime = vesselState.time;
                historyIdx++;
                Record(historyIdx);
#if DEBUG
                if (TimeWarp.WarpMode == TimeWarp.Modes.HIGH)
                {
                    Log.dbg("WRP {0} {1:0} {2:0.00}", historyIdx, history[historyIdx].downRange, history[historyIdx].AoA);
                }
                else
                {
                    Log.dbg("STD {0} {1:0} {2:0.00}", historyIdx, history[historyIdx].downRange, history[historyIdx].AoA);
                }
#endif
            }
        }
Пример #9
0
        void DriveCircularizationBurn(FlightCtrlState s)
        {
            if (!vessel.patchedConicsUnlocked() || skipCircularization)
            {
                this.users.Clear();
                return;
            }

            if (placedCircularizeNode)
            {
                if (!vessel.patchedConicSolver.maneuverNodes.Any())
                {
                    MechJebModuleFlightRecorder recorder = core.GetComputerModule <MechJebModuleFlightRecorder>();
                    if (recorder != null)
                    {
                        launchPhaseAngle = recorder.phaseAngleFromMark;
                    }
                    if (recorder != null)
                    {
                        launchLANDifference = vesselState.orbitLAN - recorder.markLAN;
                    }

                    //finished circularize
                    this.users.Clear();
                    return;
                }
            }
            else
            {
                //place circularization node
                vessel.RemoveAllManeuverNodes();
                double UT = orbit.NextApoapsisTime(vesselState.time);
                //During the circularization burn, try to correct any inclination errors because it's better to combine the two burns.
                //  For example, if you're about to do a 1500 m/s circularization burn, if you combine a 200 m/s inclination correction
                //  into it, you actually only spend 1513 m/s to execute combined manuver.  Mechjeb should also do correction burns before
                //  this if possible, and this can't correct all errors... but it's better then nothing.
                //   (A better version of this should try to match inclination & LAN if target is specified)
                Vector3d inclinationCorrection = OrbitalManeuverCalculator.DeltaVToChangeInclination(orbit, UT, desiredInclination);
                Vector3d smaCorrection         = OrbitalManeuverCalculator.DeltaVForSemiMajorAxis(orbit.PerturbedOrbit(UT, inclinationCorrection), UT,
                                                                                                  desiredOrbitAltitude + mainBody.Radius);
                Vector3d dV = inclinationCorrection + smaCorrection;
                vessel.PlaceManeuverNode(orbit, dV, UT);
                placedCircularizeNode = true;

                core.node.ExecuteOneNode(this);
            }

            if (core.node.burnTriggered)
            {
                status = "Circularizing";
            }
            else
            {
                status = "Coasting to circularization burn";
            }
        }
Пример #10
0
        // provides AoA limiting and ground track steering to pitch controllers (possibly should be moved into the attitude controller, but
        // right now it collaborates too heavily with the ascent autopilot)
        //
        protected void attitudeTo(double desiredPitch)
        {
            double desiredHeading = OrbitalManeuverCalculator.HeadingForLaunchInclination(vessel, vesselState, autopilot.desiredInclination);

            Vector3d desiredHeadingVector = Math.Sin(desiredHeading * UtilMath.Deg2Rad) * vesselState.east + Math.Cos(desiredHeading * UtilMath.Deg2Rad) * vesselState.north;

            Vector3d desiredThrustVector = Math.Cos(desiredPitch * UtilMath.Deg2Rad) * desiredHeadingVector
                                           + Math.Sin(desiredPitch * UtilMath.Deg2Rad) * vesselState.up;

            thrustVectorForNavball = desiredThrustVector;

            desiredThrustVector = desiredThrustVector.normalized;

            if (autopilot.limitAoA)
            {
                float fade = vesselState.dynamicPressure < autopilot.aoALimitFadeoutPressure ? (float)(autopilot.aoALimitFadeoutPressure / vesselState.dynamicPressure) : 1;
                autopilot.currentMaxAoA = Math.Min(fade * autopilot.maxAoA, 180d);
                autopilot.limitingAoA   = vessel.altitude <mainBody.atmosphereDepth && Vector3.Angle(vesselState.surfaceVelocity, desiredThrustVector)> autopilot.currentMaxAoA;

                if (autopilot.limitingAoA)
                {
                    desiredThrustVector = Vector3.RotateTowards(vesselState.surfaceVelocity, desiredThrustVector, (float)(autopilot.currentMaxAoA * Mathf.Deg2Rad), 1).normalized;
                }
            }

            double pitch = 90 - Vector3d.Angle(desiredThrustVector, vesselState.up);
            double hdg;

            if (pitch > 89.9)
            {
                hdg = desiredHeading;
            }
            else
            {
                hdg = MuUtils.ClampDegrees360(UtilMath.Rad2Deg * Math.Atan2(Vector3d.Dot(desiredThrustVector, vesselState.east), Vector3d.Dot(desiredThrustVector, vesselState.north)));
            }

            if (autopilot.forceRoll)
            {
                core.attitude.AxisControl(!vessel.Landed, !vessel.Landed, !vessel.Landed && vesselState.altitudeBottom > 50);

                if (desiredPitch == 90.0)
                {
                    core.attitude.attitudeTo(hdg, pitch, autopilot.turnRoll, this);
                }
                else
                {
                    core.attitude.attitudeTo(hdg, pitch, autopilot.verticalRoll, this);
                }
            }
            else
            {
                core.attitude.attitudeTo(desiredThrustVector, AttitudeReference.INERTIAL, this);
            }
        }
        override public void activateAction(int actionIndex)
        {
            base.activateAction(actionIndex);
            double   UT;
            Vessel   vessel = FlightGlobals.ActiveVessel;
            Vector3d dV     = OrbitalManeuverCalculator.DeltaVAndTimeForHohmannTransfer(this.scriptModule.orbit, core.target.TargetOrbit, this.scriptModule.vesselState.time, out UT);

            vessel.RemoveAllManeuverNodes();
            vessel.PlaceManeuverNode(this.scriptModule.orbit, dV, UT);
            this.endAction();
        }
        private PontryaginLaunch NewPontryaginForLaunch(double inc, double sma)
        {
            lambdaDot = Vector3d.zero;
            double   desiredHeading       = OrbitalManeuverCalculator.HeadingForInclination(inc, vesselState.latitude);
            Vector3d desiredHeadingVector = Math.Sin(desiredHeading * UtilMath.Deg2Rad) * vesselState.east + Math.Cos(desiredHeading * UtilMath.Deg2Rad) * vesselState.north;
            Vector3d desiredThrustVector  = Math.Cos(45 * UtilMath.Deg2Rad) * desiredHeadingVector + Math.Sin(45 * UtilMath.Deg2Rad) * vesselState.up; /* 45 pitch guess */

            lambda = desiredThrustVector;
            Log.info("sma = {0}; deltaV guess = {1}", sma, approximateDeltaV(sma));
            return(new PontryaginLaunch(core: core, mu: mainBody.gravParameter, r0: vesselState.orbitalPosition, v0: vesselState.orbitalVelocity, pv0: lambda, dV: approximateDeltaV(sma)));
        }
Пример #13
0
 public override void OnFixedUpdate()
 {
     if (NavBallGuidance && autopilot != null && autopilot.ascentPath != null)
     {
         double   angle         = UtilMath.Deg2Rad * autopilot.ascentPath.FlightPathAngle(vesselState.altitudeASL, vesselState.speedSurface);
         double   heading       = UtilMath.Deg2Rad * OrbitalManeuverCalculator.HeadingForLaunchInclination(vessel, vesselState, autopilot.desiredInclination);
         Vector3d horizontalDir = Math.Cos(heading) * vesselState.north + Math.Sin(heading) * vesselState.east;
         Vector3d dir           = Math.Cos(angle) * horizontalDir + Math.Sin(angle) * vesselState.up;
         core.target.UpdateDirectionTarget(dir);
     }
 }
Пример #14
0
 public override void OnFixedUpdate()
 {
     if (NavBallGuidance && autopilot != null && autopilot.ascentPath != null)
     {
         double   angle         = Math.PI / 180 * autopilot.ascentPath.FlightPathAngle(vesselState.altitudeASL, vesselState.speedSurface);
         double   heading       = Math.PI / 180 * OrbitalManeuverCalculator.HeadingForLaunchInclination(vessel.mainBody, autopilot.desiredInclination, launchLatitude, OrbitalManeuverCalculator.CircularOrbitSpeed(vessel.mainBody, autopilot.desiredOrbitAltitude + mainBody.Radius));
         Vector3d horizontalDir = Math.Cos(heading) * vesselState.north + Math.Sin(heading) * vesselState.east;
         Vector3d dir           = Math.Cos(angle) * horizontalDir + Math.Sin(angle) * vesselState.up;
         core.target.UpdateDirectionTarget(dir);
     }
 }
Пример #15
0
        public override ManeuverParameters MakeNodeImpl(Orbit o, double universalTime, MechJebModuleTargetController target)
        {
            if (o.inclination < 10)
            {
                errorMessage = Localizer.Format("#MechJeb_AN_error", o.inclination);//"Warning: orbital plane has a low inclination of <<1>>º (recommend > 10º) and so maneuver may not be accurate"
            }
            double UT = timeSelector.ComputeManeuverTime(o, universalTime, target);

            var dV = OrbitalManeuverCalculator.DeltaVToShiftLAN(o, UT, target.targetLongitude);

            return(new ManeuverParameters(dV, UT));
        }
Пример #16
0
        public override ManeuverParameters MakeNodeImpl(Orbit o, double universalTime, MechJebModuleTargetController target)
        {
            double UT = timeSelector.ComputeManeuverTime(o, universalTime, target);

            if (o.referenceBody.Radius + newApA < o.Radius(UT))
            {
                string burnAltitude = MuUtils.ToSI(o.Radius(UT) - o.referenceBody.Radius) + "m";
                throw new OperationException(Localizer.Format("#MechJeb_Ap_Exception", burnAltitude));//new apoapsis cannot be lower than the altitude of the burn (<<1>>)
            }

            return(new ManeuverParameters(OrbitalManeuverCalculator.DeltaVToChangeApoapsis(o, UT, newApA + o.referenceBody.Radius), UT));
        }
Пример #17
0
        /// <summary>
        /// Find the time to a target plane defined by the LAN and inc for a rocket on the ground.
        /// </summary>
        ///
        /// <param name="rotationPeriod">Rotation period of the central body (seconds).</param>
        /// <param name="latitude">Latitude of the launchite (degrees).</param>
        /// <param name="celestialLongitude">Celestial longitude of the current position of the launchsite.</param>
        /// <param name="LAN">Longitude of the Ascending Node of the target plane (degrees).</param>
        /// <param name="inc">Inclination of the target plane (degrees).</param>
        ///
        public static double TimeToPlane(double rotationPeriod, double latitude, double celestialLongitude, double LAN, double inc)
        {
            // alpha is the 90 degree angle between the line of longitude and the equator and omitted
            double beta = OrbitalManeuverCalculator.HeadingForInclination(inc, latitude) * UtilMath.Deg2Rad;
            double c    = Math.Abs(latitude) * UtilMath.Deg2Rad;                                                            // Abs for south hemisphere launch sites
            // b is how many radians to the west of the launch site that the LAN is (east in south hemisphere)
            double b = Math.Atan2(2 * Math.Sin(beta), Math.Cos(beta) / Math.Tan(c / 2) + Math.Tan(c / 2) * Math.Cos(beta)); // napier's analogies
            // LAN if we launched now
            double LANnow = celestialLongitude - Math.Sign(latitude) * b * UtilMath.Rad2Deg;


            return(MuUtils.ClampDegrees360(LAN - LANnow) / 360 * rotationPeriod);
        }
Пример #18
0
        void zeroMissObjectiveFunction(double[] x, double[] fi, object obj, Orbit initial_orbit, CelestialBody target, double UT_transfer, double UT_arrival)
        {
            Vector3d DV = new Vector3d(x[0], x[1], x[2]);

            Orbit orbit;

            OrbitalManeuverCalculator.PatchedConicInterceptBody(initial_orbit, target, DV, UT_transfer, UT_arrival, out orbit);

            Vector3d err = orbit.getTruePositionAtUT(UT_arrival) - target.orbit.getTruePositionAtUT(UT_arrival);

            fi[0] = err.x;
            fi[1] = err.y;
            fi[2] = err.z;
        }
        void DriveCircularizationBurn(FlightCtrlState s)
        {
            if (!vessel.patchedConicsUnlocked() || skipCircularization)
            {
                this.users.Clear();
                return;
            }

            if (placedCircularizeNode)
            {
                if (!vessel.patchedConicSolver.maneuverNodes.Any())
                {
                    MechJebModuleFlightRecorder recorder = core.GetComputerModule <MechJebModuleFlightRecorder>();
                    if (recorder != null)
                    {
                        launchPhaseAngle = recorder.phaseAngleFromMark;
                    }
                    if (recorder != null)
                    {
                        launchLANDifference = vesselState.orbitLAN - recorder.markLAN;
                    }

                    //finished circularize
                    this.users.Clear();
                    return;
                }
            }
            else
            {
                //place circularization node
                vessel.RemoveAllManeuverNodes();
                double UT = orbit.NextApoapsisTime(vesselState.time);
                //Vector3d dV = OrbitalManeuverCalculator.DeltaVToCircularize(orbit, UT);
                Vector3d dV = OrbitalManeuverCalculator.DeltaVForSemiMajorAxis(orbit, UT, desiredOrbitAltitude + mainBody.Radius);
                vessel.PlaceManeuverNode(orbit, dV, UT);
                placedCircularizeNode = true;

                core.node.ExecuteOneNode(this);
            }

            if (core.node.burnTriggered)
            {
                status = "Circularizing";
            }
            else
            {
                status = "Coasting to circularization burn";
            }
        }
Пример #20
0
        public override void OnFixedUpdate()
        {
            if (markUT == 0)
            {
                Mark();
            }

            timeSinceMark = vesselState.time - markUT;

            if (vessel.situation == Vessel.Situations.PRELAUNCH)
            {
                Mark(); //keep resetting stats until we launch
                return;
            }

            gravityLosses += vesselState.deltaT * Vector3d.Dot(-vesselState.surfaceVelocity.normalized, vesselState.gravityForce);
            gravityLosses -= vesselState.deltaT * Vector3d.Dot(vesselState.surfaceVelocity.normalized, vesselState.up * vesselState.radius * Math.Pow(2 * Math.PI / part.vessel.mainBody.rotationPeriod, 2));
            dragLosses    += vesselState.deltaT * vesselState.drag;

            maxDragGees = Math.Max(maxDragGees, vesselState.drag / 9.81);

            double circularPeriod = 2 * Math.PI * vesselState.radius / OrbitalManeuverCalculator.CircularOrbitSpeed(mainBody, vesselState.radius);
            double angleTraversed = (vesselState.longitude - markLongitude) + 360 * (vesselState.time - markUT) / part.vessel.mainBody.rotationPeriod;

            phaseAngleFromMark = MuUtils.ClampDegrees360(360 * (vesselState.time - markUT) / circularPeriod - angleTraversed);

            if (paused)
            {
                return;
            }

            //int oldHistoryIdx = historyIdx;

            //historyIdx = Mathf.Min(Mathf.FloorToInt((float)(timeSinceMark / precision)), history.Length - 1);

            if (vesselState.time >= (lastRecordTime + precision) && historyIdx < history.Length - 1)
            {
                lastRecordTime = vesselState.time;
                historyIdx++;
                Record(historyIdx);
                //if (TimeWarp.WarpMode == TimeWarp.Modes.HIGH)
                //    print("WRP " + historyIdx + " " + history[historyIdx].downRange.ToString("F0") + " " + history[historyIdx].AoA.ToString("F2"));
                //else
                //{
                //    print("STD " + historyIdx + " " + history[historyIdx].downRange.ToString("F0") + " " + history[historyIdx].AoA.ToString("F2"));
                //}
            }
        }
Пример #21
0
        public override ManeuverParameters MakeNodeImpl(Orbit o, double universalTime, MechJebModuleTargetController target)
        {
            if (!target.NormalTargetExists)
            {
                throw new OperationException(Localizer.Format("#MechJeb_match_v_Exception1"));//must select a target to match velocities with.
            }
            else if (o.referenceBody != target.TargetOrbit.referenceBody)
            {
                throw new OperationException(Localizer.Format("#MechJeb_match_v_Exception2"));//target must be in the same sphere of influence.
            }
            double UT = timeSelector.ComputeManeuverTime(o, universalTime, target);

            var dV = OrbitalManeuverCalculator.DeltaVToMatchVelocities(o, UT, target.TargetOrbit);

            return(new ManeuverParameters(dV, UT));
        }
Пример #22
0
        public override void OnFixedUpdate()
        {
            if (ascentPath == null)
            {
                return;
            }

            if (core.target.Target != null && core.target.Name == TARGET_NAME)
            {
                double   angle         = Math.PI / 180 * ascentPath.FlightPathAngle(vesselState.altitudeASL, vesselState.speedSurface);
                double   heading       = Math.PI / 180 * OrbitalManeuverCalculator.HeadingForInclination(desiredInclination, vesselState.latitude);
                Vector3d horizontalDir = Math.Cos(heading) * vesselState.north + Math.Sin(heading) * vesselState.east;
                Vector3d dir           = Math.Cos(angle) * horizontalDir + Math.Sin(angle) * vesselState.up;
                core.target.UpdateDirectionTarget(dir);
            }
        }
Пример #23
0
        public override ManeuverParameters MakeNodeImpl(Orbit o, double universalTime, MechJebModuleTargetController target)
        {
            double UT = timeSelector.ComputeManeuverTime(o, universalTime, target);

            if (2 * newSMA > o.Radius(UT) + o.referenceBody.sphereOfInfluence)
            {
                errorMessage = Localizer.Format("#MechJeb_Sa_errormsg");//Warning: new Semi-Major Axis is very large, and may result in a hyberbolic orbit
            }

            if (o.Radius(UT) > 2 * newSMA)
            {
                throw new OperationException(Localizer.Format("#MechJeb_Sa_Exception") + o.referenceBody.displayName + "(" + MuUtils.ToSI(o.referenceBody.Radius, 3) + "m)");//cannot make Semi-Major Axis less than twice the burn altitude plus the radius of
            }

            return(new ManeuverParameters(OrbitalManeuverCalculator.DeltaVForSemiMajorAxis(o, UT, newSMA), UT));
        }
Пример #24
0
        public override ManeuverParameters MakeNodeImpl(Orbit o, double universalTime, MechJebModuleTargetController target)
        {
            double UT = timeSelector.ComputeManeuverTime(o, universalTime, target);

            if (o.referenceBody.Radius + newPeA > o.Radius(UT))
            {
                string burnAltitude = MuUtils.ToSI(o.Radius(UT) - o.referenceBody.Radius) + "m";
                throw new Exception("new periapsis cannot be higher than the altitude of the burn (" + burnAltitude + ")");
            }
            else if (newPeA < -o.referenceBody.Radius)
            {
                throw new Exception("new periapsis cannot be lower than minus the radius of " + o.referenceBody.theName + "(-" + MuUtils.ToSI(o.referenceBody.Radius, 3) + "m)");
            }

            return(new ManeuverParameters(OrbitalManeuverCalculator.DeltaVToChangePeriapsis(o, UT, newPeA + o.referenceBody.Radius), UT));
        }
Пример #25
0
        void DriveCoastToApoapsis(FlightCtrlState s)
        {
            core.thrust.targetThrottle = 0;

            double circularSpeed       = OrbitalManeuverCalculator.CircularOrbitSpeed(mainBody, orbit.ApR);
            double apoapsisSpeed       = orbit.SwappedOrbitalVelocityAtUT(orbit.NextApoapsisTime(vesselState.time)).magnitude;
            double circularizeBurnTime = (circularSpeed - apoapsisSpeed) / vesselState.limitedMaxThrustAccel;

            //Once we get above the atmosphere, plan and execute the circularization maneuver.
            //For orbits near the edge of the atmosphere, we can't wait until we break the atmosphere
            //to start the burn, so we also compare the timeToAp with the expected circularization burn time.
            //if ((vesselState.altitudeASL > mainBody.RealMaxAtmosphereAltitude())
            //    || (vesselState.limitedMaxThrustAccel > 0 && orbit.timeToAp < circularizeBurnTime / 1.8))

            // Sarbian : removed the special case for now. Some ship where turning whil still in atmosphere
            if (vesselState.altitudeASL > mainBody.RealMaxAtmosphereAltitude())
            {
                mode = AscentMode.CIRCULARIZE;
                core.warp.MinimumWarp();
                return;
            }

            //if our apoapsis has fallen too far, resume the gravity turn
            if (orbit.ApA < desiredOrbitAltitude - 1000.0)
            {
                mode = AscentMode.GRAVITY_TURN;
                core.warp.MinimumWarp();
                return;
            }

            //point prograde and thrust gently if our apoapsis falls below the target
            core.attitude.attitudeTo(Vector3d.forward, AttitudeReference.ORBIT, this);
            core.thrust.targetThrottle = 0;
            if (autoThrottle && orbit.ApA < desiredOrbitAltitude)
            {
                core.thrust.targetThrottle = ThrottleToRaiseApoapsis(orbit.ApR, desiredOrbitAltitude + mainBody.Radius);
            }

            if (core.node.autowarp)
            {
                //warp at x2 physical warp:
                core.warp.WarpPhysicsAtRate(2);
            }

            status = "Coasting to edge of atmosphere";
        }
Пример #26
0
        public override ManeuverParameters MakeNodeImpl(Orbit o, double universalTime, MechJebModuleTargetController target)
        {
            if (!target.NormalTargetExists)
            {
                throw new Exception("must select a target to intercept.");
            }
            if (o.referenceBody != target.TargetOrbit.referenceBody)
            {
                throw new Exception("target must be in the same sphere of influence.");
            }

            double UT = timeSelector.ComputeManeuverTime(o, universalTime, target);

            var dV = OrbitalManeuverCalculator.DeltaVToInterceptAtTime(o, UT, target.TargetOrbit, UT + interceptInterval);

            return(new ManeuverParameters(dV, UT));
        }
Пример #27
0
        public override ManeuverParameters MakeNodeImpl(Orbit o, double universalTime, MechJebModuleTargetController target)
        {
            if (o.eccentricity > 0.2)
            {
                errorMessage = Localizer.Format("#MechJeb_return_errormsg_1") + o.eccentricity.ToString("F2") + Localizer.Format("#MechJeb_return_errormsg_2");//"Warning: Recommend starting moon returns from a near-circular orbit (eccentricity < 0.2). Planned return is starting from an orbit with eccentricity "" and so may not be accurate."
            }

            if (o.referenceBody.referenceBody == null)
            {
                throw new OperationException(o.referenceBody.displayName + Localizer.Format("#MechJeb_return_Exception"));// is not orbiting another body you could return to.
            }

            double   UT;
            Vector3d dV = OrbitalManeuverCalculator.DeltaVAndTimeForMoonReturnEjection(o, universalTime, o.referenceBody.referenceBody.Radius + moonReturnAltitude, out UT);

            return(new ManeuverParameters(dV, UT));
        }
        void DriveVerticalAscent(FlightCtrlState s)
        {
            if (timedLaunch)
            {
                status = "Awaiting liftoff";
                core.attitude.AxisControl(false, false, false);
                return;
            }

            if (!ascentPath.IsVerticalAscent(vesselState.altitudeASL, vesselState.speedSurface))
            {
                mode = AscentMode.GRAVITY_TURN;
            }
            if (autoThrottle && orbit.ApA > desiredOrbitAltitude)
            {
                mode = AscentMode.COAST_TO_APOAPSIS;
            }

            //during the vertical ascent we just thrust straight up at max throttle
            if (forceRoll)
            { // pre-align roll unless correctiveSteering is active as it would just interfere with that
                double desiredHeading = OrbitalManeuverCalculator.HeadingForLaunchInclination(vessel.mainBody, desiredInclination, launchLatitude, OrbitalManeuverCalculator.CircularOrbitSpeed(vessel.mainBody, desiredOrbitAltitude + mainBody.Radius));
                core.attitude.attitudeTo(desiredHeading, 90, verticalRoll, this);
            }
            else
            {
                core.attitude.attitudeTo(Vector3d.up, AttitudeReference.SURFACE_NORTH, this);
            }

            core.attitude.AxisControl(!vessel.Landed, !vessel.Landed, !vessel.Landed && vesselState.altitudeBottom > 50);

            if (autoThrottle)
            {
                core.thrust.targetThrottle = 1.0F;
            }

            if (!vessel.LiftedOff() || vessel.Landed)
            {
                status = "Awaiting liftoff";
            }
            else
            {
                status = "Vertical ascent";
            }
        }
Пример #29
0
        public void TargetPeInsertMatchInc(double PeA, double ApA, double inc, bool omitCoast)
        {
            if (status == PVGStatus.ENABLED)
            {
                return;
            }

            bool doupdate = false;

            double v0m, r0m, sma;

            ConvertToRadVel(PeA, ApA, out r0m, out v0m, out sma);

            if (r0m != old_r0m || v0m != old_v0m || inc != old_inc)
            {
                //Debug.Log("old settings changed");
                doupdate = true;
            }

            if (p == null || doupdate)
            {
                if (p != null)
                {
                    //Debug.Log("killing a thread if its there to kill");
                    p.KillThread();
                }

                //Debug.Log("mainbody.Radius = " + mainBody.Radius);
                //Debug.Log("mainbody.gravParameter = " + mainBody.gravParameter);
                lambdaDot = Vector3d.zero;
                double   desiredHeading       = OrbitalManeuverCalculator.HeadingForInclination(inc, vesselState.latitude);
                Vector3d desiredHeadingVector = Math.Sin(desiredHeading * UtilMath.Deg2Rad) * vesselState.east + Math.Cos(desiredHeading * UtilMath.Deg2Rad) * vesselState.north;
                Vector3d desiredThrustVector  = Math.Cos(45 * UtilMath.Deg2Rad) * desiredHeadingVector + Math.Sin(45 * UtilMath.Deg2Rad) * vesselState.up; /* 45 pitch guess */
                lambda = desiredThrustVector;
                PontryaginLaunch solver = new PontryaginLaunch(core: core, mu: mainBody.gravParameter, r0: vesselState.orbitalPosition, v0: vesselState.orbitalVelocity, pv0: lambda.normalized, pr0: Vector3d.zero, dV: v0m);
                solver.omitCoast = omitCoast;
                solver.flightangle4constraint(r0m, v0m, 0, inc * UtilMath.Deg2Rad);
                p = solver;
            }

            old_v0m = v0m;
            old_r0m = r0m;
            old_inc = inc;
        }
Пример #30
0
        public override ManeuverParameters MakeNodeImpl(Orbit o, double UT, MechJebModuleTargetController target)
        {
            // Check preconditions
            if (!target.NormalTargetExists)
            {
                throw new Exception("must select a target for the interplanetary transfer.");
            }

            if (o.referenceBody.referenceBody == null)
            {
                throw new Exception("doesn't make sense to plot an interplanetary transfer from an orbit around " + o.referenceBody.theName + ".");
            }

            if (o.referenceBody.referenceBody != target.TargetOrbit.referenceBody)
            {
                if (o.referenceBody == target.TargetOrbit.referenceBody)
                {
                    throw new Exception("use regular Hohmann transfer function to intercept another body orbiting " + o.referenceBody.theName + ".");
                }
                throw new Exception("an interplanetary transfer from within " + o.referenceBody.theName + "'s sphere of influence must target a body that orbits " + o.referenceBody.theName + "'s parent, " + o.referenceBody.referenceBody.theName + ".");
            }

            // Simple warnings
            if (o.referenceBody.orbit.RelativeInclination(target.TargetOrbit) > 30)
            {
                errorMessage = "Warning: target's orbital plane is at a " + o.RelativeInclination(target.TargetOrbit).ToString("F0") + "º angle to " + o.referenceBody.theName + "'s orbital plane (recommend at most 30º). Planned interplanetary transfer may not intercept target properly.";
            }
            else
            {
                double relativeInclination = Vector3d.Angle(o.SwappedOrbitNormal(), o.referenceBody.orbit.SwappedOrbitNormal());
                if (relativeInclination > 10)
                {
                    errorMessage = "Warning: Recommend starting interplanetary transfers from " + o.referenceBody.theName + " from an orbit in the same plane as " + o.referenceBody.theName + "'s orbit around " + o.referenceBody.referenceBody.theName + ". Starting orbit around " + o.referenceBody.theName + " is inclined " + relativeInclination.ToString("F1") + "º with respect to " + o.referenceBody.theName + "'s orbit around " + o.referenceBody.referenceBody.theName + " (recommend < 10º). Planned transfer may not intercept target properly.";
                }
                else if (o.eccentricity > 0.2)
                {
                    errorMessage = "Warning: Recommend starting interplanetary transfers from a near-circular orbit (eccentricity < 0.2). Planned transfer is starting from an orbit with eccentricity " + o.eccentricity.ToString("F2") + " and so may not intercept target properly.";
                }
            }

            var dV = OrbitalManeuverCalculator.DeltaVAndTimeForInterplanetaryTransferEjection(o, UT, target.TargetOrbit, waitForPhaseAngle, out UT);

            return(new ManeuverParameters(dV, UT));
        }