@@ -426,6 +426,11 @@ public float InertiaKgm2
426426 /// </summary>
427427 float forceToAccelerationFactor ;
428428
429+ /// <summary>
430+ /// switch between Polach and Pacha adhesion calculation
431+ /// </summary>
432+ bool UsePoalchAdhesion = false ;
433+
429434 /// <summary>
430435 /// Pre-calculation of slip characteristics at 0 slip speed
431436 /// </summary>
@@ -587,12 +592,12 @@ public void ComputeWheelSlipThresholdMpS()
587592 // i.e. the point where slope changes from positive (adhesion region)
588593 // to negative (slip region)
589594 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 ) ;
592597
593598 double SlipSpeedMpS = AxleSpeedMpS - TrainSpeedMpS ;
594599
595- MaximumPolachWheelAdhesion = ( float ) SlipCharacteristics ( WheelSlipThresholdMpS ) ;
600+ MaximumPolachWheelAdhesion = ( float ) SlipCharacteristicsPolach ( WheelSlipThresholdMpS ) ;
596601
597602 if ( SlipSpeedMpS == 0 )
598603 {
@@ -610,7 +615,7 @@ public void ComputeWheelSlipThresholdMpS()
610615 while ( Math . Abs ( b - a ) > MpS . FromKpH ( 0.1f ) )
611616 {
612617 double c = ( a + b ) / 2 ;
613- double fc = SlipCharacteristics ( c + dx ) - SlipCharacteristics ( c ) ;
618+ double fc = SlipCharacteristicsPolach ( c + dx ) - SlipCharacteristicsPolach ( c ) ;
614619 if ( fa * fc > 0 )
615620 {
616621 a = c ;
@@ -813,7 +818,17 @@ public void Save(BinaryWriter outf)
813818 public ( double , double , double , double ) GetAxleMotionVariation ( double axleSpeedMpS , double elapsedClockSeconds )
814819 {
815820 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+
817832 double axleInForceN = 0 ;
818833 if ( DriveType == AxleDriveType . ForceDriven )
819834 axleInForceN = DriveForceN * transmissionEfficiency ;
@@ -851,31 +866,9 @@ void Integrate(float elapsedClockSeconds)
851866 if ( elapsedClockSeconds <= 0 ) return ;
852867 double prevSpeedMpS = AxleSpeedMpS ;
853868
854- float upperSubStepStartingLimit = 100 ;
855- float tempupperSubStepLimit = upperSubStepStartingLimit ;
869+ float upperSubStepLimit = 100 ;
856870 float lowerSubStepLimit = 1 ;
857871
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-
879872 // use straight line graph approximation to increase substeps as slipspeed increases towards the threshold speed point
880873 // Points are 1 = (0, upperLimit) and 2 = (threshold, lowerLimit)
881874 var AdhesGrad = ( ( upperSubStepLimit - lowerSubStepLimit ) / ( WheelSlipThresholdMpS - 0 ) ) ;
@@ -961,17 +954,44 @@ void Integrate(float elapsedClockSeconds)
961954 /// <param name="timeSpan"></param>
962955 public virtual void Update ( float timeSpan )
963956 {
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+ }
965972
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 ;
969977
970- if ( count < 6 && count ++ == 5 )
978+ }
979+
980+ forceToAccelerationFactor = WheelRadiusM * WheelRadiusM / totalInertiaKgm2 ;
981+
982+ if ( UsePoalchAdhesion )
971983 {
972- TrainSpeedMpS = 10 / 3.6f ;
984+
973985 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+ }
975995 }
976996
977997#if DEBUG_ADHESION
@@ -1170,6 +1190,7 @@ public double SlipCharacteristics(double slipSpeedMpS)
11701190 }
11711191
11721192 /// <summary>
1193+ /// ***** Polach Adhesion *****
11731194 /// Uses the Polach creep force curves calculation described in the following document
11741195 /// "Creep forces in simulations of traction vehicles running on adhesion limit" by O. Polach 2005 Wear - http://www.sze.hu/~szenasy/VILLVONT/polachslipvizsg.pdf
11751196 ///
@@ -1183,12 +1204,55 @@ public double SlipCharacteristics(double slipSpeedMpS)
11831204 /// <param name="slipSpeedMpS">Difference between train speed and wheel speed</param>
11841205 /// <param name="speedMpS">Current speed</param>
11851206 /// <returns>Relative force transmitted to the rail</returns>
1186- public double SlipCharacteristics ( double slipSpeedMpS )
1207+ public double SlipCharacteristicsPolach ( double slipSpeedMpS )
11871208 {
11881209 slipSpeedMpS = Math . Abs ( slipSpeedMpS ) ;
11891210 double fx = Polach . SlipCharacteristics ( slipSpeedMpS ) ;
11901211 WheelAdhesion = ( float ) fx ;
11911212 return fx ;
11921213 }
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+
11931257 }
11941258}
0 commit comments