Skip to content

Commit b79cb2d

Browse files
authored
Merge pull request #732 from cesarBLG/braking-enhancement
Improvements for air brakes
2 parents ebe1c5c + c163e21 commit b79cb2d

File tree

18 files changed

+436
-149
lines changed

18 files changed

+436
-149
lines changed

Source/Documentation/Manual/cabs.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ Dedicated buttons for brake controllers
343343
.. index::
344344
single: ORTS_BAILOFF
345345

346-
In addition to the BailOff keyboard command, a cabview control named
346+
In addition to the BailOff keyboard command ``</>``, a cabview control named
347347
ORTS_BAILOFF is available. It is used to release the brakes of the engine
348348
while keeping the train brakes applied.
349349

@@ -352,13 +352,14 @@ while keeping the train brakes applied.
352352

353353
In some brake controllers, there is a button that provides a full and quick
354354
release of the train brake when pressed. OR supports this via the
355-
ORTS_QUICKRELEASE cabview control.
355+
ORTS_QUICKRELEASE cabview control, or alternatively, pressing ``<Ctrl+/>``.
356356

357357
.. index::
358358
single: ORTS_OVERCHARGE
359359

360360
Some brake controllers have a dedicated button to overcharge the brake pipe.
361-
The ORTS_OVERCHARGE cabview control can be used for this purpose.
361+
The ORTS_OVERCHARGE cabview control can be used for this purpose. Alternatively
362+
the keyboard command ``<Ctrl+Shift+/>`` is available.
362363

363364
Here is an example of one of this controls within the .cvf file::
364365

Source/Documentation/Manual/physics.rst

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2300,6 +2300,10 @@ pressure rises above the auxiliary reservoir pressure, the brake
23002300
cylinder pressure is released completely at a rate determined by the
23012301
retainer setting.
23022302

2303+
BrakeEquipmentType() can also contain a "Distributing_Valve" instead of a
2304+
"triple_valve" or a "distributor", for locomotives fitted with the
2305+
Westinghouse ET-6 distributing valve or similar equipment.
2306+
23032307
Selecting :ref:`Graduated Release Air Brakes <options-general>` in *Menu >
23042308
Options* will force self-lapping notches in the brake controller to have
23052309
graduated release. It will also force graduated release of brakes in triple
@@ -2337,6 +2341,21 @@ brake features.
23372341
Brake system charging time depends on the train length as it should, but
23382342
at the moment there is no modeling of main reservoirs and compressors.
23392343

2344+
For EP brakes, two variants are available:
2345+
2346+
- If ``Wagon(ORTSEPBrakeControlsBrakePipe`` is set to 0 (default situation),
2347+
an electrical wire (application wire) provides simultaneous fast brake application
2348+
along the train. Release time will be fast if standard air brake haven't been applied,
2349+
otherwise air brakes will determine release time. Typically this system is present
2350+
with Train Brake Controllers having an EP-only application section, followed by an
2351+
air application portion which serves as a fallback system.
2352+
- If ``Wagon(ORTSEPBrakeControlsBrakePipe`` is set to 1, brake pipe is charged and discharged
2353+
simultaneously at each car in the train, providing fast and uniform brake application and release.
2354+
The locomotive instructs the cars to "charge" or "discharge" the brake pipe to reach
2355+
a reference pressure. Standard triple valves or distributors will follow brake pipe variations
2356+
actuating the cylinders. This system is sometimes called "UIC EP brake". It is typically the system
2357+
used in high speed trains.
2358+
23402359
.. _physics-brake-controller:
23412360

23422361
Train Brake Controller Positions
@@ -2352,6 +2371,7 @@ The following notch positions can be defined for the train brake at ``Engine(Eng
23522371
single: TrainBrakesControllerSlowServiceStart
23532372
single: TrainBrakesControllerFullServiceStart
23542373
single: TrainBrakesControllerHoldStart
2374+
single: TrainBrakesControllerHoldEngineStart
23552375
single: TrainBrakesControllerEPHoldStart
23562376
single: TrainBrakesControllerSelfLapStart
23572377
single: TrainBrakesControllerRunningStart
@@ -2371,6 +2391,7 @@ The following notch positions can be defined for the train brake at ``Engine(Eng
23712391
single: ORTSTrainBrakesControllerMaxOverchargePressure
23722392
single: ORTSTrainBrakesControllerOverchargeEliminationRate
23732393
single: ORTSTrainBrakesControllerSlowApplicationRate
2394+
single: EngineBrakesControllerBailOffStart
23742395

23752396
**RELEASE and RUNNING tokens**
23762397

@@ -2430,6 +2451,15 @@ Brake Token: ``TrainBrakesControllerReleaseStart``
24302451

24312452
- Connects brake pipe to ejector(s) and/or vacuum pump. Brakes may be released by operating large or small ejector.
24322453

2454+
Brake Token: ``EngineBrakesControllerBailOffStart``
2455+
2456+
- Operation: Air, EP, Vacuum
2457+
- Brake Systems: Air single pipe, Air twin pipe, EP, Vacuum single pipe
2458+
- Description:
2459+
2460+
- Engine brake: bail off engine brakes
2461+
- Train brake: no change
2462+
24332463
**LAP, HOLDING and NEUTRAL tokens**
24342464

24352465
Brake Token: ``TrainBrakesControllerRunningStart``
@@ -2504,6 +2534,15 @@ Brake Token: ``TrainBrakesControllerNeutralHandleOffStart``
25042534
- Air brakes: Train pipe pressure is held without compensation for leakage.
25052535
- EP brakes: Brake application is held at any value.
25062536
- Vacuum brakes: Train pipe vacuum is held without compensation for leakage.
2537+
2538+
Brake Token: ``TrainBrakesControllerHoldEngineStart``
2539+
2540+
- Operation: Air, EP, Vacuum
2541+
- Brake Systems: Air single pipe, Air twin pipe, EP, Vacuum single pipe
2542+
- Description: HOLD ENGINE
2543+
2544+
- Engine brakes: engine brake cylinder pressure is held at current value.
2545+
- Train brakes: same as RELEASE/RUNNING
25072546

25082547

25092548
**SELF LAPPING APPLY tokens**
@@ -2875,6 +2914,22 @@ defined in a DynamicBrakeForceCurves table that works like the
28752914
DynamicBrakeForceCurves defined in the ENG file, than one is created
28762915
based on the MSTS parameter values.
28772916

2917+
It is possible to use dynamic brakes as a replacement for air brakes
2918+
when they are available (dynamic brake blending). During blending operation,
2919+
the following parameters will adjust the behaviour of air brakes:
2920+
2921+
.. index::
2922+
single: DynamicBrakeHasAutoBailOff
2923+
single: ORTSDynamicBrakesHasPartialBailOff
2924+
2925+
- ``Engine(DynamicBrakeHasAutoBailOff`` -- Set to 1 if brake cylinders are
2926+
emptied while dynamic brake is active
2927+
- ``Engine(ORTSDynamicBrakesHasPartialBailOff`` -- If this parameter is set to 1,
2928+
air brakes are released while dynamic brakes satisfy the train brake demand.
2929+
If dynamic braking is not sufficient, air brakes will be partially applied
2930+
so the combination air+dynamic provides the required brake demand.
2931+
2932+
28782933
Native Open Rails Braking Parameters
28792934
------------------------------------
28802935

@@ -2898,6 +2953,8 @@ MaxAuxilaryChargingRate and EmergencyResChargingRate.
28982953
single: ORTSBrakeServiceTimeFactor
28992954
single: ORTSBrakeEmergencyTimeFactor
29002955
single: ORTSBrakePipeTimeFactor
2956+
single: ORTSEPBrakeControlsBrakePipe
2957+
single: ORTSCompressorIsMuControlled
29012958

29022959
- ``Wagon(BrakePipeVolume`` -- Volume of car's brake pipe in cubic feet
29032960
(default .5).
@@ -2919,6 +2976,8 @@ MaxAuxilaryChargingRate and EmergencyResChargingRate.
29192976
for twin pipe systems, if the main reservoir pipe is used for charging the auxiliary
29202977
reservoirs. If set to false, the main reservoir pipe will not be used
29212978
by the brake system.
2979+
- ``Wagon(ORTSEPBrakeControlsBrakePipe`` -- Set to 1 for UIC EP brake: brake pipe
2980+
pressure is electrically controlled at every fitted car.
29222981
- ``Engine(ORTSMainResChargingRate`` -- Rate of main reservoir pressure change
29232982
in psi per second when the compressor is on (default .4).
29242983
- ``Engine(ORTSEngineBrakeReleaseRate`` -- Rate of engine brake pressure
@@ -2942,6 +3001,8 @@ MaxAuxilaryChargingRate and EmergencyResChargingRate.
29423001
(default .003).
29433002
- ``Engine(AirBrakeMaxMainResPipePressure`` -- Pressure in Main Reservoir
29443003
Pipe for twin pipe braking systems (default = Main Reservoir Pressure).
3004+
- ``Engine(ORTSCompressorIsMuControlled`` -- Set to 1 if compressors from
3005+
all locomotives are synchronized.
29453006

29463007
.. _physics-retainers:
29473008

Source/Orts.Simulation/Common/Scripting/BrakeController.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -226,11 +226,11 @@ public void SetUpdateValue(float value)
226226
/// </summary>
227227
public void SetDynamicBrakeIntervention(float value)
228228
{
229-
// TODO: Set dynamic brake intervention instead of controller position
230-
// There are some issues that need to be identified and fixed before setting the intervention directly
231-
if (Locomotive.DynamicBrakeController == null) return;
232-
Locomotive.DynamicBrakeChangeActiveState(value > 0);
233-
Locomotive.DynamicBrakeController.SetValue(value);
229+
if (value > 0 && Host.TrainDynamicBrakeIntervention <= 0)
230+
Host.TrainDynamicBrakeCommandStartTime = Host.Simulator.ClockTime;
231+
if (value <= 0)
232+
Host.TrainDynamicBrakeIntervention = -1;
233+
else Host.TrainDynamicBrakeIntervention = Math.Min(value, 1);
234234
}
235235

236236
/// <summary>
@@ -363,6 +363,8 @@ public enum ControllerState
363363
SMEFullServ, // TrainBrakesControllerSMEFullServiceStart
364364
SMESelfLap, // TrainBrakesControllerSMEHoldStart
365365
SMEReleaseStart, // TrainBrakesControllerSMEReleaseStart
366+
HoldEngine, // TrainBrakesControllerHoldEngineStart
367+
BailOff, // EngineBrakesControllerBailOffStart
366368
};
367369

368370
public static class ControllerStateDictionary
@@ -409,7 +411,9 @@ public static class ControllerStateDictionary
409411
{ControllerState.SMEOnly, Catalog.GetString("SME Service")},
410412
{ControllerState.SMEFullServ, Catalog.GetString("SME Full Service")},
411413
{ControllerState.SMESelfLap, Catalog.GetString("SME Self Lap")},
412-
{ControllerState.SMEReleaseStart, Catalog.GetString("SME Release Start")}
414+
{ControllerState.SMEReleaseStart, Catalog.GetString("SME Release Start")},
415+
{ControllerState.HoldEngine, Catalog.GetString("Hold Engine")},
416+
{ControllerState.BailOff, Catalog.GetString("Bail Off")}
413417
};
414418
}
415419
}

Source/Orts.Simulation/Simulation/AIs/AITrain.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4089,7 +4089,8 @@ public override void InitializeBrakes()
40894089
float fullServReductionPSI = -5;
40904090
float max = maxPressurePSI;
40914091
float fullServ = fullServPressurePSI;
4092-
BrakeLine3PressurePSI = BrakeLine4 = 0;
4092+
BrakeLine3PressurePSI = 0;
4093+
BrakeLine4 = -1;
40934094
if (FirstCar != null && FirstCar.BrakeSystem is VacuumSinglePipe)
40944095
{
40954096
max = maxPressurePSIVacuum;

Source/Orts.Simulation/Simulation/Physics/Train.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ public TrainCar LastCar
134134
// but Class VacuumSinglePipe uses it for vacuum in InHg.
135135
public float BrakeLine2PressurePSI; // extra line for dual line systems, main reservoir
136136
public float BrakeLine3PressurePSI; // extra line just in case, engine brake pressure
137-
public float BrakeLine4 = -1; // extra line just in case, ep brake control line. -1: release/inactive, 0: hold, 0 < value <=1: apply
137+
public float BrakeLine4 = -1; // extra line just in case, ep brake control line. -2: hold, -1: inactive, 0: release, 0 < value <=1: apply
138138
public RetainerSetting RetainerSetting = RetainerSetting.Exhaust;
139139
public int RetainerPercent = 100;
140140
public float TotalTrainBrakePipeVolumeM3; // Total volume of train brake pipe
@@ -4017,6 +4017,8 @@ public void UnconditionalInitializeBrakes()
40174017
fullServPressurePSI = lead.BrakeSystem is VacuumSinglePipe ? 16 : maxPressurePSI - lead.TrainBrakeController.FullServReductionPSI;
40184018
EqualReservoirPressurePSIorInHg = Math.Min(maxPressurePSI, EqualReservoirPressurePSIorInHg);
40194019
lead.TrainBrakeController.UpdatePressure(ref EqualReservoirPressurePSIorInHg, 1000, ref BrakeLine4);
4020+
if (!(lead.BrakeSystem is EPBrakeSystem))
4021+
BrakeLine4 = -1;
40204022
EqualReservoirPressurePSIorInHg =
40214023
MathHelper.Max(EqualReservoirPressurePSIorInHg, fullServPressurePSI);
40224024
}
@@ -4223,7 +4225,11 @@ public void PropagateBrakePressure(float elapsedClockSeconds)
42234225
if (LeadLocomotive is MSTSLocomotive lead)
42244226
{
42254227
if (lead.TrainBrakeController != null)
4228+
{
42264229
lead.TrainBrakeController.UpdatePressure(ref EqualReservoirPressurePSIorInHg, elapsedClockSeconds, ref BrakeLine4);
4230+
if (!(lead.BrakeSystem is EPBrakeSystem))
4231+
BrakeLine4 = -1;
4232+
}
42274233
if (lead.EngineBrakeController != null)
42284234
lead.EngineBrakeController.UpdateEngineBrakePressure(ref BrakeLine3PressurePSI, elapsedClockSeconds);
42294235
lead.BrakeSystem.PropagateBrakePressure(elapsedClockSeconds);

Source/Orts.Simulation/Simulation/RollingStocks/MSTSLocomotive.cs

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ public float OdometerM
370370
public float DynamicBrakeMaxCurrentA;
371371
public float DynamicBrakeDelayS;
372372
public bool DynamicBrakeAutoBailOff;
373+
public bool DynamicBrakePartialBailOff;
373374
public bool UsingRearCab;
374375
public bool BrakeOverchargeSoundOn = false;
375376

@@ -1020,6 +1021,7 @@ public override void Parse(string lowercasetoken, STFReader stf)
10201021
case "engine(dynamicbrakesmaximumforce": MaxDynamicBrakeForceN = stf.ReadFloatBlock(STFReader.UNITS.Force, null); break;
10211022
case "engine(dynamicbrakehasautobailoff":
10221023
case "engine(ortsdynamicbrakeshasautobailoff": DynamicBrakeAutoBailOff = stf.ReadBoolBlock(true); break;
1024+
case "engine(ortsdynamicbrakeshaspartialbailoff": DynamicBrakePartialBailOff = stf.ReadBoolBlock(false); break;
10231025
case "engine(dynamicbrakesdelaytimebeforeengaging": DynamicBrakeDelayS = stf.ReadFloatBlock(STFReader.UNITS.Time, null); break;
10241026
case "engine(dynamicbrakesresistorcurrentlimit": DynamicBrakeMaxCurrentA = stf.ReadFloatBlock(STFReader.UNITS.Current, null); break;
10251027
case "engine(numwheels": MSTSLocoNumDrvWheels = stf.ReadFloatBlock(STFReader.UNITS.None, 4.0f); if (MSTSLocoNumDrvWheels < 1) STFException.TraceWarning(stf, "Engine:NumWheels is less than 1, parts of the simulation may not function correctly"); break;
@@ -1139,6 +1141,7 @@ public override void Copy(MSTSWagon copy)
11391141
ContinuousForceTimeFactor = locoCopy.ContinuousForceTimeFactor;
11401142
DynamicBrakeForceCurves = locoCopy.DynamicBrakeForceCurves;
11411143
DynamicBrakeAutoBailOff = locoCopy.DynamicBrakeAutoBailOff;
1144+
DynamicBrakePartialBailOff = locoCopy.DynamicBrakePartialBailOff;
11421145
DynamicBrakeMaxCurrentA = locoCopy.DynamicBrakeMaxCurrentA;
11431146
CombinedControlType = locoCopy.CombinedControlType;
11441147
CombinedControlSplitPosition = locoCopy.CombinedControlSplitPosition;
@@ -1811,14 +1814,12 @@ protected void CorrectBrakingParams()
18111814
/// </summary>
18121815
public void DynamicBrakeBlending(float elapsedClockSeconds)
18131816
{
1814-
if (Math.Abs(SpeedMpS) > DynamicBrakeSpeed1MpS && airPipeSystem != null && ((airPipeSystem is EPBrakeSystem && Train.BrakeLine4 > 0f) || airPipeSystem.BrakeLine1PressurePSI < TrainBrakeController.MaxPressurePSI - 1f)
1815-
&& ThrottleController.CurrentValue == 0f && !(DynamicBrakeController != null && DynamicBrakeBlendingOverride && DynamicBrakeController.CurrentValue > 0f)
1816-
/* && (!DynamicBrakeBlendingLeverOverride && DynamicBrakeController != null && DynamicBrakeIntervention < DynamicBrakeController.CurrentValue)*/)
1817+
// Local blending
1818+
if (Math.Abs(SpeedMpS) > DynamicBrakeSpeed1MpS && airPipeSystem != null && airPipeSystem.AutoCylPressurePSI > 0.1f
1819+
&& ThrottlePercent == 0 && !(DynamicBrakeController != null && DynamicBrakeBlendingOverride && DynamicBrakeController.CurrentValue > 0))
18171820
{
1818-
float threshold = DynamicBrakeBlendingForceMatch ? 100f : 0.01f;
18191821
float maxCylPressurePSI = airPipeSystem.GetMaxCylPressurePSI();
1820-
float targetDynamicBrakePercent = airPipeSystem is EPBrakeSystem ? Train.BrakeLine4 : Math.Min(((TrainBrakeController.MaxPressurePSI - airPipeSystem.BrakeLine1PressurePSI) * airPipeSystem.GetAuxCylVolumeRatio()) / maxCylPressurePSI, 1f);
1821-
//DynamicBrakeIntervention = Math.Min(((TrainBrakeController.CurrentValue - DynamicBrakeBlendingStart) / (DynamicBrakeBlendingStop - DynamicBrakeBlendingStart)), 1f);
1822+
float target = airPipeSystem.AutoCylPressurePSI / maxCylPressurePSI;
18221823

18231824
if (!DynamicBrakeBlended)
18241825
{
@@ -1831,11 +1832,19 @@ public void DynamicBrakeBlending(float elapsedClockSeconds)
18311832
}
18321833
if (DynamicBrake)
18331834
{
1834-
float diff = DynamicBrakeBlendingForceMatch ? targetDynamicBrakePercent * MaxBrakeForceN - DynamicBrakeForceN : targetDynamicBrakePercent - DynamicBrakeIntervention;
1835-
if (diff > threshold && DynamicBrakeIntervention <= 1)
1836-
DynamicBrakeIntervention = Math.Min( DynamicBrakeIntervention + elapsedClockSeconds * (airPipeSystem.GetMaxApplicationRatePSIpS() / maxCylPressurePSI), 1.0f);
1837-
else if (diff < -threshold)
1838-
DynamicBrakeIntervention -= elapsedClockSeconds * (airPipeSystem.GetMaxReleaseRatePSIpS() / maxCylPressurePSI);
1835+
if (DynamicBrakeBlendingForceMatch)
1836+
{
1837+
float diff = target * MaxBrakeForceN - DynamicBrakeForceN;
1838+
float threshold = 100;
1839+
if (diff > threshold && DynamicBrakeIntervention < 1)
1840+
DynamicBrakeIntervention = Math.Min(DynamicBrakeIntervention + elapsedClockSeconds, 1);
1841+
else if (diff < -threshold && DynamicBrakeIntervention > 0.01f)
1842+
DynamicBrakeIntervention = Math.Max(DynamicBrakeIntervention - elapsedClockSeconds, 0.01f);
1843+
}
1844+
else
1845+
{
1846+
DynamicBrakeIntervention = target;
1847+
}
18391848
}
18401849
if (DynamicBrakeController != null)
18411850
DynamicBrakeIntervention = Math.Max(DynamicBrakeIntervention, DynamicBrakeController.CurrentValue);
@@ -1845,6 +1854,17 @@ public void DynamicBrakeBlending(float elapsedClockSeconds)
18451854
DynamicBrakeIntervention = -1;
18461855
DynamicBrakeBlended = false;
18471856
}
1857+
// Train blending
1858+
if (IsLeadLocomotive())
1859+
{
1860+
if (TrainBrakeController.TrainDynamicBrakeIntervention > DynamicBrakeIntervention)
1861+
{
1862+
DynamicBrakeBlended = true;
1863+
DynamicBrakeIntervention = TrainBrakeController.TrainDynamicBrakeIntervention;
1864+
}
1865+
if (TrainBrakeController.TrainDynamicBrakeCommandStartTime > DynamicBrakeCommandStartTime)
1866+
DynamicBrakeCommandStartTime = TrainBrakeController.TrainDynamicBrakeCommandStartTime;
1867+
}
18481868
}
18491869

18501870
/// <summary>
@@ -2246,6 +2266,7 @@ protected virtual void UpdateControllers(float elapsedClockSeconds)
22462266
}
22472267

22482268
DynamicBrakeBlending(elapsedClockSeconds);
2269+
22492270
if (DynamicBrakeController != null && DynamicBrakeController.CommandStartTime > DynamicBrakeCommandStartTime) // use the latest command time
22502271
DynamicBrakeCommandStartTime = DynamicBrakeController.CommandStartTime;
22512272

Source/Orts.Simulation/Simulation/RollingStocks/MSTSWagon.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ public enum BrakeValveType
227227
None,
228228
TripleValve, // Plain triple valve
229229
Distributor, // Triple valve with graduated release
230+
DistributingValve, // Triple valve + driver brake valve control. Only for locomotives
230231
}
231232
/// <summary>
232233
/// Type of brake valve in the car
@@ -1190,6 +1191,7 @@ public virtual void Parse(string lowercasetoken, STFReader stf)
11901191
case "triple_valve": BrakeValve = BrakeValveType.TripleValve; break;
11911192
case "distributor":
11921193
case "graduated_release_triple_valve": BrakeValve = BrakeValveType.Distributor; break;
1194+
case "distributing_valve": BrakeValve = BrakeValveType.DistributingValve; break;
11931195
case "emergency_brake_reservoir": EmergencyReservoirPresent = true; break;
11941196
case "handbrake": HandBrakePresent = true; break;
11951197
case "auxilary_reservoir": // MSTS legacy parameter - use is discouraged

0 commit comments

Comments
 (0)