diff --git a/FerramAerospaceResearch/FARGUI/FAREditorGUI/EditorGUI.cs b/FerramAerospaceResearch/FARGUI/FAREditorGUI/EditorGUI.cs index 6778ba2a2..b66dada42 100644 --- a/FerramAerospaceResearch/FARGUI/FAREditorGUI/EditorGUI.cs +++ b/FerramAerospaceResearch/FARGUI/FAREditorGUI/EditorGUI.cs @@ -227,6 +227,8 @@ void OnDestroy() #region EditorEvents private void ResetEditorEvent(ShipConstruct construct) { + FARAeroUtil.ResetEditorParts(); + if (EditorLogic.RootPart != null) { List partsList = EditorLogic.SortedShipList; diff --git a/FerramAerospaceResearch/FARGUI/FAREditorGUI/Simulation/InstantConditionSim.cs b/FerramAerospaceResearch/FARGUI/FAREditorGUI/Simulation/InstantConditionSim.cs index 6daf925d2..08645853c 100644 --- a/FerramAerospaceResearch/FARGUI/FAREditorGUI/Simulation/InstantConditionSim.cs +++ b/FerramAerospaceResearch/FARGUI/FAREditorGUI/Simulation/InstantConditionSim.cs @@ -141,15 +141,15 @@ public void GetClCdCmSteady(InstantConditionSimInput input, out InstantCondition AngVel += (sinPhi * alphaDot - cosAlpha * cosPhi * betaDot) * up; Vector3d velocity = forward * cosAlpha * cosBeta; - velocity += right * (sinPhi * cosAlpha * cosBeta + cosPhi * sinBeta); - velocity += -up * cosPhi * (sinAlpha * cosBeta + sinBeta); - - velocity.Normalize(); + velocity += right * (sinPhi * sinAlpha * cosBeta + cosPhi * sinBeta); // Rodhern: Changed velocity 'right' and 'up' components + velocity += -up * (cosPhi * sinAlpha * cosBeta - sinPhi * sinBeta); // to align vector to naive forward direction. //this is negative wrt the ground Vector3d liftVector = -forward * sinAlpha + right * sinPhi * cosAlpha - up * cosPhi * cosAlpha; - Vector3d sideways = Vector3.Cross(velocity, liftVector).normalized; + Vector3d sideways = -forward * cosAlpha * sinBeta; + sideways += right * (cosPhi * cosBeta - sinPhi * sinAlpha * sinBeta); // Rodhern: The same as Vector3.Cross(velocity, liftVector) + sideways += up * (cosPhi * sinAlpha * sinBeta + sinPhi * cosBeta); // but possibly with better accuracy. for (int i = 0; i < _wingAerodynamicModel.Count; i++) @@ -158,7 +158,7 @@ public void GetClCdCmSteady(InstantConditionSimInput input, out InstantCondition if (!(w && w.part)) continue; - w.ComputeForceEditor(velocity.normalized, input.machNumber, 2); + w.ComputeForceEditor(velocity, input.machNumber, 2); if (clear) w.EditorClClear(reset_stall); diff --git a/FerramAerospaceResearch/FARGUI/FAREditorGUI/Simulation/StabilityDerivCalculator.cs b/FerramAerospaceResearch/FARGUI/FAREditorGUI/Simulation/StabilityDerivCalculator.cs index 72fba4478..a9a3a2bb2 100644 --- a/FerramAerospaceResearch/FARGUI/FAREditorGUI/Simulation/StabilityDerivCalculator.cs +++ b/FerramAerospaceResearch/FARGUI/FAREditorGUI/Simulation/StabilityDerivCalculator.cs @@ -58,9 +58,33 @@ public StabilityDerivCalculator(InstantConditionSim instantConditionSim) _instantCondition = instantConditionSim; } - public StabilityDerivOutput CalculateStabilityDerivs(double u0, double q, double machNumber, double alpha, double beta, double phi, int flapSetting, bool spoilers, CelestialBody body, double alt) + public StabilityDerivExportOutput CalculateStabilityDerivs(CelestialBody body, double alt, double machNumber, int flapSetting, bool spoilers) { + // Rodhern: Only return a result if one is found. + + if (body.GetPressure(alt) > 0) + { + StabilityDerivExportOutput result = CalculateStabilityDerivs(body, alt, machNumber, flapSetting, spoilers, 0, 0, 0); + if (result.outputvals.stableAoAState == "") + return result; + else + return null; + } + else + return null; + } + + public StabilityDerivExportOutput 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; + StabilityDerivOutput stabDerivOutput = new StabilityDerivOutput(); + StabilityDerivExportVariables stabDerivExport = new StabilityDerivExportVariables(); stabDerivOutput.nominalVelocity = u0; stabDerivOutput.altitude = alt; stabDerivOutput.body = body; @@ -210,7 +234,7 @@ public StabilityDerivOutput CalculateStabilityDerivs(double u0, double q, double //Longitudinal Mess _instantCondition.SetState(machNumber, neededCl, CoM, 0, input.flaps, input.spoilers); - alpha = FARMathUtil.BrentsMethod(_instantCondition.FunctionIterateForAlpha, -30d, 30d, 0.001, 500); + alpha = FARMathUtil.SillySearchMethod(_instantCondition.FunctionIterateForAlpha); input.alpha = alpha; nominalOutput = _instantCondition.iterationOutput; //alpha_str = (alpha * Mathf.PI / 180).ToString(); @@ -275,8 +299,8 @@ public StabilityDerivOutput CalculateStabilityDerivs(double u0, double q, double pertOutput.Cd = (pertOutput.Cd - nominalOutput.Cd) / 0.05; pertOutput.Cm = (pertOutput.Cm - nominalOutput.Cm) / 0.05; - pertOutput.Cl *= q * area * MAC / (2 * u0 * mass); - pertOutput.Cd *= q * area * MAC / (2 * u0 * mass); + 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 @@ -292,8 +316,8 @@ public StabilityDerivOutput CalculateStabilityDerivs(double u0, double q, double pertOutput.Cd = (pertOutput.Cd - nominalOutput.Cd) / 0.1; pertOutput.Cm = (pertOutput.Cm - nominalOutput.Cm) / 0.1; - pertOutput.Cl *= q * area / mass; - pertOutput.Cd *= q * area / mass; + 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 @@ -357,7 +381,18 @@ public StabilityDerivOutput CalculateStabilityDerivs(double u0, double q, double stabDerivOutput.stabDerivs[23] = pertOutput.Cn; //Nr stabDerivOutput.stabDerivs[22] = pertOutput.C_roll; //Lr - return stabDerivOutput; + // Assign values to export variables + stabDerivExport.craftmass = mass; + stabDerivExport.envpressure = pressure; + stabDerivExport.envtemperature = temperature; + stabDerivExport.envdensity = density; + stabDerivExport.envsoundspeed = sspeed; + stabDerivExport.envg = _instantCondition.CalculateAccelerationDueToGravity(body, alt); + stabDerivExport.sitmach = machNumber; + stabDerivExport.sitdynpres = q; + stabDerivExport.siteffg = effectiveG; + + return new StabilityDerivExportOutput(stabDerivOutput, stabDerivExport); } } diff --git a/FerramAerospaceResearch/FARGUI/FAREditorGUI/Simulation/StabilityDerivExportOutput.cs b/FerramAerospaceResearch/FARGUI/FAREditorGUI/Simulation/StabilityDerivExportOutput.cs new file mode 100644 index 000000000..504303cbf --- /dev/null +++ b/FerramAerospaceResearch/FARGUI/FAREditorGUI/Simulation/StabilityDerivExportOutput.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; + +namespace FerramAerospaceResearch.FARGUI.FAREditorGUI.Simulation +{ + class StabilityDerivExportVariables + { + public double craftmass; + + public double envpressure; // in kPa + public double envtemperature; // in Kelvin + public double envdensity; + public double envsoundspeed; + public double envg; + + public double sitmach; + public double sitdynpres; + public double siteffg; // local gravity corrected for speed + } + + class StabilityDerivExportOutput + { + public StabilityDerivOutput outputvals; + public StabilityDerivExportVariables exportvals; + + public StabilityDerivExportOutput(StabilityDerivOutput outputvalues, StabilityDerivExportVariables exportvalues) + { + this.outputvals = outputvalues; + this.exportvals = exportvalues; + } + } +} diff --git a/FerramAerospaceResearch/FARGUI/FAREditorGUI/StabilityDerivExport.cs b/FerramAerospaceResearch/FARGUI/FAREditorGUI/StabilityDerivExport.cs new file mode 100644 index 000000000..c6015e9bb --- /dev/null +++ b/FerramAerospaceResearch/FARGUI/FAREditorGUI/StabilityDerivExport.cs @@ -0,0 +1,412 @@ +using System; +using System.Collections.Generic; +using System.IO; +using UnityEngine; + +namespace FerramAerospaceResearch.FARGUI.FAREditorGUI +{ + class StabilityDerivativeExportFileElement + { + public string name; + + public StabilityDerivativeExportFileElement(string name) + { + this.name = name; + } + + public virtual List Lines + { get { return new List(); } } + } + + class StructElement : StabilityDerivativeExportFileElement + { + public List subelems; + + public StructElement(string name) : base(name) + { + subelems = new List(); + } + + public void AddElement(StabilityDerivativeExportFileElement element) + { + subelems.Add(element); + } + + public void AddScalar(string name, double value) + { + ScalarElement scalar = new ScalarElement(name, value); + this.AddElement(scalar); + } + + public override List Lines + { + get + { + List result = new List(); + result.Add("# name: " + this.name); + result.Add("# type: scalar struct"); + result.Add("# ndims: 2"); + result.Add(" 1 1"); + result.Add("# length: " + subelems.Count); + foreach (StabilityDerivativeExportFileElement elem in subelems) + { + result.Add(""); + foreach (string s in elem.Lines) + result.Add(s); + } + return result; + } + } + } + + class StringElement : StabilityDerivativeExportFileElement + { + public string value; + + static public string OnlyASCII(string s) + { + if (s == null || s == "") + return ""; + var sb = new System.Text.StringBuilder(s.Length, s.Length); + foreach (char c in s) + if (31 < (int)c && (int)c < 127) + sb.Append(c); + return sb.ToString(); + } + + public StringElement(string name, string value) : base(name) + { + this.value = OnlyASCII(value); + } + + public override List Lines + { + get + { + List result = new List(); + result.Add("# name: " + this.name); + result.Add("# type: string"); + result.Add("# elements: 1"); + result.Add("# length: " + value.Length); + result.Add(value); + return result; + } + } + } + + class ScalarElement : StabilityDerivativeExportFileElement + { + public double value; + private System.Globalization.CultureInfo enus; + + public ScalarElement(string name, double value) : base(name) + { + this.value = value; + this.enus = System.Globalization.CultureInfo.CreateSpecificCulture("en-US"); + } + + public override List Lines + { + get + { + List result = new List(); + result.Add("# name: " + this.name); + result.Add("# type: scalar"); + result.Add(value.ToString("E16", enus)); + return result; + } + } + } + + class ExportTextFileCache + { + private string[] filetext; + + /// + /// Physical file read. + /// + public ExportTextFileCache () + { + filetext = LoadTextFile(); + } + + /// + /// Access text cache. + /// + public string[] TextFileLines + { get { return filetext; } } + + /// + /// Overwrite text cache with new content. + /// + public void UpdateTextFileLines(List lines) + { + filetext = lines.ToArray(); + } + + /// + /// Write cache to disk. + /// + public void FlushTextFileLines() + { + SaveTextFile(filetext); + } + + static public string TextFilePath + { + get + { + string path = KSPUtil.ApplicationRootPath; + path += "GameData/FerramAerospaceResearch/Plugins/PluginData/"; + path += "sdexport.txt"; + return path; + } + } + + static public string[] LoadTextFile() + { + string path = TextFilePath; + if (File.Exists(path)) + return File.ReadAllLines(path, System.Text.Encoding.Default); + else + return new string[] { }; + } + + static public void SaveTextFile(string[] lines) + { + string path = TextFilePath; + File.WriteAllLines(path, lines); + } + } + + class StabilityDerivativeExportFile + { + private StructElement cellelement; + private List bodytext; + private int bodytextcount; + + public StabilityDerivativeExportFile() + { + cellelement = new StructElement(""); + bodytext = new List(); + bodytextcount = -1; + } + + static public string ConfigFilePath + { + get + { + string path = KSPUtil.ApplicationRootPath; + path += "GameData/FerramAerospaceResearch/Plugins/PluginData/FerramAerospaceResearch/"; + path += "sdexpcfg.txt"; + return path; + } + } + + static public List LoadConfigList() + { + var resultlist = new List(); + string path = ConfigFilePath; + if (File.Exists(path)) + { + string[] lines = File.ReadAllLines(path, System.Text.Encoding.Default); + if (lines.Length >= 6) + { + bool b1 = lines[0].StartsWith("# Created by"); + bool b2 = lines[1] == "# name: altmach"; + bool b3 = lines[2] == "# type: matrix"; + bool b4 = lines[3].StartsWith("# rows: "); + bool b5 = lines[4] == "# columns: 2"; + if (b1 && b2 && b3 && b4 && b5) + { + var enus = System.Globalization.CultureInfo.CreateSpecificCulture("en-US"); + var floatstyle = System.Globalization.NumberStyles.Float; + int n = int.Parse(lines[3].Remove(0, 8)); + if (lines.Length >= 5 + n) + { + for (int i = 5; i < 5 + n; i++) + { + string[] line = lines[i].Trim().Split(new char[]{' '}); + if (line.Length == 2) + { + float alt; float mach; + if (float.TryParse(line[0], floatstyle, enus, out alt) + && float.TryParse(line[1], floatstyle, enus, out mach)) + { + resultlist.Add(new Vector2(alt, mach)); + } + } + } + } + } + } + } + return resultlist; + } + + public void LoadBodyText(ExportTextFileCache cache) + { + bodytext = new List(); + string[] lines = cache.TextFileLines; + if (lines.Length == 0) + bodytextcount = 0; + else if (lines.Length < 5) + bodytextcount = -1; + else + { + bool b1 = lines[0].StartsWith("# Created by"); + bool b2 = lines[1] == "# name: data"; + bool b3 = lines[2] == "# type: cell"; + bool b4 = lines[3] == "# ndims: 3"; + bool b5 = lines[4].StartsWith(" 1 1 "); + if (b1 && b2 && b3 && b4 && b5) + { + bodytextcount = int.Parse(lines[4].Remove(0, 5)); + int firstidx = 5; + int lastidx = lines.Length - 1; + for (int i = firstidx; i == firstidx && i < lastidx; i++) + if (lines[i] == "") + firstidx = i + 1; + for (int i = lastidx; i == lastidx && i > firstidx; i--) + if (lines[i] == "") + lastidx = i - 1; + for (int i = firstidx; i <= lastidx; i++) + bodytext.Add(lines[i]); + } + else + bodytextcount = -1; + } + } + + public bool BodyTextLoaded() + { + return bodytextcount >= 0; + } + + public void AddElement(StabilityDerivativeExportFileElement element) + { + cellelement.AddElement(element); + } + + public List GetAllLines() + { + List result = new List(); + result.Add("# Created by Ferram Aerospace Research plugin for Kerbal Space Program"); + result.Add("# name: data"); + result.Add("# type: cell"); + result.Add("# ndims: 3"); + result.Add(" 1 1 " + (bodytextcount + 1)); + result.Add(""); + foreach (string s in bodytext) + result.Add(s); + result.Add(""); + foreach (string s in cellelement.Lines) + result.Add(s); + return result; + } + + public void UpdateAllText(ExportTextFileCache cache) + { + if (BodyTextLoaded()) + cache.UpdateTextFileLines(GetAllLines()); + else + throw new InvalidOperationException("Cannot save result file to cache because the file was not loaded properly from cache in the first place."); + } + + static public string EditorShipName + { + get + { + EditorLogic logic = EditorLogic.fetch; + if (logic == null || logic.shipNameField == null || logic.shipNameField.text == null) + return ""; + else + return logic.shipNameField.text; + } + } + + public void AddResultElements(Simulation.StabilityDerivExportOutput output) + { + if (cellelement.subelems.Count > 0) + throw new InvalidOperationException("Cannot add result elements; top cell element was not empty."); + else + { + StructElement craft = new StructElement("craft"); + StructElement env = new StructElement("env"); + StructElement deriv = new StructElement("deriv"); + StructElement inertia = new StructElement("inertia"); + + craft.AddElement(new StringElement("name", EditorShipName)); + craft.AddScalar("mass", output.exportvals.craftmass); + craft.AddScalar("span", output.outputvals.b); + craft.AddScalar("chord", output.outputvals.MAC); + craft.AddScalar("area", output.outputvals.area); + craft.AddElement(inertia); + inertia.AddScalar("lxx", output.outputvals.stabDerivs[0]); + inertia.AddScalar("lyy", output.outputvals.stabDerivs[1]); + inertia.AddScalar("lzz", output.outputvals.stabDerivs[2]); + inertia.AddScalar("lxy", output.outputvals.stabDerivs[24]); + inertia.AddScalar("lyz", output.outputvals.stabDerivs[25]); + inertia.AddScalar("lxz", output.outputvals.stabDerivs[26]); + + env.AddElement(new StringElement("body", output.outputvals.body.name)); + env.AddScalar("altitude", output.outputvals.altitude); + env.AddScalar("mach", output.exportvals.sitmach); + env.AddScalar("pressure", output.exportvals.envpressure); + env.AddScalar("temperature", output.exportvals.envtemperature); + env.AddScalar("density", output.exportvals.envdensity); + env.AddScalar("soundspeed", output.exportvals.envsoundspeed); + env.AddScalar("g", output.exportvals.envg); + env.AddScalar("speed", output.outputvals.nominalVelocity); + env.AddScalar("dynpres", output.exportvals.sitdynpres); + env.AddScalar("effg", output.exportvals.siteffg); + + deriv.AddScalar("Cl", output.outputvals.stableCl); + deriv.AddScalar("Cd", output.outputvals.stableCd); + deriv.AddScalar("AoA", output.outputvals.stableAoA); + deriv.AddScalar("Zw", output.outputvals.stabDerivs[3]); + deriv.AddScalar("Xw", output.outputvals.stabDerivs[4]); + deriv.AddScalar("Mw", output.outputvals.stabDerivs[5]); + deriv.AddScalar("Zu", output.outputvals.stabDerivs[6]); + deriv.AddScalar("Xu", output.outputvals.stabDerivs[7]); + deriv.AddScalar("Mu", output.outputvals.stabDerivs[8]); + deriv.AddScalar("Zq", output.outputvals.stabDerivs[9]); + deriv.AddScalar("Xq", output.outputvals.stabDerivs[10]); + deriv.AddScalar("Mq", output.outputvals.stabDerivs[11]); + deriv.AddScalar("Ze", output.outputvals.stabDerivs[12]); + deriv.AddScalar("Xe", output.outputvals.stabDerivs[13]); + deriv.AddScalar("Me", output.outputvals.stabDerivs[14]); + deriv.AddScalar("Yb", output.outputvals.stabDerivs[15]); + deriv.AddScalar("Lb", output.outputvals.stabDerivs[16]); + deriv.AddScalar("Nb", output.outputvals.stabDerivs[17]); + deriv.AddScalar("Yp", output.outputvals.stabDerivs[18]); + deriv.AddScalar("Lp", output.outputvals.stabDerivs[19]); + deriv.AddScalar("Np", output.outputvals.stabDerivs[20]); + deriv.AddScalar("Yr", output.outputvals.stabDerivs[21]); + deriv.AddScalar("Lr", output.outputvals.stabDerivs[22]); + deriv.AddScalar("Nr", output.outputvals.stabDerivs[23]); + + AddElement(craft); + AddElement(env); + AddElement(deriv); + } + } + + static public bool Export(Simulation.StabilityDerivExportOutput output, ExportTextFileCache filecache = null) + { + StabilityDerivativeExportFile body = new StabilityDerivativeExportFile(); + ExportTextFileCache cache = (filecache != null) ? filecache : new ExportTextFileCache(); + body.LoadBodyText(cache); + if (body.BodyTextLoaded()) + { + body.AddResultElements(output); + body.UpdateAllText(cache); + if (filecache == null) + cache.FlushTextFileLines(); + return true; + } + else + return false; + } + } +} diff --git a/FerramAerospaceResearch/FARGUI/FAREditorGUI/StabilityDerivGUI.cs b/FerramAerospaceResearch/FARGUI/FAREditorGUI/StabilityDerivGUI.cs index ff9f1b631..82e9337c2 100644 --- a/FerramAerospaceResearch/FARGUI/FAREditorGUI/StabilityDerivGUI.cs +++ b/FerramAerospaceResearch/FARGUI/FAREditorGUI/StabilityDerivGUI.cs @@ -100,19 +100,17 @@ void SetAngleVectors(double aoA) public void Display() { + const int W160 = 160 + 20; // Rodhern: A width originally designed to be of size 160. //stabDerivHelp = GUILayout.Toggle(stabDerivHelp, "?", ButtonStyle, GUILayout.Width(200)); GUILayout.Label(Localizer.Format("FAREditorStabDerivFlightCond")); GUILayout.BeginHorizontal(); GUILayout.Label(Localizer.Format("FAREditorStabDerivPlanet")); _bodySettingDropdown.GUIDropDownDisplay(); - GUILayout.Label(Localizer.Format("FAREditorStabDerivAlt")); altitude = GUILayout.TextField(altitude, GUILayout.ExpandWidth(true)); - GUILayout.Label(Localizer.Format("FAREditorStabDerivMach")); machNumber = GUILayout.TextField(machNumber, GUILayout.ExpandWidth(true)); - GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); @@ -122,49 +120,19 @@ public void Display() spoilersDeployed = GUILayout.Toggle(spoilersDeployed, spoilersDeployed ? Localizer.Format("FAREditorStabDerivSDeploy") : Localizer.Format("FAREditorStabDerivSRetract"), GUILayout.Width(100)); GUILayout.EndHorizontal(); + GUILayout.BeginHorizontal(); if (GUILayout.Button(Localizer.Format("FAREditorStabDerivCalcButton"), GUILayout.Width(250.0F), GUILayout.Height(25.0F))) - { - CelestialBody body = _bodySettingDropdown.ActiveSelection; - FARAeroUtil.UpdateCurrentActiveBody(body); - //atm_temp_str = Regex.Replace(atm_temp_str, @"[^-?[0-9]*(\.[0-9]*)?]", ""); - //rho_str = Regex.Replace(rho_str, @"[^-?[0-9]*(\.[0-9]*)?]", ""); - machNumber = Regex.Replace(machNumber, @"[^-?[0-9]*(\.[0-9]*)?]", ""); - - altitude = Regex.Replace(altitude, @"[^-?[0-9]*(\.[0-9]*)?]", ""); - double altitudeDouble = Convert.ToDouble(altitude); - altitudeDouble *= 1000; - - - double temp = body.GetTemperature(altitudeDouble); - double pressure = body.GetPressure(altitudeDouble); - if (pressure > 0) - { - //double temp = Convert.ToSingle(atm_temp_str); - double machDouble = Convert.ToSingle(machNumber); - machDouble = FARMathUtil.Clamp(machDouble, 0.001, float.PositiveInfinity); - - double density = body.GetDensity(pressure, temp); - - double sspeed = body.GetSpeedOfSound(pressure, density); - double vel = sspeed * machDouble; - - //UpdateControlSettings(); - - double q = vel * vel * density * 0.5f; + StabDerivCalcButtonAction(CalcAndExportEnum.CalculateOnly); + if (GUILayout.Button(Localizer.Format("FAREditorStabDerivSaveButton"), GUILayout.Width(250.0F), GUILayout.Height(25.0F))) + StabDerivCalcButtonAction(CalcAndExportEnum.CalculateAndExport); + if (GUILayout.Button(Localizer.Format("FAREditorStabDerivLoopButton"), GUILayout.Width(175.0F), GUILayout.Height(25.0F))) + StabDerivCalcButtonAction(CalcAndExportEnum.LoopExport); + GUILayout.EndHorizontal(); - stabDerivOutput = simManager.StabDerivCalculator.CalculateStabilityDerivs(vel, q, machDouble, 0, 0, 0, _flapSettingDropdown.ActiveSelection, spoilersDeployed, body, altitudeDouble); - simManager.vehicleData = stabDerivOutput; - SetAngleVectors(stabDerivOutput.stableAoA); - } - else - { - PopupDialog.SpawnPopupDialog(new Vector2(0, 0), new Vector2(0, 0), "FARStabDerivError", Localizer.Format("FAREditorStabDerivError"), Localizer.Format("FAREditorStabDerivErrorExp"), Localizer.Format("FARGUIOKButton "), true, HighLogic.UISkin); - } - } GUILayout.BeginHorizontal(); GUILayout.Label(Localizer.Format("FAREditorStabDerivAirProp"), GUILayout.Width(180)); - GUILayout.Label(Localizer.Format("FAREditorStabDerivMoI"), GUILayout.Width(160)); - GUILayout.Label(Localizer.Format("FAREditorStabDerivPoI"), GUILayout.Width(160)); + GUILayout.Label(Localizer.Format("FAREditorStabDerivMoI"), GUILayout.Width(W160)); + GUILayout.Label(Localizer.Format("FAREditorStabDerivPoI"), GUILayout.Width(W160)); GUILayout.Label(Localizer.Format("FAREditorStabDerivLvlFl"), GUILayout.Width(140)); GUILayout.EndHorizontal(); @@ -175,14 +143,13 @@ public void Display() GUILayout.Label(Localizer.Format("FAREditorStabDerivScaledSpan") + stabDerivOutput.b.ToString("G3") + " " + Localizer.Format("FARUnitM")); GUILayout.EndVertical(); - - GUILayout.BeginVertical(GUILayout.Width(160)); + GUILayout.BeginVertical(GUILayout.Width(W160)); GUILayout.Label(new GUIContent(Localizer.Format("FAREditorStabDerivIxx") + stabDerivOutput.stabDerivs[0].ToString("G6") + " " + Localizer.Format("FARUnitKgMSq"), Localizer.Format("FAREditorStabDerivIxxExp"))); GUILayout.Label(new GUIContent(Localizer.Format("FAREditorStabDerivIyy") + stabDerivOutput.stabDerivs[1].ToString("G6") + " " + Localizer.Format("FARUnitKgMSq"), Localizer.Format("FAREditorStabDerivIyyExp"))); GUILayout.Label(new GUIContent(Localizer.Format("FAREditorStabDerivIzz") + stabDerivOutput.stabDerivs[2].ToString("G6") + " " + Localizer.Format("FARUnitKgMSq"), Localizer.Format("FAREditorStabDerivIzzExp"))); GUILayout.EndVertical(); - GUILayout.BeginVertical(GUILayout.Width(160)); + GUILayout.BeginVertical(GUILayout.Width(W160)); GUILayout.Label(new GUIContent(Localizer.Format("FAREditorStabDerivIxy") + stabDerivOutput.stabDerivs[24].ToString("G6") + " " + Localizer.Format("FARUnitKgMSq"), Localizer.Format("FAREditorStabDerivIxyExp"))); GUILayout.Label(new GUIContent(Localizer.Format("FAREditorStabDerivIyz") + stabDerivOutput.stabDerivs[25].ToString("G6") + " " + Localizer.Format("FARUnitKgMSq"), Localizer.Format("FAREditorStabDerivIyzExp"))); GUILayout.Label(new GUIContent(Localizer.Format("FAREditorStabDerivIxz") + stabDerivOutput.stabDerivs[26].ToString("G6") + " " + Localizer.Format("FARUnitKgMSq"), Localizer.Format("FAREditorStabDerivIxzExp"))); @@ -196,72 +163,117 @@ public void Display() GUILayout.EndHorizontal(); GUILayout.Label(new GUIContent(Localizer.Format("FARAbbrevAoA") + ": " + stabDerivOutput.stableAoAState + stabDerivOutput.stableAoA.ToString("G6") + " " + Localizer.Format("FARUnitDeg"), Localizer.Format("FAREditorStabDerivAoAExp"))); GUILayout.EndVertical(); - - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(); - GUILayout.Label(Localizer.Format("FAREditorLongDeriv"), GUILayout.Width(160)); GUILayout.EndHorizontal(); GUIStyle BackgroundStyle = new GUIStyle(GUI.skin.box); BackgroundStyle.hover = BackgroundStyle.active = BackgroundStyle.normal; - GUILayout.BeginVertical(BackgroundStyle); GUILayout.BeginHorizontal(); - GUILayout.Label(Localizer.Format("FAREditorDownVelDeriv"), GUILayout.Width(160)); - GUILayout.Label(Localizer.Format("FAREditorFwdVelDeriv"), GUILayout.Width(160)); - GUILayout.Label(Localizer.Format("FAREditorPitchRateDeriv"), GUILayout.Width(160)); - GUILayout.Label(Localizer.Format("FAREditorPitchCtrlDeriv"), GUILayout.Width(160)); + GUILayout.Label(Localizer.Format("FAREditorLongDeriv"), GUILayout.Width(W160)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); - StabilityLabel(Localizer.Format("FAREditorZw"), stabDerivOutput.stabDerivs[3], " " + Localizer.Format("FARUnitInvSec"), Localizer.Format("FAREditorZwExp"), 160, -1); - StabilityLabel(Localizer.Format("FAREditorZu"), stabDerivOutput.stabDerivs[6], " " + Localizer.Format("FARUnitInvSec"), Localizer.Format("FAREditorZuExp"), 160, -1); - StabilityLabel(Localizer.Format("FAREditorZq"), stabDerivOutput.stabDerivs[9], " " + Localizer.Format("FARUnitMPerSec"), Localizer.Format("FAREditorZqExp"), 160, 0); - StabilityLabel(Localizer.Format("FAREditorZDeltae"), stabDerivOutput.stabDerivs[12], " " + Localizer.Format("FARUnitMPerSecSq"), Localizer.Format("FAREditorZDeltaeExp"), 160, 0); + GUILayout.Label(Localizer.Format("FAREditorDownVelDeriv"), GUILayout.Width(W160)); + GUILayout.Label(Localizer.Format("FAREditorFwdVelDeriv"), GUILayout.Width(W160)); + GUILayout.Label(Localizer.Format("FAREditorPitchRateDeriv"), GUILayout.Width(W160)); + GUILayout.Label(Localizer.Format("FAREditorPitchCtrlDeriv"), GUILayout.Width(W160)); + GUILayout.EndHorizontal(); + GUILayout.BeginVertical(BackgroundStyle); + GUILayout.BeginHorizontal(); + StabilityLabel(Localizer.Format("FAREditorZw"), stabDerivOutput.stabDerivs[3], " " + Localizer.Format("FARUnitInvSec"), Localizer.Format("FAREditorZwExp"), W160, -1); + StabilityLabel(Localizer.Format("FAREditorZu"), stabDerivOutput.stabDerivs[6], " " + Localizer.Format("FARUnitInvSec"), Localizer.Format("FAREditorZuExp"), W160, -1); + StabilityLabel(Localizer.Format("FAREditorZq"), stabDerivOutput.stabDerivs[9], " " + Localizer.Format("FARUnitMPerSec"), Localizer.Format("FAREditorZqExp"), W160, 0); + StabilityLabel(Localizer.Format("FAREditorZDeltae"), stabDerivOutput.stabDerivs[12], " " + Localizer.Format("FARUnitMPerSecSq"), Localizer.Format("FAREditorZDeltaeExp"), W160, 0); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); - StabilityLabel(Localizer.Format("FAREditorXw"), stabDerivOutput.stabDerivs[4], " " + Localizer.Format("FARUnitInvSec"), Localizer.Format("FAREditorXwExp"), 160, 0); - StabilityLabel(Localizer.Format("FAREditorXu"), stabDerivOutput.stabDerivs[7], " " + Localizer.Format("FARUnitInvSec"), Localizer.Format("FAREditorXuExp"), 160, -1); - StabilityLabel(Localizer.Format("FAREditorXq"), stabDerivOutput.stabDerivs[10], " " + Localizer.Format("FARUnitMPerSec"), Localizer.Format("FAREditorXqExp"), 160, 0); - StabilityLabel(Localizer.Format("FAREditorXDeltae"), stabDerivOutput.stabDerivs[13], " " + Localizer.Format("FARUnitMPerSecSq"), Localizer.Format("FAREditorXDeltaeExp"), 160, 0); + StabilityLabel(Localizer.Format("FAREditorXw"), stabDerivOutput.stabDerivs[4], " " + Localizer.Format("FARUnitInvSec"), Localizer.Format("FAREditorXwExp"), W160, 0); + StabilityLabel(Localizer.Format("FAREditorXu"), stabDerivOutput.stabDerivs[7], " " + Localizer.Format("FARUnitInvSec"), Localizer.Format("FAREditorXuExp"), W160, -1); + StabilityLabel(Localizer.Format("FAREditorXq"), stabDerivOutput.stabDerivs[10], " " + Localizer.Format("FARUnitMPerSec"), Localizer.Format("FAREditorXqExp"), W160, 0); + StabilityLabel(Localizer.Format("FAREditorXDeltae"), stabDerivOutput.stabDerivs[13], " " + Localizer.Format("FARUnitMPerSecSq"), Localizer.Format("FAREditorXDeltaeExp"), W160, 0); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); - StabilityLabel(Localizer.Format("FAREditorMw"), stabDerivOutput.stabDerivs[5], " " + Localizer.Format("FARUnitInvMSec"), Localizer.Format("FAREditorMwExp"), 160, -1); - StabilityLabel(Localizer.Format("FAREditorMu"), stabDerivOutput.stabDerivs[8], " " + Localizer.Format("FARUnitInvMSec"), Localizer.Format("FAREditorMuExp"), 160, 0); - StabilityLabel(Localizer.Format("FAREditorMq"), stabDerivOutput.stabDerivs[11], " " + Localizer.Format("FARUnitInvSec"), Localizer.Format("FAREditorMqExp"), 160, -1); - StabilityLabel(Localizer.Format("FAREditorMDeltae"), stabDerivOutput.stabDerivs[14], " " + Localizer.Format("FARUnitInvSecSq"), Localizer.Format("FAREditorMDeltaeExp"), 160, 1); + StabilityLabel(Localizer.Format("FAREditorMw"), stabDerivOutput.stabDerivs[5], " " + Localizer.Format("FARUnitInvMSec"), Localizer.Format("FAREditorMwExp"), W160, -1); + StabilityLabel(Localizer.Format("FAREditorMu"), stabDerivOutput.stabDerivs[8], " " + Localizer.Format("FARUnitInvMSec"), Localizer.Format("FAREditorMuExp"), W160, 0); + StabilityLabel(Localizer.Format("FAREditorMq"), stabDerivOutput.stabDerivs[11], " " + Localizer.Format("FARUnitInvSec"), Localizer.Format("FAREditorMqExp"), W160, -1); + StabilityLabel(Localizer.Format("FAREditorMDeltae"), stabDerivOutput.stabDerivs[14], " " + Localizer.Format("FARUnitInvSecSq"), Localizer.Format("FAREditorMDeltaeExp"), W160, 1); GUILayout.EndHorizontal(); GUILayout.EndVertical(); GUILayout.BeginHorizontal(); - GUILayout.Label(Localizer.Format("FAREditorLatDeriv"), GUILayout.Width(160)); + GUILayout.Label(Localizer.Format("FAREditorLatDeriv"), GUILayout.Width(W160)); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); - GUILayout.Label(Localizer.Format("FAREditorSideslipDeriv"), GUILayout.Width(160)); - GUILayout.Label(Localizer.Format("FAREditorRollRateDeriv"), GUILayout.Width(160)); - GUILayout.Label(Localizer.Format("FAREditorYawRateDeriv"), GUILayout.Width(160)); + GUILayout.Label(Localizer.Format("FAREditorSideslipDeriv"), GUILayout.Width(W160)); + GUILayout.Label(Localizer.Format("FAREditorRollRateDeriv"), GUILayout.Width(W160)); + GUILayout.Label(Localizer.Format("FAREditorYawRateDeriv"), GUILayout.Width(W160)); GUILayout.EndHorizontal(); GUILayout.BeginVertical(BackgroundStyle); GUILayout.BeginHorizontal(); - StabilityLabel(Localizer.Format("FAREditorYβ"), stabDerivOutput.stabDerivs[15], " " + Localizer.Format("FARUnitMPerSecSq"), Localizer.Format("FAREditorYβExp"), 160, -1); - StabilityLabel(Localizer.Format("FAREditorYp"), stabDerivOutput.stabDerivs[18], " " + Localizer.Format("FARUnitMPerSec"), Localizer.Format("FAREditorYpExp"), 160, 0); - StabilityLabel(Localizer.Format("FAREditorYr"), stabDerivOutput.stabDerivs[21], " " + Localizer.Format("FARUnitMPerSec"), Localizer.Format("FAREditorYrExp"), 160, 1); + StabilityLabel(Localizer.Format("FAREditorYβ"), stabDerivOutput.stabDerivs[15], " " + Localizer.Format("FARUnitMPerSecSq"), Localizer.Format("FAREditorYβExp"), W160, -1); + StabilityLabel(Localizer.Format("FAREditorYp"), stabDerivOutput.stabDerivs[18], " " + Localizer.Format("FARUnitMPerSec"), Localizer.Format("FAREditorYpExp"), W160, 0); + StabilityLabel(Localizer.Format("FAREditorYr"), stabDerivOutput.stabDerivs[21], " " + Localizer.Format("FARUnitMPerSec"), Localizer.Format("FAREditorYrExp"), W160, 1); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); - StabilityLabel(Localizer.Format("FAREditorLβ"), stabDerivOutput.stabDerivs[16], " " + Localizer.Format("FARUnitInvSecSq"), Localizer.Format("FAREditorLβExp"), 160, -1); - StabilityLabel(Localizer.Format("FAREditorLp"), stabDerivOutput.stabDerivs[19], " " + Localizer.Format("FARUnitInvSec"), Localizer.Format("FAREditorLpExp"), 160, -1); - StabilityLabel(Localizer.Format("FAREditorLr"), stabDerivOutput.stabDerivs[22], " " + Localizer.Format("FARUnitInvSec"), Localizer.Format("FAREditorLrExp"), 160, 1); + StabilityLabel(Localizer.Format("FAREditorLβ"), stabDerivOutput.stabDerivs[16], " " + Localizer.Format("FARUnitInvSecSq"), Localizer.Format("FAREditorLβExp"), W160, -1); + StabilityLabel(Localizer.Format("FAREditorLp"), stabDerivOutput.stabDerivs[19], " " + Localizer.Format("FARUnitInvSec"), Localizer.Format("FAREditorLpExp"), W160, -1); + StabilityLabel(Localizer.Format("FAREditorLr"), stabDerivOutput.stabDerivs[22], " " + Localizer.Format("FARUnitInvSec"), Localizer.Format("FAREditorLrExp"), W160, 1); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); - StabilityLabel(Localizer.Format("FAREditorNβ"), stabDerivOutput.stabDerivs[17], " " + Localizer.Format("FARUnitInvSecSq"), Localizer.Format("FAREditorNβExp"), 160, 1); - StabilityLabel(Localizer.Format("FAREditorNp"), stabDerivOutput.stabDerivs[20], " " + Localizer.Format("FARUnitInvSec"), Localizer.Format("FAREditorNpExp"), 160, 0); - StabilityLabel(Localizer.Format("FAREditorNr"), stabDerivOutput.stabDerivs[23], " " + Localizer.Format("FARUnitInvSec"), Localizer.Format("FAREditorNrExp"), 160, -1); + StabilityLabel(Localizer.Format("FAREditorNβ"), stabDerivOutput.stabDerivs[17], " " + Localizer.Format("FARUnitInvSecSq"), Localizer.Format("FAREditorNβExp"), W160, 1); + StabilityLabel(Localizer.Format("FAREditorNp"), stabDerivOutput.stabDerivs[20], " " + Localizer.Format("FARUnitInvSec"), Localizer.Format("FAREditorNpExp"), W160, 0); + StabilityLabel(Localizer.Format("FAREditorNr"), stabDerivOutput.stabDerivs[23], " " + Localizer.Format("FARUnitInvSec"), Localizer.Format("FAREditorNrExp"), W160, -1); GUILayout.EndHorizontal(); GUILayout.EndVertical(); DrawTooltip(); } + private enum CalcAndExportEnum { CalculateOnly, CalculateAndExport, LoopExport }; + + private void StabDerivCalcButtonAction(CalcAndExportEnum exportflag) + { + CelestialBody body = _bodySettingDropdown.ActiveSelection; + FARAeroUtil.UpdateCurrentActiveBody(body); + altitude = Regex.Replace(altitude, @"[^-?[0-9]*(\.[0-9]*)?]", ""); + double altitudeDouble = Convert.ToDouble(altitude) * 1000; + machNumber = Regex.Replace(machNumber, @"[^-?[0-9]*(\.[0-9]*)?]", ""); + double machDouble = FARMathUtil.Clamp(Convert.ToSingle(machNumber), 0.001, float.PositiveInfinity); + int flapsettingInt = _flapSettingDropdown.ActiveSelection; + bool spoilersDeployedBool = spoilersDeployed; + + if (exportflag == CalcAndExportEnum.LoopExport) + { + int n = 0; + ExportTextFileCache filecache = new ExportTextFileCache(); + foreach (Vector2 altmach in StabilityDerivativeExportFile.LoadConfigList()) + { + StabilityDerivExportOutput output = simManager.StabDerivCalculator.CalculateStabilityDerivs(body, (double)altmach.x, (double)altmach.y, flapsettingInt, spoilersDeployedBool); + if (output != null && StabilityDerivativeExportFile.Export(output, filecache)) + n++; + } + if (n > 0) + { + filecache.FlushTextFileLines(); + PopupDialog.SpawnPopupDialog(new Vector2(0, 0), new Vector2(0, 0), "FARStabDerivLoopCount", Localizer.Format("FAREditorStabDerivLoopDone"), Localizer.Format("FAREditorStabDerivLoopDoneExp", n), Localizer.Format("FARGUIOKButton"), true, HighLogic.UISkin); + } + else + PopupDialog.SpawnPopupDialog(new Vector2(0, 0), new Vector2(0, 0), "FARStabDerivSaveError", Localizer.Format("FAREditorStabDerivSaveError"), Localizer.Format("FAREditorStabDerivSaveErrorExp"), Localizer.Format("FARGUIOKButton"), true, HighLogic.UISkin); + return; // in the LoopExport case skip the usual calculation + } + + StabilityDerivExportOutput stabDerivResult = simManager.StabDerivCalculator.CalculateStabilityDerivs(body, altitudeDouble, machDouble, flapsettingInt, spoilersDeployedBool); + if (stabDerivResult == null) + PopupDialog.SpawnPopupDialog(new Vector2(0, 0), new Vector2(0, 0), "FARStabDerivError", Localizer.Format("FAREditorStabDerivError"), Localizer.Format("FAREditorStabDerivErrorExp"), Localizer.Format("FARGUIOKButton"), true, HighLogic.UISkin); + else + { + stabDerivOutput = stabDerivResult.outputvals; + simManager.vehicleData = stabDerivResult.outputvals; + SetAngleVectors(stabDerivResult.outputvals.stableAoA); + + if (exportflag == CalcAndExportEnum.CalculateAndExport && !StabilityDerivativeExportFile.Export(stabDerivResult)) + PopupDialog.SpawnPopupDialog(new Vector2(0, 0), new Vector2(0, 0), "FARStabDerivSaveError", Localizer.Format("FAREditorStabDerivSaveError"), Localizer.Format("FAREditorStabDerivSaveErrorExp"), Localizer.Format("FARGUIOKButton"), true, HighLogic.UISkin); + } + } + private void StabilityLabel(String text1, double val, String text2, String tooltip, int width, int sign) { Color color = Color.white; diff --git a/FerramAerospaceResearch/FARMathUtil.cs b/FerramAerospaceResearch/FARMathUtil.cs index a7512a23a..dfa1887c9 100644 --- a/FerramAerospaceResearch/FARMathUtil.cs +++ b/FerramAerospaceResearch/FARMathUtil.cs @@ -60,7 +60,7 @@ public static double Lerp(double x1, double x2, double y1, double y2, double x) y += y1; return y; } - + public static T Clamp(this T val, T min, T max) where T : IComparable { if (val.CompareTo(min) < 0) return min; @@ -81,7 +81,7 @@ public static bool Approximately(double p, double q, double error) return true; return false; } - + public static double ArithmeticGeometricMean(double a, double b, double error) { while (!Approximately(a, b, error)) @@ -101,7 +101,7 @@ public static double ModifiedArithmeticGeometricMean(double a, double b, double double tmpA = 0.5 * (a + b); double tmpSqrt = Math.Sqrt((a - c) * (b - c)); b = c + tmpSqrt; - c = c - tmpSqrt; + c = c - tmpSqrt; a = tmpA; } return (a + b) * 0.5; @@ -133,7 +133,7 @@ public static double BrentsMethod(Func function, double a, doubl if (fa * fb >= 0) return 0; - if(Math.Abs(fa) < Math.Abs(fb)) + if (Math.Abs(fa) < Math.Abs(fb)) { double tmp = fa; fa = fb; @@ -146,13 +146,13 @@ public static double BrentsMethod(Func function, double a, doubl double c = a, d = a, fc = function(c); - double s = b, fs = fb; + double s = b, fs = fb; bool flag = true; int iter = 0; - while(fs != 0 && Math.Abs(a - b) > epsilon && iter < maxIter) + while (fs != 0 && Math.Abs(a - b) > epsilon && iter < maxIter) { - if((fa - fc) > double.Epsilon && (fb - fc) > double.Epsilon) //inverse quadratic interpolation + if ((fa - fc) > double.Epsilon && (fb - fc) > double.Epsilon) //inverse quadratic interpolation { s = a * fc * fb / ((fa - fb) * (fa - fc)); s += b * fc * fa / ((fb - fa) * (fb - fc)); @@ -165,7 +165,7 @@ public static double BrentsMethod(Func function, double a, doubl s = b - s; } - double b_s = Math.Abs(b - s), b_c = Math.Abs(b-c), c_d = Math.Abs(c - d); + double b_s = Math.Abs(b - s), b_c = Math.Abs(b - c), c_d = Math.Abs(c - d); //Conditions for bisection method bool condition1; @@ -248,5 +248,131 @@ public static double BrentsMethod(Func function, double a, doubl } return s; } + + private const double rightedge = 30d; + private const double leftedge = -rightedge; + private const double xstepinitial = 5d; + private const double xstepsize = 10d; + private const double minpart = 1d / 8d; + private const double maxpart = 7d / 8d; + private const double tol_triangle = 1E-3; + private const double tol_linear = 3E-4; + private const double tol_brent = 1E-3; + private const int iterlim = 500; + + public static double SillySearchMethod(Func function) + { + double x0 = 0d; + double f0 = function(x0); + MirroredFunction mfobj = new MirroredFunction(function, f0 > 0d); + if (mfobj.IsMirrored) f0 = -f0; + Func f = mfobj.Delegate; + double x1 = xstepinitial; + double f1 = f(x1); + if (f1 < f0) return mfobj.BrentSolve("Negative initial gradient."); + + LblSkipRight: + if (f1 > 0) return mfobj.LinearSolution(x0, f0, x1, f1); + double x2 = Clamp(x1 + xstepsize, 0d, rightedge); + if (x2 == x1) return mfobj.BrentSolve("Reached far right edge."); + double f2 = f(x2); + if (f2 > f1) + { // skip right + x0 = x1; f0 = f1; + x1 = x2; f1 = f2; + goto LblSkipRight; + } + + LblTriangle: + if (f1 > 0) return mfobj.LinearSolution(x0, f0, x1, f1); + if (x2 - x0 < tol_triangle) return mfobj.BrentSolve("Local maximum is negative (search point x= " + x0 + ")."); + double x01 = (x0 + x1) / 2d; + double x12 = (x1 + x2) / 2d; + double f01 = f(x01); + double f12 = f(x12); + if (f01 >= f1 && f01 >= f12) + { // maximum at x01 + x1 = x01; f1 = f01; + x2 = x1; f2 = f1; + goto LblTriangle; + } + else if (f12 > f1 && f12 > f01) + { // maximum at x12 + x0 = x1; f0 = f1; + x1 = x12; f1 = f12; + goto LblTriangle; + } + else + { // shrink around x1 + x0 = x01; f0 = f01; + x2 = x12; f2 = f12; + goto LblTriangle; + } + } + + public class MirroredFunction + { + private Func F; + private bool mirror; + + public MirroredFunction(Func original, bool mirrored) + { + F = original; + mirror = mirrored; + } + + public Func Delegate + { + get + { + if (mirror) + return this.InvokeMirrored; + else + return this.F; + } + } + + public bool IsMirrored { get { return this.mirror; } } + + private double InvokeMirrored(double x) + { + return -F.Invoke(-x); + } + + public double LinearSolution(double x0, double f0, double x1, double f1) + { + if (this.IsMirrored) + { + double oldx0 = x0; + double oldf0 = f0; + x0 = -x1; f0 = -f1; + x1 = -oldx0; f1 = -oldf0; + } + + LblLoop: + double x = x0 + (x0 - x1) * f0 / (f1 - f0); + if (x1 - x0 < tol_linear) return x; + x = Clamp(x, maxpart * x0 + minpart * x1, minpart * x0 + maxpart * x1); + double fx = F(x); + if (fx < 0d) + { + x0 = x; f0 = fx; + goto LblLoop; + } + else if (fx > 0d) + { + x1 = x; f1 = fx; + goto LblLoop; + } + else + return x; + } + + public double BrentSolve(string dbgmsg) + { + Debug.Log("[FAR]: MirroredFunction (mirrored= " + mirror + ") reverting to BrentsMethod: " + dbgmsg); + return FARMathUtil.BrentsMethod(this.F, leftedge, rightedge, tol_brent, iterlim); + } + } } } diff --git a/FerramAerospaceResearch/FerramAerospaceResearch.csproj b/FerramAerospaceResearch/FerramAerospaceResearch.csproj index fdca9a7d4..82915916d 100644 --- a/FerramAerospaceResearch/FerramAerospaceResearch.csproj +++ b/FerramAerospaceResearch/FerramAerospaceResearch.csproj @@ -121,6 +121,7 @@ + @@ -130,6 +131,7 @@ + diff --git a/FerramAerospaceResearch/Properties/AssemblyInfo.cs b/FerramAerospaceResearch/Properties/AssemblyInfo.cs index ae30914eb..465b0b209 100644 --- a/FerramAerospaceResearch/Properties/AssemblyInfo.cs +++ b/FerramAerospaceResearch/Properties/AssemblyInfo.cs @@ -8,9 +8,9 @@ [assembly: AssemblyTitle("FerramAerospaceResearch")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Microsoft")] +//[assembly: AssemblyCompany("Microsoft")] [assembly: AssemblyProduct("FerramAerospaceResearch")] -[assembly: AssemblyCopyright("Copyright © Michael Ferrara 2018")] +[assembly: AssemblyCopyright("Copyright © Michael Ferrara et al. 2018")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: KSPAssembly("FerramAerospaceResearch", 0, 15)] diff --git a/GameData/FerramAerospaceResearch/Localization/Localization.cfg b/GameData/FerramAerospaceResearch/Localization/Localization.cfg index dd3b8ba31..bab98791e 100644 --- a/GameData/FerramAerospaceResearch/Localization/Localization.cfg +++ b/GameData/FerramAerospaceResearch/Localization/Localization.cfg @@ -64,9 +64,9 @@ FARDebugVoxels = Display Debug Voxels FAREditorTitleTransonic = Transonic Area Ruling Analysis - FAREditorTransMaxArea = Max Cross-Section Area: - FAREditorTransMach1DragArea = Mach 1 Wave Drag-Area: - FAREditorTransCritMach = Critical Mach Number: + FAREditorTransMaxArea = Max Cross-Section Area:\u0020 + FAREditorTransMach1DragArea = Mach 1 Wave Drag-Area:\u0020 + FAREditorTransCritMach = Critical Mach Number:\u0020 FAREditorTransMinDragExp1 = Minimal wave drag is achieved by maintaining a\nsmooth, minimal curvature cross-section curve, including the\neffects of intake -> engine ducting. FAREditorTransMinDragExp2 = Minimize curvature to minimize wave drag. FAREditorTransAreaCurve = Show cross-sectional area curve (green) @@ -76,31 +76,37 @@ FAREditorStabDerivFlightCond = Flight Condition: FAREditorStabDerivPlanet = Planet: FAREditorStabDerivAlt = Altitude (km): - FAREditorStabDerivMach = Mach Number: - FAREditorStabDerivFlap = Flap Setting: + FAREditorStabDerivMach = Mach Number: + FAREditorStabDerivFlap = Flap Setting: FAREditorStabDerivSpoiler = Spoilers: FAREditorStabDerivSDeploy = Deployed FAREditorStabDerivSRetract = Retracted FAREditorStabDerivCalcButton = Calculate Stability Derivatives + FAREditorStabDerivSaveButton = Export Stability Derivatives + FAREditorStabDerivLoopButton = Run Export Loop FAREditorStabDerivError = Error! - FAREditorStabDerivErrorExp = Altitude was above atmosphere + FAREditorStabDerivErrorExp = Unable to determine stable angle of attack. Typical problems include insufficient lift at the given speed and altitude. Altitude cannot be above the atmosphere. + FAREditorStabDerivSaveError = Error! + FAREditorStabDerivSaveErrorExp = Unable to export stability derivatives. You may need to delete previous exported values. + FAREditorStabDerivLoopDone = Calculation loop complete + FAREditorStabDerivLoopDoneExp = The stability derivatives export loop calculated and exported <<1>> solution result(s). FAREditorStabDerivAirProp = Aircraft Properties FAREditorStabDerivMoI = Moments of Inertia FAREditorStabDerivPoI = Products of Inertia FAREditorStabDerivLvlFl = Level Flight - FAREditorStabDerivRefArea = Ref Area: - FAREditorStabDerivScaledChord = Scaled Chord: - FAREditorStabDerivScaledSpan = Scaled Span: + FAREditorStabDerivRefArea = Ref Area:\u0020 + FAREditorStabDerivScaledChord = Scaled Chord:\u0020 + FAREditorStabDerivScaledSpan = Scaled Span:\u0020 - FAREditorStabDerivIxx = Ixx: - FAREditorStabDerivIyy = Iyy: - FAREditorStabDerivIzz = Izz: - FAREditorStabDerivIxy = Ixy: - FAREditorStabDerivIyz = Iyz: - FAREditorStabDerivIxz = Ixz: + FAREditorStabDerivIxx = Ixx:\u0020 + FAREditorStabDerivIyy = Iyy:\u0020 + FAREditorStabDerivIzz = Izz:\u0020 + FAREditorStabDerivIxy = Ixy:\u0020 + FAREditorStabDerivIyz = Iyz:\u0020 + FAREditorStabDerivIxz = Ixz:\u0020 FAREditorStabDerivIxxExp = Inertia about X-axis due to rotation about X-axis FAREditorStabDerivIyyExp = Inertia about Y-axis due to rotation about Y-axis @@ -109,7 +115,7 @@ FAREditorStabDerivIyzExp = Inertia about Y-axis due to rotation about Z-axis; is equal to inertia about Z-axis due to rotation about Y-axis FAREditorStabDerivIxzExp = Inertia about X-axis due to rotation about Z-axis; is equal to inertia about Z-axis due to rotation about X-axis - FAREditorStabDerivu0 = u0: + FAREditorStabDerivu0 = u0:\u0020 FAREditorStabDerivu0Exp = Air speed based on this mach number and temperature. FAREditorStabDerivClExp = Required lift coefficient at this mass, speed and air density. FAREditorStabDerivCdExp = Resulting drag coefficient at this mass, speed and air density. @@ -121,20 +127,20 @@ FAREditorPitchRateDeriv = Pitch Rate Derivatives FAREditorPitchCtrlDeriv = Pitch Ctrl Derivatives - FAREditorZw = Zw: - FAREditorZu = Zu: - FAREditorZq = Zq: - FAREditorZDeltae = Zδe: + FAREditorZw = Zw:\u0020 + FAREditorZu = Zu:\u0020 + FAREditorZq = Zq:\u0020 + FAREditorZDeltae = Zδe:\u0020 - FAREditorXw = Xw: - FAREditorXu = Xu: - FAREditorXq = Xq: - FAREditorXDeltae = Xδe: + FAREditorXw = Xw:\u0020 + FAREditorXu = Xu:\u0020 + FAREditorXq = Xq:\u0020 + FAREditorXDeltae = Xδe:\u0020 - FAREditorMw = Mw: - FAREditorMu = Mu: - FAREditorMq = Mq: - FAREditorMDeltae = Mδe: + FAREditorMw = Mw:\u0020 + FAREditorMu = Mu:\u0020 + FAREditorMq = Mq:\u0020 + FAREditorMDeltae = Mδe:\u0020 FAREditorZwExp = Change in Z-direction acceleration with respect to Z-direction velocity; should be negative. FAREditorZuExp = Change in Z-direction acceleration with respect to X-direction velocity; should be negative. @@ -157,17 +163,17 @@ FAREditorRollRateDeriv = Roll Rate Derivatives FAREditorYawRateDeriv = Yaw Rate Derivatives - FAREditorYβ = Yβ: - FAREditorYp = Yp: - FAREditorYr = Yr: + FAREditorYβ = Yβ:\u0020 + FAREditorYp = Yp:\u0020 + FAREditorYr = Yr:\u0020 - FAREditorLβ = Lβ: - FAREditorLp = Lp: - FAREditorLr = Lr: + FAREditorLβ = Lβ:\u0020 + FAREditorLp = Lp:\u0020 + FAREditorLr = Lr:\u0020 - FAREditorNβ = Nβ: - FAREditorNp = Np: - FAREditorNr = Nr: + FAREditorNβ = Nβ:\u0020 + FAREditorNp = Np:\u0020 + FAREditorNr = Nr:\u0020 FAREditorYβExp = Change in Y-direction acceleration with respect to sideslip angle β; should be negative. FAREditorYpExp = Change in Y-direction acceleration with respect to roll-right rate; sign unimportant. @@ -187,8 +193,8 @@ FAREditorSimGraphParams = Params FAREditorSimInit = Init - FAREditorSimEndTime = EndTime: - FAREditorSimTimestep = dt: + FAREditorSimEndTime = EndTime: + FAREditorSimTimestep = dt: FAREditorSimRunButton = Run Simulation FAREditorStaticGraphAoA = Angle of Attack, degrees @@ -200,11 +206,11 @@ FAREditorStaticSwitchAoA = Switch To AoA Sweep FAREditorStaticSwitchMach = Switch To Mach Sweep - FAREditorStaticPitchSetting = Pitch Setting: + FAREditorStaticPitchSetting = Pitch Setting: - FAREditorStaticGraphLowLim = Lower: - FAREditorStaticGraphUpLim = Upper: - FAREditorStaticGraphPtCount = Num Pts: + FAREditorStaticGraphLowLim = Lower: + FAREditorStaticGraphUpLim = Upper: + FAREditorStaticGraphPtCount = Num Pts: FAREditorStaticSweepMach = Sweep Mach FAREditorStaticSweepAoA = Sweep AoA diff --git a/GameData/FerramAerospaceResearch/Localization/Localization_de-de.cfg b/GameData/FerramAerospaceResearch/Localization/Localization_de-de.cfg index 53c158595..343dab1db 100644 --- a/GameData/FerramAerospaceResearch/Localization/Localization_de-de.cfg +++ b/GameData/FerramAerospaceResearch/Localization/Localization_de-de.cfg @@ -60,9 +60,9 @@ FARVelIndShow = Zeige Tempo-Anzeige FARDebugVoxels = Debug Voxels anzeigen FAREditorTitleTransonic = Transonische Flächenanalyse -FAREditorTransMaxArea = Maximale Querschnittsfläche: -FAREditorTransMach1DragArea = Mach 1 Wellenwiderstandsfläche: -FAREditorTransCritMach = Kritische Mach-Zahl: +FAREditorTransMaxArea = Maximale Querschnittsfläche:\u0020 +FAREditorTransMach1DragArea = Mach 1 Wellenwiderstandsfläche:\u0020 +FAREditorTransCritMach = Kritische Mach-Zahl:\u0020 FAREditorTransMinDragExp1 = Minimaler Wellenwiderstand wird durch eine glatte,\n\rminimale Krümmungs-Querschnittsflächen-Kurve erreicht,\n\r unter der Berücksichtigung des Einlass->Triebwerk–Rohres. FAREditorTransMinDragExp2 = Minimiere Krümmung um Wellenwiderstand zu minimieren. FAREditorTransAreaCurve = Zeige Kurve: Querschnittsfläche (green) @@ -79,8 +79,14 @@ FAREditorStabDerivSDeploy = Ausgefahren FAREditorStabDerivSRetract = Eingefahren FAREditorStabDerivCalcButton = Berechne Stabilitätswerte +FAREditorStabDerivSaveButton = Stabilitätswerte speichern +FAREditorStabDerivLoopButton = Run Export Loop FAREditorStabDerivError = Fehler! FAREditorStabDerivErrorExp = Höhe war über der Atmosphäre +FAREditorStabDerivSaveError = Fehler! +FAREditorStabDerivSaveErrorExp = Unable to export stability derivatives. You may need to delete previous exported values. +FAREditorStabDerivLoopDone = Calculation loop complete +FAREditorStabDerivLoopDoneExp = The stability derivatives export loop calculated and exported <<1>> solution result(s). FAREditorStabDerivAirProp = Flugzeug-Eigenschaften FAREditorStabDerivMoI = Trägheitsmoment @@ -88,16 +94,16 @@ FAREditorStabDerivPoI = Trägheitsprodukt FAREditorStabDerivLvlFl = Level-Flug // TODO: FAREditorStabDeriv localization -FAREditorStabDerivRefArea = Ref Area: -FAREditorStabDerivScaledChord = Scaled Chord: -FAREditorStabDerivScaledSpan = Scaled Span: +FAREditorStabDerivRefArea = Ref Area:\u0020 +FAREditorStabDerivScaledChord = Scaled Chord:\u0020 +FAREditorStabDerivScaledSpan = Scaled Span:\u0020 -FAREditorStabDerivIxx = Ixx: -FAREditorStabDerivIyy = Iyy: -FAREditorStabDerivIzz = Izz: -FAREditorStabDerivIxy = Ixy: -FAREditorStabDerivIyz = Iyz: -FAREditorStabDerivIxz = Ixz: +FAREditorStabDerivIxx = Ixx:\u0020 +FAREditorStabDerivIyy = Iyy:\u0020 +FAREditorStabDerivIzz = Izz:\u0020 +FAREditorStabDerivIxy = Ixy:\u0020 +FAREditorStabDerivIyz = Iyz:\u0020 +FAREditorStabDerivIxz = Ixz:\u0020 FAREditorStabDerivIxxExp = Trägheit um X-Achse durch Rotation um X-Achse FAREditorStabDerivIyyExp = Trägheit um Y-Achse durch Rotation um Y-Achse @@ -106,7 +112,7 @@ FAREditorStabDerivIxyExp = Trägheit um X-Achse durch Rotation um Y-Achse; ist g FAREditorStabDerivIyzExp = Trägheit um Y-Achse durch Rotation um Z-Achse; ist gleich der Trägheit um Z-Achse durch Rotation um Y-Achse FAREditorStabDerivIxzExp = Trägheit um X-Achse durch Rotation um Z-Achse; ist gleich der Trägheit um Z-Achse durch Rotation um X-Achse -FAREditorStabDerivu0 = u0: +FAREditorStabDerivu0 = u0:\u0020 FAREditorStabDerivu0Exp = Lufttempo basierend auf dieser Mach-Zahl und Temperatur. FAREditorStabDerivClExp = Benötigter Liftkoeffizient bei diesem Gewicht, Tempo und Luftdruck. FAREditorStabDerivCdExp = Resultierender Luftwiderstandsfaktor bei diesem Gewicht, Tempo und Luftdruck. @@ -118,20 +124,20 @@ FAREditorFwdVelDeriv = Vorwärts-Tempo-Ableitungen FAREditorPitchRateDeriv = Nickraten-Ableitungen FAREditorPitchCtrlDeriv = Nickkontroll-Ableitungen -FAREditorZw = Zw: -FAREditorZu = Zu: -FAREditorZq = Zq: -FAREditorZDeltae = Zδe: +FAREditorZw = Zw:\u0020 +FAREditorZu = Zu:\u0020 +FAREditorZq = Zq:\u0020 +FAREditorZDeltae = Zδe:\u0020 -FAREditorXw = Xw: -FAREditorXu = Xu: -FAREditorXq = Xq: -FAREditorXDeltae = Xδe: +FAREditorXw = Xw:\u0020 +FAREditorXu = Xu:\u0020 +FAREditorXq = Xq:\u0020 +FAREditorXDeltae = Xδe:\u0020 -FAREditorMw = Mw: -FAREditorMu = Mu: -FAREditorMq = Mq: -FAREditorMDeltae = Mδe: +FAREditorMw = Mw:\u0020 +FAREditorMu = Mu:\u0020 +FAREditorMq = Mq:\u0020 +FAREditorMDeltae = Mδe:\u0020 FAREditorZwExp = Änderung in Z-gerichteter Beschleunigung hinsichtlich zum Tempo in Z-Richtung; sollte negativ sein. FAREditorZuExp = Änderung in Z-gerichteter Beschleunigung hinsichtlich zum Tempo in X-Richtung; sollte negativ sein. @@ -153,17 +159,17 @@ FAREditorSideslipDeriv = Seitengleitflug-Ableitungen FAREditorRollRateDeriv = Rollraten-Ableitungen FAREditorYawRateDeriv = Gierraten-Ableitungen -FAREditorYβ = Yβ: -FAREditorYp = Yp: -FAREditorYr = Yr: +FAREditorYβ = Yβ:\u0020 +FAREditorYp = Yp:\u0020 +FAREditorYr = Yr:\u0020 -FAREditorLβ = Lβ: -FAREditorLp = Lp: -FAREditorLr = Lr: +FAREditorLβ = Lβ:\u0020 +FAREditorLp = Lp:\u0020 +FAREditorLr = Lr:\u0020 -FAREditorNβ = Nβ: -FAREditorNp = Np: -FAREditorNr = Nr: +FAREditorNβ = Nβ:\u0020 +FAREditorNp = Np:\u0020 +FAREditorNr = Nr:\u0020 FAREditorYβExp = Änderung in Y-gerichteter Beschleunigung hinsichtlich zum Schiebewinkel β; sollte negativ sein. FAREditorYpExp = Änderung in Y-gerichteter Beschleunigung hinsichtlich zur Rechts-Roll-Rate; Vorzeichen unwichtig. diff --git a/GameData/FerramAerospaceResearch/Localization/Localization_ru.cfg b/GameData/FerramAerospaceResearch/Localization/Localization_ru.cfg index f65f4eb99..40a2a354b 100644 --- a/GameData/FerramAerospaceResearch/Localization/Localization_ru.cfg +++ b/GameData/FerramAerospaceResearch/Localization/Localization_ru.cfg @@ -46,9 +46,9 @@ FARDebugVoxels = Показать отладочные воксели FAREditorTitleTransonic = Анализ трансзвукового сечения - FAREditorTransMaxArea = Макс. поперечное сечение: - FAREditorTransMach1DragArea = Сечение волнового сопр. при M=1: - FAREditorTransCritMach = Критическое число Маха: + FAREditorTransMaxArea = Макс. поперечное сечение:\u0020 + FAREditorTransMach1DragArea = Сечение волнового сопр. при M=1:\u0020 + FAREditorTransCritMach = Критическое число Маха:\u0020 FAREditorTransMinDragExp1 = Минимальное волновое сопротивление достигается сглаживанием\nи уменьшением кривизны профиля поперечного сечения, включая\nэффекты потоков воздухозаборник -> двигатель. FAREditorTransMinDragExp2 = Снижайте сечение для уменьшения волнового сопротивления. FAREditorTransAreaCurve = Показать профиль поперечного сечения (зел.) @@ -58,31 +58,37 @@ FAREditorStabDerivFlightCond = Условие полёта: FAREditorStabDerivPlanet = Планета: FAREditorStabDerivAlt = Высота (км): - FAREditorStabDerivMach = Число Маха: - FAREditorStabDerivFlap = Положение закрылков: + FAREditorStabDerivMach = Число Маха: + FAREditorStabDerivFlap = Положение закрылков: FAREditorStabDerivSpoiler = Спойлеры: FAREditorStabDerivSDeploy = Выпущены FAREditorStabDerivSRetract = Убраны FAREditorStabDerivCalcButton = Вычислить коэфф-ты устойчивости + FAREditorStabDerivSaveButton = Хранить коэфф-ты устойчивости + FAREditorStabDerivLoopButton = Run Export Loop FAREditorStabDerivError = Ошибка! FAREditorStabDerivErrorExp = Введена высота за пределами атмосферы + FAREditorStabDerivSaveError = Ошибка! + FAREditorStabDerivSaveErrorExp = Unable to export stability derivatives. You may need to delete previous exported values. + FAREditorStabDerivLoopDone = Calculation loop complete + FAREditorStabDerivLoopDoneExp = The stability derivatives export loop calculated and exported <<1>> solution result(s). FAREditorStabDerivAirProp = Параметры судна FAREditorStabDerivMoI = Моменты инерции FAREditorStabDerivPoI = Центробежные моменты инерции FAREditorStabDerivLvlFl = Горизонтальный полёт - FAREditorStabDerivRefArea = Эфф. сечение: - FAREditorStabDerivScaledChord = Отн. хорда: - FAREditorStabDerivScaledSpan = Отн. размах: + FAREditorStabDerivRefArea = Эфф. сечение:\u0020 + FAREditorStabDerivScaledChord = Отн. хорда:\u0020 + FAREditorStabDerivScaledSpan = Отн. размах:\u0020 - FAREditorStabDerivIxx = Ixx: - FAREditorStabDerivIyy = Iyy: - FAREditorStabDerivIzz = Izz: - FAREditorStabDerivIxy = Ixy: - FAREditorStabDerivIyz = Iyz: - FAREditorStabDerivIxz = Ixz: + FAREditorStabDerivIxx = Ixx:\u0020 + FAREditorStabDerivIyy = Iyy:\u0020 + FAREditorStabDerivIzz = Izz:\u0020 + FAREditorStabDerivIxy = Ixy:\u0020 + FAREditorStabDerivIyz = Iyz:\u0020 + FAREditorStabDerivIxz = Ixz:\u0020 FAREditorStabDerivIxxExp = Инерция относительно оси X при повороте вокруг оси X FAREditorStabDerivIyyExp = Инерция относительно оси Y при повороте вокруг оси Y @@ -91,7 +97,7 @@ FAREditorStabDerivIyzExp = Инерция относительно оси Y при повороте вокруг оси Z; равна инерции относительно оси Z при повороте вокруг оси Y FAREditorStabDerivIxzExp = Инерция относительно оси X при повороте вокруг оси Z; равна инерции относительно оси Z при повороте вокруг оси X - FAREditorStabDerivu0 = u0: + FAREditorStabDerivu0 = u0:\u0020 FAREditorStabDerivu0Exp = Воздушная скорость при заданных числе Маха и температуре. FAREditorStabDerivClExp = Необходимый коэффициент подъёмной силы при таких массе, скорости и плотности воздуха. FAREditorStabDerivCdExp = Итоговый коэффициент сопротивления при таких массе, скорости и плотности воздуха. @@ -103,20 +109,20 @@ FAREditorPitchRateDeriv = Производные угл. скор. тангажа //?? FAREditorPitchCtrlDeriv = Производные упр. тангажом - FAREditorZw = Zw: - FAREditorZu = Zu: - FAREditorZq = Zq: - FAREditorZDeltae = Zδe: + FAREditorZw = Zw:\u0020 + FAREditorZu = Zu:\u0020 + FAREditorZq = Zq:\u0020 + FAREditorZDeltae = Zδe:\u0020 - FAREditorXw = Xw: - FAREditorXu = Xu: - FAREditorXq = Xq: - FAREditorXDeltae = Xδe: + FAREditorXw = Xw:\u0020 + FAREditorXu = Xu:\u0020 + FAREditorXq = Xq:\u0020 + FAREditorXDeltae = Xδe:\u0020 - FAREditorMw = Mw: - FAREditorMu = Mu: - FAREditorMq = Mq: - FAREditorMDeltae = Mδe: + FAREditorMw = Mw:\u0020 + FAREditorMu = Mu:\u0020 + FAREditorMq = Mq:\u0020 + FAREditorMDeltae = Mδe:\u0020 FAREditorZwExp = Изменение ускорения по оси Z с изменением скорости вдоль оси Z; должно быть отрицательным. FAREditorZuExp = Изменение ускорения по оси Z с изменением скорости вдоль оси X; должно быть отрицательным. @@ -139,17 +145,17 @@ FAREditorRollRateDeriv = Производные угл. скор. крена FAREditorYawRateDeriv = Производные угл. скор. рыскания - FAREditorYβ = Yβ: - FAREditorYp = Yp: - FAREditorYr = Yr: + FAREditorYβ = Yβ:\u0020 + FAREditorYp = Yp:\u0020 + FAREditorYr = Yr:\u0020 - FAREditorLβ = Lβ: - FAREditorLp = Lp: - FAREditorLr = Lr: + FAREditorLβ = Lβ:\u0020 + FAREditorLp = Lp:\u0020 + FAREditorLr = Lr:\u0020 - FAREditorNβ = Nβ: - FAREditorNp = Np: - FAREditorNr = Nr: + FAREditorNβ = Nβ:\u0020 + FAREditorNp = Np:\u0020 + FAREditorNr = Nr:\u0020 FAREditorYβExp = Изменение ускорения по оси Y с изменением угла скольжения β; должно быть отрицательным. FAREditorYpExp = Изменение ускорения по оси Y с изменением угловой скорости крена вправо; знак неважен. @@ -169,8 +175,8 @@ FAREditorSimGraphParams = Парам-ры FAREditorSimInit = Нач. - FAREditorSimEndTime = МаксВр: - FAREditorSimTimestep = dt: + FAREditorSimEndTime = МаксВр: + FAREditorSimTimestep = dt: FAREditorSimRunButton = Запуск симуляции FAREditorStaticGraphAoA = Угол атаки, градусы @@ -182,11 +188,11 @@ FAREditorStaticSwitchAoA = Перекл. на угол атаки FAREditorStaticSwitchMach = Перекл. на число Маха - FAREditorStaticPitchSetting = Угол тангажа: + FAREditorStaticPitchSetting = Угол тангажа: - FAREditorStaticGraphLowLim = От: - FAREditorStaticGraphUpLim = До: - FAREditorStaticGraphPtCount = Точек: + FAREditorStaticGraphLowLim = От: + FAREditorStaticGraphUpLim = До: + FAREditorStaticGraphPtCount = Точек: FAREditorStaticSweepMach = Изм-е ч. Маха FAREditorStaticSweepAoA = Изм-е УгАт @@ -235,15 +241,15 @@ FARFlightDataOption7 = Дальность + Длительность FARFlightDataOption8 = БК и Терм Скор - FARFlightData0 = Тангаж: \nРыскание: \nКрен: - FARFlightData1 = Угол атаки: \nУгол скольж-я: - FARFlightData2 = Дин. давление: - FARFlightData3 = Подъём. сила: \nЛобовое сопр.: \nБоковое сопр.: - FARFlightData4 = Cl: \nCd: \nCy: \nЭфф. сечение: - FARFlightData5 = L/D: \nV*L/D: + FARFlightData0 = Тангаж: \nРыскание: \nКрен: + FARFlightData1 = Угол атаки: \nУгол скольж-я: + FARFlightData2 = Дин. давление: + FARFlightData3 = Подъём. сила: \nЛобовое сопр.: \nБоковое сопр.: + FARFlightData4 = Cl: \nCd: \nCy: \nЭфф. сечение: + FARFlightData5 = L/D: \nV*L/D: FARFlightData6 = Доля топлива: \nПотр-е топлива: \nПоступление возд.: \nУдел. избыт. мощн.: - FARFlightData7 = Оцен. длит.: \nОцен. дальн.: - FARFlightData8 = БК: \nТерм. скорость: + FARFlightData7 = Оцен. длит.: \nОцен. дальн.: + FARFlightData8 = БК: \nТерм. скорость: FARFlightGUIWindowSelect0 = Полётные данные diff --git a/GameData/FerramAerospaceResearch/Localization/Localization_zh-cn.cfg b/GameData/FerramAerospaceResearch/Localization/Localization_zh-cn.cfg index a7c1cd794..febf49230 100644 --- a/GameData/FerramAerospaceResearch/Localization/Localization_zh-cn.cfg +++ b/GameData/FerramAerospaceResearch/Localization/Localization_zh-cn.cfg @@ -45,9 +45,9 @@ FARDebugVoxels = 显示调试体素 FAREditorTitleTransonic = 跨音速面积律分析 - FAREditorTransMaxArea = 最大截面积: - FAREditorTransMach1DragArea = 马赫1波阻面积: - FAREditorTransCritMach = 临界马赫数: + FAREditorTransMaxArea = 最大截面积:\u0020 + FAREditorTransMach1DragArea = 马赫1波阻面积:\u0020 + FAREditorTransCritMach = 临界马赫数:\u0020 FAREditorTransMinDragExp1 = 为了得到最小的波阻,应保持一个光滑并且曲率\n最小的截面积曲线(考虑进气->引擎的管道效应在内). FAREditorTransMinDragExp2 = 最小的曲率可以得到最小的波阻. FAREditorTransAreaCurve = 显示截面积曲线 (绿色) @@ -57,31 +57,37 @@ FAREditorStabDerivFlightCond = 飞行环境: FAREditorStabDerivPlanet = 星球: FAREditorStabDerivAlt = 高度 (km): - FAREditorStabDerivMach = 马赫数: - FAREditorStabDerivFlap = 襟翼设置: + FAREditorStabDerivMach = 马赫数: + FAREditorStabDerivFlap = 襟翼设置: FAREditorStabDerivSpoiler = 扰流板: FAREditorStabDerivSDeploy = 展开 FAREditorStabDerivSRetract = 收回 FAREditorStabDerivCalcButton = 计算稳定性导数 + FAREditorStabDerivSaveButton = Export Stability Derivatives + FAREditorStabDerivLoopButton = Run Export Loop FAREditorStabDerivError = 错误! FAREditorStabDerivErrorExp = 高度在大气层之外 + FAREditorStabDerivSaveError = Error! + FAREditorStabDerivSaveErrorExp = Unable to export stability derivatives. You may need to delete previous exported values. + FAREditorStabDerivLoopDone = Calculation loop complete + FAREditorStabDerivLoopDoneExp = The stability derivatives export loop calculated and exported <<1>> solution result(s). FAREditorStabDerivAirProp = 飞行器属性 FAREditorStabDerivMoI = 惯性力矩 FAREditorStabDerivPoI = 惯性积 FAREditorStabDerivLvlFl = 水平飞行 - FAREditorStabDerivRefArea = 参考面积: - FAREditorStabDerivScaledChord = 弦长: - FAREditorStabDerivScaledSpan = 翼展: + FAREditorStabDerivRefArea = 参考面积:\u0020 + FAREditorStabDerivScaledChord = 弦长:\u0020 + FAREditorStabDerivScaledSpan = 翼展:\u0020 - FAREditorStabDerivIxx = Ixx: - FAREditorStabDerivIyy = Iyy: - FAREditorStabDerivIzz = Izz: - FAREditorStabDerivIxy = Ixy: - FAREditorStabDerivIyz = Iyz: - FAREditorStabDerivIxz = Ixz: + FAREditorStabDerivIxx = Ixx:\u0020 + FAREditorStabDerivIyy = Iyy:\u0020 + FAREditorStabDerivIzz = Izz:\u0020 + FAREditorStabDerivIxy = Ixy:\u0020 + FAREditorStabDerivIyz = Iyz:\u0020 + FAREditorStabDerivIxz = Ixz:\u0020 FAREditorStabDerivIxxExp = 由绕 X轴旋转而关于 X轴的转动惯量 FAREditorStabDerivIyyExp = 由绕 Y轴旋转而关于 Y轴的转动惯量 @@ -90,7 +96,7 @@ FAREditorStabDerivIyzExp = 由绕 Z轴旋转而关于 Y轴的转动惯量; 等于由绕 Y轴旋转而关于 Z轴的转动惯量 FAREditorStabDerivIxzExp = 由绕 Z轴旋转而关于 X轴的转动惯量; 等于由绕 X轴旋转而关于 Z轴的转动惯量 - FAREditorStabDerivu0 = 空速: + FAREditorStabDerivu0 = 空速:\u0020 FAREditorStabDerivu0Exp = 空速基于马赫数和温度. FAREditorStabDerivClExp = 在这个质量,速度和空气密度下所需的升力系数. FAREditorStabDerivCdExp = 在这个质量,速度和空气密度下导出的阻力系数. @@ -102,20 +108,20 @@ FAREditorPitchRateDeriv = 俯仰速率导数 FAREditorPitchCtrlDeriv = 俯仰控制导数 - FAREditorZw = Zw: - FAREditorZu = Zu: - FAREditorZq = Zq: - FAREditorZDeltae = Zδe: + FAREditorZw = Zw:\u0020 + FAREditorZu = Zu:\u0020 + FAREditorZq = Zq:\u0020 + FAREditorZDeltae = Zδe:\u0020 - FAREditorXw = Xw: - FAREditorXu = Xu: - FAREditorXq = Xq: - FAREditorXDeltae = Xδe: + FAREditorXw = Xw:\u0020 + FAREditorXu = Xu:\u0020 + FAREditorXq = Xq:\u0020 + FAREditorXDeltae = Xδe:\u0020 - FAREditorMw = Mw: - FAREditorMu = Mu: - FAREditorMq = Mq: - FAREditorMDeltae = Mδe: + FAREditorMw = Mw:\u0020 + FAREditorMu = Mu:\u0020 + FAREditorMq = Mq:\u0020 + FAREditorMDeltae = Mδe:\u0020 FAREditorZwExp = Z方向加速度相对于Z方向速度的变化; 应该为负. FAREditorZuExp = Z方向加速度相对于X方向速度的变化; 应该为负. @@ -138,17 +144,17 @@ FAREditorRollRateDeriv = 滚转率导数 FAREditorYawRateDeriv = 偏航率导数 - FAREditorYβ = Yβ: - FAREditorYp = Yp: - FAREditorYr = Yr: + FAREditorYβ = Yβ:\u0020 + FAREditorYp = Yp:\u0020 + FAREditorYr = Yr:\u0020 - FAREditorLβ = Lβ: - FAREditorLp = Lp: - FAREditorLr = Lr: + FAREditorLβ = Lβ:\u0020 + FAREditorLp = Lp:\u0020 + FAREditorLr = Lr:\u0020 - FAREditorNβ = Nβ: - FAREditorNp = Np: - FAREditorNr = Nr: + FAREditorNβ = Nβ:\u0020 + FAREditorNp = Np:\u0020 + FAREditorNr = Nr:\u0020 FAREditorYβExp = Y方向加速度相对于侧滑角β的变化; 应该为负. FAREditorYpExp = Y方向加速度相对于向右滚转率的变化; 符号不重要. @@ -168,8 +174,8 @@ FAREditorSimGraphParams = 参数 FAREditorSimInit = 初始化 - FAREditorSimEndTime = 终止时间: - FAREditorSimTimestep = 步进时间: + FAREditorSimEndTime = 终止时间: + FAREditorSimTimestep = 步进时间: FAREditorSimRunButton = 运行模拟 FAREditorStaticGraphAoA = 攻角, 度 @@ -181,11 +187,11 @@ FAREditorStaticSwitchAoA = 切换至攻角扫描 FAREditorStaticSwitchMach = 切换至马赫数扫描 - FAREditorStaticPitchSetting = 俯仰设置: + FAREditorStaticPitchSetting = 俯仰设置: - FAREditorStaticGraphLowLim = 下限: - FAREditorStaticGraphUpLim = 上限: - FAREditorStaticGraphPtCount = 数据点: + FAREditorStaticGraphLowLim = 下限: + FAREditorStaticGraphUpLim = 上限: + FAREditorStaticGraphPtCount = 数据点: FAREditorStaticSweepMach = 马赫扫描 FAREditorStaticSweepAoA = 攻角扫描 @@ -234,15 +240,15 @@ FARFlightDataOption7 = 航程 + 航时 FARFlightDataOption8 = 弹道系数 + 终端速度 - FARFlightData0 = 俯仰角: \n方位角: \n滚转角: - FARFlightData1 = 攻角: \n侧滑角: - FARFlightData2 = 动压: - FARFlightData3 = 升力: \n阻力: \n侧向力: - FARFlightData4 = 升力系数: \n阻力系数: \n侧向力系数: \n参考面积: - FARFlightData5 = 升阻比: \n速度 *升阻比: + FARFlightData0 = 俯仰角: \n方位角: \n滚转角: + FARFlightData1 = 攻角: \n侧滑角: + FARFlightData2 = 动压: + FARFlightData3 = 升力: \n阻力: \n侧向力: + FARFlightData4 = 升力系数: \n阻力系数: \n侧向力系数: \n参考面积: + FARFlightData5 = 升阻比: \n速度 *升阻比: FARFlightData6 = 燃油比: \n推力比油耗: \n空气供给: \n规格. 过剩功率: - FARFlightData7 = 预估航时: \n预估航程: - FARFlightData8 = 弹道系数: \n终端速度: + FARFlightData7 = 预估航时: \n预估航程: + FARFlightData8 = 弹道系数: \n终端速度: FARFlightGUIWindowSelect0 = 飞行数据 diff --git a/GameData/FerramAerospaceResearch/Plugins/PluginData/FerramAerospaceResearch/sdexpcfg.txt b/GameData/FerramAerospaceResearch/Plugins/PluginData/FerramAerospaceResearch/sdexpcfg.txt new file mode 100644 index 000000000..50da1d6ad --- /dev/null +++ b/GameData/FerramAerospaceResearch/Plugins/PluginData/FerramAerospaceResearch/sdexpcfg.txt @@ -0,0 +1,70 @@ +# Created by Ferram Aerospace Research plugin for Kerbal Space Program +# name: altmach +# type: matrix +# rows: 65 +# columns: 2 + 0 0.10 + 0 0.25 + 0 0.35 + 0 0.50 + 0 0.70 + 0 0.85 + 0 0.95 + 0 1.20 + 0 1.50 + 0 2 + 0 3 + 0 5 + 2E3 0.10 + 2E3 0.35 + 2E3 0.50 + 2E3 0.70 + 2E3 0.95 + 2E3 1.20 + 2E3 2 + 2E3 5 + 5E3 0.35 + 5E3 0.70 + 5E3 0.95 + 5E3 1.20 + 5E3 1.50 + 5E3 3 + 8E3 0.35 + 8E3 0.85 + 8E3 0.95 + 8E3 1.20 + 8E3 1.50 + 8E3 5 + 12E3 0.35 + 12E3 0.50 + 12E3 0.70 + 12E3 0.85 + 12E3 0.95 + 12E3 1.20 + 12E3 1.50 + 12E3 2 + 12E3 3 + 12E3 5 + 18E3 0.35 + 18E3 0.85 + 18E3 1.20 + 18E3 2 + 24E3 0.50 + 24E3 0.95 + 24E3 1.20 + 24E3 3 + 30E3 0.70 + 30E3 1.20 + 30E3 2 + 30E3 3 + 30E3 5 + 40E3 0.85 + 40E3 1.20 + 40E3 2 + 40E3 3 + 40E3 5 + 60E3 0.85 + 60E3 1.20 + 60E3 2 + 60E3 3 + 60E3 5 diff --git a/GameData/FerramAerospaceResearch/Plugins/PluginData/sdexport.txt b/GameData/FerramAerospaceResearch/Plugins/PluginData/sdexport.txt new file mode 100644 index 000000000..e69de29bb diff --git a/README.md b/README.md index 18b3c6db1..0b85e97ff 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,10 @@ Set all the other winglet/control surface values to zero CHANGELOG ======================================================= +0.15.9.6 "" ----------------------------------- + +Merged in Rodhern's update 3 + 0.15.9.5V "Lighthill"------------------------------------ Update for KSP 1.5.1 @@ -148,7 +152,7 @@ Update license Fix an issue where voxels could be incredibly asymmetric on symmetric crafts -0.15.7V "K�chemann"------------------------------------ +0.15.7V "Kchemann"------------------------------------ Update to ModuleManager 2.6.25 Update for KSP 1.1.3 compatibility @@ -193,7 +197,7 @@ Fix RealChute / RealChuteLite interaction breaking stock chute behavior, thanks Fix mass-calc error for wing-mass-strength that resulted in all planes gaining unhealthy amounts of weight Attempt to make debug-compatibility actually work, thanks to NathanKell -0.15.6.1V "von K�rm�n"------------------------------------ +0.15.6.1V "von Krmn"------------------------------------ Fix a critical CPU usage bug that resulted in voxelization threads SpinWaiting forever, monopolizing the processor Fix parachutes without RealChute configs not applying forces when FAR + RC are installed, thanks to stupid_chris