diff --git a/Source/Documentation/Manual/physics.rst b/Source/Documentation/Manual/physics.rst index 44daf2f406..136f3d0c49 100644 --- a/Source/Documentation/Manual/physics.rst +++ b/Source/Documentation/Manual/physics.rst @@ -2944,6 +2944,8 @@ MaxAuxilaryChargingRate and EmergencyResChargingRate. .. index:: single: BrakePipeVolume single: ORTSEmergencyValveActuationRate + single: ORTSEmergencyDumpValveRate + single: ORTSEmergencyDumpValveTimer single: ORTSMainResPipeAuxResCharging single: ORTSMainResChargingRate single: ORTSEngineBrakeReleaseRate @@ -2972,6 +2974,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 9604823e92..6da9640466 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..3949830ec6 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,23 +350,25 @@ 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) TripleValveState = ValveState.Release; else if (TripleValveState != ValveState.Emergency && targetPressurePSI > AutoCylPressurePSI + (TripleValveState != ValveState.Apply ? 2.2f : 0f)) TripleValveState = ValveState.Apply; - else + else if (TripleValveState != ValveState.Emergency) TripleValveState = ValveState.Lap; } 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; + } } }