Esempio n. 1
0
            public static         CoordLocator[,] GenerateCoordLocators(float[,] values)
            {
                int width  = values.GetUpperBound(0);
                int height = values.GetUpperBound(1);

                CoordLocator[,] coordLocators = new CoordLocator[width + 1, height + 1];
                for (int i = 0; i <= width; i++)
                {
                    for (int j = 0; j <= height; j++)
                    {
                        coordLocators[i, j] = new CoordLocator(i, j, values[i, j]);
                    }
                }
                return(coordLocators);
            }
        private void UpdateGraphs()
        {
            float bottom = currentConditions.lowerBoundAltitude;
            float top    = currentConditions.upperBoundAltitude;
            float left   = currentConditions.lowerBoundSpeed;
            float right  = currentConditions.upperBoundSpeed;
            Func <EnvelopePoint, float> scale = (pt) => 1;

            if (WindTunnelSettings.UseCoefficients)
            {
                scale = (pt) => 1 / pt.dynamicPressure;
            }

            ((SurfGraph)graphables["Excess Thrust"]).SetValues(envelopePoints.SelectToArray(pt => pt.Thrust_excess), left, right, bottom, top);
            ((SurfGraph)graphables["Excess Acceleration"]).SetValues(envelopePoints.SelectToArray(pt => pt.Accel_excess), left, right, bottom, top);
            ((SurfGraph)graphables["Thrust Available"]).SetValues(envelopePoints.SelectToArray(pt => pt.Thrust_available), left, right, bottom, top);
            ((SurfGraph)graphables["Level AoA"]).SetValues(envelopePoints.SelectToArray(pt => pt.AoA_level * Mathf.Rad2Deg), left, right, bottom, top);
            ((SurfGraph)graphables["Max Lift AoA"]).SetValues(envelopePoints.SelectToArray(pt => pt.AoA_max * Mathf.Rad2Deg), left, right, bottom, top);
            ((SurfGraph)graphables["Max Lift"]).SetValues(envelopePoints.SelectToArray(pt => pt.Lift_max), left, right, bottom, top);
            ((SurfGraph)graphables["Lift/Drag Ratio"]).SetValues(envelopePoints.SelectToArray(pt => pt.LDRatio), left, right, bottom, top);
            ((SurfGraph)graphables["Drag"]).SetValues(envelopePoints.SelectToArray(pt => pt.drag * scale(pt)), left, right, bottom, top);
            ((SurfGraph)graphables["Lift Slope"]).SetValues(envelopePoints.SelectToArray(pt => pt.dLift / pt.dynamicPressure), left, right, bottom, top);
            ((SurfGraph)graphables["Pitch Input"]).SetValues(envelopePoints.SelectToArray(pt => pt.pitchInput), left, right, bottom, top);
            ((SurfGraph)graphables["Fuel Burn Rate"]).SetValues(envelopePoints.SelectToArray(pt => pt.fuelBurnRate), left, right, bottom, top);
            //((SurfGraph)graphables["Stability Derivative"]).SetValues(envelopePoints.SelectToArray(pt => pt.stabilityDerivative), left, right, bottom, top);
            //((SurfGraph)graphables["Stability Range"]).SetValues(envelopePoints.SelectToArray(pt => pt.stabilityRange), left, right, bottom, top);
            //((SurfGraph)graphables["Stability Score"]).SetValues(envelopePoints.SelectToArray(pt => pt.stabilityScore), left, right, bottom, top);

            float[,] economy = envelopePoints.SelectToArray(pt => pt.fuelBurnRate / pt.speed * 1000 * 100);
            int       stallpt  = CoordLocator.GenerateCoordLocators(envelopePoints.SelectToArray(pt => pt.Thrust_excess)).First(0, 0, c => c.value >= 0);
            SurfGraph toModify = (SurfGraph)graphables["Fuel Economy"];

            toModify.SetValues(economy, left, right, bottom, top);
            float minEconomy = economy[stallpt, 0] / 3;

            toModify.ZMax = minEconomy;
            ((OutlineMask)graphables["Envelope Mask"]).SetValues(envelopePoints.SelectToArray(pt => pt.Thrust_excess), left, right, bottom, top);
        }
Esempio n. 3
0
        private static List <AscentPathPoint> GetOptimalPath(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];

            exitSpeed    = Math.Min(exitSpeed, conditions.upperBoundSpeed);
            exitAlt      = Math.Min(exitAlt, conditions.upperBoundAltitude);
            initialSpeed = Math.Max(initialSpeed, conditions.lowerBoundSpeed);
            initialAlt   = Math.Max(initialAlt, conditions.lowerBoundAltitude);

            stopwatch.Start();

            EnvelopePointExtensions.UniqueQueue <PathSolverCoords> queue = new EnvelopePointExtensions.UniqueQueue <PathSolverCoords>(500);
            PathSolverCoords baseCoord = new PathSolverCoords(conditions.lowerBoundSpeed, conditions.lowerBoundAltitude, conditions.stepSpeed, conditions.stepAltitude, conditions.XResolution, conditions.YResolution);

            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 PathSolverCoords(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 PathSolverCoords(exitCoordFinder.Current.x, exitCoordFinder.Current.y, baseCoord);
                exitSpeed = baseCoord.x; exitAlt = baseCoord.y;
            }

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

            PathSolverCoords coord;

            while (queue.Count > 0)
            {
                coord = queue.Dequeue();
                List <PathSolverCoords> neighbors    = coord.GetNeighbors(neighborPredicate, predicateData);
                PathSolverCoords        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 PathSolverCoords(initialSpeed, initialAlt, baseCoord);
            coord = new PathSolverCoords(costMatrix.First(0, 0, f => f >= initialSpeed && f < float.MaxValue / 100) + 1, coord.yi, baseCoord);
            PathSolverCoords 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 (Math.Abs(coord.x - exitSpeed) < 10 && Math.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));
                    if (coord.y + -d.y * step < 0)
                    {
                        coord = coord.Offset(-d.x * step, -coord.y);
                    }
                    else
                    {
                        coord = coord.Offset(-d * step);
                    }
                }
                catch (Exception)
                {
                    Debug.Log("Exception in gradient finding.");
                    Debug.Log(iter);
                    Debug.Log("xW: " + xW + " yW: " + yW);
                    throw;
                }
            }
            coord = new PathSolverCoords(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);
        }