@@ -426,6 +426,11 @@ public float InertiaKgm2
426
426
/// </summary>
427
427
float forceToAccelerationFactor ;
428
428
429
+ /// <summary>
430
+ /// switch between Polach and Pacha adhesion calculation
431
+ /// </summary>
432
+ bool UsePoalchAdhesion = false ;
433
+
429
434
/// <summary>
430
435
/// Pre-calculation of slip characteristics at 0 slip speed
431
436
/// </summary>
@@ -587,12 +592,12 @@ public void ComputeWheelSlipThresholdMpS()
587
592
// i.e. the point where slope changes from positive (adhesion region)
588
593
// to negative (slip region)
589
594
double dx = 0.001 ;
590
- double fa = SlipCharacteristics ( a + dx ) - SlipCharacteristics ( a ) ;
591
- double fb = SlipCharacteristics ( b + dx ) - SlipCharacteristics ( b ) ;
595
+ double fa = SlipCharacteristicsPolach ( a + dx ) - SlipCharacteristicsPolach ( a ) ;
596
+ double fb = SlipCharacteristicsPolach ( b + dx ) - SlipCharacteristicsPolach ( b ) ;
592
597
593
598
double SlipSpeedMpS = AxleSpeedMpS - TrainSpeedMpS ;
594
599
595
- MaximumPolachWheelAdhesion = ( float ) SlipCharacteristics ( WheelSlipThresholdMpS ) ;
600
+ MaximumPolachWheelAdhesion = ( float ) SlipCharacteristicsPolach ( WheelSlipThresholdMpS ) ;
596
601
597
602
if ( SlipSpeedMpS == 0 )
598
603
{
@@ -610,7 +615,7 @@ public void ComputeWheelSlipThresholdMpS()
610
615
while ( Math . Abs ( b - a ) > MpS . FromKpH ( 0.1f ) )
611
616
{
612
617
double c = ( a + b ) / 2 ;
613
- double fc = SlipCharacteristics ( c + dx ) - SlipCharacteristics ( c ) ;
618
+ double fc = SlipCharacteristicsPolach ( c + dx ) - SlipCharacteristicsPolach ( c ) ;
614
619
if ( fa * fc > 0 )
615
620
{
616
621
a = c ;
@@ -813,7 +818,17 @@ public void Save(BinaryWriter outf)
813
818
public ( double , double , double , double ) GetAxleMotionVariation ( double axleSpeedMpS , double elapsedClockSeconds )
814
819
{
815
820
double slipSpeedMpS = axleSpeedMpS - TrainSpeedMpS ;
816
- double axleOutForceN = Math . Sign ( slipSpeedMpS ) * AxleWeightN * SlipCharacteristics ( slipSpeedMpS ) ;
821
+ double axleOutForceN = 0 ;
822
+
823
+ if ( UsePoalchAdhesion )
824
+ {
825
+ axleOutForceN = Math . Sign ( slipSpeedMpS ) * AxleWeightN * SlipCharacteristicsPolach ( slipSpeedMpS ) ;
826
+ }
827
+ else
828
+ {
829
+ axleOutForceN = AxleWeightN * SlipCharacteristicsPacha ( ( float ) axleSpeedMpS - TrainSpeedMpS , TrainSpeedMpS , AdhesionK , AdhesionLimit ) ;
830
+ }
831
+
817
832
double axleInForceN = 0 ;
818
833
if ( DriveType == AxleDriveType . ForceDriven )
819
834
axleInForceN = DriveForceN * transmissionEfficiency ;
@@ -851,31 +866,9 @@ void Integrate(float elapsedClockSeconds)
851
866
if ( elapsedClockSeconds <= 0 ) return ;
852
867
double prevSpeedMpS = AxleSpeedMpS ;
853
868
854
- float upperSubStepStartingLimit = 100 ;
855
- float tempupperSubStepLimit = upperSubStepStartingLimit ;
869
+ float upperSubStepLimit = 100 ;
856
870
float lowerSubStepLimit = 1 ;
857
871
858
- float screenFrameUpperLimit = 60 ;
859
- float screenFrameLowerLimit = 40 ;
860
-
861
- var ScreenFrameRate = Simulator . SmoothedFrameRate ;
862
-
863
- // Reduces the number of substeps if screen FPS drops below a nominal rate of 60 fps
864
- if ( ( int ) ScreenFrameRate >= screenFrameUpperLimit ) // Screen FPS > 60, hold substeps @ maximum value
865
- {
866
- tempupperSubStepLimit = upperSubStepStartingLimit ;
867
- }
868
- else if ( ( int ) ScreenFrameRate < screenFrameLowerLimit ) // Screen FPS < 40, hold substeps @ minimum value
869
- {
870
- tempupperSubStepLimit = upperSubStepStartingLimit * ( screenFrameLowerLimit / screenFrameUpperLimit ) ;
871
- }
872
- else
873
- {
874
- tempupperSubStepLimit = ( int ) ( ( ScreenFrameRate / 60 ) * upperSubStepStartingLimit ) ;
875
- }
876
-
877
- var upperSubStepLimit = tempupperSubStepLimit ;
878
-
879
872
// use straight line graph approximation to increase substeps as slipspeed increases towards the threshold speed point
880
873
// Points are 1 = (0, upperLimit) and 2 = (threshold, lowerLimit)
881
874
var AdhesGrad = ( ( upperSubStepLimit - lowerSubStepLimit ) / ( WheelSlipThresholdMpS - 0 ) ) ;
@@ -961,17 +954,44 @@ void Integrate(float elapsedClockSeconds)
961
954
/// <param name="timeSpan"></param>
962
955
public virtual void Update ( float timeSpan )
963
956
{
964
- forceToAccelerationFactor = WheelRadiusM * WheelRadiusM / totalInertiaKgm2 ;
957
+ // Test to determine whether to use Polach or Pacha adhesion
958
+ var ScreenFrameRate = Simulator . SmoothedFrameRate ;
959
+
960
+ // Switches between Polach (high performance) adhesion model and Pacha (low performance) adhesion model
961
+ if ( ScreenFrameRate > 59 )
962
+ {
963
+ UsePoalchAdhesion = true ;
964
+ }
965
+ else if ( ScreenFrameRate < 55 )
966
+ {
967
+ UsePoalchAdhesion = false ;
968
+ if ( TrainSpeedMpS > 0 )
969
+ {
970
+ Trace . TraceInformation ( "Advanced adhesion model switched to low performance option due to low frame rate {0} at ElapsedClockSeconds of {1}" , ScreenFrameRate , timeSpan ) ;
971
+ }
965
972
966
- Polach . Update ( ) ;
967
- axleStaticForceN = AxleWeightN * SlipCharacteristics ( 0 ) ;
968
- ComputeWheelSlipThresholdMpS ( ) ;
973
+ // Set values for Pacha adhesion
974
+ WheelSlipThresholdMpS = MpS . FromKpH ( AdhesionK / AdhesionLimit ) ;
975
+ WheelAdhesion = 0.99f ;
976
+ MaximumPolachWheelAdhesion = 0.99f ;
969
977
970
- if ( count < 6 && count ++ == 5 )
978
+ }
979
+
980
+ forceToAccelerationFactor = WheelRadiusM * WheelRadiusM / totalInertiaKgm2 ;
981
+
982
+ if ( UsePoalchAdhesion )
971
983
{
972
- TrainSpeedMpS = 10 / 3.6f ;
984
+
973
985
Polach . Update ( ) ;
974
- axleStaticForceN = AxleWeightN * SlipCharacteristics ( 0 ) ;
986
+ axleStaticForceN = AxleWeightN * SlipCharacteristicsPolach ( 0 ) ;
987
+ ComputeWheelSlipThresholdMpS ( ) ;
988
+
989
+ if ( count < 6 && count ++ == 5 )
990
+ {
991
+ TrainSpeedMpS = 10 / 3.6f ;
992
+ Polach . Update ( ) ;
993
+ axleStaticForceN = AxleWeightN * SlipCharacteristicsPolach ( 0 ) ;
994
+ }
975
995
}
976
996
977
997
#if DEBUG_ADHESION
@@ -1170,6 +1190,7 @@ public double SlipCharacteristics(double slipSpeedMpS)
1170
1190
}
1171
1191
1172
1192
/// <summary>
1193
+ /// ***** Polach Adhesion *****
1173
1194
/// Uses the Polach creep force curves calculation described in the following document
1174
1195
/// "Creep forces in simulations of traction vehicles running on adhesion limit" by O. Polach 2005 Wear - http://www.sze.hu/~szenasy/VILLVONT/polachslipvizsg.pdf
1175
1196
///
@@ -1183,12 +1204,55 @@ public double SlipCharacteristics(double slipSpeedMpS)
1183
1204
/// <param name="slipSpeedMpS">Difference between train speed and wheel speed</param>
1184
1205
/// <param name="speedMpS">Current speed</param>
1185
1206
/// <returns>Relative force transmitted to the rail</returns>
1186
- public double SlipCharacteristics ( double slipSpeedMpS )
1207
+ public double SlipCharacteristicsPolach ( double slipSpeedMpS )
1187
1208
{
1188
1209
slipSpeedMpS = Math . Abs ( slipSpeedMpS ) ;
1189
1210
double fx = Polach . SlipCharacteristics ( slipSpeedMpS ) ;
1190
1211
WheelAdhesion = ( float ) fx ;
1191
1212
return fx ;
1192
1213
}
1214
+
1215
+
1216
+ /// <summary>
1217
+ /// ***** Pacha Adhesion *****
1218
+ /// Slip characteristics computation
1219
+ /// - Uses adhesion limit calculated by Curtius-Kniffler formula:
1220
+ /// 7.5
1221
+ /// umax = --------------------- + 0.161
1222
+ /// speed * 3.6 + 44.0
1223
+ /// - Computes slip speed
1224
+ /// - Computes relative adhesion force as a result of slip characteristics:
1225
+ /// 2*K*umax^2*dV
1226
+ /// u = ---------------------
1227
+ /// umax^2*dv^2 + K^2
1228
+ ///
1229
+ /// For high slip speeds the formula is replaced with an exponentially
1230
+ /// decaying function (with smooth coupling) which reaches 40% of
1231
+ /// maximum adhesion at infinity. The transition point between equations
1232
+ /// is at dV = sqrt(3)*K/umax (inflection point)
1233
+ ///
1234
+ /// </summary>
1235
+ /// <param name="slipSpeedMpS">Difference between train speed and wheel speed</param>
1236
+ /// <param name="speedMpS">Current speed</param>
1237
+ /// <param name="K">Slip speed correction</param>
1238
+ /// <param name="umax">Relative weather conditions, usually from 0.2 to 1.0</param>
1239
+ /// <returns>Relative force transmitted to the rail</returns>
1240
+ public float SlipCharacteristicsPacha ( float slipSpeedMpS , float speedMpS , float K , float umax )
1241
+ {
1242
+ var slipSpeedKpH = MpS . ToKpH ( slipSpeedMpS ) ;
1243
+ float x = slipSpeedKpH * umax / K ; // Slip percentage
1244
+ float absx = Math . Abs ( x ) ;
1245
+ float sqrt3 = ( float ) Math . Sqrt ( 3 ) ;
1246
+ if ( absx > sqrt3 )
1247
+ {
1248
+ // At infinity, adhesion is 40% of maximum (Polach, 2005)
1249
+ // The value must be lower than 85% for the formula to work
1250
+ float inftyFactor = 0.4f ;
1251
+ return Math . Sign ( slipSpeedKpH ) * umax * ( ( sqrt3 / 2 - inftyFactor ) * ( float ) Math . Exp ( ( sqrt3 - absx ) / ( 2 * sqrt3 - 4 * inftyFactor ) ) + inftyFactor ) ;
1252
+ }
1253
+ return 2.0f * umax * x / ( 1 + x * x ) ;
1254
+ }
1255
+
1256
+
1193
1257
}
1194
1258
}
0 commit comments