@@ -426,9 +426,15 @@ public float OdometerM
426426 protected float TractionForceRampUpNpS ;
427427 protected float TractionForceRampDownNpS ;
428428 protected float TractionForceRampDownToZeroNpS = - 1 ;
429+ protected float TractionPowerRampUpWpS ;
430+ protected float TractionPowerRampDownWpS ;
431+ protected float TractionPowerRampDownToZeroWpS = - 1 ;
429432 protected float DynamicBrakeForceRampUpNpS ;
430433 protected float DynamicBrakeForceRampDownNpS ;
431434 protected float DynamicBrakeForceRampDownToZeroNpS = - 1 ;
435+ protected float DynamicBrakePowerRampUpWpS ;
436+ protected float DynamicBrakePowerRampDownWpS ;
437+ protected float DynamicBrakePowerRampDownToZeroWpS = - 1 ;
432438
433439 public CombinedControl CombinedControlType ;
434440 public float CombinedControlSplitPosition ;
@@ -979,9 +985,15 @@ public override void Parse(string lowercasetoken, STFReader stf)
979985 case "engine(ortstractiveforcerampuprate" : TractionForceRampUpNpS = stf . ReadFloatBlock ( STFReader . UNITS . Force , null ) ; break ;
980986 case "engine(ortstractiveforcerampdownrate" : TractionForceRampDownNpS = stf . ReadFloatBlock ( STFReader . UNITS . Force , null ) ; break ;
981987 case "engine(ortstractiveforcerampdowntozerorate" : TractionForceRampDownToZeroNpS = stf . ReadFloatBlock ( STFReader . UNITS . Force , null ) ; break ;
988+ case "engine(ortstractivepowerrampuprate" : TractionPowerRampUpWpS = stf . ReadFloatBlock ( STFReader . UNITS . Power , null ) ; break ;
989+ case "engine(ortstractivepowerrampdownrate" : TractionPowerRampDownWpS = stf . ReadFloatBlock ( STFReader . UNITS . Power , null ) ; break ;
990+ case "engine(ortstractivepowerrampdowntozerorate" : TractionPowerRampDownToZeroWpS = stf . ReadFloatBlock ( STFReader . UNITS . Power , null ) ; break ;
982991 case "engine(ortsdynamicbrakeforcerampuprate" : DynamicBrakeForceRampUpNpS = stf . ReadFloatBlock ( STFReader . UNITS . Force , null ) ; break ;
983992 case "engine(ortsdynamicbrakeforcerampdownrate" : DynamicBrakeForceRampDownNpS = stf . ReadFloatBlock ( STFReader . UNITS . Force , null ) ; break ;
984993 case "engine(ortsdynamicbrakeforcerampdowntozerorate" : DynamicBrakeForceRampDownToZeroNpS = stf . ReadFloatBlock ( STFReader . UNITS . Force , null ) ; break ;
994+ case "engine(ortsdynamicbrakepowerrampuprate" : DynamicBrakePowerRampUpWpS = stf . ReadFloatBlock ( STFReader . UNITS . Power , null ) ; break ;
995+ case "engine(ortsdynamicbrakepowerrampdownrate" : DynamicBrakePowerRampDownWpS = stf . ReadFloatBlock ( STFReader . UNITS . Power , null ) ; break ;
996+ case "engine(ortsdynamicbrakepowerrampdowntozerorate" : DynamicBrakePowerRampDownToZeroWpS = stf . ReadFloatBlock ( STFReader . UNITS . Power , null ) ; break ;
985997
986998 case "engine(enginecontrollers(throttle" : ThrottleController = new MSTSNotchController ( stf ) ; break ;
987999 case "engine(enginecontrollers(regulator" : ThrottleController = new MSTSNotchController ( stf ) ; break ;
@@ -1238,9 +1250,15 @@ public override void Copy(MSTSWagon copy)
12381250 TractionForceRampUpNpS = locoCopy . TractionForceRampUpNpS ;
12391251 TractionForceRampDownNpS = locoCopy . TractionForceRampDownNpS ;
12401252 TractionForceRampDownToZeroNpS = locoCopy . TractionForceRampDownToZeroNpS ;
1253+ TractionPowerRampUpWpS = locoCopy . TractionPowerRampUpWpS ;
1254+ TractionPowerRampDownWpS = locoCopy . TractionPowerRampDownWpS ;
1255+ TractionPowerRampDownToZeroWpS = locoCopy . TractionPowerRampDownToZeroWpS ;
12411256 DynamicBrakeForceRampUpNpS = locoCopy . DynamicBrakeForceRampUpNpS ;
12421257 DynamicBrakeForceRampDownNpS = locoCopy . DynamicBrakeForceRampDownNpS ;
12431258 DynamicBrakeForceRampDownToZeroNpS = locoCopy . DynamicBrakeForceRampDownToZeroNpS ;
1259+ DynamicBrakePowerRampUpWpS = locoCopy . DynamicBrakePowerRampUpWpS ;
1260+ DynamicBrakePowerRampDownWpS = locoCopy . DynamicBrakePowerRampDownWpS ;
1261+ DynamicBrakePowerRampDownToZeroWpS = locoCopy . DynamicBrakePowerRampDownToZeroWpS ;
12441262 MaxContinuousForceN = locoCopy . MaxContinuousForceN ;
12451263 SpeedOfMaxContinuousForceMpS = locoCopy . SpeedOfMaxContinuousForceMpS ;
12461264 MSTSSpeedOfMaxContinuousForceMpS = locoCopy . MSTSSpeedOfMaxContinuousForceMpS ;
@@ -1586,7 +1604,9 @@ public override void Initialize()
15861604 }
15871605
15881606 if ( TractionForceRampDownToZeroNpS < 0 ) TractionForceRampDownToZeroNpS = TractionForceRampDownNpS ;
1607+ if ( TractionPowerRampDownToZeroWpS < 0 ) TractionPowerRampDownToZeroWpS = TractionPowerRampDownWpS ;
15891608 if ( DynamicBrakeForceRampDownToZeroNpS < 0 ) DynamicBrakeForceRampDownToZeroNpS = DynamicBrakeForceRampDownNpS ;
1609+ if ( DynamicBrakePowerRampDownToZeroWpS < 0 ) DynamicBrakePowerRampDownToZeroWpS = DynamicBrakePowerRampDownWpS ;
15901610
15911611 if ( MaxSteamHeatPressurePSI == 0 ) // Check to see if steam heating is fitted to locomotive
15921612 {
@@ -2499,21 +2519,25 @@ protected virtual void UpdateControllers(float elapsedClockSeconds)
24992519 }
25002520#endif
25012521 }
2502- 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 )
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 )
25032523 {
25042524 if ( targetForceN > maxForceN ) targetForceN = maxForceN ;
25052525 if ( forceN > maxForceN ) forceN = maxForceN ;
25062526 if ( targetForceN > forceN )
25072527 {
2508- float ramp = rampUpNpS ;
2509- if ( ramp > 0 ) forceN = Math . Min ( forceN + ramp * elapsedClockSeconds , targetForceN ) ;
2510- else forceN = targetForceN ;
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 ;
25112533 }
25122534 else if ( targetForceN < forceN )
25132535 {
2514- float ramp = targetForceN == 0 ? rampZeroNpS : rampDownNpS ;
2515- if ( ramp > 0 ) forceN = Math . Max ( forceN - ramp * elapsedClockSeconds , targetForceN ) ;
2516- else forceN = targetForceN ;
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 ;
25172541 }
25182542 }
25192543 public virtual float GetAvailableTractionForceN ( float t )
@@ -2570,7 +2594,7 @@ protected virtual void UpdateTractionForce(float elapsedClockSeconds)
25702594 float maxPowerW = electric . ElectricPowerSupply . AvailableTractionPowerW ;
25712595 if ( targetForceN * AbsTractionSpeedMpS > maxPowerW ) maxForceN = maxPowerW / AbsTractionSpeedMpS ;
25722596 }
2573- UpdateForceWithRamp ( ref TractionForceN , elapsedClockSeconds , targetForceN , maxForceN , TractionForceRampUpNpS , TractionForceRampDownNpS , TractionForceRampDownToZeroNpS ) ;
2597+ UpdateForceWithRamp ( ref TractionForceN , elapsedClockSeconds , targetForceN , maxForceN , TractionForceRampUpNpS , TractionForceRampDownNpS , TractionForceRampDownToZeroNpS , TractionPowerRampUpWpS , TractionPowerRampDownWpS , TractionPowerRampDownToZeroWpS ) ;
25742598 }
25752599 else
25762600 {
@@ -2629,7 +2653,7 @@ protected virtual void UpdateDynamicBrakeForce(float elapsedClockSeconds)
26292653 float limitForceN = GetAvailableDynamicBrakeForceN ( maxdynamic ) ;
26302654 float targetForceN = GetAvailableDynamicBrakeForceN ( d ) ;
26312655 float maxForceN = limitForceN >= targetForceN ? limitForceN : float . MaxValue ;
2632- UpdateForceWithRamp ( ref DynamicBrakeForceN , elapsedClockSeconds , targetForceN , maxForceN , DynamicBrakeForceRampUpNpS , DynamicBrakeForceRampDownNpS , DynamicBrakeForceRampDownToZeroNpS ) ;
2656+ UpdateForceWithRamp ( ref DynamicBrakeForceN , elapsedClockSeconds , targetForceN , maxForceN , DynamicBrakeForceRampUpNpS , DynamicBrakeForceRampDownNpS , DynamicBrakeForceRampDownToZeroNpS , DynamicBrakePowerRampUpWpS , DynamicBrakePowerRampDownWpS , DynamicBrakePowerRampDownToZeroWpS ) ;
26332657 }
26342658 else
26352659 {
0 commit comments