예제 #1
0
        public static void PrecomputeGlobalCenterOfLift(FARCenterQuery lift, FARCenterQuery dummy, Vector3 vel)
        {
            /* Center of lift is the location where the derivative of
             * the total torque provided by aerodynamic forces relative to
             * AoA is zero (or at least minimal). This approximates the
             * derivative by a simple subtraction, like before. */

            var parts = GetAllEditorModules();

            for (int i = 0; i < parts.Count; i++)
            {
                FARBaseAerodynamics ba = parts[i];
                ba.velocityEditor = vel;
                ba.ResetCenterOfLift();
            }

            FlightEnv defaultfltenv = FlightEnv.NewDefaultVal();

            // run computations twice to let things like flap interactions settle
            for (int i = 0; i < parts.Count; i++)
            {
                FARBaseAerodynamics ba = parts[i];
                ba.PrecomputeCenterOfLift(vel, defaultfltenv, dummy);
            }
            for (int i = 0; i < parts.Count; i++)
            {
                FARBaseAerodynamics ba = parts[i];
                ba.PrecomputeCenterOfLift(vel, defaultfltenv, lift);
            }
        }
        public void SimulateAeroProperties(out Vector3 aeroForce, out Vector3 aeroTorque, Vector3 velocityWorldVector, double altitude)
        {
            // Rodhern: It seems that this method, 'SimulateAeroProperties', is only used in FARAPI, which in turn can be used by say KSPTrajectories.
            //          The parameter 'FARCenterQuery dummy' is from a code fix by Benjamin Chung (commit 18fbb9d29431679a4de9dfc22a443f400d2d4f8b).

            FARCenterQuery center = new FARCenterQuery();
            FARCenterQuery dummy  = new FARCenterQuery();

            float pressure;
            float density;
            float temperature;
            float speedOfSound;

            CelestialBody body = vessel.mainBody;      //Calculate main gas properties

            pressure     = (float)body.GetPressure(altitude);
            temperature  = (float)body.GetTemperature(altitude);
            density      = (float)body.GetDensity(pressure, temperature);
            speedOfSound = (float)body.GetSpeedOfSound(pressure, density);

            if (pressure <= 0 || temperature <= 0 || density <= 0 || speedOfSound <= 0)
            {
                aeroForce  = Vector3.zero;
                aeroTorque = Vector3.zero;
                return;
            }

            float     velocityMag         = velocityWorldVector.magnitude;
            float     machNumber          = velocityMag / speedOfSound;
            float     reynoldsNumber      = (float)FARAeroUtil.CalculateReynoldsNumber(density, Length, velocityMag, machNumber, temperature, body.atmosphereAdiabaticIndex);
            float     reynoldsPerLength   = reynoldsNumber / (float)Length;
            float     pseudoKnudsenNumber = machNumber / (reynoldsNumber + machNumber);
            float     skinFriction        = (float)FARAeroUtil.SkinFrictionDrag(reynoldsNumber, machNumber);
            FlightEnv fenv = FlightEnv.NewPredicted(vessel.mainBody, altitude, machNumber);

            if (_currentAeroSections != null)
            {
                for (int i = 0; i < _currentAeroSections.Count; i++)
                {
                    FARAeroSection curSection = _currentAeroSections[i];
                    if (curSection != null)
                    {
                        curSection.PredictionCalculateAeroForces(density, machNumber, reynoldsPerLength, pseudoKnudsenNumber, skinFriction, velocityWorldVector, center);
                    }
                }

                for (int i = 0; i < _legacyWingModels.Count; i++)
                {
                    FARWingAerodynamicModel curWing = _legacyWingModels[i];
                    if ((object)curWing != null)
                    {
                        Vector3d force = curWing.PrecomputeCenterOfLift(velocityWorldVector, fenv, dummy);
                        center.AddForce(curWing.transform.position, force);
                    }
                }
            }

            aeroForce  = center.force;
            aeroTorque = center.TorqueAt(vessel.CoM);
        }
        public InstantConditionSimVars(InstantConditionSim parent, CelestialBody body, double altitude, double machNumber, double neededCl, double beta, double phi, int flap, bool spoilers)
        {
            this.parent   = parent;
            this.neededCl = neededCl;
            this.CoM      = parent.GetCoM();
            FlightEnv fltenv = FlightEnv.NewSim(body, altitude, machNumber);

            iterationInput  = new InstantConditionSimInput(0, beta, phi, 0, 0, 0, fltenv, 0, flap, spoilers);
            iterationOutput = new InstantConditionSimOutput();
        }
 public InstantConditionSimInput(double alpha, double beta, double phi, double alphaDot, double betaDot, double phiDot, FlightEnv fltenv, double pitchValue, int flaps, bool spoilers)
 {
     this.alpha      = alpha;
     this.beta       = beta;
     this.phi        = phi;
     this.alphaDot   = alphaDot;
     this.betaDot    = betaDot;
     this.phiDot     = phiDot;
     this.fltenv     = fltenv;
     this.pitchValue = pitchValue;
     this.flaps      = flaps;
     this.spoilers   = spoilers;
 }
 /// <summary>
 /// The single parameter constructor creates an object that represents
 /// an artificial default condition. This default condition is straight
 /// and level flight, flaps and spoilers retracted, yoke centered, at
 /// mach 0.5 in a 1-density (kg/m3) atmosphere (in Kerbin's case).
 /// At Kerbin that is roughly travelling at altitude 1 km at 170 m/s.
 /// </summary>
 public InstantConditionSimInput(CelestialBody body)
 {
     this.fltenv = FlightEnv.NewDefaultVal(body);
 }
예제 #6
0
 public virtual Vector3d PrecomputeCenterOfLift(Vector3d velocity, FlightEnv fltenv, FARCenterQuery center)
 {
     return(Vector3d.zero);
 }
예제 #7
0
        public GraphData MachNumberSweep(double aoAdegrees, double pitch, double lowerBound, double upperBound, int numPoints, int flapSetting, bool spoilers, CelestialBody body)
        {
            FARAeroUtil.UpdateCurrentActiveBody(body);

            FARAeroUtil.ResetEditorParts();

            double[] ClValues    = new double[(int)numPoints];
            double[] CdValues    = new double[(int)numPoints];
            double[] CmValues    = new double[(int)numPoints];
            double[] LDValues    = new double[(int)numPoints];
            double[] AlphaValues = new double[(int)numPoints];

            InstantConditionSimInput input = new InstantConditionSimInput(aoAdegrees, 0, 0, 0, 0, 0, FlightEnv.NewDefaultVal(body), pitch, flapSetting, spoilers);

            for (int i = 0; i < numPoints; i++)
            {
                input.fltenv.MachNumber = lowerBound + (upperBound - lowerBound) * (i == 0? 0 : i / (numPoints - 1.0));

                if (input.fltenv.MachNumber < 1E-3)
                {
                    input.fltenv.MachNumber = 1E-3;
                }

                InstantConditionSimOutput output;

                _instantCondition.GetClCdCmSteady(input, out output, i == 0, false);
                AlphaValues[i] = input.fltenv.MachNumber;
                ClValues[i]    = output.Cl;
                CdValues[i]    = output.Cd;
                CmValues[i]    = output.Cm;
                LDValues[i]    = output.Cl * 0.1 / output.Cd;
            }

            GraphData data = new GraphData();

            data.xValues = AlphaValues;
            data.AddData(ClValues, GUIColors.GetColor(0), Localizer.Format("FARAbbrevCl"), true);
            data.AddData(CdValues, GUIColors.GetColor(1), Localizer.Format("FARAbbrevCd"), true);
            data.AddData(CmValues, GUIColors.GetColor(2), Localizer.Format("FARAbbrevCm"), true);
            data.AddData(LDValues, GUIColors.GetColor(3), Localizer.Format("FARAbbrevL_D"), true);

            data.exportdata.AddSizeVariables(_instantCondition, pitch, flapSetting, spoilers);
            data.exportdata.AddMachSweepXVariable(aoAdegrees, AlphaValues);
            data.exportdata.AddYVariables(data);

            return(data);
        }
예제 #8
0
        public int ExportSweep(CelestialBody body, double pitch, int flapSetting, bool spoilers)
        {
            if (!IsReady())
            {
                return(0);
            }

            FARAeroUtil.UpdateCurrentActiveBody(body);
            FARAeroUtil.ResetEditorParts();

            StaticAnalysisExportFile  exportdata = new StaticAnalysisExportFile();
            InstantConditionSimInput  input      = new InstantConditionSimInput(0, 0, 0, 0, 0, 0, FlightEnv.NewDefaultVal(body), pitch, flapSetting, spoilers);
            InstantConditionSimOutput output;

            Vector3d centerofmass = _instantCondition.GetCoM();

            // Loop through each combination (two dimensions).
            foreach (float mach in exportdata.MachNumberList)
            {
                input.fltenv.MachNumber = mach;
                input.alpha             = 0;                              // zero is used as a neutral value for the reset
                _instantCondition.ResetClCdCmSteady(centerofmass, input); // reset old results (particularly cossweep) that may not reflect the current mach number

                foreach (float aoadeg in exportdata.AoADegreeList)
                {
                    input.alpha = aoadeg;
                    _instantCondition.GetClCdCmSteady(input, out output, true, true);
                    exportdata.AddDatapoint(mach, aoadeg, output.Cl, output.Cd, output.Cm);
                }
            }

            exportdata.Export();
            return(exportdata.DataCount);
        }
예제 #9
0
        public GraphData AngleOfAttackSweep(double machNumber, double pitch, double lowerBound, double upperBound, int numPoints, int flapSetting, bool spoilers, CelestialBody body)
        {
            if (machNumber < 1E-3)
            {
                machNumber = 1E-3;
            }

            FARAeroUtil.UpdateCurrentActiveBody(body);

            FARAeroUtil.ResetEditorParts();

            double[] ClValues    = new double[(int)numPoints];
            double[] CdValues    = new double[(int)numPoints];
            double[] CmValues    = new double[(int)numPoints];
            double[] LDValues    = new double[(int)numPoints];
            double[] AlphaValues = new double[(int)numPoints];
            double[] ClValues2   = new double[(int)numPoints];
            double[] CdValues2   = new double[(int)numPoints];
            double[] CmValues2   = new double[(int)numPoints];
            double[] LDValues2   = new double[(int)numPoints];

            InstantConditionSimInput input = new InstantConditionSimInput(0, 0, 0, 0, 0, 0, FlightEnv.NewDefaultVal(body), pitch, flapSetting, spoilers);

            input.fltenv.MachNumber = machNumber;

            for (int i = 0; i < 2 * numPoints; i++)
            {
                double angle = 0;
                if (i < numPoints)
                {
                    angle = lowerBound + (upperBound - lowerBound) * (i == 0? 0 : i / (numPoints - 1.0));
                }
                else
                {
                    angle = upperBound + (lowerBound - upperBound) * (i == numPoints ? 0 : (i - numPoints) / (numPoints - 1.0));
                }
                input.alpha = angle;

                InstantConditionSimOutput output;

                _instantCondition.GetClCdCmSteady(input, out output, i == 0, false);

                if (i < numPoints)
                {
                    AlphaValues[i] = angle;
                    ClValues[i]    = output.Cl;
                    CdValues[i]    = output.Cd;
                    CmValues[i]    = output.Cm;
                    LDValues[i]    = output.Cl * 0.1 / output.Cd;
                }
                else
                {
                    ClValues2[numPoints * 2 - 1 - i] = output.Cl;
                    CdValues2[numPoints * 2 - 1 - i] = output.Cd;
                    CmValues2[numPoints * 2 - 1 - i] = output.Cm;
                    LDValues2[numPoints * 2 - 1 - i] = output.Cl * 0.1 / output.Cd;
                }
            }

            GraphData data = new GraphData();

            data.xValues = AlphaValues;
            data.AddData(ClValues2, GUIColors.GetColor(0) * 0.5f, "Cl2", false);
            data.AddData(ClValues, GUIColors.GetColor(0), Localizer.Format("FARAbbrevCl"), true);
            data.AddData(CdValues2, GUIColors.GetColor(1) * 0.5f, "Cd2", false);
            data.AddData(CdValues, GUIColors.GetColor(1), Localizer.Format("FARAbbrevCd"), true);
            data.AddData(CmValues2, GUIColors.GetColor(2) * 0.5f, "Cm2", false);
            data.AddData(CmValues, GUIColors.GetColor(2), Localizer.Format("FARAbbrevCm"), true);
            data.AddData(LDValues2, GUIColors.GetColor(3) * 0.5f, "L/D2", false);
            data.AddData(LDValues, GUIColors.GetColor(3), Localizer.Format("FARAbbrevL_D"), true);

            data.exportdata.AddSizeVariables(_instantCondition, pitch, flapSetting, spoilers);
            data.exportdata.AddAoASweepXVariable(machNumber, AlphaValues);
            data.exportdata.AddYVariables(data);

            return(data);
        }