@@ -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 ;
@@ -929,10 +933,10 @@ public override void Parse(string lowercasetoken, STFReader stf)
929933 case "engine(ortsunloadingspeed" : UnloadingSpeedMpS = stf . ReadFloatBlock ( STFReader . UNITS . Speed , null ) ; break ;
930934 case "engine(ortsslipcontrolsystem" :
931935 stf . MustMatch ( "(" ) ;
932- string slipControlType = stf . ReadString ( ) . ToLowerInvariant ( ) ;
936+ string slipControlType = stf . ReadString ( ) ;
933937 try
934938 {
935- SlipControlSystem = ( SlipControlType ) Enum . Parse ( typeof ( SlipControlType ) , slipControlType . First ( ) . ToString ( ) . ToUpper ( ) + slipControlType . Substring ( 1 ) ) ;
939+ SlipControlSystem = ( SlipControlType ) Enum . Parse ( typeof ( SlipControlType ) , slipControlType , true ) ;
936940 }
937941 catch
938942 {
@@ -1683,6 +1687,13 @@ public override void Initialize()
16831687 }
16841688 }
16851689 }
1690+ SlipControlActive = new bool [ LocomotiveAxles . Count ] ;
1691+ if ( SlipControlSystem == SlipControlType . Unknown )
1692+ {
1693+ if ( AntiSlip ) SlipControlSystem = SlipControlType . ReduceForce ;
1694+ else if ( WheelslipCausesThrottleDown ) SlipControlSystem = SlipControlType . CutPower ;
1695+ else SlipControlSystem = SlipControlType . None ;
1696+ }
16861697
16871698 // Calculate minimum speed to pickup water
16881699 const float Aconst = 2 ;
@@ -2719,8 +2730,9 @@ protected virtual void UpdateTractiveForce(float elapsedClockSeconds)
27192730 UpdateDynamicBrakeForce ( elapsedClockSeconds ) ;
27202731 TractiveForceN -= Math . Sign ( WheelSpeedMpS ) * DynamicBrakeForceN ;
27212732
2722- foreach ( var axle in LocomotiveAxles )
2733+ for ( int i = 0 ; i < LocomotiveAxles . Count ; i ++ )
27232734 {
2735+ var axle = LocomotiveAxles [ i ] ;
27242736 if ( axle . DriveType == AxleDriveType . ForceDriven )
27252737 {
27262738 float prevForceN = axle . DriveForceN ;
@@ -2736,17 +2748,46 @@ protected virtual void UpdateTractiveForce(float elapsedClockSeconds)
27362748 else adhesionLimit = axle . MaximumWheelAdhesion ;
27372749 axle . DriveForceN = Math . Sign ( axle . DriveForceN ) * Math . Min ( adhesionLimit * axle . AxleWeightN , Math . Abs ( axle . DriveForceN ) ) ;
27382750 }
2739- else if ( TractionForceN > 0 ) // only for traction (not for dynamic brake)
2751+ else if ( SlipControlSystem == SlipControlType . CutPower )
2752+ {
2753+ if ( TractionForceN > 0 )
2754+ {
2755+ if ( axle . HuDIsWheelSlip ) SlipControlActive [ i ] = true ;
2756+ }
2757+ else
2758+ {
2759+ // Only restore traction when throttle is set to 0
2760+ SlipControlActive [ i ] = false ;
2761+ }
2762+ // Disable traction in the axle if slipping
2763+ if ( SlipControlActive [ i ] ) axle . DriveForceN = 0 ;
2764+ }
2765+ else if ( SlipControlSystem == SlipControlType . ReduceForce )
27402766 {
2741- if ( WheelslipCausesThrottleDown && WheelSlip )
2767+ if ( TractionForceN > 0 && axle . DriveForceN != 0 && AdvancedAdhesionModel )
27422768 {
2743- // Disable traction in the axle if slipping
2744- axle . DriveForceN = 0 ;
2769+ if ( axle . SlipPercent > axle . SlipWarningTresholdPercent ) SlipControlActive [ i ] = true ;
27452770 }
2746- else if ( AntiSlip && AdvancedAdhesionModel && WheelSlipWarning )
2771+ else
27472772 {
2748- // Reduce tractive force to 0 in 3 seconds until wheel slip warning ends
2749- float newForceN = Math . Max ( Math . Abs ( prevForceN ) - TractiveForceN * axle . TractiveForceFraction * elapsedClockSeconds / 3 , 0 ) ;
2773+ SlipControlActive [ i ] = false ;
2774+ }
2775+ if ( SlipControlActive [ i ] )
2776+ {
2777+ float absForceN = Math . Abs ( axle . DriveForceN ) ;
2778+ float newForceN ;
2779+ if ( axle . SlipPercent < axle . SlipWarningTresholdPercent * 0.9f )
2780+ {
2781+ // If well below slip threshold, restore full power in 10 seconds
2782+ newForceN = Math . Min ( Math . Abs ( prevForceN ) + absForceN * elapsedClockSeconds / 10 , absForceN ) ;
2783+
2784+ // If full force is restored, disengage slip control
2785+ if ( newForceN / absForceN > 0.95f ) SlipControlActive [ i ] = false ;
2786+ }
2787+ else
2788+ {
2789+ newForceN = Math . Max ( Math . Abs ( prevForceN ) - absForceN * elapsedClockSeconds / 3 , 0 ) ;
2790+ }
27502791 if ( axle . DriveForceN > 0 && prevForceN >= 0 ) axle . DriveForceN = newForceN ;
27512792 else if ( axle . DriveForceN < 0 && prevForceN <= 0 ) axle . DriveForceN = - newForceN ;
27522793 }
0 commit comments