Skip to content

Commit

Permalink
Automatic merge of T1.5.1-794-g4cad06780 and 14 pull requests
Browse files Browse the repository at this point in the history
- Pull request #570 at 3539862: Experimental glTF 2.0 support with PBR lighting
- Pull request #839 at d00beb9: First phase of https://blueprints.launchpad.net/or/+spec/additional-cruise-control-parameters
- Pull request #876 at f92de76: docs: add source for documents previously on website to source Documentation folder
- Pull request #882 at a055bca: Blueprint/train car operations UI window
- Pull request #885 at d9ce84b: feat: Add notifications to Menu
- Pull request #886 at 6c0785b: Scene viewer extension to TrackViewer
- Pull request #892 at 1f5ba4c: Signal Function OPP_SIG_ID_TRAINPATH
- Pull request #896 at 5866028: First implementation of https://blueprints.launchpad.net/or/+spec/specific-sounds-for-ai-trains
- Pull request #897 at 0a9d939: feat: Improved system information collection
- Pull request #899 at 0fb4d1c: Duplex steam engines - Booster Engine addition
- Pull request #903 at 22edf27: Downloading route content (Github, zip)
- Pull request #906 at 5850660: Bug fix for https://bugs.launchpad.net/or/+bug/2047299 Crash loading a 3Dcab-only loco
- Pull request #907 at 9b0b04f: Bug fix for https://bugs.launchpad.net/or/+bug/2047300 Dynamic tracks disappear after long tunnel
- Pull request #908 at 4b4afe3: feat: supports switching adhesion precisions
  • Loading branch information
openrails-bot committed Dec 28, 2023
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 89 deletions.
Expand Up @@ -283,23 +283,105 @@ public void Restore(BinaryReader inf)
AxleList[i].Restore(inf);
}
}

/// <summary>
/// switch between Polach and Pacha adhesion calculation
/// </summary>
public static bool UsePolachAdhesion = false; // "static" so there's only one value in the program.
public bool PreviousUsePolachAdhesion = false; // Keep a note for each Axles so that we can tell if it changed.

/// <summary>
/// Updates each axle on the list
/// </summary>
/// <param name="elapsedClockSeconds">Time span within the simulation cycle</param>
public void Update(float elapsedClockSeconds)
/// <param name="elapsedSeconds">Time span within the simulation cycle</param>
public void Update(float elapsedSeconds)
{
UsePolachAdhesion = AdhesionPrecision.IsPrecisionHigh(this, elapsedSeconds, Car.Simulator.GameTime);
foreach (var axle in AxleList)
{
axle.Update(elapsedClockSeconds);
if (UsePolachAdhesion != PreviousUsePolachAdhesion) // There's been a transition
{
axle.AxleSpeedMpS = axle.TrainSpeedMpS; // So the transition doesn't cause a wheelslip
}
axle.Update(elapsedSeconds);
}
PreviousUsePolachAdhesion = UsePolachAdhesion;
}
public List<Axle>.Enumerator GetEnumerator()
{
return AxleList.GetEnumerator();
}

static class AdhesionPrecision // "static" so all "Axles" share the same level of precision
{
enum AdhesionPrecisionLevel
{
/// <summary>
/// Initial level uses Polach algorithm
/// </summary>
High = 0,
/// <summary>
/// Low-performance PCs use Pacha's algorithm
/// </summary>
Low = 1,
/// <summary>
/// After frequent transitions, low-performance PCs are locked to Pacha's algorithm
/// </summary>
LowLocked = 2
}

// Adjustable limits
const float LowerLimitS = 0.025f; // timespan 0.025 = 40 fps screen rate, low timeSpan and high FPS
const float UpperLimitS = 0.033f; // timespan 0.033 = 30 fps screen rate, high timeSpan and low FPS
const double IntervalBetweenDowngradesLimitS = 5 * 60; // Locks in low precision if < 5 mins between downgrades

static AdhesionPrecisionLevel PrecisionLevel = AdhesionPrecisionLevel.High;
static double TimeOfLatestDowngrade = 0 - IntervalBetweenDowngradesLimitS; // Starts at -5 mins

// Tested by dropping the framerate below 30 fps interactively. Did this by opening and closing the HelpWindow after inserting
// Threading.Thread.Sleep(40);
// into HelpWindow.PrepareFrame() temporarily.
public static bool IsPrecisionHigh(Axles axles, float elapsedSeconds, double gameTime)
{
// Switches between Polach (high precision) adhesion model and Pacha (low precision) adhesion model depending upon the PC performance
switch (PrecisionLevel)
{
case AdhesionPrecisionLevel.High:
if (elapsedSeconds > UpperLimitS)
{
var screenFrameRate = 1 / elapsedSeconds;
var timeSincePreviousDowngradeS = gameTime - TimeOfLatestDowngrade;
if (timeSincePreviousDowngradeS < IntervalBetweenDowngradesLimitS)
{
Trace.TraceInformation($"At {gameTime:F0} secs, advanced adhesion model switched to low precision permanently after {timeSincePreviousDowngradeS:F0} secs since previous switch (less than limit of {IntervalBetweenDowngradesLimitS})");
PrecisionLevel = AdhesionPrecisionLevel.LowLocked;
}
else
{
TimeOfLatestDowngrade = gameTime;
Trace.TraceInformation($"At {gameTime:F0} secs, advanced adhesion model switched to low precision after low frame rate {screenFrameRate:F1} below limit {1 / UpperLimitS:F0}");
PrecisionLevel = AdhesionPrecisionLevel.Low;
}
}
break;

case AdhesionPrecisionLevel.Low:
if (elapsedSeconds > 0 // When debugging step by step, elapsedSeconds == 0, so test for that
&& elapsedSeconds < LowerLimitS)
{
PrecisionLevel = AdhesionPrecisionLevel.High;
var ScreenFrameRate = 1 / elapsedSeconds;
Trace.TraceInformation($"At {gameTime:F0} secs, advanced adhesion model switched to high precision after high frame rate {ScreenFrameRate:F1} above limit {1 / LowerLimitS:F0}");
}
break;

case AdhesionPrecisionLevel.LowLocked:
break;
}
return (PrecisionLevel == AdhesionPrecisionLevel.High);
}
}
}


/// <summary>
Expand Down Expand Up @@ -433,12 +515,6 @@ public float InertiaKgm2
/// </summary>
float forceToAccelerationFactor;

/// <summary>
/// switch between Polach and Pacha adhesion calculation
/// </summary>
public static bool UsePolachAdhesion = false; // "static" so it's shared by all axles of the Player's loco
public double GameTime; // Set by MSTSLocomotive and used by AdhesionPrecision.IsPrecisionHigh

/// <summary>
/// Pre-calculation of slip characteristics at 0 slip speed
/// </summary>
Expand Down Expand Up @@ -561,7 +637,7 @@ public float TransmissionEfficiency
/// <summary>
/// Axle speed value, in metric meters per second
/// </summary>
public double AxleSpeedMpS { get; private set; }
public double AxleSpeedMpS { get; set; }

/// <summary>
/// Axle angular position in radians
Expand Down Expand Up @@ -845,7 +921,7 @@ public void Save(BinaryWriter outf)
double slipSpeedMpS = axleSpeedMpS - TrainSpeedMpS;
double axleOutForceN = 0;

if (UsePolachAdhesion)
if (Axles.UsePolachAdhesion)
{
axleOutForceN = Math.Sign(slipSpeedMpS) * AxleWeightN * SlipCharacteristicsPolach(slipSpeedMpS);
}
Expand Down Expand Up @@ -891,7 +967,7 @@ void Integrate(float elapsedClockSeconds)
if (elapsedClockSeconds <= 0) return;
double prevSpeedMpS = AxleSpeedMpS;

if (UsePolachAdhesion)
if (Axles.UsePolachAdhesion)
{

float upperSubStepLimit = 100;
Expand Down Expand Up @@ -980,7 +1056,7 @@ void Integrate(float elapsedClockSeconds)
{
var k1 = GetAxleMotionVariation(AxleSpeedMpS, dt);

if (i == 0 && !UsePolachAdhesion)
if (i == 0 && !Axles.UsePolachAdhesion)
{
if (k1.Item1 * dt > Math.Max((Math.Abs(SlipSpeedMpS) - 1) * 10, 1) / 100)
{
Expand Down Expand Up @@ -1023,8 +1099,7 @@ void Integrate(float elapsedClockSeconds)
/// <param name="elapsedSeconds"></param>
public virtual void Update(float elapsedSeconds)
{
UsePolachAdhesion = AdhesionPrecision.IsPrecisionHigh(elapsedSeconds, GameTime);
if (UsePolachAdhesion)
if (Axles.UsePolachAdhesion)
{
forceToAccelerationFactor = WheelRadiusM * WheelRadiusM / totalInertiaKgm2;

Expand Down Expand Up @@ -1128,79 +1203,6 @@ public virtual void Update(float elapsedSeconds)
}
}

static class AdhesionPrecision // "static" so all "Axle"s share the same level of precision
{
enum AdhesionPrecisionLevel
{
/// <summary>
/// Initial level uses Polach algorithm
/// </summary>
High = 0,
/// <summary>
/// Low-performance PCs use Pacha's algorithm
/// </summary>
Low = 1,
/// <summary>
/// After frequent transitions, low-performance PCs are locked to Pacha's algorithm
/// </summary>
LowLocked = 2
}

// Adjustable limits
const float LowerLimitS = 0.025f; // timespan 0.025 = 40 fps screen rate, low timeSpan and high FPS
const float UpperLimitS = 0.033f; // timespan 0.033 = 30 fps screen rate, high timeSpan and low FPS
const double IntervalBetweenDowngradesLimitS = 5 * 60; // Locks in low precision if < 5 mins between downgrades

static AdhesionPrecisionLevel PrecisionLevel = AdhesionPrecisionLevel.High;
static double TimeOfLatestDowngrade = 0 - IntervalBetweenDowngradesLimitS; // Starts at -5 mins

// Tested by varying the framerate interactively. Did this by opening and closing the HelpWindow after inserting
// Threading.Thread.Sleep(40);
// into HelpWindow.PrepareFrame() temporarily.
public static bool IsPrecisionHigh(float elapsedSeconds, double gameTime)
{
// Switches between Polach (high precision) adhesion model and Pacha (low precision) adhesion model depending upon the PC performance
switch (PrecisionLevel)
{
case AdhesionPrecisionLevel.High:
if (elapsedSeconds > UpperLimitS)
{
var screenFrameRate = 1 / elapsedSeconds;
var timeSincePreviousDowngradeS = gameTime - TimeOfLatestDowngrade;
if (timeSincePreviousDowngradeS < IntervalBetweenDowngradesLimitS)
{
Trace.TraceInformation($"At {gameTime:F0} secs, advanced adhesion model switched to low precision permanently after {timeSincePreviousDowngradeS:F0} secs since previous switch (less than limit of {IntervalBetweenDowngradesLimitS})");
PrecisionLevel = AdhesionPrecisionLevel.LowLocked;
}
else
{
TimeOfLatestDowngrade = gameTime;

Trace.TraceInformation($"At {gameTime:F0} secs, advanced adhesion model switched to low precision after low frame rate {screenFrameRate:F1} below limit {1 / UpperLimitS:F0}");
PrecisionLevel = AdhesionPrecisionLevel.Low;

}
}
break;

case AdhesionPrecisionLevel.Low:
if (elapsedSeconds > 0 // When debugging step by step, elapsedSeconds == 0, so test for that
&& elapsedSeconds < LowerLimitS)
{
PrecisionLevel = AdhesionPrecisionLevel.High;
var ScreenFrameRate = 1 / elapsedSeconds;
Trace.TraceInformation($"At {gameTime:F0} secs, advanced adhesion model switched to high precision after high frame rate {ScreenFrameRate:F1} above limit {1 / LowerLimitS:F0}");
}
break;

case AdhesionPrecisionLevel.LowLocked:
break;

}
return (PrecisionLevel == AdhesionPrecisionLevel.High);
}
}

class PolachCalculator
{
Axle Axle;
Expand Down
2 changes: 1 addition & 1 deletion Source/RunActivity/Viewer3D/Popups/HUDWindow.cs
Expand Up @@ -1080,7 +1080,7 @@ void TextPageForceInfo(TableData table)
if (mstsLocomotive.AdvancedAdhesionModel)
{
var text = Viewer.Catalog.GetString("(Advanced adhesion model)");
if (Axle.UsePolachAdhesion == false) text += "???";
if (Axles.UsePolachAdhesion == false) text += "???";
TableAddLine(table, text);
int row0 = table.CurrentRow;
TableSetCell(table, table.CurrentRow++, table.CurrentLabelColumn, Viewer.Catalog.GetString("Wheel slip (Thres)"));
Expand Down

0 comments on commit 607889f

Please sign in to comment.