2929using Orts . Simulation . RollingStocks . SubSystems . PowerTransmissions ;
3030using SharpDX . Direct2D1 ;
3131using SharpDX . Direct3D9 ;
32+ using Orts . Formats . OR ;
33+ using static Orts . Simulation . RollingStocks . SubSystems . PowerTransmissions . Axle ;
3234
3335namespace Orts . Simulation . RollingStocks . SubSystems . PowerTransmissions
3436{
@@ -429,7 +431,7 @@ public float InertiaKgm2
429431 /// <summary>
430432 /// switch between Polach and Pacha adhesion calculation
431433 /// </summary>
432- bool UsePolachAdhesion = false ;
434+ public static bool UsePolachAdhesion = false ; // "static" so it's shared by all axles of the Player's loco
433435
434436 /// <summary>
435437 /// Pre-calculation of slip characteristics at 0 slip speed
@@ -996,37 +998,13 @@ void Integrate(float elapsedClockSeconds)
996998 /// - computes axle dynamic model according to its driveType
997999 /// - computes wheelslip indicators
9981000 /// </summary>
999- /// <param name="timeSpan "></param>
1000- public virtual void Update ( float timeSpan )
1001+ /// <param name="elapsedSeconds "></param>
1002+ public virtual void Update ( float elapsedSeconds )
10011003 {
1002- // Test to determine whether to use Polach or Pacha adhesion
1003-
1004- // Switches between Polach (high performance) adhesion model and Pacha (low performance) adhesion model depending upon the PC performance
1005- if ( timeSpan < 0.025 ) // timespan 0.025 = 40 fps screen rate, low timeSpan and high FPS
1006- {
1007- UsePolachAdhesion = true ;
1008- }
1009- else if ( timeSpan > 0.033 ) // timespan 0.033 = 30 fps screen rate, high timeSpan and low FPS
1010- {
1011- UsePolachAdhesion = false ;
1012- if ( TrainSpeedMpS > 0 )
1013- {
1014- var ScreenFrameRate = 1 / timeSpan ;
1015- Trace . TraceInformation ( "Advanced adhesion model switched to low performance option due to low frame rate {0} at ElapsedClockSeconds of {1}" , ScreenFrameRate , timeSpan ) ;
1016-
1017- }
1018-
1019- // Set values for Pacha adhesion
1020- WheelSlipThresholdMpS = MpS . FromKpH ( AdhesionK / AdhesionLimit ) ;
1021- WheelAdhesion = 0.99f ;
1022- MaximumPolachWheelAdhesion = 0.99f ;
1023-
1024- }
1025-
1026- forceToAccelerationFactor = WheelRadiusM * WheelRadiusM / totalInertiaKgm2 ;
1027-
1004+ UsePolachAdhesion = AdhesionPrecision . IsPrecisionHigh ( elapsedSeconds ) ;
10281005 if ( UsePolachAdhesion )
10291006 {
1007+ forceToAccelerationFactor = WheelRadiusM * WheelRadiusM / totalInertiaKgm2 ;
10301008
10311009 Polach . Update ( ) ;
10321010 axleStaticForceN = AxleWeightN * SlipCharacteristicsPolach ( 0 ) ;
@@ -1039,6 +1017,15 @@ public virtual void Update(float timeSpan)
10391017 axleStaticForceN = AxleWeightN * SlipCharacteristicsPolach ( 0 ) ;
10401018 }
10411019 }
1020+ else
1021+ {
1022+ // Set values for Pacha adhesion
1023+ WheelSlipThresholdMpS = MpS . FromKpH ( AdhesionK / AdhesionLimit ) ;
1024+ WheelAdhesion = 0.99f ;
1025+ MaximumPolachWheelAdhesion = 0.99f ;
1026+
1027+ forceToAccelerationFactor = WheelRadiusM * WheelRadiusM / totalInertiaKgm2 ;
1028+ }
10421029
10431030#if DEBUG_ADHESION
10441031 double [ ] spd = new double [ 50 ] ;
@@ -1063,9 +1050,9 @@ public virtual void Update(float timeSpan)
10631050 Console . WriteLine ( "" ) ;
10641051#endif
10651052
1066- motor ? . Update ( timeSpan ) ;
1053+ motor ? . Update ( elapsedSeconds ) ;
10671054
1068- Integrate ( timeSpan ) ;
1055+ Integrate ( elapsedSeconds ) ;
10691056 // TODO: We should calculate brake force here
10701057 // Adding and substracting the brake force is correct for normal operation,
10711058 // but during wheelslip this will produce wrong results.
@@ -1084,14 +1071,14 @@ public virtual void Update(float timeSpan)
10841071 {
10851072 IsWheelSlip = IsWheelSlipWarning = true ;
10861073 }
1087- WheelSlipTimeS += timeSpan ;
1074+ WheelSlipTimeS += elapsedSeconds ;
10881075 }
10891076 else if ( Math . Abs ( SlipSpeedPercent ) > SlipWarningTresholdPercent )
10901077 {
10911078 // Wait some time before indicating wheelslip to avoid false triggers
10921079 if ( WheelSlipWarningTimeS > 1 ) IsWheelSlipWarning = true ;
10931080 IsWheelSlip = false ;
1094- WheelSlipWarningTimeS += timeSpan ;
1081+ WheelSlipWarningTimeS += elapsedSeconds ;
10951082 }
10961083 else
10971084 {
@@ -1100,16 +1087,65 @@ public virtual void Update(float timeSpan)
11001087 WheelSlipWarningTimeS = WheelSlipTimeS = 0 ;
11011088 }
11021089
1103- if ( timeSpan > 0.0f )
1090+ if ( elapsedSeconds > 0.0f )
11041091 {
1105- slipDerivationMpSS = ( SlipSpeedMpS - previousSlipSpeedMpS ) / timeSpan ;
1092+ slipDerivationMpSS = ( SlipSpeedMpS - previousSlipSpeedMpS ) / elapsedSeconds ;
11061093 previousSlipSpeedMpS = SlipSpeedMpS ;
11071094
1108- slipDerivationPercentpS = ( SlipSpeedPercent - previousSlipPercent ) / timeSpan ;
1095+ slipDerivationPercentpS = ( SlipSpeedPercent - previousSlipPercent ) / elapsedSeconds ;
11091096 previousSlipPercent = SlipSpeedPercent ;
11101097 }
11111098 }
11121099
1100+ static class AdhesionPrecision // "static" so all "Axle"s share the same level of precision
1101+ {
1102+ enum AdhesionPrecisionLevel
1103+ {
1104+ /// <summary>
1105+ /// Initial level uses Polach algorithm
1106+ /// </summary>
1107+ High ,
1108+ /// <summary>
1109+ /// Low-performance PCs use Pacha's algorithm
1110+ /// </summary>
1111+ Low
1112+ }
1113+
1114+ static AdhesionPrecisionLevel PrecisionLevel = AdhesionPrecisionLevel . High ;
1115+ static double TimeOfLatestDowngrade = 0 ;
1116+
1117+ // Adjustable limits
1118+ const float UpperLimitS = 0.033f ; // timespan 0.033 = 30 fps screen rate, high timeSpan and low FPS
1119+
1120+ // Tested by varying the framerate interactively. Did this by opening and closing the HelpWindow after inserting
1121+ // Threading.Thread.Sleep(40);
1122+ // into HelpWindow.PrepareFrame() temporarily.
1123+ public static bool IsPrecisionHigh ( float elapsedSeconds )
1124+ {
1125+ if ( elapsedSeconds > 0 ) // Ignore period with elapsedSeconds == 0 until user starts game.
1126+ {
1127+ // Switches between Polach (high precision) adhesion model and Pacha (low precision) adhesion model depending upon the PC performance
1128+ switch ( PrecisionLevel )
1129+ {
1130+ case AdhesionPrecisionLevel . High :
1131+ if ( elapsedSeconds > UpperLimitS )
1132+ {
1133+ var screenFrameRate = 1 / elapsedSeconds ;
1134+ {
1135+ Trace . TraceInformation ( $ "Advanced adhesion model switched to low precision permanently after low frame rate { screenFrameRate : F1} below limit { 1 / UpperLimitS : F0} ") ;
1136+ PrecisionLevel = AdhesionPrecisionLevel . Low ;
1137+ }
1138+ }
1139+ break ;
1140+
1141+ case AdhesionPrecisionLevel . Low :
1142+ break ;
1143+ }
1144+ }
1145+ return ( PrecisionLevel == AdhesionPrecisionLevel . High ) ;
1146+ }
1147+ }
1148+
11131149 class PolachCalculator
11141150 {
11151151 Axle Axle ;
@@ -1200,6 +1236,7 @@ public void Update()
12001236 polach_Ks = ( 1.2 * zeroSpeedAdhesion ) - 0.26 ;
12011237 if ( polach_Ks < 0.1 ) polach_Ks = 0.1f ;
12021238 }
1239+
12031240 public double SlipCharacteristics ( double slipSpeedMpS )
12041241 {
12051242 var polach_uadhesion = zeroSpeedAdhesion * ( ( ( 1 - polach_A ) * Math . Exp ( - polach_B * slipSpeedMpS ) ) + polach_A ) ;
0 commit comments