Esempio n. 1
0
            public VelPoint(AeroPredictor vessel, CelestialBody body, float altitude, float speed)
            {
                this.altitude = altitude;
                this.speed    = speed;
                AeroPredictor.Conditions conditions = new AeroPredictor.Conditions(body, speed, altitude);
                float gravParameter, radius;

                lock (body)
                {
                    gravParameter = (float)body.gravParameter;
                    radius        = (float)body.Radius;
                }
                this.mach            = conditions.mach;
                this.dynamicPressure = 0.0005f * conditions.atmDensity * speed * speed;
                float   weight = (vessel.Mass * gravParameter / ((radius + altitude) * (radius + altitude))) - (vessel.Mass * speed * speed / (radius + altitude));
                Vector3 thrustForce = vessel.GetThrustForce(conditions);

                AoA_max          = vessel.GetMaxAoA(conditions, out Lift_max);
                AoA_level        = Mathf.Min(vessel.GetAoA(conditions, weight), AoA_max);
                pitchInput       = vessel.GetPitchInput(conditions, AoA_level);
                Thrust_available = thrustForce.magnitude;
                Vector3 force = vessel.GetAeroForce(conditions, AoA_level, pitchInput);

                drag          = AeroPredictor.GetDragForceMagnitude(force, AoA_level);
                Thrust_excess = -drag - AeroPredictor.GetDragForceMagnitude(thrustForce, AoA_level);
                Accel_excess  = Thrust_excess / vessel.Mass / WindTunnelWindow.gAccel;
                LDRatio       = Mathf.Abs(AeroPredictor.GetLiftForceMagnitude(force, AoA_level) / drag);
                dLift         = (vessel.GetLiftForceMagnitude(conditions, AoA_level + WindTunnelWindow.AoAdelta, pitchInput) -
                                 vessel.GetLiftForceMagnitude(conditions, AoA_level, pitchInput)) / (WindTunnelWindow.AoAdelta * Mathf.Rad2Deg);
            }
Esempio n. 2
0
 public GenData(AeroPredictor vessel, Conditions conditions, float speed, CalculationManager manager)
 {
     this.vessel     = vessel;
     this.conditions = conditions;
     this.speed      = speed;
     this.storeState = manager.GetStateToken();
 }
Esempio n. 3
0
        private IEnumerator ProcessOptimalLine(string graphName, AeroPredictor vessel, Conditions conditions, float exitSpeed, float exitAlt, float initialSpeed, float initialAlt, CostIncreaseFunction costIncreaseFunc, Predicate <float> neighborPredicate, float[,] predicateData, CostIncreaseFunction timeDifferenceFunc)
        {
            CalculationManager singleUseManager = new CalculationManager();
            LineGenData        lineGenData      = new LineGenData(singleUseManager, vessel, conditions, exitSpeed, exitAlt, initialSpeed, initialAlt, costIncreaseFunc, neighborPredicate, predicateData, timeDifferenceFunc);

            ThreadPool.QueueUserWorkItem(OptimalLineTask, lineGenData);
            while (!singleUseManager.Completed)
            {
                yield return(0);
            }
            List <AscentPathPoint> results = (List <AscentPathPoint>)lineGenData.state.Result;

            if (timeDifferenceFunc != costIncreaseFunc)
            {
                ((MetaLineGraph)graphables[graphName]).SetValues(results.Select(pt => new Vector2(pt.speed, pt.altitude)).ToArray(), new float[][] { results.Select(pt => pt.climbAngle * Mathf.Rad2Deg).ToArray(), results.Select(pt => pt.climbRate).ToArray(), results.Select(pt => pt.cost).ToArray(), results.Select(pt => pt.time).ToArray() });
            }
            else
            {
                ((MetaLineGraph)graphables[graphName]).SetValues(results.Select(pt => new Vector2(pt.speed, pt.altitude)).ToArray(), new float[][] { results.Select(pt => pt.climbAngle * Mathf.Rad2Deg).ToArray(), results.Select(pt => pt.climbRate).ToArray(), results.Select(pt => pt.cost).ToArray() });
            }
            //this.GetOptimalPath(vessel, conditions, 1410, 17700, 0, 0, fuelToClimb, f => f > 0, excessP).Select(pt => new Vector2(pt.speed, pt.altitude)).ToArray());
            //((LineGraph)graphables["Time-Optimal Path"]).SetValues(
            //this.GetOptimalPath(vessel, conditions, 1410, 17700, 0, 0, timeToClimb, f => f > 0, excessP).Select(pt => new Vector2(pt.speed, pt.altitude)).ToArray());
            singleUseManager.Dispose();
        }
Esempio n. 4
0
        public void Calculate(AeroPredictor vessel, CelestialBody body, float altitude, float speed, float lowerBound = -20f, float upperBound = 20f, float step = 0.5f)
        {
            Conditions newConditions = new Conditions(body, altitude, speed, lowerBound, upperBound, step);

            if (newConditions.Equals(currentConditions))
            {
                valuesSet = true;
                return;
            }

            Cancel();

            if (!cache.TryGetValue(newConditions, out AoAPoints))
            {
                WindTunnelWindow.Instance.StartCoroutine(Processing(calculationManager, newConditions, vessel));
            }
            else
            {
                AverageLiftSlope          = AoAPoints.Select(pt => pt.dLift / pt.dynamicPressure).Where(v => !float.IsNaN(v) && !float.IsInfinity(v)).Average();
                currentConditions         = newConditions;
                calculationManager.Status = CalculationManager.RunStatus.Completed;
                UpdateGraphs();
                valuesSet = true;
            }
        }
        public static SimulatedEngine Borrow(ModuleEngines module, AeroPredictor vessel)
        {
            SimulatedEngine engine = pool.Borrow();

            engine.vessel = vessel;
            // This is possibly dangerous and may lead to NullReferenceException
            engine.Init(module, null);
            return(engine);
        }
            public EnvelopePoint(AeroPredictor vessel, CelestialBody body, float altitude, float speed, float AoA_guess = float.NaN, float maxA_guess = float.NaN, float pitchI_guess = float.NaN)
            {
                this.altitude = altitude;
                this.speed    = speed;
                AeroPredictor.Conditions conditions = new AeroPredictor.Conditions(body, speed, altitude);
                float gravParameter, radius;

                lock (body)
                {
                    gravParameter = (float)body.gravParameter;
                    radius        = (float)body.Radius;
                }
                this.mach            = conditions.mach;
                this.dynamicPressure = 0.0005f * conditions.atmDensity * speed * speed;
                float   weight = (vessel.Mass * gravParameter / ((radius + altitude) * (radius + altitude))); // TODO: Minus centrifugal force...
                Vector3 thrustForce = vessel.GetThrustForce(conditions);

                //AoA_max = vessel.GetMaxAoA(conditions, out Lift_max, maxA_guess);
                if (float.IsNaN(maxA_guess))
                {
                    AoA_max = vessel.GetMaxAoA(conditions, out Lift_max, maxA_guess);
                }
                else
                {
                    AoA_max  = maxA_guess;
                    Lift_max = AeroPredictor.GetLiftForceMagnitude(vessel.GetAeroForce(conditions, AoA_max, 1) + thrustForce, AoA_max);
                }

                AoA_level = vessel.GetAoA(conditions, weight, guess: AoA_guess, pitchInputGuess: 0, lockPitchInput: true);
                if (AoA_level < AoA_max)
                {
                    pitchInput = vessel.GetPitchInput(conditions, AoA_level, guess: pitchI_guess);
                }
                else
                {
                    pitchInput = 1;
                }

                Thrust_available = thrustForce.magnitude;
                force            = vessel.GetAeroForce(conditions, AoA_level, pitchInput);
                liftforce        = AeroPredictor.ToFlightFrame(force, AoA_level); //vessel.GetLiftForce(body, speed, altitude, AoA_level, mach, atmDensity);
                drag             = AeroPredictor.GetDragForceMagnitude(force, AoA_level);
                float lift = AeroPredictor.GetLiftForceMagnitude(force, AoA_level);

                Thrust_excess = -drag - AeroPredictor.GetDragForceMagnitude(thrustForce, AoA_level);
                if (weight > Lift_max)// AoA_level >= AoA_max)
                {
                    Thrust_excess = Lift_max - weight;
                    AoA_level     = AoA_max;
                }
                Accel_excess = (Thrust_excess / vessel.Mass / WindTunnelWindow.gAccel);
                LDRatio      = Mathf.Abs(lift / drag);
                dLift        = (vessel.GetLiftForceMagnitude(conditions, AoA_level + WindTunnelWindow.AoAdelta, pitchInput) -
                                vessel.GetLiftForceMagnitude(conditions, AoA_level, pitchInput)) / (WindTunnelWindow.AoAdelta * Mathf.Rad2Deg);
            }
 public GenData(AeroPredictor vessel, Conditions conditions, float speed, float altitude, CalculationManager manager, float AoA_guess = float.NaN, float maxA_guess = float.NaN, float pitchI_guess = float.NaN)
 {
     this.vessel       = vessel;
     this.conditions   = conditions;
     this.speed        = speed;
     this.altitude     = altitude;
     this.storeState   = manager.GetStateToken();
     this.AoA_guess    = AoA_guess;
     this.maxA_guess   = maxA_guess;
     this.pitchI_guess = pitchI_guess;
 }
Esempio n. 8
0
 public LineGenData(CalculationManager manager, AeroPredictor vessel, Conditions conditions, float exitSpeed, float exitAlt, float initialSpeed, float initialAlt, CostIncreaseFunction costIncreaseFunc, Predicate <float> neighborPredicate, float[,] predicateData, CostIncreaseFunction timeDifferenceFunc)
 {
     this.state              = manager.GetStateToken();
     this.vessel             = vessel;
     this.conditions         = conditions;
     this.exitSpeed          = exitSpeed;
     this.exitAlt            = exitAlt;
     this.initialSpeed       = initialSpeed;
     this.initialAlt         = initialAlt;
     this.costIncreaseFunc   = costIncreaseFunc;
     this.timeDifferenceFunc = timeDifferenceFunc;
     this.neighborPredicate  = neighborPredicate;
     this.predicateData      = predicateData;
 }
Esempio n. 9
0
        public override void OnAxesChanged(AeroPredictor vessel, float xMin, float xMax, float yMin, float yMax, float zMin, float zMax)
        {
            const float variance = 0.75f;
            const int   numPts   = 125;

            if (!currentConditions.Contains(currentConditions.Modify(lowerBound: xMin, upperBound: xMax)))
            {
                Calculate(vessel, currentConditions.body, currentConditions.altitude, xMin, xMax, (xMax - xMin) / numPts);
            }
            else if (currentConditions.step > (xMax - xMin / numPts) / variance)
            {
                Calculate(vessel, currentConditions.body, currentConditions.altitude, xMin, xMax, (xMax - xMin) / numPts);
            }
        }
Esempio n. 10
0
        public void Calculate(AeroPredictor vessel, CelestialBody body, float lowerBoundSpeed = 0, float upperBoundSpeed = 2000, float stepSpeed = 50f, float lowerBoundAltitude = 0, float upperBoundAltitude = 60000, float stepAltitude = 500)
        {
            Conditions newConditions = new Conditions(body, lowerBoundSpeed, upperBoundSpeed, stepSpeed, lowerBoundAltitude, upperBoundAltitude, stepAltitude);

            if (currentConditions.Equals(newConditions) && calculationManager.Status != CalculationManager.RunStatus.PreStart)
            {
                return;
            }

            Cancel();

            bool       loadedCache = false;
            Conditions loadedConditions;

            if (cache.TryGetValue(newConditions, out envelopePoints))
            {
                loadedCache       = true;
                loadedConditions  = cachedConditions[newConditions];
                currentConditions = loadedConditions;
            }
            else if (TryGetContaining(newConditions, out loadedConditions, out envelopePoints))
            {
                loadedCache       = true;
                currentConditions = loadedConditions;
            }
            if (loadedCache)
            {
                calculationManager.Status = CalculationManager.RunStatus.Completed;
                UpdateGraphs();
                valuesSet = true;

                if (loadedConditions.stepSpeed > stepSpeed || loadedConditions.stepAltitude > stepAltitude)
                {
                    WindTunnel.Instance.StartCoroutine(RefinementProcessing(calculationManager, newConditions, vessel, envelopePoints, loadedConditions,
                                                                            new Queue <Conditions>(new Conditions[] { newConditions.Modify(stepSpeed: stepSpeed / 2, stepAltitude: stepAltitude / 2) }), true));
                }
                else if (loadedConditions.stepSpeed > stepSpeed / 2 || loadedConditions.stepAltitude > stepAltitude / 2)
                {
                    WindTunnel.Instance.StartCoroutine(RefinementProcessing(calculationManager, newConditions, vessel, envelopePoints, loadedConditions, forcePushToGraph: true));
                }

                return;
            }

            WindTunnel.Instance.StartCoroutine(Processing(calculationManager, newConditions, vessel));
        }
Esempio n. 11
0
        public override void OnAxesChanged(AeroPredictor vessel, float xMin, float xMax, float yMin, float yMax, float zMin, float zMax)
        {
            const float variance = 0.5f;
            const int   numPts   = 80;

            xMin = (xMin < -180 ? -180 : xMin) * Mathf.Deg2Rad;
            xMax = (xMax > 180 ? 180 : xMax) * Mathf.Deg2Rad;
            float step = Mathf.Min(2 * Mathf.Deg2Rad, (xMax - xMin) / numPts * Mathf.Deg2Rad);

            if (!currentConditions.Contains(currentConditions.Modify(lowerBound: xMin, upperBound: xMax)))
            {
                Calculate(vessel, currentConditions.body, currentConditions.altitude, currentConditions.speed, xMin, xMax, step);
            }
            else if (currentConditions.step > step / variance)
            {
                Calculate(vessel, currentConditions.body, currentConditions.altitude, currentConditions.speed, xMin, xMax, step);
            }
        }
Esempio n. 12
0
        public void CalculateOptimalLines(AeroPredictor vessel, Conditions conditions, float exitSpeed, float exitAlt, float initialSpeed, float initialAlt)
        {
            float[,] accel    = envelopePoints.SelectToArray(pt => pt.Accel_excess * WindTunnelWindow.gAccel);
            float[,] burnRate = envelopePoints.SelectToArray(pt => pt.fuelBurnRate);
            CostIncreaseFunction timeToClimb = (current, last) =>
            {
                float dE = Mathf.Abs(WindTunnelWindow.gAccel * (last.y - current.y) / ((current.x + last.x) / 2) + (last.x - current.x));
                float P  = (accel[current.xi, current.yi] + accel[last.xi, last.yi]) / 2;
                return(dE / P);
            };
            CostIncreaseFunction fuelToClimb = (current, last) =>
            {
                float dF = (burnRate[current.xi, current.yi] + burnRate[last.xi, last.yi]) / 2;
                return(timeToClimb(current, last) * dF);
            };

            WindTunnelWindow.Instance.StartCoroutine(ProcessOptimalLine("Fuel-Optimal Path", vessel, conditions, exitSpeed, exitAlt, initialSpeed, initialAlt, fuelToClimb, f => f > 0, accel, timeToClimb));
            WindTunnelWindow.Instance.StartCoroutine(ProcessOptimalLine("Time-Optimal Path", vessel, conditions, exitSpeed, exitAlt, initialSpeed, initialAlt, timeToClimb, f => f > 0, accel, timeToClimb));
        }
Esempio n. 13
0
            public AoAPoint(AeroPredictor vessel, CelestialBody body, float altitude, float speed, float AoA)
            {
                this.altitude = altitude;
                this.speed    = speed;
                AeroPredictor.Conditions conditions = new AeroPredictor.Conditions(body, speed, altitude);
                this.AoA             = AoA;
                this.mach            = conditions.mach;
                this.dynamicPressure = 0.0005f * conditions.atmDensity * speed * speed;
                this.pitchInput      = vessel.GetPitchInput(conditions, AoA);
                this.pitchInput_dry  = vessel.GetPitchInput(conditions, AoA, true);
                Vector3 force = AeroPredictor.ToFlightFrame(vessel.GetAeroForce(conditions, AoA, pitchInput), AoA);

                torque     = vessel.GetAeroTorque(conditions, AoA).x;
                torque_dry = vessel.GetAeroTorque(conditions, AoA, 0, true).x;
                Lift       = force.y;
                Drag       = -force.z;
                LDRatio    = Mathf.Abs(Lift / Drag);
                dLift      = (vessel.GetLiftForceMagnitude(conditions, AoA + WindTunnelWindow.AoAdelta, pitchInput) - Lift) /
                             (WindTunnelWindow.AoAdelta * Mathf.Rad2Deg);
            }
Esempio n. 14
0
        public void Calculate(AeroPredictor vessel, CelestialBody body, float altitude, float lowerBound = 0, float upperBound = 2000, float step = 50)
        {
            Conditions newConditions = new Conditions(body, altitude, lowerBound, upperBound, step);

            if (newConditions.Equals(currentConditions))
            {
                valuesSet = true;
                return;
            }

            Cancel();

            if (!cache.TryGetValue(newConditions, out VelPoints))
            {
                WindTunnel.Instance.StartCoroutine(Processing(calculationManager, newConditions, vessel));
            }
            else
            {
                currentConditions         = newConditions;
                calculationManager.Status = CalculationManager.RunStatus.Completed;
                UpdateGraphs();
                valuesSet = true;
            }
        }
Esempio n. 15
0
        private IEnumerator Processing(CalculationManager manager, Conditions conditions, AeroPredictor vessel)
        {
            int numPts = (int)Math.Ceiling((conditions.upperBound - conditions.lowerBound) / conditions.step);

            VelPoint[] newVelPoints = new VelPoint[numPts + 1];
            float      trueStep     = (conditions.upperBound - conditions.lowerBound) / numPts;

            CalculationManager.State[] results = new CalculationManager.State[numPts + 1];

            for (int i = 0; i <= numPts; i++)
            {
                //newAoAPoints[i] = new AoAPoint(vessel, conditions.body, conditions.altitude, conditions.speed, conditions.lowerBound + trueStep * i);
                GenData genData = new GenData(vessel, conditions, conditions.lowerBound + trueStep * i, manager);
                results[i] = genData.storeState;
                ThreadPool.QueueUserWorkItem(GenerateVelPoint, genData);
            }

            while (!manager.Completed)
            {
                if (manager.Status == CalculationManager.RunStatus.Cancelled)
                {
                    yield break;
                }
                yield return(0);
            }

            for (int i = 0; i <= numPts; i++)
            {
                newVelPoints[i] = (VelPoint)results[i].Result;
            }
            if (!manager.Cancelled)
            {
                cache.Add(conditions, newVelPoints);
                VelPoints         = newVelPoints;
                currentConditions = conditions;
                UpdateGraphs();
                valuesSet = true;
            }
        }
        private static void GenerateLevel(Conditions conditions, CalculationManager manager, ref CalculationManager.State[,] results, AeroPredictor vessel)
        {
            float[,] AoAs_guess = null, maxAs_guess = null, pitchIs_guess = null;
            if (results != null)
            {
                AoAs_guess    = results.SelectToArray(pt => ((EnvelopePoint)pt.Result).AoA_level);
                maxAs_guess   = results.SelectToArray(pt => ((EnvelopePoint)pt.Result).AoA_max);
                pitchIs_guess = results.SelectToArray(pt => ((EnvelopePoint)pt.Result).pitchInput);
            }
            int   numPtsX   = (int)Math.Ceiling((conditions.upperBoundSpeed - conditions.lowerBoundSpeed) / conditions.stepSpeed);
            int   numPtsY   = (int)Math.Ceiling((conditions.upperBoundAltitude - conditions.lowerBoundAltitude) / conditions.stepAltitude);
            float trueStepX = (conditions.upperBoundSpeed - conditions.lowerBoundSpeed) / numPtsX;
            float trueStepY = (conditions.upperBoundAltitude - conditions.lowerBoundAltitude) / numPtsY;

            results = new CalculationManager.State[numPtsX + 1, numPtsY + 1];

            for (int j = 0; j <= numPtsY; j++)
            {
                for (int i = 0; i <= numPtsX; i++)
                {
                    if (manager.Cancelled)
                    {
                        return;
                    }
                    float x         = (float)i / numPtsX;
                    float y         = (float)j / numPtsY;
                    float aoa_guess = AoAs_guess != null?AoAs_guess.Lerp2(x, y) : float.NaN;

                    float maxA_guess = maxAs_guess != null?maxAs_guess.Lerp2(x, y) : float.NaN;

                    float pi_guess = pitchIs_guess != null?pitchIs_guess.Lerp2(x, y) : float.NaN;

                    GenData genData = new GenData(vessel, conditions, conditions.lowerBoundSpeed + trueStepX * i, conditions.lowerBoundAltitude + trueStepY * j, manager, aoa_guess, maxA_guess, pi_guess);
                    results[i, j] = genData.storeState;
                    ThreadPool.QueueUserWorkItem(GenerateSurfPoint, genData);
                }
            }
        }
Esempio n. 17
0
        private List <AscentPathPoint> GetOptimalPath(AeroPredictor vessel, Conditions conditions, float exitSpeed, float exitAlt, float initialSpeed, float initialAlt, CostIncreaseFunction costIncreaseFunc, Predicate <float> neighborPredicate, float[,] predicateData, CostIncreaseFunction timeFunc)
        {
            System.Diagnostics.Stopwatch stopwatch    = new System.Diagnostics.Stopwatch();
            System.Diagnostics.Stopwatch profileWatch = new System.Diagnostics.Stopwatch();
            long[] sections = new long[3];
            stopwatch.Start();

            EnvelopePointExtensions.UniqueQueue <Coords> queue = new EnvelopePointExtensions.UniqueQueue <Coords>(500);
            Coords baseCoord = new Coords(conditions.lowerBoundSpeed, conditions.lowerBoundAltitude, conditions.stepSpeed, conditions.stepAltitude, Mathf.RoundToInt((conditions.upperBoundSpeed - conditions.lowerBoundSpeed) / conditions.stepSpeed) + 1, Mathf.RoundToInt((conditions.upperBoundAltitude - conditions.lowerBoundAltitude) / conditions.stepAltitude) + 1);

            float rangeX = (conditions.upperBoundSpeed - conditions.lowerBoundSpeed) - conditions.stepSpeed;
            float rangeY = (conditions.upperBoundAltitude - conditions.lowerBoundAltitude) - conditions.stepAltitude;

            profileWatch.Start();
            float[,] costMatrix = new float[baseCoord.width, baseCoord.height];
            costMatrix.SetAll(float.MaxValue);

            baseCoord = new Coords(exitSpeed, exitAlt, baseCoord);
            if (!neighborPredicate(predicateData.Lerp2(exitSpeed / rangeX, exitAlt / rangeY)))
            {
                IEnumerator <CoordLocator> exitCoordFinder = CoordLocator.GenerateCoordLocators(predicateData).GetTaxicabNeighbors(baseCoord.xi, baseCoord.yi, -1, Linq2.Quadrant.II, Linq2.Quadrant.III, Linq2.Quadrant.IV);
                while (exitCoordFinder.MoveNext() && !neighborPredicate(exitCoordFinder.Current.value))
                {
                }
                baseCoord = new Coords(exitCoordFinder.Current.x, exitCoordFinder.Current.y, baseCoord);
                exitSpeed = baseCoord.x; exitAlt = baseCoord.y;
            }

            costMatrix[baseCoord.xi, baseCoord.yi] = 0;
            foreach (Coords c in baseCoord.GetNeighbors(neighborPredicate, predicateData))
            {
                queue.Enqueue(c);
            }

            Coords coord;

            while (queue.Count > 0)
            {
                coord = queue.Dequeue();
                List <Coords> neighbors    = coord.GetNeighbors(neighborPredicate, predicateData);
                Coords        bestNeighbor = neighbors[0];
                float         bestCost     = costMatrix[bestNeighbor.xi, bestNeighbor.yi];
                for (int i = neighbors.Count - 1; i >= 1; i--)
                {
                    if (costMatrix[neighbors[i].xi, neighbors[i].yi] < bestCost)
                    {
                        bestNeighbor = neighbors[i];
                        bestCost     = costMatrix[bestNeighbor.xi, bestNeighbor.yi];
                    }
                }
                float newCost = bestCost + costIncreaseFunc(coord, bestNeighbor);
                if (newCost < costMatrix[coord.xi, coord.yi])
                {
                    costMatrix[coord.xi, coord.yi] = newCost;
                    neighbors.Remove(bestNeighbor);
                    for (int i = neighbors.Count - 1; i >= 0; i--)
                    {
                        if (costMatrix[neighbors[i].xi, neighbors[i].yi] > newCost)
                        {
                            queue.Enqueue(neighbors[i]);
                        }
                    }
                }
            }
            profileWatch.Stop();
            sections[0] = profileWatch.ElapsedMilliseconds;
            profileWatch.Reset();
            profileWatch.Start();

            float[,] gradientx = new float[baseCoord.width - 1, baseCoord.height - 1];
            float[,] gradienty = new float[baseCoord.width - 1, baseCoord.height - 1];
            for (int i = baseCoord.width - 2; i >= 0; i--)
            {
                for (int j = baseCoord.height - 2; j >= 0; j--)
                {
                    gradientx[i, j] = ((costMatrix[i + 1, j] - costMatrix[i, j]) + (costMatrix[i + 1, j + 1] - costMatrix[i, j + 1])) / 2 / conditions.stepAltitude;
                    gradienty[i, j] = ((costMatrix[i, j + 1] - costMatrix[i, j]) + (costMatrix[i + 1, j + 1] - costMatrix[i + 1, j])) / 2 / conditions.stepSpeed;
                }
            }
            profileWatch.Stop();
            sections[1] = profileWatch.ElapsedMilliseconds;
            profileWatch.Reset();
            profileWatch.Start();

            /*new Graphing.SurfGraph(costMatrix, conditions.lowerBoundSpeed, conditions.upperBoundSpeed, conditions.lowerBoundAltitude, conditions.upperBoundAltitude).
             *  WriteToFile("costMatrix");
             * new Graphing.SurfGraph(gradientx, conditions.lowerBoundSpeed + conditions.stepSpeed / 2, conditions.upperBoundSpeed - conditions.stepSpeed / 2, conditions.lowerBoundAltitude + conditions.stepAltitude / 2, conditions.upperBoundAltitude - conditions.stepAltitude / 2).
             *  WriteToFile("gradientX");
             * new Graphing.SurfGraph(gradienty, conditions.lowerBoundSpeed + conditions.stepSpeed / 2, conditions.upperBoundSpeed - conditions.stepSpeed / 2, conditions.lowerBoundAltitude + conditions.stepAltitude / 2, conditions.upperBoundAltitude - conditions.stepAltitude / 2).
             *  WriteToFile("gradientY");*/

            List <AscentPathPoint> result = new List <AscentPathPoint>(300);

            int iter = -1;

            coord = new Coords(initialSpeed, initialAlt, baseCoord);
            coord = new Coords(costMatrix.First(0, 0, f => f >= initialSpeed && f < float.MaxValue / 100) + 1, coord.yi, baseCoord);
            Coords lastCoord = coord;
            float  lastCost = 0, lastTime = 0;

            while (true)
            {
                iter++;
                if (iter % 10 == 0)
                {
                    //result.Add(new EnvelopePoint(vessel, conditions.body, coord.y, coord.x));
                    if (result.Count > 0)
                    {
                        lastCost = result[result.Count - 1].cost;
                        lastTime = result[result.Count - 1].time;
                    }
                    result.Add(new AscentPathPoint(coord.x, coord.y, costIncreaseFunc(coord, lastCoord) + lastCost, (coord.y - lastCoord.y) / timeFunc(coord, lastCoord), timeFunc(coord, lastCoord) + lastTime));
                    float dx = (coord.x - lastCoord.x) / rangeX;
                    float dy = (coord.y - lastCoord.y) / rangeY;
                    float r  = Mathf.Sqrt(dx * dx + dy * dy);
                    //Debug.LogFormat("{0}\t{1}\t{2}", coord.x, coord.y, r);
                    lastCoord = coord;
                    if (r < 0.00001f && iter > 0)
                    {
                        break;
                    }
                }
                float xW = (coord.x - conditions.stepSpeed / 2) / rangeX;
                float yW = (coord.y - conditions.stepAltitude / 2) / rangeY;
                if (Mathf.Abs(coord.x - exitSpeed) < 10 && Mathf.Abs(coord.y - exitAlt) < 100)
                {
                    break;
                }
                try
                {
                    Vector2 d = new Vector2(gradientx.Lerp2(xW, yW), gradienty.Lerp2(xW, yW));
                    if (d.sqrMagnitude <= 0)
                    {
                        break;
                    }
                    float step = 5 / Mathf.Sqrt(d.x * d.x + (d.y * conditions.stepSpeed / conditions.stepAltitude) * (d.y * conditions.stepSpeed / conditions.stepAltitude));
                    coord = coord.Offset(-d * step);
                }
                catch (Exception ex)
                {
                    Debug.Log("Exception in gradient finding.");
                    Debug.Log(iter);
                    Debug.Log("xW: " + xW + " yW: " + yW);
                    throw ex;
                }
            }
            coord = new Coords(exitSpeed, exitAlt, lastCoord);
            if (result.Count > 0)
            {
                lastCost = result[result.Count - 1].cost;
                lastTime = result[result.Count - 1].time;
            }
            result.Add(new AscentPathPoint(coord.x, coord.y, costIncreaseFunc(coord, lastCoord) + lastCost, (coord.y - lastCoord.y) / timeFunc(coord, lastCoord), timeFunc(coord, lastCoord) + lastTime));
            profileWatch.Stop();
            stopwatch.Stop();

            Debug.Log("Time: " + stopwatch.ElapsedMilliseconds + "  Iterations: " + iter);
            Debug.Log("Costing: " + sections[0] + " Gradients: " + sections[1] + " Minimizing: " + profileWatch.ElapsedMilliseconds);
            return(result);
        }
Esempio n. 18
0
        private IEnumerator Processing(CalculationManager manager, Conditions conditions, AeroPredictor vessel)
        {
            int numPtsX = (int)Math.Ceiling((conditions.upperBoundSpeed - conditions.lowerBoundSpeed) / conditions.stepSpeed);
            int numPtsY = (int)Math.Ceiling((conditions.upperBoundAltitude - conditions.lowerBoundAltitude) / conditions.stepAltitude);

            EnvelopePoint[,] newEnvelopePoints = new EnvelopePoint[numPtsX + 1, numPtsY + 1];

            GenData rootData = new GenData(vessel, conditions, 0, 0, manager);

            //System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
            //timer.Start();
            ThreadPool.QueueUserWorkItem(SetupInBackground, rootData, true);

            while (!manager.Completed)
            {
                //Debug.Log(manager.PercentComplete + "% done calculating...");
                if (manager.Status == CalculationManager.RunStatus.Cancelled)
                {
                    yield break;
                }
                yield return(0);
            }
            //timer.Stop();
            //Debug.Log("Time taken: " + timer.ElapsedMilliseconds / 1000f);

            newEnvelopePoints = ((CalculationManager.State[, ])rootData.storeState.Result)
                                .SelectToArray(pt => (EnvelopePoint)pt.Result);

            AddToCache(conditions, newEnvelopePoints);
            if (!manager.Cancelled)
            {
                envelopePoints    = newEnvelopePoints;
                currentConditions = conditions;
                UpdateGraphs();
                CalculateOptimalLines(vessel, conditions, WindTunnelWindow.Instance.TargetSpeed, WindTunnelWindow.Instance.TargetAltitude, 0, 0);

                valuesSet = true;
            }
            yield return(0);

            if (!manager.Cancelled)
            {
                Conditions nextConditions = conditions.Modify(stepSpeed: conditions.stepSpeed / 2, stepAltitude: conditions.stepAltitude / 2);
                WindTunnel.Instance.StartCoroutine(RefinementProcessing(calculationManager, nextConditions, vessel, newEnvelopePoints, conditions));
            }
        }
Esempio n. 19
0
        private IEnumerator RefinementProcessing(CalculationManager manager, Conditions conditions, AeroPredictor vessel, EnvelopePoint[,] basisData, Conditions basisConditions = new Conditions(), Queue <Conditions> followOnConditions = null, bool forcePushToGraph = false)
        {
            int numPtsX = (int)Math.Ceiling((conditions.upperBoundSpeed - conditions.lowerBoundSpeed) / conditions.stepSpeed);
            int numPtsY = (int)Math.Ceiling((conditions.upperBoundAltitude - conditions.lowerBoundAltitude) / conditions.stepAltitude);

            EnvelopePoint[,] newEnvelopePoints = new EnvelopePoint[numPtsX + 1, numPtsY + 1];

            CalculationManager backgroundManager = new CalculationManager();

            manager.OnCancelCallback           += backgroundManager.Cancel;
            CalculationManager.State[,] results = new CalculationManager.State[numPtsX + 1, numPtsY + 1];
            GenData rootData = new GenData(vessel, conditions, 0, 0, backgroundManager);

            ThreadPool.QueueUserWorkItem(ContinueInBackground, new object[] { rootData, results, basisData, basisConditions });
            while (!backgroundManager.Completed)
            {
                if (manager.Status == CalculationManager.RunStatus.Cancelled)
                {
                    backgroundManager.Cancel();
                    yield break;
                }
                yield return(0);
            }
            manager.OnCancelCallback -= backgroundManager.Cancel;

            newEnvelopePoints = ((CalculationManager.State[, ])rootData.storeState.Result)
                                .SelectToArray(pt => (EnvelopePoint)pt.Result);

            AddToCache(conditions, newEnvelopePoints);
            if (currentConditions.Equals(conditions) || (forcePushToGraph && !backgroundManager.Cancelled))
            {
                envelopePoints    = newEnvelopePoints;
                currentConditions = conditions;
                UpdateGraphs();
                valuesSet = true;
            }
            backgroundManager.Dispose();
            if (!manager.Cancelled && followOnConditions != null && followOnConditions.Count > 0)
            {
                yield return(0);

                Conditions nextConditions = followOnConditions.Dequeue();
                WindTunnel.Instance.StartCoroutine(RefinementProcessing(manager, nextConditions, vessel, newEnvelopePoints, conditions, followOnConditions, forcePushToGraph));
            }
        }
Esempio n. 20
0
        public EnvelopePoint(AeroPredictor vessel, CelestialBody body, float altitude, float speed, float AoA_guess = float.NaN, float maxA_guess = float.NaN, float pitchI_guess = float.NaN)
        {
            this.altitude = altitude;
            this.speed    = speed;
            AeroPredictor.Conditions conditions = new AeroPredictor.Conditions(body, speed, altitude);
            float gravParameter, radius;

            gravParameter        = (float)body.gravParameter;
            radius               = (float)body.Radius;
            this.mach            = conditions.mach;
            this.dynamicPressure = 0.0005f * conditions.atmDensity * speed * speed;
            float   weight = (vessel.Mass * gravParameter / ((radius + altitude) * (radius + altitude))) - (vessel.Mass * speed * speed / (radius + altitude));
            Vector3 thrustForce = vessel.GetThrustForce(conditions);

            fuelBurnRate = vessel.GetFuelBurnRate(conditions);
            //AoA_max = vessel.GetMaxAoA(conditions, out Lift_max, maxA_guess);
            if (float.IsNaN(maxA_guess))
            {
                AoA_max = vessel.GetMaxAoA(conditions, out Lift_max, maxA_guess);
                //Lift_max = AeroPredictor.GetLiftForceMagnitude(vessel.GetAeroForce(conditions, AoA_max, 1) + thrustForce, AoA_max);
            }
            else
            {
                AoA_max  = maxA_guess;
                Lift_max = AeroPredictor.GetLiftForceMagnitude(vessel.GetAeroForce(conditions, AoA_max, 1) + thrustForce, AoA_max);
            }

            AoA_level = vessel.GetAoA(conditions, weight, guess: AoA_guess, pitchInputGuess: 0, lockPitchInput: true);
            if (AoA_level < AoA_max)
            {
                pitchInput = vessel.GetPitchInput(conditions, AoA_level, guess: pitchI_guess);
            }
            else
            {
                pitchInput = 1;
            }

            if (speed < 5 && Math.Abs(altitude) < 10)
            {
                AoA_level = 0;
            }

            Thrust_available = thrustForce.magnitude;

            //vessel.GetAeroCombined(conditions, AoA_level, pitchInput, out force, out Vector3 torque);
            force     = vessel.GetAeroForce(conditions, AoA_level, pitchInput);
            aeroforce = AeroPredictor.ToFlightFrame(force, AoA_level); //vessel.GetLiftForce(body, speed, altitude, AoA_level, mach, atmDensity);
            drag      = -aeroforce.z;
            float lift = aeroforce.y;

            Thrust_excess = -drag - AeroPredictor.GetDragForceMagnitude(thrustForce, AoA_level);
            if (weight > Lift_max)// AoA_level >= AoA_max)
            {
                Thrust_excess = Lift_max - weight;
                AoA_level     = AoA_max;
            }
            Accel_excess = (Thrust_excess / vessel.Mass / WindTunnelWindow.gAccel);
            LDRatio      = Math.Abs(lift / drag);
            dLift        = (vessel.GetLiftForceMagnitude(conditions, AoA_level + WindTunnelWindow.AoAdelta, pitchInput) - lift)
                           / (WindTunnelWindow.AoAdelta * Mathf.Rad2Deg);
            //stabilityDerivative = (vessel.GetAeroTorque(conditions, AoA_level + WindTunnelWindow.AoAdelta, pitchInput).x - torque.x)
            //    / (WindTunnelWindow.AoAdelta * Mathf.Rad2Deg);
            //GetStabilityValues(vessel, conditions, AoA_level, out stabilityRange, out stabilityScore);

            completed = true;
        }
        private IEnumerator Processing(CalculationManager manager, Conditions conditions, AeroPredictor vessel)
        {
            int numPtsX = (int)Math.Ceiling((conditions.upperBoundSpeed - conditions.lowerBoundSpeed) / conditions.stepSpeed);
            int numPtsY = (int)Math.Ceiling((conditions.upperBoundAltitude - conditions.lowerBoundAltitude) / conditions.stepAltitude);

            EnvelopePoint[,] newEnvelopePoints = new EnvelopePoint[numPtsX + 1, numPtsY + 1];

            GenData rootData = new GenData(vessel, conditions, 0, 0, manager);

            ThreadPool.QueueUserWorkItem(SetupInBackground, rootData);

            while (!manager.Completed)
            {
                //Debug.Log(manager.PercentComplete + "% done calculating...");
                if (manager.Status == CalculationManager.RunStatus.Cancelled)
                {
                    yield break;
                }
                yield return(0);
            }

            newEnvelopePoints = ((CalculationManager.State[, ])rootData.storeState.Result)
                                .SelectToArray(pt => (EnvelopePoint)pt.Result);

            if (!manager.Cancelled)
            {
                //cache.Add(conditions, newEnvelopePoints);
                AddToCache(conditions, newEnvelopePoints);
                envelopePoints    = newEnvelopePoints;
                currentConditions = conditions;
                GenerateGraphs();
                valuesSet = true;
            }

            float stepSpeed = conditions.stepSpeed, stepAltitude = conditions.stepAltitude;

            for (int i = 2; i <= 2; i++)
            {
                yield return(0);

                CalculationManager backgroundManager = new CalculationManager();
                manager.OnCancelCallback += backgroundManager.Cancel;
                conditions = new Conditions(conditions.body, conditions.lowerBoundSpeed, conditions.upperBoundSpeed,
                                            stepSpeed / i, conditions.lowerBoundAltitude, conditions.upperBoundAltitude, stepAltitude / i);
                CalculationManager.State[,] prevResults = ((CalculationManager.State[, ])rootData.storeState.Result).SelectToArray(p => p);
                rootData = new GenData(vessel, conditions, 0, 0, backgroundManager);
                ThreadPool.QueueUserWorkItem(ContinueInBackground, new object[] { rootData, prevResults });
                while (!backgroundManager.Completed)
                {
                    if (manager.Status == CalculationManager.RunStatus.Cancelled)
                    {
                        backgroundManager.Cancel();
                        yield break;
                    }
                    yield return(0);
                }

                newEnvelopePoints = ((CalculationManager.State[, ])rootData.storeState.Result)
                                    .SelectToArray(pt => (EnvelopePoint)pt.Result);

                if (!manager.Cancelled)
                {
                    //cache.Add(conditions, newEnvelopePoints);
                    AddToCache(conditions, newEnvelopePoints);
                    envelopePoints    = newEnvelopePoints;
                    currentConditions = conditions;
                    UpdateGraphs();
                    valuesSet = true;
                }
            }
        }
Esempio n. 22
0
        private static void GenerateLevel(Conditions conditions, CalculationManager manager, ref CalculationManager.State[,] results, AeroPredictor vessel, Conditions basisConditions = new Conditions(), EnvelopePoint[,] resultPoints = null)
        {
            float[,] AoAs_guess = null, maxAs_guess = null, pitchIs_guess = null;
            if (resultPoints != null)
            {
                AoAs_guess    = resultPoints.SelectToArray(pt => pt.AoA_level);
                maxAs_guess   = resultPoints.SelectToArray(pt => pt.AoA_max);
                pitchIs_guess = resultPoints.SelectToArray(pt => pt.pitchInput);
            }
            else if (results != null)
            {
                AoAs_guess    = results.SelectToArray(pt => ((EnvelopePoint)pt.Result).AoA_level);
                maxAs_guess   = results.SelectToArray(pt => ((EnvelopePoint)pt.Result).AoA_max);
                pitchIs_guess = results.SelectToArray(pt => ((EnvelopePoint)pt.Result).pitchInput);
                resultPoints  = results.SelectToArray(pt => (EnvelopePoint)pt.Result);
            }
            int   numPtsX   = (int)Math.Ceiling((conditions.upperBoundSpeed - conditions.lowerBoundSpeed) / conditions.stepSpeed);
            int   numPtsY   = (int)Math.Ceiling((conditions.upperBoundAltitude - conditions.lowerBoundAltitude) / conditions.stepAltitude);
            float trueStepX = (conditions.upperBoundSpeed - conditions.lowerBoundSpeed) / numPtsX;
            float trueStepY = (conditions.upperBoundAltitude - conditions.lowerBoundAltitude) / numPtsY;

            results = new CalculationManager.State[numPtsX + 1, numPtsY + 1];

            for (int j = 0; j <= numPtsY; j++)
            {
                for (int i = 0; i <= numPtsX; i++)
                {
                    if (manager.Cancelled)
                    {
                        return;
                    }
                    float x         = (float)i / numPtsX;
                    float y         = (float)j / numPtsY;
                    float aoa_guess = AoAs_guess != null?AoAs_guess.Lerp2(x, y) : float.NaN;

                    float maxA_guess = maxAs_guess != null?maxAs_guess.Lerp2(x, y) : float.NaN;

                    float pi_guess = pitchIs_guess != null?pitchIs_guess.Lerp2(x, y) : float.NaN;

                    float   speed    = conditions.lowerBoundSpeed + trueStepX * i;
                    float   altitude = conditions.lowerBoundAltitude + trueStepY * j;
                    GenData genData  = new GenData(vessel, conditions, speed, altitude, manager, aoa_guess, maxA_guess, pi_guess);
                    results[i, j] = genData.storeState;
                    if (!basisConditions.Equals(Conditions.Blank) && !basisConditions.Equals(new Conditions()) &&
                        basisConditions.Contains(speed, altitude, out int ii, out int jj))
                    {
                        results[i, j].StoreResult(resultPoints[ii, jj]);
                    }
Esempio n. 23
0
        private static void GetStabilityValues(AeroPredictor vessel, AeroPredictor.Conditions conditions, float AoA_centre, out float stabilityRange, out float stabilityScore)
        {
            const int step       = 5;
            const int range      = 90;
            const int alphaSteps = range / step;

            float[] torques = new float[2 * alphaSteps + 1];
            float[] aoas = new float[2 * alphaSteps + 1];
            int     start, end;

            for (int i = 0; i <= 2 * alphaSteps; i++)
            {
                aoas[i]    = (i - alphaSteps) * step * Mathf.Deg2Rad;
                torques[i] = vessel.GetAeroTorque(conditions, aoas[i], 0).x;
            }
            int eq  = 0 + alphaSteps;
            int dir = (int)Math.Sign(torques[eq]);

            if (dir == 0)
            {
                start = eq - 1;
                end   = eq + 1;
            }
            else
            {
                while (eq > 0 && eq < 2 * alphaSteps)
                {
                    eq += dir;
                    if (Math.Sign(torques[eq]) != dir)
                    {
                        break;
                    }
                }
                if (eq == 0 || eq == 2 * alphaSteps)
                {
                    stabilityRange = 0;
                    stabilityScore = 0;
                    return;
                }
                if (dir < 0)
                {
                    start = eq;
                    end   = eq + 1;
                }
                else
                {
                    start = eq - 1;
                    end   = eq;
                }
            }
            while (torques[start] > 0 && start > 0)
            {
                start -= 1;
            }
            while (torques[end] < 0 && end < 2 * alphaSteps - 1)
            {
                end += 1;
            }
            float min = (Mathf.InverseLerp(torques[start], torques[start + 1], 0) + start) * step;
            float max = (-Mathf.InverseLerp(torques[end], torques[end - 1], 0) + end) * step;

            stabilityRange = max - min;
            stabilityScore = 0;
            for (int i = start; i < end; i++)
            {
                stabilityScore += (torques[i] + torques[i + 1]) / 2 * step;
            }
        }
Esempio n. 24
0
        private IEnumerator Processing(CalculationManager manager, Conditions conditions, AeroPredictor vessel)
        {
            int numPts = (int)Math.Ceiling((conditions.upperBound - conditions.lowerBound) / conditions.step);

            AoAPoint[] newAoAPoints = new AoAPoint[numPts + 1];
            float      trueStep     = (conditions.upperBound - conditions.lowerBound) / numPts;

            CalculationManager.State[] results = new CalculationManager.State[numPts + 1];

            for (int i = 0; i <= numPts; i++)
            {
                //newAoAPoints[i] = new AoAPoint(vessel, conditions.body, conditions.altitude, conditions.speed, conditions.lowerBound + trueStep * i);
                GenData genData = new GenData(vessel, conditions, conditions.lowerBound + trueStep * i, manager);
                results[i] = genData.storeState;
                ThreadPool.QueueUserWorkItem(GenerateAoAPoint, genData);
            }

            while (!manager.Completed)
            {
                if (manager.Status == CalculationManager.RunStatus.Cancelled)
                {
                    yield break;
                }
                yield return(0);
            }

            for (int i = 0; i <= numPts; i++)
            {
                newAoAPoints[i] = (AoAPoint)results[i].Result;
            }
            if (!manager.Cancelled)
            {
                cache.Add(conditions, newAoAPoints);
                AoAPoints         = newAoAPoints;
                AverageLiftSlope  = AoAPoints.Select(pt => pt.dLift / pt.dynamicPressure).Where(v => !float.IsNaN(v) && !float.IsInfinity(v)).Average();
                currentConditions = conditions;
                GenerateGraphs();
                valuesSet = true;
            }
        }