@@ -77,7 +77,8 @@ public class AirSinglePipe : MSTSBrakeSystem
7777 protected float QuickServiceVentRatePSIpS ;
7878 protected float AcceleratedApplicationFactor ;
7979 protected float AcceleratedApplicationLimitPSIpS = 5.0f ;
80- protected float InitialApplicationThresholdPSI = 1.0f ;
80+ protected float InitialApplicationThresholdPSI ;
81+ protected float TripleValveSensitivityPSI ;
8182 protected float BrakeCylinderSpringPressurePSI ;
8283 protected float ServiceMaxCylPressurePSI ;
8384 protected float AcceleratedEmergencyReleaseThresholdPSI = 20.0f ;
@@ -164,6 +165,7 @@ public override void InitializeFromCopy(BrakeSystem copy)
164165 AcceleratedApplicationFactor = thiscopy . AcceleratedApplicationFactor ;
165166 AcceleratedApplicationLimitPSIpS = thiscopy . AcceleratedApplicationLimitPSIpS ;
166167 InitialApplicationThresholdPSI = thiscopy . InitialApplicationThresholdPSI ;
168+ TripleValveSensitivityPSI = thiscopy . TripleValveSensitivityPSI ;
167169 BrakeCylinderSpringPressurePSI = thiscopy . BrakeCylinderSpringPressurePSI ;
168170 ServiceMaxCylPressurePSI = thiscopy . ServiceMaxCylPressurePSI ;
169171 }
@@ -305,7 +307,7 @@ public override void Parse(string lowercasetoken, STFReader stf)
305307 case "wagon(ortsquickserviceventrate" : QuickServiceVentRatePSIpS = stf . ReadFloatBlock ( STFReader . UNITS . PressureRateDefaultPSIpS , null ) ; break ;
306308 case "wagon(ortsacceleratedapplicationfactor" : AcceleratedApplicationFactor = stf . ReadFloatBlock ( STFReader . UNITS . None , null ) ; break ;
307309 case "wagon(ortsacceleratedapplicationmaxventrate" : AcceleratedApplicationLimitPSIpS = stf . ReadFloatBlock ( STFReader . UNITS . PressureRateDefaultPSIpS , 5.0f ) ; break ;
308- case "wagon(ortsinitialapplicationthreshold" : InitialApplicationThresholdPSI = stf . ReadFloatBlock ( STFReader . UNITS . PressureDefaultPSI , 1.0f ) ; break ;
310+ case "wagon(ortsinitialapplicationthreshold" : InitialApplicationThresholdPSI = stf . ReadFloatBlock ( STFReader . UNITS . PressureDefaultPSI , null ) ; break ;
309311 case "wagon(ortscylinderspringpressure" : BrakeCylinderSpringPressurePSI = stf . ReadFloatBlock ( STFReader . UNITS . PressureDefaultPSI , null ) ; break ;
310312 case "wagon(ortsmaxservicecylinderpressure" : ServiceMaxCylPressurePSI = stf . ReadFloatBlock ( STFReader . UNITS . PressureDefaultPSI , null ) ; break ;
311313 }
@@ -404,6 +406,22 @@ public override void Initialize()
404406 if ( ( Car as MSTSWagon ) . EmergencyReservoirPresent && EmergencyValveActuationRatePSIpS == 0 )
405407 EmergencyValveActuationRatePSIpS = 15 ;
406408
409+ if ( InitialApplicationThresholdPSI == 0 )
410+ {
411+ if ( ( Car as MSTSWagon ) . BrakeValve == MSTSWagon . BrakeValveType . Distributor )
412+ InitialApplicationThresholdPSI = 2.2f ; // UIC spec: brakes should release if brake pipe is within 0.15 bar of control res
413+ else
414+ InitialApplicationThresholdPSI = 1.0f ;
415+ }
416+
417+ if ( TripleValveSensitivityPSI == 0 )
418+ {
419+ if ( ( Car as MSTSWagon ) . BrakeValve == MSTSWagon . BrakeValveType . Distributor )
420+ TripleValveSensitivityPSI = 1.4f ; // UIC spec: brakes should respond to 0.1 bar changes in brake pipe
421+ else
422+ TripleValveSensitivityPSI = 1.0f ;
423+ }
424+
407425 if ( EmergResVolumeM3 > 0 && EmergAuxVolumeRatio > 0 && BrakePipeVolumeM3 > 0 )
408426 {
409427 AuxBrakeLineVolumeRatio = EmergResVolumeM3 / EmergAuxVolumeRatio / BrakePipeVolumeM3 ;
@@ -440,7 +458,8 @@ public void UpdateTripleValveState(float elapsedClockSeconds)
440458
441459 if ( valveType == MSTSWagon . BrakeValveType . Distributor )
442460 {
443- float targetPressurePSI = ( ControlResPressurePSI - BrakeLine1PressurePSI ) * AuxCylVolumeRatio ;
461+ float applicationPSI = ControlResPressurePSI - BrakeLine1PressurePSI ;
462+ float targetPressurePSI = applicationPSI * AuxCylVolumeRatio ;
444463 if ( ! disableGradient && EmergencyValveActuationRatePSIpS > 0 && ( prevBrakePipePressurePSI - BrakeLine1PressurePSI ) > Math . Max ( elapsedClockSeconds , 0.0001f ) * EmergencyValveActuationRatePSIpS )
445464 {
446465 if ( prevState == ValveState . Release ) // If valve transitions from release to emergency, quick service activates
@@ -450,17 +469,24 @@ public void UpdateTripleValveState(float elapsedClockSeconds)
450469 }
451470 TripleValveState = ValveState . Emergency ;
452471 }
453- else if ( TripleValveState != ValveState . Emergency &&
454- targetPressurePSI > AutoCylPressurePSI + ( TripleValveState == ValveState . Release ? AuxCylVolumeRatio * InitialApplicationThresholdPSI : ( TripleValveState == ValveState . Apply ? 0.0f : 2.2f ) ) )
472+ else if ( TripleValveState != ValveState . Emergency && targetPressurePSI > AutoCylPressurePSI + ( TripleValveState == ValveState . Apply ? 0.0f : TripleValveSensitivityPSI * AuxCylVolumeRatio ) )
455473 {
456- if ( prevState == ValveState . Release ) // If valve transitions from release to apply, quick service activates
474+ if ( prevState == ValveState . Release )
457475 {
458- QuickServiceActive = true ;
459- UniformChargingActive = false ;
476+ if ( applicationPSI > InitialApplicationThresholdPSI ) // If valve transitions from release to apply, quick service activates
477+ {
478+ QuickServiceActive = true ;
479+ UniformChargingActive = false ;
480+
481+ TripleValveState = ValveState . Apply ;
482+ }
483+ }
484+ else
485+ {
486+ TripleValveState = ValveState . Apply ;
460487 }
461- TripleValveState = ValveState . Apply ;
462488 }
463- else if ( targetPressurePSI < AutoCylPressurePSI - ( TripleValveState == ValveState . Release ? 0.0f : 2.2f ) || targetPressurePSI < 2.2f )
489+ else if ( targetPressurePSI < AutoCylPressurePSI - ( TripleValveState == ValveState . Release ? 0.0f : TripleValveSensitivityPSI * AuxCylVolumeRatio ) || applicationPSI < InitialApplicationThresholdPSI )
464490 {
465491 TripleValveState = ValveState . Release ;
466492 }
@@ -480,17 +506,24 @@ public void UpdateTripleValveState(float elapsedClockSeconds)
480506 }
481507 TripleValveState = ValveState . Emergency ;
482508 }
483- else if ( TripleValveState != ValveState . Emergency &&
484- BrakeLine1PressurePSI < AuxResPressurePSI - ( TripleValveState == ValveState . Release ? InitialApplicationThresholdPSI : ( TripleValveState == ValveState . Apply ? 0.0f : 1.0f ) ) )
509+ else if ( TripleValveState != ValveState . Emergency && BrakeLine1PressurePSI < AuxResPressurePSI - ( TripleValveState == ValveState . Apply ? 0.0f : TripleValveSensitivityPSI ) )
485510 {
486- if ( prevState == ValveState . Release ) // If valve transitions from release to apply, quick service activates
511+ if ( prevState == ValveState . Release )
487512 {
488- QuickServiceActive = true ;
489- UniformChargingActive = false ;
513+ if ( BrakeLine1PressurePSI < AuxResPressurePSI - InitialApplicationThresholdPSI ) // If valve transitions from release to apply, quick service activates
514+ {
515+ QuickServiceActive = true ;
516+ UniformChargingActive = false ;
517+
518+ TripleValveState = ValveState . Apply ;
519+ }
520+ }
521+ else
522+ {
523+ TripleValveState = ValveState . Apply ;
490524 }
491- TripleValveState = ValveState . Apply ;
492525 }
493- else if ( BrakeLine1PressurePSI > AuxResPressurePSI + ( TripleValveState == ValveState . Release ? 0.0f : 2.0f ) )
526+ else if ( BrakeLine1PressurePSI > AuxResPressurePSI + ( TripleValveState == ValveState . Release ? 0.0f : TripleValveSensitivityPSI * 2 ) )
494527 {
495528 TripleValveState = ValveState . Release ;
496529 }
@@ -685,14 +718,14 @@ public override void Update(float elapsedClockSeconds)
685718 }
686719
687720 // Handle brake release: reduce cylinder pressure if all triple valve, EP holding valve and retainers allow so
688- if ( threshold < 2.2f ) // Prevent brakes getting stuck with a small amount of air on distributor systems
721+ if ( threshold < InitialApplicationThresholdPSI * AuxCylVolumeRatio ) // Prevent brakes getting stuck with a small amount of air on distributor systems
689722 threshold = 0 ;
690723 float minCylPressurePSI = Math . Max ( threshold , RetainerPressureThresholdPSI ) ;
691724
692725 if ( TripleValveState == ValveState . Release && HoldingValve == ValveState . Release && AutoCylPressurePSI > minCylPressurePSI )
693726 {
694727 float dp = elapsedClockSeconds * ReleaseRatePSIpS ;
695- if ( AutoCylPressurePSI < threshold + 1 && threshold > 2.2f )
728+ if ( AutoCylPressurePSI < threshold + 1 && threshold > InitialApplicationThresholdPSI * AuxCylVolumeRatio )
696729 dp *= MathHelper . Clamp ( AutoCylPressurePSI - threshold , 0.1f , 1.0f ) ; // Reduce release rate if nearing target pressure to prevent toggling between release and lap
697730 if ( AutoCylPressurePSI - dp < minCylPressurePSI )
698731 dp = AutoCylPressurePSI - minCylPressurePSI ;
0 commit comments