public void AddSizeVariables(InstantConditionSim ics, double pitch, int flapSetting, bool spoilers) { Vector3d com; double mass, area, mac, b; ics.GetCoMAndSize(out com, out mass, out area, out mac, out b); AddVariableToList("CoM", "Center of Mass", new double[3] { com.x, com.y, com.z }); AddVariableToList("mass", "Craft mass (kg)", new double[1] { mass }); AddVariableToList("area", "Reference area for Cl and Cd (m^2)", new double[1] { area }); AddVariableToList("mac", "Weighted wing chord (m)", new double[1] { mac }); AddVariableToList("b", "Weighted wing span (m)", new double[1] { b }); AddVariableToList("pitch", "Elevator setting, [-1; 1]", new double[1] { pitch }); AddVariableToList("flapSetting", "Flap setting (0= up, 1-2= take off, 3= landing)", new double[1] { flapSetting }); AddVariableToList("spoilers", "Spoiler setting (0= retracted, 1= deployed)", new double[1] { spoilers? 1: 0 }); }
public EditorSimManager(InstantConditionSim _instantSim) { _instantCondition = _instantSim; StabDerivCalculator = new StabilityDerivCalculator(_instantCondition); SweepSim = new SweepSim(_instantCondition); _aeroCenter = new EditorAeroCenter(); vehicleData = new StabilityDerivOutput(); }
public EditorSimManager(InstantConditionSim _instantSim) { _instantCondition = _instantSim; _stabDerivCalculator = new StabilityDerivCalculator(_instantCondition); _stabDerivLinearSim = new StabilityDerivLinearSim(_instantCondition); _sweepSim = new SweepSim(_instantCondition); _aeroCenter = new EditorAeroCenter(); vehicleData = new StabilityDerivOutput(); }
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(); }
void Start() { if (CompatibilityChecker.IsAllCompatible() && instance == null) instance = this; else { GameObject.Destroy(this); return; } _vehicleAero = new VehicleAerodynamics(); guiRect = new Rect(Screen.width / 4, Screen.height / 6, 10, 10); _instantSim = new InstantConditionSim(); GUIDropDown<int> flapSettingDropDown = new GUIDropDown<int>(new string[] { "0 (up)", "1 (init climb)", "2 (takeoff)", "3 (landing)" }, new int[] { 0, 1, 2, 3 }, 0); GUIDropDown<CelestialBody> celestialBodyDropdown = CreateBodyDropdown(); _simManager = new EditorSimManager(_instantSim); _editorGraph = new StaticAnalysisGraphGUI(_simManager, flapSettingDropDown, celestialBodyDropdown); _stabDeriv = new StabilityDerivGUI(_simManager, flapSettingDropDown, celestialBodyDropdown); _stabDerivLinSim = new StabilityDerivSimulationGUI(_simManager); Color crossSection = GUIColors.GetColor(3); crossSection.a = 0.8f; Color crossSectionDeriv = GUIColors.GetColor(2); crossSectionDeriv.a = 0.8f; _areaRulingOverlay = new EditorAreaRulingOverlay(new Color(0.05f, 0.05f, 0.05f, 0.7f), crossSection, crossSectionDeriv, 10, 5); guiRect.height = 500; guiRect.width = 650; GameEvents.onEditorPartEvent.Add(UpdateGeometryEvent); GameEvents.onEditorUndo.Add(ResetEditorEvent); GameEvents.onEditorRedo.Add(ResetEditorEvent); GameEvents.onEditorShipModified.Add(ResetEditorEvent); GameEvents.onEditorLoad.Add(ResetEditorEvent); GameEvents.onGUIEngineersReportReady.Add(AddDesignConcerns); GameEvents.onGUIEngineersReportDestroy.Add(RemoveDesignConcerns); RequestUpdateVoxel(); }
void OnDestroy() { GameEvents.onEditorPartEvent.Remove(UpdateGeometryEvent); GameEvents.onEditorUndo.Remove(ResetEditorEvent); GameEvents.onEditorRedo.Remove(ResetEditorEvent); GameEvents.onEditorShipModified.Remove(ResetEditorEvent); GameEvents.onEditorLoad.Remove(ResetEditorEvent); GameEvents.onGUIEngineersReportReady.Remove(AddDesignConcerns); GameEvents.onGUIEngineersReportDestroy.Remove(AddDesignConcerns); EditorLogic.fetch.Unlock("FAREdLock"); if (blizzyEditorGUIButton != null) blizzyEditorGUIButton.Destroy(); _stabDerivLinSim = null; _instantSim = null; _areaRulingOverlay = null; _editorGraph = null; _stabDeriv = null; if(_vehicleAero != null) _vehicleAero.ForceCleanup(); _vehicleAero = null; }
public StabilityDerivLinearSim(InstantConditionSim instantConditionSim) { _instantCondition = instantConditionSim; }
public SweepSim(InstantConditionSim instantConditionSim) { _instantCondition = instantConditionSim; }
public SweepSim(InstantConditionSim instantConditionSim) { _instantCondition = instantConditionSim; }
public StabilityDerivCalculator(InstantConditionSim instantConditionSim) { _instantCondition = instantConditionSim; }
public static GraphData RunTransientSimLateral( StabilityDerivOutput vehicleData, double endTime, double initDt, double[] InitCond ) { var A = new SimMatrix(4, 4); A.PrintToConsole(); int i = 0; int j = 0; int num = 0; var Derivs = new double[27]; vehicleData.stabDerivs.CopyTo(Derivs, 0); Derivs[15] = Derivs[15] / vehicleData.nominalVelocity; Derivs[18] = Derivs[18] / vehicleData.nominalVelocity; Derivs[21] = Derivs[21] / vehicleData.nominalVelocity - 1; double Lb = Derivs[16] / (1 - Derivs[26] * Derivs[26] / (Derivs[0] * Derivs[2])); double Nb = Derivs[17] / (1 - Derivs[26] * Derivs[26] / (Derivs[0] * Derivs[2])); double Lp = Derivs[19] / (1 - Derivs[26] * Derivs[26] / (Derivs[0] * Derivs[2])); double Np = Derivs[20] / (1 - Derivs[26] * Derivs[26] / (Derivs[0] * Derivs[2])); double Lr = Derivs[22] / (1 - Derivs[26] * Derivs[26] / (Derivs[0] * Derivs[2])); double Nr = Derivs[23] / (1 - Derivs[26] * Derivs[26] / (Derivs[0] * Derivs[2])); Derivs[16] = Lb + Derivs[26] / Derivs[0] * Nb; Derivs[17] = Nb + Derivs[26] / Derivs[2] * Lb; Derivs[19] = Lp + Derivs[26] / Derivs[0] * Np; Derivs[20] = Np + Derivs[26] / Derivs[2] * Lp; Derivs[22] = Lr + Derivs[26] / Derivs[0] * Nr; Derivs[23] = Nr + Derivs[26] / Derivs[2] * Lr; foreach (double f in Derivs) { if (num < 15) { num++; //Avoid Ix, Iy, Iz and long derivs continue; } num++; FARLogger.Info("" + i + "," + j); if (i <= 2) { A.Add(f, i, j); } if (j < 2) { j++; } else { j = 0; i++; } } A.Add(InstantConditionSim.CalculateAccelerationDueToGravity(vehicleData.body, vehicleData.altitude) * Math.Cos(vehicleData.stableAoA * Math.PI / 180) / vehicleData.nominalVelocity, 3, 0); A.Add(1, 1, 3); A.PrintToConsole(); //We should have an array that looks like this: /* i ---------------> * j [ Yb / u0 , Yp / u0 , -(1 - Yr/ u0) , g Cos(θ0) / u0 ] * | [ Lb , Lp , Lr , 0 ] * | [ Nb , Np , Nr , 0 ] * \ / [ 0 , 1 , 0 , 0 ] * V //And one that looks like this: * * [ Z e ] * [ X e ] * [ M e ] * [ 0 ] * * */ var transSolve = new RungeKutta4(endTime, initDt, A, InitCond); transSolve.Solve(); var lines = new GraphData { xValues = transSolve.time }; double[] yVal = transSolve.GetSolution(0); ScaleAndClampValues(yVal, 180 / Math.PI, 50); lines.AddData(yVal, FARConfig.GUIColors.LdColor, "β", true); yVal = transSolve.GetSolution(1); ScaleAndClampValues(yVal, 180 / Math.PI, 50); lines.AddData(yVal, FARConfig.GUIColors.CmColor, "p", true); yVal = transSolve.GetSolution(2); ScaleAndClampValues(yVal, 180 / Math.PI, 50); lines.AddData(yVal, FARConfig.GUIColors.CdColor, "r", true); yVal = transSolve.GetSolution(3); ScaleAndClampValues(yVal, 180 / Math.PI, 50); lines.AddData(yVal, FARConfig.GUIColors.ClColor, "φ", true); return(lines); }
public static GraphData RunTransientSimLongitudinal( StabilityDerivOutput vehicleData, double endTime, double initDt, double[] InitCond ) { var A = new SimMatrix(4, 4); var B = new SimMatrix(1, 4); A.PrintToConsole(); int i = 0; int j = 0; int num = 0; foreach (double f in vehicleData.stabDerivs) { if (num < 3 || num >= 15) { num++; //Avoid Ix, Iy, Iz continue; } num++; FARLogger.Info(i + "," + j); if (i <= 2) { if (num == 10) { A.Add(f + vehicleData.nominalVelocity, i, j); } else { A.Add(f, i, j); } } else { B.Add(f, 0, j); } if (j < 2) { j++; } else { j = 0; i++; } } A.Add(-InstantConditionSim.CalculateAccelerationDueToGravity(vehicleData.body, vehicleData.altitude), 3, 1); A.Add(1, 2, 3); A.PrintToConsole(); //We should have an array that looks like this: /* i ---------------> * j [ Z w , Z u , Z q + u, 0 ] * | [ X w , X u , X q , -g ] * | [ M w , M u , M q , 0 ] * \ / [ 0 , 0 , 1 , 0 ] * V //And one that looks like this: * * [ Z e ] * [ X e ] * [ M e ] * [ 0 ] * * */ var transSolve = new RungeKutta4(endTime, initDt, A, InitCond); transSolve.Solve(); var lines = new GraphData { xValues = transSolve.time }; double[] yVal = transSolve.GetSolution(0); ScaleAndClampValues(yVal, 1, 50); lines.AddData(yVal, FARConfig.GUIColors.LdColor, "w", true); yVal = transSolve.GetSolution(1); ScaleAndClampValues(yVal, 1, 50); lines.AddData(yVal, FARConfig.GUIColors.CmColor, "u", true); yVal = transSolve.GetSolution(2); ScaleAndClampValues(yVal, 180 / Math.PI, 50); lines.AddData(yVal, FARConfig.GUIColors.CdColor, "q", true); yVal = transSolve.GetSolution(3); ScaleAndClampValues(yVal, 180 / Math.PI, 50); lines.AddData(yVal, FARConfig.GUIColors.ClColor, "θ", true); return(lines); }
public StabilityDerivLinearSim(InstantConditionSim instantConditionSim) { _instantCondition = instantConditionSim; }
public StabilityDerivCalculator(InstantConditionSim instantConditionSim) { _instantCondition = instantConditionSim; }
public StabilityDerivOutput CalculateStabilityDerivs( CelestialBody body, double alt, double machNumber, int flapSetting, bool spoilers, double alpha, double beta, double phi ) { double pressure = body.GetPressure(alt); double temperature = body.GetTemperature(alt); double density = body.GetDensity(pressure, temperature); double sspeed = body.GetSpeedOfSound(pressure, density); double u0 = sspeed * machNumber; double q = u0 * u0 * density * 0.5f; var stabDerivOutput = new StabilityDerivOutput { nominalVelocity = u0, altitude = alt, body = body }; Vector3d CoM = Vector3d.zero; double mass = 0; double MAC = 0; double b = 0; double area = 0; double Ix = 0; double Iy = 0; double Iz = 0; double Ixy = 0; double Iyz = 0; double Ixz = 0; var input = new InstantConditionSimInput(alpha, beta, phi, 0, 0, 0, machNumber, 0, flapSetting, spoilers); var pertOutput = new InstantConditionSimOutput(); _instantCondition.GetClCdCmSteady(input, out InstantConditionSimOutput nominalOutput, true); List <Part> partsList = EditorLogic.SortedShipList; foreach (Part p in partsList) { if (FARAeroUtil.IsNonphysical(p)) { continue; } double partMass = p.mass; if (p.Resources.Count > 0) { partMass += p.GetResourceMass(); } // If you want to use GetModuleMass, you need to start from p.partInfo.mass, not p.mass CoM += partMass * (Vector3d)p.transform.TransformPoint(p.CoMOffset); mass += partMass; var w = p.GetComponent <FARWingAerodynamicModel>(); if (w == null) { continue; } if (w.isShielded) { continue; } area += w.S; MAC += w.GetMAC() * w.S; b += w.Getb_2() * w.S; if (w is FARControllableSurface controllableSurface) { controllableSurface.SetControlStateEditor(CoM, p.transform.up, 0, 0, 0, input.flaps, input.spoilers); } } if (area.NearlyEqual(0)) { area = _instantCondition._maxCrossSectionFromBody; MAC = _instantCondition._bodyLength; b = 1; } MAC /= area; b /= area; CoM /= mass; mass *= 1000; stabDerivOutput.b = b; stabDerivOutput.MAC = MAC; stabDerivOutput.area = area; foreach (Part p in partsList) { if (p == null || FARAeroUtil.IsNonphysical(p)) { continue; } //This section handles the parallel axis theorem Vector3 relPos = p.transform.TransformPoint(p.CoMOffset) - CoM; double x2 = relPos.z * relPos.z; double y2 = relPos.x * relPos.x; double z2 = relPos.y * relPos.y; double x = relPos.z; double y = relPos.x; double z = relPos.y; double partMass = p.mass; if (p.Resources.Count > 0) { partMass += p.GetResourceMass(); } // If you want to use GetModuleMass, you need to start from p.partInfo.mass, not p.mass Ix += (y2 + z2) * partMass; Iy += (x2 + z2) * partMass; Iz += (x2 + y2) * partMass; Ixy += -x * y * partMass; Iyz += -z * y * partMass; Ixz += -x * z * partMass; //And this handles the part's own moment of inertia Vector3 principalInertia = p.Rigidbody.inertiaTensor; Quaternion prncInertRot = p.Rigidbody.inertiaTensorRotation; //The rows of the direction cosine matrix for a quaternion var Row1 = new Vector3(prncInertRot.x * prncInertRot.x - prncInertRot.y * prncInertRot.y - prncInertRot.z * prncInertRot.z + prncInertRot.w * prncInertRot.w, 2 * (prncInertRot.x * prncInertRot.y + prncInertRot.z * prncInertRot.w), 2 * (prncInertRot.x * prncInertRot.z - prncInertRot.y * prncInertRot.w)); var Row2 = new Vector3(2 * (prncInertRot.x * prncInertRot.y - prncInertRot.z * prncInertRot.w), -prncInertRot.x * prncInertRot.x + prncInertRot.y * prncInertRot.y - prncInertRot.z * prncInertRot.z + prncInertRot.w * prncInertRot.w, 2 * (prncInertRot.y * prncInertRot.z + prncInertRot.x * prncInertRot.w)); var Row3 = new Vector3(2 * (prncInertRot.x * prncInertRot.z + prncInertRot.y * prncInertRot.w), 2 * (prncInertRot.y * prncInertRot.z - prncInertRot.x * prncInertRot.w), -prncInertRot.x * prncInertRot.x - prncInertRot.y * prncInertRot.y + prncInertRot.z * prncInertRot.z + prncInertRot.w * prncInertRot.w); //And converting the principal moments of inertia into the coordinate system used by the system Ix += principalInertia.x * Row1.x * Row1.x + principalInertia.y * Row1.y * Row1.y + principalInertia.z * Row1.z * Row1.z; Iy += principalInertia.x * Row2.x * Row2.x + principalInertia.y * Row2.y * Row2.y + principalInertia.z * Row2.z * Row2.z; Iz += principalInertia.x * Row3.x * Row3.x + principalInertia.y * Row3.y * Row3.y + principalInertia.z * Row3.z * Row3.z; Ixy += principalInertia.x * Row1.x * Row2.x + principalInertia.y * Row1.y * Row2.y + principalInertia.z * Row1.z * Row2.z; Ixz += principalInertia.x * Row1.x * Row3.x + principalInertia.y * Row1.y * Row3.y + principalInertia.z * Row1.z * Row3.z; Iyz += principalInertia.x * Row2.x * Row3.x + principalInertia.y * Row2.y * Row3.y + principalInertia.z * Row2.z * Row3.z; } Ix *= 1000; Iy *= 1000; Iz *= 1000; stabDerivOutput.stabDerivs[0] = Ix; stabDerivOutput.stabDerivs[1] = Iy; stabDerivOutput.stabDerivs[2] = Iz; stabDerivOutput.stabDerivs[24] = Ixy; stabDerivOutput.stabDerivs[25] = Iyz; stabDerivOutput.stabDerivs[26] = Ixz; //This is the effect of gravity double effectiveG = InstantConditionSim.CalculateAccelerationDueToGravity(body, alt); //This is the effective reduction of gravity due to high velocity effectiveG -= u0 * u0 / (alt + body.Radius); double neededCl = mass * effectiveG / (q * area); _instantCondition.GetClCdCmSteady(input, out pertOutput, true, true); //Longitudinal Mess _instantCondition.SetState(machNumber, neededCl, CoM, 0, input.flaps, input.spoilers); FARMathUtil.OptimizationResult optResult = FARMathUtil.Secant(_instantCondition.FunctionIterateForAlpha, 0, 10, 1e-4, 1e-4, minLimit: -90, maxLimit: 90); alpha = optResult.Result; input.alpha = alpha; nominalOutput = _instantCondition.iterationOutput; input.alpha = alpha + 2; _instantCondition.GetClCdCmSteady(input, out pertOutput, true, true); stabDerivOutput.stableCl = neededCl; stabDerivOutput.stableCd = nominalOutput.Cd; stabDerivOutput.stableAoA = optResult.Converged ? alpha : double.NaN; stabDerivOutput.stableAoAState = ""; if (optResult.Converged && Math.Abs((nominalOutput.Cl - neededCl) / neededCl) > 0.1) { stabDerivOutput.stableAoAState = nominalOutput.Cl > neededCl ? "<" : ">"; } FARLogger.Info("Cl needed: " + neededCl.ToString(CultureInfo.InvariantCulture) + ", AoA: " + stabDerivOutput.stableAoA.ToString(CultureInfo.InvariantCulture) + ", Cl: " + nominalOutput.Cl.ToString(CultureInfo.InvariantCulture) + ", Cd: " + nominalOutput.Cd.ToString(CultureInfo.InvariantCulture) + ", function calls: " + optResult.FunctionCalls.ToString()); if (!optResult.Converged) { // couldn't find stable AoA, no reason to compute invalid stability derivatives for (int i = 3; i < 24; i++) { stabDerivOutput.stabDerivs[i] = double.NaN; } return(stabDerivOutput); } //vert vel derivs pertOutput.Cl = (pertOutput.Cl - nominalOutput.Cl) / (2 * FARMathUtil.deg2rad); pertOutput.Cd = (pertOutput.Cd - nominalOutput.Cd) / (2 * FARMathUtil.deg2rad); pertOutput.Cm = (pertOutput.Cm - nominalOutput.Cm) / (2 * FARMathUtil.deg2rad); pertOutput.Cl += nominalOutput.Cd; pertOutput.Cd -= nominalOutput.Cl; pertOutput.Cl *= -q * area / (mass * u0); pertOutput.Cd *= -q * area / (mass * u0); pertOutput.Cm *= q * area * MAC / (Iy * u0); stabDerivOutput.stabDerivs[3] = pertOutput.Cl; //Zw stabDerivOutput.stabDerivs[4] = pertOutput.Cd; //Xw stabDerivOutput.stabDerivs[5] = pertOutput.Cm; //Mw // Rodhern: The motivation for the revised stability derivatives sign interpretations of Zq, Xq, Ze and Xe // is to align the sign conventions used for Zu, Zq, Ze, Xu, Xq and Xe. Further explanation can be found // here: https://forum.kerbalspaceprogram.com/index.php?/topic/109098-official-far-craft-repository/&do=findComment&comment=2425057 input.alpha = alpha; input.machNumber = machNumber + 0.05; _instantCondition.GetClCdCmSteady(input, out pertOutput, true); //fwd vel derivs pertOutput.Cl = (pertOutput.Cl - nominalOutput.Cl) / 0.05 * machNumber; pertOutput.Cd = (pertOutput.Cd - nominalOutput.Cd) / 0.05 * machNumber; pertOutput.Cm = (pertOutput.Cm - nominalOutput.Cm) / 0.05 * machNumber; pertOutput.Cl += 2 * nominalOutput.Cl; pertOutput.Cd += 2 * nominalOutput.Cd; pertOutput.Cl *= -q * area / (mass * u0); pertOutput.Cd *= -q * area / (mass * u0); pertOutput.Cm *= q * area * MAC / (u0 * Iy); stabDerivOutput.stabDerivs[6] = pertOutput.Cl; //Zu stabDerivOutput.stabDerivs[7] = pertOutput.Cd; //Xu stabDerivOutput.stabDerivs[8] = pertOutput.Cm; //Mu input.machNumber = machNumber; _instantCondition.GetClCdCmSteady(input, out pertOutput, true, true); input.alphaDot = -0.05; _instantCondition.GetClCdCmSteady(input, out pertOutput, true); //pitch rate derivs pertOutput.Cl = (pertOutput.Cl - nominalOutput.Cl) / 0.05; pertOutput.Cd = (pertOutput.Cd - nominalOutput.Cd) / 0.05; pertOutput.Cm = (pertOutput.Cm - nominalOutput.Cm) / 0.05; pertOutput.Cl *= -q * area * MAC / (2 * u0 * mass); // Rodhern: Replaced 'q' by '-q', so that formulas pertOutput.Cd *= -q * area * MAC / (2 * u0 * mass); // for Zq and Xq match those for Zu and Xu. pertOutput.Cm *= q * area * MAC * MAC / (2 * u0 * Iy); stabDerivOutput.stabDerivs[9] = pertOutput.Cl; //Zq stabDerivOutput.stabDerivs[10] = pertOutput.Cd; //Xq stabDerivOutput.stabDerivs[11] = pertOutput.Cm; //Mq input.alphaDot = 0; input.pitchValue = 0.1; _instantCondition.GetClCdCmSteady(input, out pertOutput, true); //elevator derivs pertOutput.Cl = (pertOutput.Cl - nominalOutput.Cl) / 0.1; pertOutput.Cd = (pertOutput.Cd - nominalOutput.Cd) / 0.1; pertOutput.Cm = (pertOutput.Cm - nominalOutput.Cm) / 0.1; pertOutput.Cl *= -q * area / mass; // Rodhern: Replaced 'q' by '-q', so that formulas pertOutput.Cd *= -q * area / mass; // for Ze and Xe match those for Zu and Xu. pertOutput.Cm *= q * area * MAC / Iy; stabDerivOutput.stabDerivs[12] = pertOutput.Cl; //Ze stabDerivOutput.stabDerivs[13] = pertOutput.Cd; //Xe stabDerivOutput.stabDerivs[14] = pertOutput.Cm; //Me //Lateral Mess input.pitchValue = 0; input.beta = beta + 2; _instantCondition.GetClCdCmSteady(input, out pertOutput, true); //sideslip angle derivs pertOutput.Cy = (pertOutput.Cy - nominalOutput.Cy) / (2 * FARMathUtil.deg2rad); pertOutput.Cn = (pertOutput.Cn - nominalOutput.Cn) / (2 * FARMathUtil.deg2rad); pertOutput.C_roll = (pertOutput.C_roll - nominalOutput.C_roll) / (2 * FARMathUtil.deg2rad); pertOutput.Cy *= q * area / mass; pertOutput.Cn *= q * area * b / Iz; pertOutput.C_roll *= q * area * b / Ix; stabDerivOutput.stabDerivs[15] = pertOutput.Cy; //Yb stabDerivOutput.stabDerivs[17] = pertOutput.Cn; //Nb stabDerivOutput.stabDerivs[16] = pertOutput.C_roll; //Lb input.beta = beta; _instantCondition.GetClCdCmSteady(input, out pertOutput, true, true); input.phiDot = -0.05; _instantCondition.GetClCdCmSteady(input, out pertOutput, true); //roll rate derivs pertOutput.Cy = (pertOutput.Cy - nominalOutput.Cy) / 0.05; pertOutput.Cn = (pertOutput.Cn - nominalOutput.Cn) / 0.05; pertOutput.C_roll = (pertOutput.C_roll - nominalOutput.C_roll) / 0.05; pertOutput.Cy *= q * area * b / (2 * mass * u0); pertOutput.Cn *= q * area * b * b / (2 * Iz * u0); pertOutput.C_roll *= q * area * b * b / (2 * Ix * u0); stabDerivOutput.stabDerivs[18] = pertOutput.Cy; //Yp stabDerivOutput.stabDerivs[20] = pertOutput.Cn; //Np stabDerivOutput.stabDerivs[19] = pertOutput.C_roll; //Lp input.phiDot = 0; _instantCondition.GetClCdCmSteady(input, out pertOutput, true, true); input.betaDot = -0.05; //yaw rate derivs _instantCondition.GetClCdCmSteady(input, out pertOutput, true); pertOutput.Cy = (pertOutput.Cy - nominalOutput.Cy) / 0.05f; pertOutput.Cn = (pertOutput.Cn - nominalOutput.Cn) / 0.05f; pertOutput.C_roll = (pertOutput.C_roll - nominalOutput.C_roll) / 0.05f; pertOutput.Cy *= q * area * b / (2 * mass * u0); pertOutput.Cn *= q * area * b * b / (2 * Iz * u0); pertOutput.C_roll *= q * area * b * b / (2 * Ix * u0); stabDerivOutput.stabDerivs[21] = pertOutput.Cy; //Yr stabDerivOutput.stabDerivs[23] = pertOutput.Cn; //Nr stabDerivOutput.stabDerivs[22] = pertOutput.C_roll; //Lr return(stabDerivOutput); }
public AeroStabilityConcern(InstantConditionSim instantSim, EditorFacilities editorFacility) { _instantSim = instantSim; _editorFacility = editorFacility; _simInput = new InstantConditionSimInput(); }