diff --git a/Source/Documentation/Manual/physics.rst b/Source/Documentation/Manual/physics.rst index ee68f7278a..85b89e903d 100644 --- a/Source/Documentation/Manual/physics.rst +++ b/Source/Documentation/Manual/physics.rst @@ -2540,7 +2540,7 @@ Brake Token: ``TrainBrakesControllerNeutralHandleOffStart`` - Air brakes: Train pipe pressure is held without compensation for leakage. - EP brakes: Brake application is held at any value. - Vacuum brakes: Train pipe vacuum is held without compensation for leakage. - + Brake Token: ``TrainBrakesControllerHoldEngineStart`` - Operation: Air, EP, Vacuum @@ -2950,6 +2950,8 @@ MaxAuxilaryChargingRate and EmergencyResChargingRate. .. index:: single: BrakePipeVolume single: ORTSEmergencyValveActuationRate + single: ORTSEmergencyDumpValveRate + single: ORTSEmergencyDumpValveTimer single: ORTSMainResPipeAuxResCharging single: ORTSMainResChargingRate single: ORTSEngineBrakeReleaseRate @@ -2978,6 +2980,11 @@ MaxAuxilaryChargingRate and EmergencyResChargingRate. brake actuation of the triple valve. If the pressure in the brake pipe decreases at a higher rate than specified, the triple valve will switch to emergency mode. +- ``Wagon(ORTSEmergencyDumpValveRate)``-- Rate at which BP is locally discharged + at every wagon during an emergency brake application. +- ``Wagon(ORTSEmergencyDumpValveTimer)``-- Timer for emergency dump valve to close + after it is activated. If set to 0, it will close as soon as BP is discharged. + Default value will prevent BP from being charged for 2 minutes. - ``Wagon(ORTSMainResPipeAuxResCharging`` -- Boolean value that indicates, for twin pipe systems, if the main reservoir pipe is used for charging the auxiliary reservoirs. If set to false, the main reservoir pipe will not be used diff --git a/Source/Documentation/Manual/sound.rst b/Source/Documentation/Manual/sound.rst index 89fb1dea82..212f99c915 100644 --- a/Source/Documentation/Manual/sound.rst +++ b/Source/Documentation/Manual/sound.rst @@ -403,6 +403,9 @@ Trigger Function 243 GenericItem2Off ========= ===================================== +Trigger 252 is activated when the braking system detects an +emergency brake application and starts venting air from the Brake Pipe. + Variable Triggers ----------------- diff --git a/Source/Orts.Simulation/Common/Events.cs b/Source/Orts.Simulation/Common/Events.cs index 0396ddc9f1..a1cce35972 100644 --- a/Source/Orts.Simulation/Common/Events.cs +++ b/Source/Orts.Simulation/Common/Events.cs @@ -255,6 +255,7 @@ public enum Event OverchargeBrakingOn, OverchargeBrakingOff, + EmergencyVentValveOn, // Cruise Control LeverFromZero, @@ -523,6 +524,7 @@ public static Event From(Source source, int eventID) case 250: return Event.OverchargeBrakingOn; case 251: return Event.OverchargeBrakingOff; + case 252: return Event.EmergencyVentValveOn; // Cruise Control case 298: return Event.LeverFromZero; diff --git a/Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/Brakes/MSTS/AirSinglePipe.cs b/Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/Brakes/MSTS/AirSinglePipe.cs index 8df6254049..7c45e06b9a 100644 --- a/Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/Brakes/MSTS/AirSinglePipe.cs +++ b/Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/Brakes/MSTS/AirSinglePipe.cs @@ -51,6 +51,9 @@ public class AirSinglePipe : MSTSBrakeSystem protected float MaxAuxilaryChargingRatePSIpS = 1.684f; protected float BrakeInsensitivityPSIpS = 0.07f; protected float EmergencyValveActuationRatePSIpS = 0; + protected float EmergencyDumpValveRatePSIpS = 0; + protected float EmergencyDumpValveTimerS = 120; + protected float? EmergencyDumpStartTime; protected float EmergResChargingRatePSIpS = 1.684f; protected float EmergAuxVolumeRatio = 1.4f; protected string DebugType = string.Empty; @@ -116,6 +119,8 @@ public override void InitializeFromCopy(BrakeSystem copy) MaxAuxilaryChargingRatePSIpS = thiscopy.MaxAuxilaryChargingRatePSIpS; BrakeInsensitivityPSIpS = thiscopy.BrakeInsensitivityPSIpS; EmergencyValveActuationRatePSIpS = thiscopy.EmergencyValveActuationRatePSIpS; + EmergencyDumpValveRatePSIpS = thiscopy.EmergencyDumpValveRatePSIpS; + EmergencyDumpValveTimerS = thiscopy.EmergencyDumpValveTimerS; EmergResChargingRatePSIpS = thiscopy.EmergResChargingRatePSIpS; EmergAuxVolumeRatio = thiscopy.EmergAuxVolumeRatio; TwoPipes = thiscopy.TwoPipes; @@ -232,6 +237,8 @@ public override void Parse(string lowercasetoken, STFReader stf) case "wagon(brakepipevolume": BrakePipeVolumeM3 = Me3.FromFt3(stf.ReadFloatBlock(STFReader.UNITS.VolumeDefaultFT3, null)); break; case "wagon(ortsbrakeinsensitivity": BrakeInsensitivityPSIpS = stf.ReadFloatBlock(STFReader.UNITS.PressureRateDefaultPSIpS, 0.07f); break; case "wagon(ortsemergencyvalveactuationrate": EmergencyValveActuationRatePSIpS = stf.ReadFloatBlock(STFReader.UNITS.PressureRateDefaultPSIpS, 15f); break; + case "wagon(ortsemergencydumpvalverate": EmergencyDumpValveRatePSIpS = stf.ReadFloatBlock(STFReader.UNITS.PressureRateDefaultPSIpS, 15f); break; + case "wagon(ortsemergencydumpvalvetimer": EmergencyDumpValveTimerS = stf.ReadFloatBlock(STFReader.UNITS.Time, 120.0f); break; case "wagon(ortsmainrespipeauxrescharging": MRPAuxResCharging = this is AirTwinPipe && stf.ReadBoolBlock(true); break; } } @@ -307,7 +314,10 @@ public override void Initialize(bool handbrakeOn, float maxPressurePSI, float fu CylPressurePSI = AutoCylPressurePSI = immediateRelease ? 0 : Math.Min((maxPressurePSI - BrakeLine1PressurePSI) * AuxCylVolumeRatio, MaxCylPressurePSI); AuxResPressurePSI = Math.Max(TwoPipes ? maxPressurePSI : maxPressurePSI - AutoCylPressurePSI / AuxCylVolumeRatio, BrakeLine1PressurePSI); if ((Car as MSTSWagon).EmergencyReservoirPresent) + { EmergResPressurePSI = Math.Max(AuxResPressurePSI, maxPressurePSI); + if (EmergencyValveActuationRatePSIpS == 0) EmergencyValveActuationRatePSIpS = 15; + } TripleValveState = AutoCylPressurePSI < 1 ? ValveState.Release : ValveState.Lap; HoldingValve = ValveState.Release; HandbrakePercent = handbrakeOn & (Car as MSTSWagon).HandBrakePresent ? 100 : 0; @@ -340,11 +350,13 @@ public override void InitializeMoving () public void UpdateTripleValveState(float elapsedClockSeconds) { + var prevState = TripleValveState; var valveType = (Car as MSTSWagon).BrakeValve; + bool disableGradient = !(Car.Train.LeadLocomotive is MSTSLocomotive) && Car.Train.TrainType != Orts.Simulation.Physics.Train.TRAINTYPE.STATIC; if (valveType == MSTSWagon.BrakeValveType.Distributor) { float targetPressurePSI = (ControlResPressurePSI - BrakeLine1PressurePSI) * AuxCylVolumeRatio; - if (targetPressurePSI > AutoCylPressurePSI && EmergencyValveActuationRatePSIpS > 0 && (prevBrakePipePressurePSI - BrakeLine1PressurePSI) > Math.Max(elapsedClockSeconds, 0.0001f) * EmergencyValveActuationRatePSIpS) + if (!disableGradient && targetPressurePSI > AutoCylPressurePSI && EmergencyValveActuationRatePSIpS > 0 && (prevBrakePipePressurePSI - BrakeLine1PressurePSI) > Math.Max(elapsedClockSeconds, 0.0001f) * EmergencyValveActuationRatePSIpS) TripleValveState = ValveState.Emergency; else if (targetPressurePSI < AutoCylPressurePSI - (TripleValveState != ValveState.Release ? 2.2f : 0f) || targetPressurePSI < 2.2f) // The latter is a UIC regulation (0.15 bar) @@ -356,7 +368,7 @@ public void UpdateTripleValveState(float elapsedClockSeconds) } else if (valveType == MSTSWagon.BrakeValveType.TripleValve || valveType == MSTSWagon.BrakeValveType.DistributingValve) { - if (BrakeLine1PressurePSI < AuxResPressurePSI - 1 && EmergencyValveActuationRatePSIpS > 0 && (prevBrakePipePressurePSI - BrakeLine1PressurePSI) > Math.Max(elapsedClockSeconds, 0.0001f) * EmergencyValveActuationRatePSIpS) + if (!disableGradient && BrakeLine1PressurePSI < AuxResPressurePSI - 1 && EmergencyValveActuationRatePSIpS > 0 && (prevBrakePipePressurePSI - BrakeLine1PressurePSI) > Math.Max(elapsedClockSeconds, 0.0001f) * EmergencyValveActuationRatePSIpS) TripleValveState = ValveState.Emergency; else if (BrakeLine1PressurePSI > AuxResPressurePSI + 1) TripleValveState = ValveState.Release; @@ -371,6 +383,15 @@ public void UpdateTripleValveState(float elapsedClockSeconds) { TripleValveState = ValveState.Release; } + if (TripleValveState == ValveState.Emergency) + { + if (prevState != ValveState.Emergency) + { + EmergencyDumpStartTime = (float)Car.Simulator.GameTime; + Car.SignalEvent(Event.EmergencyVentValveOn); + } + } + else EmergencyDumpStartTime = null; prevBrakePipePressurePSI = BrakeLine1PressurePSI; } @@ -440,6 +461,20 @@ public override void Update(float elapsedClockSeconds) EmergResPressurePSI -= dp; AuxResPressurePSI += dp * EmergAuxVolumeRatio; } + if (EmergencyDumpValveTimerS == 0) + { + if (BrakeLine1PressurePSI < 1) EmergencyDumpStartTime = null; + } + else if (Car.Simulator.GameTime - EmergencyDumpStartTime > EmergencyDumpValveTimerS) + { + EmergencyDumpStartTime = null; + } + if (EmergencyDumpValveRatePSIpS > 0 && EmergencyDumpStartTime != null) + { + BrakeLine1PressurePSI -= elapsedClockSeconds * EmergencyDumpValveRatePSIpS; + if (BrakeLine1PressurePSI < 0) + BrakeLine1PressurePSI = 0; + } } }