Skip to content

Commit

Permalink
update for FAR 0.15.1
Browse files Browse the repository at this point in the history
  • Loading branch information
neuoy committed May 15, 2015
1 parent a843bc6 commit 7a9a5f3
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 128 deletions.
4 changes: 2 additions & 2 deletions Plugin/DebugFastStart.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ public void Start()
if (AppDomain.CurrentDomain.GetAssemblies().Any(a => a.FullName.ToLower().Contains("testautomation")))
return;

HighLogic.SaveFolder = "default";
HighLogic.LoadScene(GameScenes.TRACKSTATION);
//HighLogic.SaveFolder = "default";
//HighLogic.LoadScene(GameScenes.TRACKSTATION);

CheatOptions.InfiniteFuel = true;
}
Expand Down
4 changes: 2 additions & 2 deletions Plugin/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.1.3.0")]
[assembly: AssemblyFileVersion("1.1.3.0")]
[assembly: AssemblyVersion("1.2.0.0")]
[assembly: AssemblyFileVersion("1.2.0.0")]
7 changes: 5 additions & 2 deletions Plugin/Trajectories.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
<StartAction>Program</StartAction>
<StartProgram>D:\dev\KerbalSpaceProgram\0.90_dev\KSP.exe</StartProgram>
<StartProgram>D:\dev\KerbalSpaceProgram\1.0_dev\KSP.exe</StartProgram>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\..\0.90_dev\GameData\Trajectories\Plugin\</OutputPath>
<OutputPath>..\..\1.0_dev\GameData\Trajectories\Plugin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
Expand All @@ -40,9 +40,11 @@
<ItemGroup>
<Reference Include="Assembly-CSharp">
<HintPath>..\..\1.0_dev\KSP_Data\Managed\Assembly-CSharp.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Assembly-CSharp-firstpass">
<HintPath>..\..\1.0_dev\KSP_Data\Managed\Assembly-CSharp-firstpass.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
Expand All @@ -52,6 +54,7 @@
<Reference Include="System.Xml" />
<Reference Include="UnityEngine">
<HintPath>..\..\1.0_dev\KSP_Data\Managed\UnityEngine.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
Expand Down
15 changes: 15 additions & 0 deletions Plugin/Util.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,21 @@ public static MethodInfo GetMethodEx(this Type type, string methodName, Type[] t
}
}

public static MethodInfo GetMethodEx(this Type type, string methodName, BindingFlags flags, Type[] types)
{
try
{
var res = type.GetMethod(methodName, flags, null, types, null);
if (res == null)
throw new Exception("method not found");
return res;
}
catch (Exception e)
{
throw new Exception("Failed to GetMethod " + methodName + " on type " + type.FullName + " with types " + types.ToString() + ":\n" + e.Message + "\n" + e.StackTrace);
}
}

public static Vector3d SwapYZ(Vector3d v)
{
return new Vector3d(v.x, v.z, v.y);
Expand Down
168 changes: 47 additions & 121 deletions Plugin/VesselAerodynamicModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,9 @@ class VesselAerodynamicModel
private double referenceDrag = 0;
private DateTime nextAllowedAutomaticUpdate = DateTime.Now;

private Type FARBasicDragModelType;
private Type FARWingAerodynamicModelType;
private MethodInfo FARBasicDragModel_RunDragCalculation;
private FieldInfo FARBasicDragModel_YmaxForce;
private FieldInfo FARBasicDragModel_XZmaxForce;
private MethodInfo FARWingAerodynamicModel_CalculateForces;
private FieldInfo FARWingAerodynamicModel_rho;
private FieldInfo FARWingAerodynamicModel_stall;
private FieldInfo FARWingAerodynamicModel_YmaxForce;
private FieldInfo FARWingAerodynamicModel_XZmaxForce;
private MethodInfo FARAeroUtil_GetMachNumber;
private MethodInfo FARAeroUtil_GetCurrentDensity;
private Type FARAPIType;
private MethodInfo FARAPI_CalculateVesselAeroForces;
private MethodInfo FARAeroUtil_GetCurrentDensity;

public bool Verbose { get; set; }

Expand Down Expand Up @@ -119,46 +110,49 @@ public void Invalidate()

public double computeFARReferenceDrag()
{
Vector3 forces = computeForces_FAR(10, 2, new Vector3d(3000.0, 0, 0), new Vector3(0, 1, 0), 0, 0.25);
Vector3 forces = computeForces_FAR(3000, new Vector3d(3000.0, 0, 0), new Vector3(0, 1, 0), 0, 0.25);
return forces.sqrMagnitude;
}

private void initFARModel()
{
Debug.Log("Trajectories: Initializing aerodynamic model...");

bool farInstalled = false;

foreach (var loadedAssembly in AssemblyLoader.loadedAssemblies)
{
switch (loadedAssembly.name)
try
{
case "NEAR":
useNEAR = true;
goto case "FerramAerospaceResearch";
case "FerramAerospaceResearch":
string namespaceName = useNEAR ? "NEAR" : "ferram4";
FARBasicDragModelType = loadedAssembly.assembly.GetType(namespaceName + ".FARBasicDragModel");
FARBasicDragModel_YmaxForce = FARBasicDragModelType.GetField("YmaxForce", BindingFlags.Public | BindingFlags.Instance);
FARBasicDragModel_XZmaxForce = FARBasicDragModelType.GetField("XZmaxForce", BindingFlags.Public | BindingFlags.Instance);
FARWingAerodynamicModelType = loadedAssembly.assembly.GetType(namespaceName + ".FARWingAerodynamicModel");
FARWingAerodynamicModel_CalculateForces = FARWingAerodynamicModelType.GetMethodEx("CalculateForces", BindingFlags.Public | BindingFlags.Instance);
FARWingAerodynamicModel_rho = FARWingAerodynamicModelType.GetField("rho", BindingFlags.NonPublic | BindingFlags.Instance);
if(FARWingAerodynamicModel_rho == null)
FARWingAerodynamicModel_rho = loadedAssembly.assembly.GetType(namespaceName + ".FARBaseAerodynamics").GetField("rho", BindingFlags.Public | BindingFlags.Instance); // this has changed in FAR 0.14.3
FARWingAerodynamicModel_stall = FARWingAerodynamicModelType.GetField("stall", BindingFlags.NonPublic | BindingFlags.Instance);
FARWingAerodynamicModel_YmaxForce = FARWingAerodynamicModelType.GetField("YmaxForce", BindingFlags.Public | BindingFlags.Instance);
FARWingAerodynamicModel_XZmaxForce = FARWingAerodynamicModelType.GetField("XZmaxForce", BindingFlags.Public | BindingFlags.Instance);
if (!useNEAR)
{
FARBasicDragModel_RunDragCalculation = FARBasicDragModelType.GetMethodEx("RunDragCalculation", new Type[] { typeof(Vector3d), typeof(double), typeof(double) });
FARAeroUtil_GetMachNumber = loadedAssembly.assembly.GetType(namespaceName + ".FARAeroUtil").GetMethodEx("GetMachNumber", new Type[] { typeof(CelestialBody), typeof(double), typeof(Vector3d)});
FARAeroUtil_GetCurrentDensity = loadedAssembly.assembly.GetType(namespaceName + ".FARAeroUtil").GetMethodEx("GetCurrentDensity", new Type[] { typeof(CelestialBody), typeof(double), typeof(bool) });
}
else
{
FARBasicDragModel_RunDragCalculation = FARBasicDragModelType.GetMethodEx("RunDragCalculation", new Type[] { typeof(Vector3d), typeof(double) });
}
farInstalled = true;
break;
switch (loadedAssembly.name)
{
case "NEAR":
useNEAR = true;
goto case "FerramAerospaceResearch";
case "FerramAerospaceResearch":
string namespaceName = useNEAR ? "NEAR" : "FerramAerospaceResearch";
FARAPIType = loadedAssembly.assembly.GetType(namespaceName + ".FARAPI");
if (useNEAR)
{
throw new Exception("NEAR support not implemented yet");
}
else
{
// public static void FerramAerospaceResearch.FARAPI.CalculateVesselAeroForces(Vessel vessel, out Vector3 aeroForce, out Vector3 aeroTorque, Vector3 velocityWorldVector, double altitude)
FARAPI_CalculateVesselAeroForces = FARAPIType.GetMethodEx("CalculateVesselAeroForces", BindingFlags.Public | BindingFlags.Static, new Type[] { typeof(Vessel), typeof(Vector3).MakeByRefType(), typeof(Vector3).MakeByRefType(), typeof(Vector3), typeof(double) });

// public static double FerramAerospaceResearch.FARAeroUtil.GetCurrentDensity(CelestialBody body, double altitude, bool densitySmoothingAtOcean = true)
FARAeroUtil_GetCurrentDensity = loadedAssembly.assembly.GetType(namespaceName + ".FARAeroUtil").GetMethodEx("GetCurrentDensity", new Type[] { typeof(CelestialBody), typeof(double), typeof(bool) });
}
farInstalled = true;
break;
}
}
catch(Exception e)
{
Debug.Log("Trajectories: failed to interface with assembly " + loadedAssembly.name);
Debug.Log("Using stock model instead");
Debug.Log(e.ToString());
}
}

Expand Down Expand Up @@ -236,7 +230,6 @@ private Vector2 computeCacheEntry(int v, int a, int m)

double maxAltitude = body_.atmosphereDepth;
double currentAltitude = maxAltitude * (double)m / (double)(cachedFARForces.GetLength(2) - 1);
double machNumber = useNEAR ? 0.0 : (double)FARAeroUtil_GetMachNumber.Invoke(null, new object[] { body_, currentAltitude, new Vector3d((float)vel, 0, 0) });
double pressure = FlightGlobals.getStaticPressure(currentAltitude, body_);
double temperature = FlightGlobals.getExternalTemperature(currentAltitude, body_);
double stockRho = FlightGlobals.getAtmDensity(pressure, temperature);
Expand All @@ -246,7 +239,7 @@ private Vector2 computeCacheEntry(int v, int a, int m)
double invScale = 1.0 / (rho * v2); // divide by v² and rho before storing the force, to increase accuracy (the reverse operation is performed when reading from the cache)

double AoA = maxFARAngleOfAttack * ((double)a / (double)(cachedFARForces.GetLength(1) - 1) * 2.0 - 1.0);
Vector3d force = computeForces_FAR(rho, machNumber, velocity, new Vector3(0, 1, 0), AoA, 0.25) * invScale;
Vector3d force = computeForces_FAR(currentAltitude, velocity, new Vector3(0, 1, 0), AoA, 0.25) * invScale;
return cachedFARForces[v, a, m] = new Vector2((float)force.x, (float)force.y);
}

Expand Down Expand Up @@ -361,7 +354,7 @@ private Vector3d computeForces_StockDrag(CelestialBody body, Vector3d bodySpaceP
return airVelocity * (-0.5 * rho * velocityMag * stockDragCoeff_ * crossSectionalArea);
}

public Vector3d computeForces_FAR(double rho, double machNumber, Vector3d airVelocity, Vector3d vup, double angleOfAttack, double dt)
public Vector3d computeForces_FAR(double altitude, Vector3d airVelocity, Vector3d vup, double angleOfAttack, double dt)
{
Transform vesselTransform = vessel_.ReferenceTransform;

Expand All @@ -373,82 +366,16 @@ public Vector3d computeForces_FAR(double rho, double machNumber, Vector3d airVel

Vector3d airVelocityForFixedAoA = (vesselForward * Math.Cos(-angleOfAttack) + vesselUp * Math.Sin(-angleOfAttack)) * airVelocity.magnitude;

Vector3d totalForce = new Vector3d(0, 0, 0);

foreach (var part in vessel_.Parts)
{
if (part.Rigidbody == null)
continue;

foreach (var module in part.Modules)
{
if (FARBasicDragModelType.IsInstanceOfType(module))
{
double YmaxForce = 0, XZmaxForce = 0;
if (!useNEAR)
{
// make sure we don't trigger aerodynamic failures during prediction
YmaxForce = (double)FARBasicDragModel_YmaxForce.GetValue(module);
XZmaxForce = (double)FARBasicDragModel_XZmaxForce.GetValue(module);
FARBasicDragModel_YmaxForce.SetValue(module, Double.MaxValue);
FARBasicDragModel_XZmaxForce.SetValue(module, Double.MaxValue);
}

if(useNEAR)
totalForce += (Vector3d)FARBasicDragModel_RunDragCalculation.Invoke(module, new object[] { airVelocityForFixedAoA, rho });
else
totalForce += (Vector3d)FARBasicDragModel_RunDragCalculation.Invoke(module, new object[] { airVelocityForFixedAoA, machNumber, rho });

if (!useNEAR)
{
FARBasicDragModel_YmaxForce.SetValue(module, YmaxForce);
FARBasicDragModel_XZmaxForce.SetValue(module, XZmaxForce);
}
}

if (FARWingAerodynamicModelType.IsInstanceOfType(module))
{
double YmaxForce = 0, XZmaxForce = 0;
if (!useNEAR)
{
// make sure we don't trigger aerodynamic failures during prediction
YmaxForce = (double)FARWingAerodynamicModel_YmaxForce.GetValue(module);
XZmaxForce = (double)FARWingAerodynamicModel_XZmaxForce.GetValue(module);
FARWingAerodynamicModel_YmaxForce.SetValue(module, Double.MaxValue);
FARWingAerodynamicModel_XZmaxForce.SetValue(module, Double.MaxValue);
}

double rhoBackup = (double)FARWingAerodynamicModel_rho.GetValue(module);
FARWingAerodynamicModel_rho.SetValue(module, rho);

// FAR uses the stall value computed in the previous frame to compute the new one. This is incompatible with prediction code that shares the same state variables as the normal simulation.
// This is also incompatible with forces caching that is made to improve performances, as such caching can't depend on the previous wing state
// To solve this problem, we assume wings never stall during prediction, and we backup/restore the stall value each time
double stallBackup = (double)FARWingAerodynamicModel_stall.GetValue(module);
FARWingAerodynamicModel_stall.SetValue(module, 0);

double PerpVelocity = Vector3d.Dot(part.partTransform.forward, airVelocityForFixedAoA.normalized);
double FARAoA = Math.Asin(Math.Min(Math.Max(PerpVelocity, -1), 1));
if(useNEAR)
totalForce += (Vector3d)FARWingAerodynamicModel_CalculateForces.Invoke(module, new object[] { airVelocityForFixedAoA, FARAoA });
else
totalForce += (Vector3d)FARWingAerodynamicModel_CalculateForces.Invoke(module, new object[] { airVelocityForFixedAoA, machNumber, FARAoA });

FARWingAerodynamicModel_rho.SetValue(module, rhoBackup);
FARWingAerodynamicModel_stall.SetValue(module, stallBackup);

if (!useNEAR)
{
FARWingAerodynamicModel_YmaxForce.SetValue(module, YmaxForce);
FARWingAerodynamicModel_XZmaxForce.SetValue(module, XZmaxForce);
}
}
}
}
Debug.Log("Trajectories: getting FAR forces");
Vector3 worldAirVel = new Vector3((float)airVelocityForFixedAoA.x, (float)airVelocityForFixedAoA.y, (float)airVelocityForFixedAoA.z);
var parameters = new object[] { vessel_, new Vector3(), new Vector3(), worldAirVel, altitude };
FARAPI_CalculateVesselAeroForces.Invoke(null, parameters);
Vector3d totalForce = (Vector3)parameters[1];
Debug.Log("Trajectories: got FAR forces");

if (Double.IsNaN(totalForce.x) || Double.IsNaN(totalForce.y) || Double.IsNaN(totalForce.z))
{
Debug.Log("Trajectories: WARNING: FAR/NEAR totalForce is NAN (rho=" + rho + ", machNumber=" + machNumber + ", airVelocity=" + airVelocity.magnitude + ", angleOfAttack=" + angleOfAttack);
Debug.Log("Trajectories: WARNING: FAR/NEAR totalForce is NAN (altitude=" + altitude + ", airVelocity=" + airVelocity.magnitude + ", angleOfAttack=" + angleOfAttack);
return new Vector3d(0, 0, 0); // Don't send NaN into the simulation as it would cause bad things (infinite loops, crash, etc.). I think this case only happens at the atmosphere edge, so the total force should be 0 anyway.
}

Expand Down Expand Up @@ -485,7 +412,7 @@ public Vector3d computeForces_FAR(double rho, double machNumber, Vector3d airVel
Vector3d res = predictedVesselRight * localForce.x + predictedVesselUp * localForce.y + predictedVesselBackward * localForce.z;
if (Double.IsNaN(res.x) || Double.IsNaN(res.y) || Double.IsNaN(res.z))
{
Debug.Log("Trajectories: res is NaN (rho=" + rho + ", machNumber=" + machNumber + ", airVelocity=" + airVelocity.magnitude + ", angleOfAttack=" + angleOfAttack);
Debug.Log("Trajectories: res is NaN (altitude=" + altitude + ", airVelocity=" + airVelocity.magnitude + ", angleOfAttack=" + angleOfAttack);
return new Vector3d(0, 0, 0); // Don't send NaN into the simulation as it would cause bad things (infinite loops, crash, etc.). I think this case only happens at the atmosphere edge, so the total force should be 0 anyway.
}
return res;
Expand All @@ -507,9 +434,8 @@ private Vector3d computeForces_FAR(CelestialBody body, Vector3d bodySpacePositio

double rho = useNEAR ? stockRho : (double)FARAeroUtil_GetCurrentDensity.Invoke(null, new object[] { body, altitudeAboveSea, false });

double actualMachNumber = useNEAR ? 0.0 : (double)FARAeroUtil_GetMachNumber.Invoke(null, new object[] { body_, altitudeAboveSea, new Vector3d((float)airVelocity.magnitude, 0, 0) });
#if !USE_CACHE
return computeForces_FAR(rho, actualMachNumber, airVelocity, bodySpacePosition, angleOfAttack, dt);
return computeForces_FAR(altitudeAboveSea, airVelocity, bodySpacePosition, angleOfAttack, dt);
#else
//double approxMachNumber = useNEAR ? 0.0 : (double)FARAeroUtil_GetMachNumber.Invoke(null, new object[] { body_, body.maxAtmosphereAltitude * 0.5, new Vector3d((float)airVelocity.magnitude, 0, 0) });
//Util.PostSingleScreenMessage("machNum", "machNumber = " + actualMachNumber + " ; approx machNumber = " + approxMachNumber);
Expand Down
Loading

0 comments on commit 7a9a5f3

Please sign in to comment.