@@ -135,6 +135,7 @@ public enum SoundState
135135 public float MaxPowerW ;
136136 public float MaxForceN ;
137137 public float AbsTractionSpeedMpS ;
138+ public float PrevAbsTractionSpeedMpS ;
138139 public float MaxCurrentA = 0 ;
139140 public float MaxSpeedMpS = 1e3f ;
140141 public float UnloadingSpeedMpS ;
@@ -1432,7 +1433,7 @@ public override void Save(BinaryWriter outf)
14321433 outf . Write ( CurrentTrackSandBoxCapacityM3 ) ;
14331434 outf . Write ( CurrentTrackSanderSandConsumptionM3pS ) ;
14341435 outf . Write ( CurrentTrackSanderAirConsumptionM3pS ) ;
1435-
1436+ outf . Write ( AbsTractionSpeedMpS ) ;
14361437
14371438 base . Save ( outf ) ;
14381439
@@ -1492,6 +1493,8 @@ public override void Restore(BinaryReader inf)
14921493 CurrentTrackSanderSandConsumptionM3pS = inf . ReadSingle ( ) ;
14931494 CurrentTrackSanderAirConsumptionM3pS = inf . ReadSingle ( ) ;
14941495
1496+ AbsTractionSpeedMpS = PrevAbsTractionSpeedMpS = inf . ReadSingle ( ) ;
1497+
14951498 base . Restore ( inf ) ;
14961499
14971500 LocomotivePowerSupply ? . Restore ( inf ) ;
@@ -1968,6 +1971,7 @@ public override void InitializeMoving()
19681971 BrakeSystem . LocoInitializeMoving ( ) ;
19691972 EngineBrakeController ? . InitializeMoving ( ) ;
19701973 }
1974+ AbsTractionSpeedMpS = PrevAbsTractionSpeedMpS = SpeedMpS ;
19711975 }
19721976
19731977 //================================================================================================//
@@ -2519,25 +2523,40 @@ protected virtual void UpdateControllers(float elapsedClockSeconds)
25192523 }
25202524#endif
25212525 }
2522- public void UpdateForceWithRamp ( ref float forceN , float elapsedClockSeconds , float targetForceN , float maxForceN , float targetPowerW , float maxPowerW , float rampUpNpS = 0 , float rampDownNpS = 0 , float rampZeroNpS = 0 , float rampUpWpS = 0 , float rampDownWpS = 0 , float rampZeroWpS = 0 )
2526+ public void UpdateForceWithRamp ( ref float forceN , float elapsedClockSeconds , float targetForceN , float maxForceN , float rampUpNpS = 0 , float rampDownNpS = 0 , float rampZeroNpS = 0 , float rampUpWpS = 0 , float rampDownWpS = 0 , float rampZeroWpS = 0 )
25232527 {
25242528 if ( targetForceN > maxForceN ) targetForceN = maxForceN ;
25252529 if ( forceN > maxForceN ) forceN = maxForceN ;
2526- if ( targetForceN > forceN )
2530+ if ( AbsTractionSpeedMpS > 0 )
2531+ {
2532+ float powerW = forceN * PrevAbsTractionSpeedMpS ;
2533+ float targetPowerW = targetForceN * AbsTractionSpeedMpS ;
2534+ if ( targetPowerW > powerW && rampUpWpS > 0 )
2535+ {
2536+ float maxChangeW = rampUpWpS * elapsedClockSeconds ;
2537+ if ( powerW + maxChangeW < targetPowerW )
2538+ {
2539+ targetPowerW = powerW + maxChangeW ;
2540+ targetForceN = Math . Min ( targetForceN , targetPowerW / AbsTractionSpeedMpS ) ;
2541+ }
2542+ }
2543+ if ( targetPowerW < powerW && ( targetPowerW == 0 ? rampZeroWpS : rampDownWpS ) > 0 )
2544+ {
2545+ float maxChangeW = ( targetPowerW == 0 ? rampZeroWpS : rampDownWpS ) * elapsedClockSeconds ;
2546+ if ( powerW - maxChangeW > targetPowerW )
2547+ {
2548+ targetPowerW = powerW - maxChangeW ;
2549+ targetForceN = Math . Max ( targetForceN , Math . Min ( forceN , targetPowerW / AbsTractionSpeedMpS ) ) ;
2550+ }
2551+ }
2552+ }
2553+ if ( targetForceN > forceN && rampUpNpS > 0 )
25272554 {
2528- float maxChangeN = float . MaxValue ;
2529- if ( rampUpNpS > 0 ) maxChangeN = Math . Min ( maxChangeN , rampUpNpS * elapsedClockSeconds ) ;
2530- if ( rampUpWpS > 0 && AbsTractionSpeedMpS > 0 ) maxChangeN = Math . Min ( maxChangeN , rampUpWpS / AbsTractionSpeedMpS * elapsedClockSeconds ) ;
2531- if ( forceN + maxChangeN > targetForceN ) forceN = targetForceN ;
2532- else forceN += maxChangeN ;
2555+ forceN = Math . Min ( targetForceN , forceN + rampUpNpS * elapsedClockSeconds ) ;
25332556 }
2534- else if ( targetForceN < forceN )
2557+ else if ( targetForceN < forceN && ( targetForceN == 0 ? rampZeroNpS : rampDownNpS ) > 0 )
25352558 {
2536- float maxChangeN = float . MaxValue ;
2537- if ( ( targetForceN == 0 ? rampZeroNpS : rampDownNpS ) > 0 ) maxChangeN = Math . Min ( maxChangeN , ( targetForceN == 0 ? rampZeroNpS : rampDownNpS ) * elapsedClockSeconds ) ;
2538- if ( ( targetForceN == 0 ? rampZeroWpS : rampDownWpS ) > 0 && AbsTractionSpeedMpS > 0 ) maxChangeN = Math . Min ( maxChangeN , ( targetForceN == 0 ? rampZeroWpS : rampDownWpS ) / AbsTractionSpeedMpS * elapsedClockSeconds ) ;
2539- if ( forceN - maxChangeN < targetForceN ) forceN = targetForceN ;
2540- else forceN -= maxChangeN ;
2559+ forceN = Math . Max ( targetForceN , forceN - ( targetForceN == 0 ? rampZeroNpS : rampDownNpS ) * elapsedClockSeconds ) ;
25412560 }
25422561 }
25432562 public virtual float GetAvailableTractionForceN ( float t )
@@ -2681,6 +2700,7 @@ protected virtual void UpdateTractiveForce(float elapsedClockSeconds)
26812700 // More modern locomotive have a more sophisticated system that eliminates slip in the majority (if not all circumstances).
26822701 // Simple adhesion control does not have any slip control feature built into it.
26832702 // TODO - a full review of slip/no slip control.
2703+ PrevAbsTractionSpeedMpS = AbsTractionSpeedMpS ;
26842704 if ( TractionMotorType == TractionMotorTypes . AC )
26852705 {
26862706 AbsTractionSpeedMpS = AbsSpeedMpS ;
0 commit comments