@@ -241,10 +241,14 @@ public float CurrentLocomotiveSteamHeatBoilerWaterCapacityL
241241 // Adhesion parameters
242242 public enum SlipControlType
243243 {
244+ Unknown ,
244245 None ,
246+ CutPower ,
247+ ReduceForce ,
245248 Full
246249 }
247250 public SlipControlType SlipControlSystem ;
251+ public bool [ ] SlipControlActive ;
248252 float BaseFrictionCoefficientFactor ; // Factor used to adjust Curtius formula depending upon weather conditions
249253 float SlipFrictionCoefficientFactor ;
250254 public float SteamStaticWheelForce ;
@@ -928,10 +932,10 @@ public override void Parse(string lowercasetoken, STFReader stf)
928932 case "engine(ortsunloadingspeed" : UnloadingSpeedMpS = stf . ReadFloatBlock ( STFReader . UNITS . Speed , null ) ; break ;
929933 case "engine(ortsslipcontrolsystem" :
930934 stf . MustMatch ( "(" ) ;
931- string slipControlType = stf . ReadString ( ) . ToLowerInvariant ( ) ;
935+ string slipControlType = stf . ReadString ( ) ;
932936 try
933937 {
934- SlipControlSystem = ( SlipControlType ) Enum . Parse ( typeof ( SlipControlType ) , slipControlType . First ( ) . ToString ( ) . ToUpper ( ) + slipControlType . Substring ( 1 ) ) ;
938+ SlipControlSystem = ( SlipControlType ) Enum . Parse ( typeof ( SlipControlType ) , slipControlType , true ) ;
935939 }
936940 catch
937941 {
@@ -1684,6 +1688,13 @@ public override void Initialize()
16841688 }
16851689 }
16861690 }
1691+ SlipControlActive = new bool [ LocomotiveAxles . Count ] ;
1692+ if ( SlipControlSystem == SlipControlType . Unknown )
1693+ {
1694+ if ( AntiSlip ) SlipControlSystem = SlipControlType . ReduceForce ;
1695+ else if ( WheelslipCausesThrottleDown ) SlipControlSystem = SlipControlType . CutPower ;
1696+ else SlipControlSystem = SlipControlType . None ;
1697+ }
16871698
16881699 // Calculate minimum speed to pickup water
16891700 const float Aconst = 2 ;
@@ -2722,8 +2733,9 @@ protected virtual void UpdateTractiveForce(float elapsedClockSeconds)
27222733 UpdateDynamicBrakeForce ( elapsedClockSeconds ) ;
27232734 TractiveForceN -= Math . Sign ( WheelSpeedMpS ) * DynamicBrakeForceN ;
27242735
2725- foreach ( var axle in LocomotiveAxles )
2736+ for ( int i = 0 ; i < LocomotiveAxles . Count ; i ++ )
27262737 {
2738+ var axle = LocomotiveAxles [ i ] ;
27272739 if ( axle . DriveType == AxleDriveType . ForceDriven )
27282740 {
27292741 float prevForceN = axle . DriveForceN ;
@@ -2739,17 +2751,46 @@ protected virtual void UpdateTractiveForce(float elapsedClockSeconds)
27392751 else adhesionLimit = axle . MaximumWheelAdhesion ;
27402752 axle . DriveForceN = Math . Sign ( axle . DriveForceN ) * Math . Min ( adhesionLimit * axle . AxleWeightN , Math . Abs ( axle . DriveForceN ) ) ;
27412753 }
2742- else if ( TractionForceN > 0 ) // only for traction (not for dynamic brake)
2754+ else if ( SlipControlSystem == SlipControlType . CutPower )
2755+ {
2756+ if ( TractionForceN > 0 )
2757+ {
2758+ if ( axle . HuDIsWheelSlip ) SlipControlActive [ i ] = true ;
2759+ }
2760+ else
2761+ {
2762+ // Only restore traction when throttle is set to 0
2763+ SlipControlActive [ i ] = false ;
2764+ }
2765+ // Disable traction in the axle if slipping
2766+ if ( SlipControlActive [ i ] ) axle . DriveForceN = 0 ;
2767+ }
2768+ else if ( SlipControlSystem == SlipControlType . ReduceForce )
27432769 {
2744- if ( WheelslipCausesThrottleDown && WheelSlip )
2770+ if ( TractionForceN > 0 && axle . DriveForceN != 0 && AdvancedAdhesionModel )
27452771 {
2746- // Disable traction in the axle if slipping
2747- axle . DriveForceN = 0 ;
2772+ if ( axle . SlipPercent > axle . SlipWarningTresholdPercent ) SlipControlActive [ i ] = true ;
27482773 }
2749- else if ( AntiSlip && AdvancedAdhesionModel && WheelSlipWarning )
2774+ else
27502775 {
2751- // Reduce tractive force to 0 in 3 seconds until wheel slip warning ends
2752- float newForceN = Math . Max ( Math . Abs ( prevForceN ) - TractiveForceN * axle . TractiveForceFraction * elapsedClockSeconds / 3 , 0 ) ;
2776+ SlipControlActive [ i ] = false ;
2777+ }
2778+ if ( SlipControlActive [ i ] )
2779+ {
2780+ float absForceN = Math . Abs ( axle . DriveForceN ) ;
2781+ float newForceN ;
2782+ if ( axle . SlipPercent < axle . SlipWarningTresholdPercent * 0.9f )
2783+ {
2784+ // If well below slip threshold, restore full power in 10 seconds
2785+ newForceN = Math . Min ( Math . Abs ( prevForceN ) + absForceN * elapsedClockSeconds / 10 , absForceN ) ;
2786+
2787+ // If full force is restored, disengage slip control
2788+ if ( newForceN / absForceN > 0.95f ) SlipControlActive [ i ] = false ;
2789+ }
2790+ else
2791+ {
2792+ newForceN = Math . Max ( Math . Abs ( prevForceN ) - absForceN * elapsedClockSeconds / 3 , 0 ) ;
2793+ }
27532794 if ( axle . DriveForceN > 0 && prevForceN >= 0 ) axle . DriveForceN = newForceN ;
27542795 else if ( axle . DriveForceN < 0 && prevForceN <= 0 ) axle . DriveForceN = - newForceN ;
27552796 }
0 commit comments