Пример #1
0
        void DoMapView()
        {
            if ((MapView.MapIsEnabled || camTrajectory) && !vessel.LandedOrSplashed && this.enabled)
            {
                ReentrySimulation.Result drawnResult = Result;
                if (drawnResult != null)
                {
                    if (drawnResult.outcome == ReentrySimulation.Outcome.LANDED)
                    {
                        GLUtils.DrawGroundMarker(drawnResult.body, drawnResult.endPosition.latitude, drawnResult.endPosition.longitude, Color.blue, MapView.MapIsEnabled, 60);
                    }

                    if (showTrajectory && drawnResult.outcome != ReentrySimulation.Outcome.ERROR && drawnResult.outcome != ReentrySimulation.Outcome.NO_REENTRY)
                    {
                        double interval = Math.Max(Math.Min((drawnResult.endUT - drawnResult.input_UT) / 1000, 10), 0.1);
                        //using (var list = drawnResult.WorldTrajectory(interval, worldTrajectory && MapView.MapIsEnabled))
                        using (var list = drawnResult.WorldTrajectory(interval, worldTrajectory))
                        {
                            if (!MapView.MapIsEnabled && (noSkipToFreefall || vessel.staticPressurekPa > 0))
                            {
                                list.value[0] = vesselState.CoM;
                            }
                            GLUtils.DrawPath(drawnResult.body, list.value, Color.red, MapView.MapIsEnabled);
                        }
                    }
                }
            }
        }
Пример #2
0
 void DoMapView()
 {
     ReentrySimulation.Result drawnResult = GetResult();
     if (MapView.MapIsEnabled && this.enabled && drawnResult != null)
     {
         if (drawnResult.outcome == ReentrySimulation.Outcome.LANDED)
         {
             GLUtils.DrawMapViewGroundMarker(drawnResult.body, drawnResult.endPosition.latitude, drawnResult.endPosition.longitude, Color.blue, 60);
         }
     }
 }
Пример #3
0
        public override void Drive(FlightCtrlState s)
        {
            if (landStep == LandStep.OFF)
            {
                return;
            }

            descentSpeedPolicy = PickDescentSpeedPolicy();

            predictor.descentSpeedPolicy = PickDescentSpeedPolicy(); //create a separate IDescentSpeedPolicy object for the simulation
            predictor.endAltitudeASL     = DecelerationEndAltitude();

            prediction = predictor.GetResult(); //grab a reference to the current result, in case a new one comes in while we're doing stuff

            if (!PredictionReady && landStep != LandStep.DEORBIT_BURN && landStep != LandStep.PLANE_CHANGE && landStep != LandStep.LOW_DEORBIT_BURN &&
                landStep != LandStep.UNTARGETED_DEORBIT && landStep != LandStep.FINAL_DESCENT)
            {
                return;
            }

            switch (landStep)
            {
            case LandStep.UNTARGETED_DEORBIT:
                DriveUntargetedDeorbit(s);
                break;

            case LandStep.PLANE_CHANGE:
                DrivePlaneChange(s);
                break;

            case LandStep.LOW_DEORBIT_BURN:
                DriveLowDeorbitBurn(s);
                break;

            case LandStep.DEORBIT_BURN:
                DriveDeorbitBurn(s);
                break;

            case LandStep.COURSE_CORRECTIONS:
                DriveCourseCorrections(s);
                break;

            case LandStep.KILLING_HORIZONTAL_VELOCITY:
                DriveKillHorizontalVelocity(s);
                break;

            case LandStep.FINAL_DESCENT:
                DriveUntargetedLanding(s);
                break;

            default:
                break;
            }
        }
        public override void Drive(FlightCtrlState s)
        {
            if (!active)
            {
                return;
            }

            // If the latest prediction is a landing, aerobrake or no-reentry prediciton then keep it.
            // However if it is any other sort or result it is not much use to us, so do not bother!
            {
                ReentrySimulation.Result result = predictor.Result;
                if (null != result)
                {
                    if (result.outcome != ReentrySimulation.Outcome.ERROR && result.outcome != ReentrySimulation.Outcome.TIMED_OUT)
                    {
                        this.prediction = result;
                    }
                }
            }
            {
                ReentrySimulation.Result result = predictor.GetErrorResult();
                if (null != result)
                {
                    if (result.outcome != ReentrySimulation.Outcome.ERROR && result.outcome != ReentrySimulation.Outcome.TIMED_OUT)
                    {
                        this.errorPrediction = result;
                    }
                }
            }

            descentSpeedPolicy = PickDescentSpeedPolicy();

            predictor.descentSpeedPolicy            = PickDescentSpeedPolicy(); //create a separate IDescentSpeedPolicy object for the simulation
            predictor.decelEndAltitudeASL           = DecelerationEndAltitude();
            predictor.parachuteSemiDeployMultiplier = this.parachutePlan.Multiplier;

            // Consider lowering the langing gear
            {
                double minalt = Math.Min(vesselState.altitudeBottom, Math.Min(vesselState.altitudeASL, vesselState.altitudeTrue));
                if (deployGears && !deployedGears && (minalt < 1000))
                {
                    DeployLandingGears();
                }
            }

            base.Drive(s);
        }
Пример #5
0
        void DrawGUIPrediction()
        {
            ReentrySimulation.Result result = predictor.Result;
            if (result != null)
            {
                switch (result.outcome)
                {
                case ReentrySimulation.Outcome.LANDED:
                    GUILayout.Label("Landing Predictions:");
                    GUILayout.Label(Coordinates.ToStringDMS(result.endPosition.latitude, result.endPosition.longitude) + "\nASL:" + MuUtils.ToSI(result.endASL, -1, 4) + "m");
                    GUILayout.Label(result.body.GetExperimentBiomeSafe(result.endPosition.latitude, result.endPosition.longitude));
                    double error = Vector3d.Distance(mainBody.GetWorldSurfacePosition(result.endPosition.latitude, result.endPosition.longitude, 0) - mainBody.position,
                                                     mainBody.GetWorldSurfacePosition(core.target.targetLatitude, core.target.targetLongitude, 0) - mainBody.position);
                    GUILayout.Label("Target difference = " + MuUtils.ToSI(error, 0) + "m"
                                    + "\nMax drag: " + result.maxDragGees.ToString("F1") + "g"
                                    + "\nDelta-v needed: " + result.deltaVExpended.ToString("F1") + "m/s"
                                    + "\nTime to land: " + (vessel.Landed ? "0.0s" : GuiUtils.TimeToDHMS(result.endUT - Planetarium.GetUniversalTime(), 1)));
                    break;

                case ReentrySimulation.Outcome.AEROBRAKED:
                    GUILayout.Label("Predicted orbit after aerobraking:");
                    Orbit o = result.AeroBrakeOrbit();
                    if (o.eccentricity > 1)
                    {
                        GUILayout.Label("Hyperbolic, eccentricity = " + o.eccentricity.ToString("F2"));
                    }
                    else
                    {
                        GUILayout.Label(MuUtils.ToSI(o.PeA, 3) + "m x " + MuUtils.ToSI(o.ApA, 3) + "m");
                    }
                    GUILayout.Label("Max drag: " + result.maxDragGees.ToString("F1") + "g"
                                    + "\nExit atmosphere in: " + GuiUtils.TimeToDHMS(result.aeroBrakeUT - Planetarium.GetUniversalTime(), 1));
                    break;

                case ReentrySimulation.Outcome.NO_REENTRY:
                    GUILayout.Label("Orbit does not reenter:\n"
                                    + MuUtils.ToSI(orbit.PeA, 3) + "m Pe > " + MuUtils.ToSI(mainBody.RealMaxAtmosphereAltitude(), 3) + (mainBody.atmosphere ? "m atmosphere height" : "m ground"));
                    break;

                case ReentrySimulation.Outcome.TIMED_OUT:
                    GUILayout.Label("Reentry simulation timed out.");
                    break;
                }
            }
        }
Пример #6
0
        private void CheckForResult()
        {
            lock (readyResults)
            {
                while (readyResults.Count > 0)
                {
                    ReentrySimulation.Result newResult = (ReentrySimulation.Result)readyResults.Dequeue();

                    // If running the simulation resulted in an error then just ignore it.
                    if (newResult.outcome != ReentrySimulation.Outcome.ERROR)
                    {
                        if (newResult.body != null)
                        {
                            newResult.endASL = newResult.body.TerrainAltitude(newResult.endPosition.latitude, newResult.endPosition.longitude);
                        }

                        if (newResult.multiplierHasError)
                        {
                            if (errorResult != null)
                            {
                                errorResult.Release();
                            }
                            errorResult = newResult;
                        }
                        else
                        {
                            if (result != null)
                            {
                                result.Release();
                            }
                            result = newResult;
                        }
                    }
                    else
                    {
                        if (newResult.exception != null)
                        {
                            print("Exception in the last simulation\n" + newResult.exception.Message + "\n" + newResult.exception.StackTrace);
                        }
                        newResult.Release();
                    }
                }
            }
        }
        void DrawGUIPrediction()
        {
            ReentrySimulation.Result result = predictor.GetResult();
            if (result != null)
            {
                switch (result.outcome)
                {
                case ReentrySimulation.Outcome.LANDED:
                    GUILayout.Label("Predicted landing site:");
                    GUILayout.Label(Coordinates.ToStringDMS(result.endPosition.latitude, result.endPosition.longitude));
                    double error = Vector3d.Distance(mainBody.GetRelSurfacePosition(result.endPosition.latitude, result.endPosition.longitude, 0),
                                                     mainBody.GetRelSurfacePosition(core.target.targetLatitude, core.target.targetLongitude, 0));
                    GUILayout.Label("Difference from target = " + MuUtils.ToSI(error, 0) + "m");
                    if (result.maxDragGees > 0)
                    {
                        GUILayout.Label("Predicted max drag gees: " + result.maxDragGees.ToString("F1"));
                    }
                    break;

                case ReentrySimulation.Outcome.AEROBRAKED:
                    GUILayout.Label("Predicted orbit after aerobraking:");
                    Orbit o = result.EndOrbit();
                    if (o.eccentricity > 1)
                    {
                        GUILayout.Label("Hyperbolic, eccentricity = " + o.eccentricity.ToString("F2"));
                    }
                    else
                    {
                        GUILayout.Label(MuUtils.ToSI(o.PeA, 3) + "m x " + MuUtils.ToSI(o.ApA, 3) + "m");
                    }
                    break;

                case ReentrySimulation.Outcome.NO_REENTRY:
                    GUILayout.Label("Orbit does not reenter:");
                    GUILayout.Label(MuUtils.ToSI(orbit.PeA, 3) + "m Pe > " + MuUtils.ToSI(mainBody.RealMaxAtmosphereAltitude(), 3) + "m atmosphere height");
                    break;

                case ReentrySimulation.Outcome.TIMED_OUT:
                    GUILayout.Label("Reentry simulation timed out.");
                    break;
                }
            }
        }
        void DoMapView()
        {
            if (MapView.MapIsEnabled && vessel.isActiveVessel && this.enabled)
            {
                ReentrySimulation.Result drawnResult = GetResult();
                if (drawnResult != null)
                {
                    if (drawnResult.outcome == ReentrySimulation.Outcome.LANDED)
                    {
                        GLUtils.DrawMapViewGroundMarker(drawnResult.body, drawnResult.endPosition.latitude, drawnResult.endPosition.longitude, Color.blue, 60);
                    }

                    if (showTrajectory && drawnResult.outcome != ReentrySimulation.Outcome.ERROR && drawnResult.outcome != ReentrySimulation.Outcome.NO_REENTRY)
                    {
                        double interval = (drawnResult.endUT - drawnResult.input_UT) / 100;
                        GLUtils.DrawPath(drawnResult.body, drawnResult.WorldTrajectory(interval, worldTrajectory), Color.red);
                    }
                }
            }
        }
Пример #9
0
        protected void RunSimulation(object o)
        {
            ReentrySimulation sim = (ReentrySimulation)o;

            ReentrySimulation.Result newResult = sim.RunSimulation();

            result = newResult;

            //see how long the simulation took
            stopwatch.Stop();
            long millisecondsToCompletion = stopwatch.ElapsedMilliseconds;

            stopwatch.Reset();

            //set the delay before the next simulation
            millisecondsBetweenSimulations = 2 * millisecondsToCompletion;

            //start the stopwatch that will count off this delay
            stopwatch.Start();

            simulationRunning = false;
        }
        public override void Drive(FlightCtrlState s)
        {
            if (landStep == LandStep.OFF) return;

            descentSpeedPolicy = PickDescentSpeedPolicy();

            predictor.descentSpeedPolicy = PickDescentSpeedPolicy(); //create a separate IDescentSpeedPolicy object for the simulation
            predictor.endAltitudeASL = DecelerationEndAltitude();

            prediction = predictor.GetResult(); //grab a reference to the current result, in case a new one comes in while we're doing stuff

            if (!PredictionReady && landStep != LandStep.DEORBIT_BURN && landStep != LandStep.PLANE_CHANGE && landStep != LandStep.LOW_DEORBIT_BURN
                && landStep != LandStep.UNTARGETED_DEORBIT && landStep != LandStep.FINAL_DESCENT) return;

            switch (landStep)
            {
                case LandStep.UNTARGETED_DEORBIT:
                    DriveUntargetedDeorbit(s);
                    break;

                case LandStep.PLANE_CHANGE:
                    DrivePlaneChange(s);
                    break;

                case LandStep.LOW_DEORBIT_BURN:
                    DriveLowDeorbitBurn(s);
                    break;

                case LandStep.DEORBIT_BURN:
                    DriveDeorbitBurn(s);
                    break;

                case LandStep.COURSE_CORRECTIONS:
                    DriveCourseCorrections(s);
                    break;

                case LandStep.KILLING_HORIZONTAL_VELOCITY:
                    DriveKillHorizontalVelocity(s);
                    break;

                case LandStep.FINAL_DESCENT:
                    DriveUntargetedLanding(s);
                    break;

                default:
                    break;
            }
        }
        protected void RunSimulation(object o)
        {
            try
            {
                ReentrySimulation sim = (ReentrySimulation)o;
                ReentrySimulation.Result newResult = sim.RunSimulation();

                if (newResult.multiplierHasError)
                {
                    // If running the simualtion resulted in an error then just ignore it.
                    if (ReentrySimulation.Outcome.ERROR != newResult.outcome)
                    {
                        errorResult = newResult;
                    }

                    //see how long the simulation took
                    errorStopwatch.Stop();
                    long millisecondsToCompletion = errorStopwatch.ElapsedMilliseconds;

                    errorStopwatch.Reset();

                    //set the delay before the next simulation
                    millisecondsBetweenErrorSimulations = Math.Min(Math.Max(4 * millisecondsToCompletion, 400), 5); // Note that we are going to run the simualtions with error in less often that the real simulations

                    //start the stopwatch that will count off this delay
                    errorStopwatch.Start();
                    errorSimulationRunning = false;
                }
                else
                {
                    // If running the simualtion resulted in an error then just ignore it.
                    if (ReentrySimulation.Outcome.ERROR != newResult.outcome)
                    {
                        result = newResult;
                    }
                    //see how long the simulation took
                    stopwatch.Stop();
                    long millisecondsToCompletion = stopwatch.ElapsedMilliseconds;
                    stopwatch.Reset();

                    //set the delay before the next simulation
                    millisecondsBetweenSimulations = Math.Min(Math.Max(2 * millisecondsToCompletion, 200), 5); // Do not wait for too long before running another simulation, but also give the processor a rest.

                    // How long should we set the max_dt to be in the future? Calculate for interationsPerSecond runs per second. If we do not enter the atmosphere, however do not do so as we will complete so quickly, it is not a good guide to how long the reentry simulation takes.
                    if (newResult.outcome == ReentrySimulation.Outcome.AEROBRAKED || newResult.outcome == ReentrySimulation.Outcome.LANDED)
                    {
                        if (this.variabledt)
                        {
                            dt = (newResult.maxdt * ((double)millisecondsToCompletion / (double)1000)) / ((double)1 / ((double)3 * (double)interationsPerSecond));
                            // There is no point in having a dt that is smaller than the physics frame rate as we would be trying to be more precise than the game.
                            dt = Math.Max(dt, sim.min_dt);
                            // Set a sensible upper limit to dt as well. - in this case 10 seconds
                            dt = Math.Min(dt, 10);
                        }
                    }

                    // TODO remove debugging
                    //Debug.Log("Result:" + this.result.outcome + " Time to run: " + millisecondsToCompletion + " millisecondsBetweenSimulations: " + millisecondsBetweenSimulations + " new dt: " + dt + " Time.fixedDeltaTime " + Time.fixedDeltaTime + "\n" + this.result.ToString()); // Note the endASL will be zero as it has not yet been calculated, and we are not allowed to calculate it from this thread :(

                    //start the stopwatch that will count off this delay
                    stopwatch.Start();
                    simulationRunning = false;
                }
            }
            catch (Exception ex)
            {
                Debug.Log("Exception in MechJebModuleLandingPredictions.RunSimulation\n" + ex.StackTrace);
                Debug.LogException(ex);
            }
        }
        // Incorporates a new simulation result into the simulation data set and calculate a new semi deployment multiplier. If the data set has a poor correlation, then it might just leave the mutiplier. If the correlation becomes positive then it will clear the dataset and start again.
        public void AddResult(ReentrySimulation.Result newResult)
        {
            // if this result is the same as the old result, then it is not new!
            if (newResult.multiplierHasError)
            {
                if (lastErrorResult != null)
                {
                    if (newResult.id == lastErrorResult.id)
                    {
                        return;
                    }
                }
                lastErrorResult = newResult;
            }
            else
            {
                if (lastResult != null)
                {
                    if (newResult.id == lastResult.id)
                    {
                        return;
                    }
                }
                lastResult = newResult;
            }

            // What was the overshoot for this new result?
            double overshoot = newResult.GetOvershoot(this.autoPilot.core.target.targetLatitude, this.autoPilot.core.target.targetLongitude);

            //Debug.Log("overshoot: " + overshoot.ToString("F2") + " multiplier: " + newResult.parachuteMultiplier.ToString("F4") + " hasError:" + newResult.multiplierHasError);

            // Add the new result to the linear regression
            regression.Add(overshoot, newResult.parachuteMultiplier);

            // What is the correlation coefficent of the data. If it is weak a correlation then we will dismiss the dataset and use it to change the current multiplier
            correlation = regression.CorrelationCoefficent;
            if (correlation > -0.2) // TODO this is the best value to test for non-correlation?
            {
                // If the correlation is less that 0 then we will give up controlling the parachutes and throw away the dataset. Also check that we have got several bits of data, just in case we get two datapoints that are badly correlated.
                if (correlation > 0 && this.regression.dataSetSize > 5)
                {
                    ClearData();
                    // Debug.Log("Giving up control of the parachutes as the data does not correlate: " + correlation);
                }
                else
                {
                    // Debug.Log("Ignoring the simulation dataset because the correlation is not significant enough: " + correlation);
                }
            }
            else
            {
                // How much data is there? If just one datapoint then we need to slightly vary the multplier to avoid doing exactly the same multiplier again and getting a divide by zero!. If there is just two then we will not update the multiplier as we can't conclude much from two points of data!
                int dataSetSize = regression.dataSetSize;
                if (dataSetSize == 1)
                {
                    this.currentMultiplier *= 0.99999;
                }
                else if (dataSetSize == 2)
                {
                    // Doing nothing
                }
                else
                {
                    // Use the linear regression to give us a new prediciton for when to open the parachutes
                    try
                    {
                        this.currentMultiplier = regression.yIntercept;
                    }
                    catch (Exception)
                    {
                        // If there is not enough data then we expect an exception. However we need to vary the multiplier everso slightly so that we get different data in order to start generating data. This should never happen as we have already checked the size of the dataset.
                        this.currentMultiplier *= 0.99999;
                    }
                }

                // Impose sensible limits on the multiplier
                if (this.currentMultiplier < 1 || double.IsNaN(currentMultiplier))
                {
                    this.currentMultiplier = 1;
                }
                if (this.currentMultiplier > this.maxMultiplier)
                {
                    this.currentMultiplier = this.maxMultiplier;
                }
            }

            return;
        }
 private void CheckForResult()
 {
     lock (readyResults)
     {
         while (readyResults.Count > 0)
         {
             ReentrySimulation.Result newResult = readyResults.Dequeue();
             
             // If running the simulation resulted in an error then just ignore it.
             if (newResult.outcome != ReentrySimulation.Outcome.ERROR)
             {
                 if (newResult.body != null)
                     newResult.endASL = newResult.body.TerrainAltitude(newResult.endPosition.latitude, newResult.endPosition.longitude);
                 
                 if (newResult.multiplierHasError)
                 {
                     if (errorResult != null)
                         errorResult.Release();
                     errorResult = newResult;
                 }
                 else
                 {
                     if (result != null)
                         result.Release();
                     result = newResult;
                 }
             }
             else
             {
                 if (newResult.exception != null)
                     print("Exception in the last simulation\n" + newResult.exception.Message + "\n" + newResult.exception.StackTrace);
                 newResult.Release();
             }
         }
     }
 }
        protected void RunSimulation(object o)
        {
            try
            {
                ReentrySimulation        sim       = (ReentrySimulation)o;
                ReentrySimulation.Result newResult = sim.RunSimulation();

                if (newResult.multiplierHasError)
                {
                    // If running the simualtion resulted in an error then just ignore it.
                    if (ReentrySimulation.Outcome.ERROR != newResult.outcome)
                    {
                        errorResult = newResult;
                    }

                    //see how long the simulation took
                    errorStopwatch.Stop();
                    long millisecondsToCompletion = errorStopwatch.ElapsedMilliseconds;

                    errorStopwatch.Reset();

                    //set the delay before the next simulation
                    millisecondsBetweenErrorSimulations = Math.Min(Math.Max(4 * millisecondsToCompletion, 400), 5); // Note that we are going to run the simualtions with error in less often that the real simulations

                    //start the stopwatch that will count off this delay
                    errorStopwatch.Start();
                    errorSimulationRunning = false;
                }
                else
                {
                    // If running the simualtion resulted in an error then just ignore it.
                    if (ReentrySimulation.Outcome.ERROR != newResult.outcome)
                    {
                        result = newResult;
                    }
                    //see how long the simulation took
                    stopwatch.Stop();
                    long millisecondsToCompletion = stopwatch.ElapsedMilliseconds;
                    stopwatch.Reset();

                    //set the delay before the next simulation
                    millisecondsBetweenSimulations = Math.Min(Math.Max(2 * millisecondsToCompletion, 200), 5); // Do not wait for too long before running another simulation, but also give the processor a rest.

                    // How long should we set the max_dt to be in the future? Calculate for interationsPerSecond runs per second. If we do not enter the atmosphere, however do not do so as we will complete so quickly, it is not a good guide to how long the reentry simulation takes.
                    if (newResult.outcome == ReentrySimulation.Outcome.AEROBRAKED || newResult.outcome == ReentrySimulation.Outcome.LANDED)
                    {
                        if (this.variabledt)
                        {
                            dt = (newResult.maxdt * ((double)millisecondsToCompletion / (double)1000)) / ((double)1 / ((double)3 * (double)interationsPerSecond));
                            // There is no point in having a dt that is smaller than the physics frame rate as we would be trying to be more precise than the game.
                            dt = Math.Max(dt, (double)Time.fixedDeltaTime);
                            // Set a sensible upper limit to dt as well. - in this case 10 seconds
                            dt = Math.Min(dt, 10);
                        }
                    }

                    // TODO remove debugging
                    //Debug.Log("Result:" + this.result.outcome + " Time to run: " + millisecondsToCompletion + " millisecondsBetweenSimulations: " + millisecondsBetweenSimulations + " new dt: " + dt + " Time.fixedDeltaTime " + Time.fixedDeltaTime + "\n" + this.result.ToString()); // Note the endASL will be zero as it has not yet been calculated, and we are not allowed to calculate it from this thread :(

                    //start the stopwatch that will count off this delay
                    stopwatch.Start();
                    simulationRunning = false;
                }
            }
            catch (Exception ex)
            {
                Debug.Log("Exception in MechJebModuleLandingPredictions.RunSimulation\n" + ex.StackTrace);
                Debug.LogException(ex);
            }
        }
        public override void Drive(FlightCtrlState s)
        {
            if (!active)
                return;

            // If the latest prediction is a landing, aerobrake or no-reentry prediciton then keep it.
            // However if it is any other sort or result it is not much use to us, so do not bother!
            {
                ReentrySimulation.Result result = predictor.Result;
                if (null != result)
                {
                    if (result.outcome != ReentrySimulation.Outcome.ERROR && result.outcome != ReentrySimulation.Outcome.TIMED_OUT)
                    {
                        this.prediction = result;
                    }
                }
            }
            {
                ReentrySimulation.Result result = predictor.GetErrorResult();
                if (null != result)
                {
                    if (result.outcome != ReentrySimulation.Outcome.ERROR && result.outcome != ReentrySimulation.Outcome.TIMED_OUT)
                    {
                        this.errorPrediction = result;
                    }
                }
            }

            descentSpeedPolicy = PickDescentSpeedPolicy();

            PatchPredictorPolicy();

            // Consider lowering the langing gear
            {
                double minalt = Math.Min(vesselState.altitudeBottom, Math.Min(vesselState.altitudeASL, vesselState.altitudeTrue));
                if (deployGears && !deployedGears && (minalt < 1000))
                    DeployLandingGears();
            }

            base.Drive(s);
        }
Пример #16
0
        private void RunSimulation(object o)
        {
            ReentrySimulation sim = (ReentrySimulation)o;

            try
            {
                ReentrySimulation.Result newResult = sim.RunSimulation();

                lock (readyResults)
                {
                    readyResults.Enqueue(newResult);
                }

                if (newResult.multiplierHasError)
                {
                    //see how long the simulation took
                    errorStopwatch.Stop();
                    long millisecondsToCompletion = errorStopwatch.ElapsedMilliseconds;
                    lastErrorSimTime  = millisecondsToCompletion * 0.001;
                    lastErrorSimSteps = newResult.steps;

                    errorStopwatch.Reset();

                    //set the delay before the next simulation
                    millisecondsBetweenErrorSimulations = Math.Min(Math.Max(4 * millisecondsToCompletion, 400), 5);
                    // Note that we are going to run the simulations with error in less often that the real simulations

                    //start the stopwatch that will count off this delay
                    errorStopwatch.Start();
                    errorSimulationRunning = false;
                }
                else
                {
                    //see how long the simulation took
                    stopwatch.Stop();
                    long millisecondsToCompletion = stopwatch.ElapsedMilliseconds;
                    stopwatch.Reset();

                    //set the delay before the next simulation
                    millisecondsBetweenSimulations = Math.Min(Math.Max(2 * millisecondsToCompletion, 200), 5);
                    lastSimTime  = millisecondsToCompletion * 0.001;
                    lastSimSteps = newResult.steps;
                    // Do not wait for too long before running another simulation, but also give the processor a rest.

                    // How long should we set the max_dt to be in the future? Calculate for interationsPerSecond runs per second. If we do not enter the atmosphere, however do not do so as we will complete so quickly, it is not a good guide to how long the reentry simulation takes.
                    if (newResult.outcome == ReentrySimulation.Outcome.AEROBRAKED ||
                        newResult.outcome == ReentrySimulation.Outcome.LANDED)
                    {
                        if (this.variabledt)
                        {
                            dt = newResult.maxdt * (millisecondsToCompletion / 1000d) / (1d / (3d * interationsPerSecond));
                            // There is no point in having a dt that is smaller than the physics frame rate as we would be trying to be more precise than the game.
                            dt = Math.Max(dt, sim.min_dt);
                            // Set a sensible upper limit to dt as well. - in this case 10 seconds
                            dt = Math.Min(dt, 10);
                        }
                    }

                    //Debug.Log("Result:" + this.result.outcome + " Time to run: " + millisecondsToCompletion + " millisecondsBetweenSimulations: " + millisecondsBetweenSimulations + " new dt: " + dt + " Time.fixedDeltaTime " + Time.fixedDeltaTime + "\n" + this.result.ToString()); // Note the endASL will be zero as it has not yet been calculated, and we are not allowed to calculate it from this thread :(

                    //start the stopwatch that will count off this delay
                    stopwatch.Start();
                    simulationRunning = false;
                }
            }
            catch (Exception ex)
            {
                //Debug.Log(string.Format("Exception in MechJebModuleLandingPredictions.RunSimulation\n{0}", ex.StackTrace));
                //Debug.LogException(ex);
                Dispatcher.InvokeAsync(() => Debug.LogException(ex));
            }
            finally
            {
                sim.Release();
            }
        }
        public override void Drive(FlightCtrlState s)
        {
            if (landStep == LandStep.OFF) return;

            // If the latest prediction is a landing, aerobrake or no-reentry prediciton then keep it. However if it is any other sort or result it is not much use to us, so do not bother!
            {
                ReentrySimulation.Result result = predictor.GetResult();
                if (null != result)
                {
                    if (result.outcome != ReentrySimulation.Outcome.ERROR && result.outcome != ReentrySimulation.Outcome.TIMED_OUT)
                    {
                        this.prediction = result;
                    }
                }
            }
            {
                ReentrySimulation.Result result = predictor.GetErrorResult();
                if (null != result)
                {
                    if (result.outcome != ReentrySimulation.Outcome.ERROR && result.outcome != ReentrySimulation.Outcome.TIMED_OUT)
                    {
                        this.errorPrediction = result;
                    }
                }
            }

            descentSpeedPolicy = PickDescentSpeedPolicy();

            predictor.descentSpeedPolicy = PickDescentSpeedPolicy(); //create a separate IDescentSpeedPolicy object for the simulation
            predictor.decelEndAltitudeASL = DecelerationEndAltitude();
            predictor.parachuteSemiDeployMultiplier = this.parachutePlan.Multiplier;

            // Consider lowering the langing gear
            {
                double minalt = Math.Min(vesselState.altitudeBottom, Math.Min(vesselState.altitudeASL, vesselState.altitudeTrue));
                if (deployGears && !deployedGears && (minalt < 1000)) DeployLandingGears();
            }

            if (!PredictionReady && landStep != LandStep.DEORBIT_BURN && landStep != LandStep.PLANE_CHANGE && landStep != LandStep.LOW_DEORBIT_BURN
                && landStep != LandStep.UNTARGETED_DEORBIT && landStep != LandStep.FINAL_DESCENT) return;

            switch (landStep)
            {
                case LandStep.UNTARGETED_DEORBIT:
                    DriveUntargetedDeorbit(s);
                    break;

                case LandStep.PLANE_CHANGE:
                    DrivePlaneChange(s);
                    break;

                case LandStep.LOW_DEORBIT_BURN:
                    DriveLowDeorbitBurn(s);
                    break;

                case LandStep.DEORBIT_BURN:
                    DriveDeorbitBurn(s);
                    break;

                case LandStep.COURSE_CORRECTIONS:
                    DriveCourseCorrections(s);
                    break;

                case LandStep.KILLING_HORIZONTAL_VELOCITY:
                    DriveKillHorizontalVelocity(s);
                    break;

                case LandStep.FINAL_DESCENT:
                    DriveUntargetedLanding(s);
                    break;

                default:
                    break;
            }
        }
        protected void RunSimulation(object o)
        {
            ReentrySimulation sim = (ReentrySimulation)o;

            ReentrySimulation.Result newResult = sim.RunSimulation();

            result = newResult;

            //see how long the simulation took
            stopwatch.Stop();
            long millisecondsToCompletion = stopwatch.ElapsedMilliseconds;
            stopwatch.Reset();

            //set the delay before the next simulation
            millisecondsBetweenSimulations = 2 * millisecondsToCompletion;

            //start the stopwatch that will count off this delay
            stopwatch.Start();

            simulationRunning = false;
        }
        // Incorporates a new simulation result into the simulation data set and calculate a new semi deployment multiplier. If the data set has a poor correlation, then it might just leave the mutiplier. If the correlation becomes positive then it will clear the dataset and start again.
        public void AddResult(ReentrySimulation.Result newResult)
        {
            // if this result is the same as the old result, then it is not new!
            if (newResult.multiplierHasError)
            {
                if (lastErrorResult != null)
                {
                    if (newResult.id == lastErrorResult.id) { return; }
                }
                lastErrorResult = newResult;
            }
            else
            {
                if (lastResult != null)
                {
                    if (newResult.id == lastResult.id) { return; }
                }
                lastResult = newResult;
            }
            
            // What was the overshoot for this new result?
            double overshoot = newResult.GetOvershoot(this.autoPilot.core.target.targetLatitude, this.autoPilot.core.target.targetLongitude);

            //Debug.Log("overshoot: " + overshoot.ToString("F2") + " multiplier: " + newResult.parachuteMultiplier.ToString("F4") + " hasError:" + newResult.multiplierHasError);

            // Add the new result to the linear regression
            regression.Add(overshoot, newResult.parachuteMultiplier);

            // What is the correlation coefficent of the data. If it is weak a correlation then we will dismiss the dataset and use it to change the current multiplier
            correlation = regression.CorrelationCoefficent;
            if (correlation > -0.2) // TODO this is the best value to test for non-correlation?
            {
                // If the correlation is less that 0 then we will give up controlling the parachutes and throw away the dataset. Also check that we have got several bits of data, just in case we get two datapoints that are badly correlated.
                if (correlation > 0 && this.regression.dataSetSize > 5)
                {
                    ClearData();
                    // Debug.Log("Giving up control of the parachutes as the data does not correlate: " + correlation);
                }
                else
                {
                    // Debug.Log("Ignoring the simulation dataset because the correlation is not significant enough: " + correlation);
                }
            }
            else
            {
                // How much data is there? If just one datapoint then we need to slightly vary the multplier to avoid doing exactly the same multiplier again and getting a divide by zero!. If there is just two then we will not update the multiplier as we can't conclude much from two points of data!  
                int dataSetSize = regression.dataSetSize;
                if (dataSetSize == 1)
                {
                    this.currentMultiplier *= 0.99999;
                }
                else if (dataSetSize == 2)
                {
                    // Doing nothing
                }
                else
                {
                    // Use the linear regression to give us a new prediciton for when to open the parachutes
                    try
                    {
                        this.currentMultiplier = regression.yIntercept;
                    }
                    catch (Exception)
                    {
                        // If there is not enough data then we expect an exception. However we need to vary the multiplier everso slightly so that we get different data in order to start generating data. This should never happen as we have already checked the size of the dataset.
                        this.currentMultiplier *= 0.99999;
                    }
                }

                // Impose sensible limits on the multiplier
                if (this.currentMultiplier < 1 || double.IsNaN(currentMultiplier)) { this.currentMultiplier = 1; }
                if (this.currentMultiplier > this.maxMultiplier) { this.currentMultiplier = this.maxMultiplier; }
            }

            return;
        }
Пример #20
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();
                }
            }
        }