Skip to content

Commit 7e5907e

Browse files
authored
Merge pull request #463 from peternewell/brake-enhamcements#3
Add SME brake function https://blueprints.launchpad.net/or/+spec/brake-enhancements
2 parents 98da648 + 3277b50 commit 7e5907e

File tree

10 files changed

+204
-26
lines changed

10 files changed

+204
-26
lines changed

Source/Documentation/Manual/physics.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3235,6 +3235,21 @@ the ``ORTSEmergencyBrakingDisablesWSP (1)`` parameter.
32353235

32363236
When WSP is active the brake cylinder pressure reading will go yellow in the extended HuD on the BRAKE INFORMATION screen.
32373237

3238+
SME (sometimes also called SEM) Brake System
3239+
--------------------------------------------
3240+
3241+
SME braking is a straight air-brake system having an automatic emergency feature by means of which the simplicity of the straight air brake
3242+
is retained for service operation, but it also has the additional protection afforded by the automatic application of the brake in
3243+
case of a break-in-two or the bursting of a hose. SME braking is typically used on short DMU rail sets. SME braking is a form of electro-pneumatic (EP)
3244+
brake system, however EP and SME equipped cars cannot be mixed together in the same consist.
3245+
3246+
To activate SME braking, set ``BrakeSystemType ( SME )``.
3247+
3248+
The following brake tokens can be used with it:
3249+
``TrainBrakesControllerSMEOnlyStart``
3250+
``TrainBrakesControllerSMEFullServiceStart``
3251+
``TrainBrakesControllerSMEHoldStart``
3252+
``TrainBrakesControllerSMEReleaseStart``
32383253

32393254
Dynamically Evolving Tractive Force
32403255
===================================

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,10 @@ public enum ControllerState
260260
EPOnly, // TrainBrakesControllerEPOnlyStart
261261
EPFullServ, // TrainBrakesControllerEPFullServiceStart
262262
SlowService, // TrainBrakesControllerSlowServiceStart
263+
SMEOnly, // TrainBrakesControllerSMEOnlyStart
264+
SMEFullServ, // TrainBrakesControllerSMEFullServiceStart
265+
SMESelfLap, // TrainBrakesControllerSMEHoldStart
266+
SMEReleaseStart, // TrainBrakesControllerSMEReleaseStart
263267
};
264268

265269
public static class ControllerStateDictionary
@@ -302,7 +306,11 @@ public static class ControllerStateDictionary
302306
{ControllerState.BrakeNotch, Catalog.GetString("Notch")},
303307
{ControllerState.EPOnly, Catalog.GetString("EP Service")},
304308
{ControllerState.EPFullServ, Catalog.GetString("EP Full Service")},
305-
{ControllerState.SlowService, Catalog.GetString("Slow service")}
309+
{ControllerState.SlowService, Catalog.GetString("Slow service")},
310+
{ControllerState.SMEOnly, Catalog.GetString("SME Service")},
311+
{ControllerState.SMEFullServ, Catalog.GetString("SME Full Service")},
312+
{ControllerState.SMESelfLap, Catalog.GetString("SME Self Lap")},
313+
{ControllerState.SMEReleaseStart, Catalog.GetString("SME Release Start")}
306314
};
307315
}
308316
}

Source/Orts.Simulation/Orts.Simulation.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@
113113
<Compile Include="Simulation\RollingStocks\SubSystems\Brakes\MSTS\ManualBraking.cs" />
114114
<Compile Include="Simulation\RollingStocks\SubSystems\Brakes\MSTS\MSTSBrakeSystem.cs" />
115115
<Compile Include="Simulation\RollingStocks\SubSystems\Brakes\MSTS\SingleTransferPipe.cs" />
116+
<Compile Include="Simulation\RollingStocks\SubSystems\Brakes\MSTS\SMEBrakeSystem.cs" />
116117
<Compile Include="Simulation\RollingStocks\SubSystems\Brakes\MSTS\StraightVacuumSinglePipe.cs" />
117118
<Compile Include="Simulation\RollingStocks\SubSystems\Brakes\MSTS\VacuumSinglePipe.cs" />
118119
<Compile Include="Simulation\RollingStocks\SubSystems\Controllers\BrakeController.cs" />

Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/Brakes/MSTS/AirSinglePipe.cs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,30 @@ public override string GetFullStatus(BrakeSystem lastCarBrakeSystem, Dictionary<
142142

143143
public override string[] GetDebugStatus(Dictionary<BrakeSystemComponent, PressureUnit> units)
144144
{
145-
return new string[] {
145+
MSTSLocomotive lead = (MSTSLocomotive)Car.Train.LeadLocomotive;
146+
147+
if (lead != null && lead.BrakeSystem is SMEBrakeSystem)
148+
{
149+
// Set values for SME type brake
150+
return new string[] {
151+
DebugType,
152+
string.Format("{0}{1}",FormatStrings.FormatPressure(CylPressurePSI, PressureUnit.PSI, units[BrakeSystemComponent.BrakeCylinder], true), (Car as MSTSWagon).WheelBrakeSlideProtectionActive ? "???" : ""),
153+
FormatStrings.FormatPressure(BrakeLine1PressurePSI, PressureUnit.PSI, units[BrakeSystemComponent.BrakePipe], true),
154+
FormatStrings.FormatPressure(AuxResPressurePSI, PressureUnit.PSI, units[BrakeSystemComponent.AuxiliaryReservoir], true),
155+
(Car as MSTSWagon).EmergencyReservoirPresent ? FormatStrings.FormatPressure(EmergResPressurePSI, PressureUnit.PSI, units[BrakeSystemComponent.EmergencyReservoir], true) : string.Empty,
156+
TwoPipes ? FormatStrings.FormatPressure(CylPressurePSI, PressureUnit.PSI, units[BrakeSystemComponent.MainPipe], true) : string.Empty,
157+
(Car as MSTSWagon).RetainerPositions == 0 ? string.Empty : RetainerDebugState,
158+
Simulator.Catalog.GetString(GetStringAttribute.GetPrettyName(TripleValveState)),
159+
string.Empty, // Spacer because the state above needs 2 columns.
160+
(Car as MSTSWagon).HandBrakePresent ? string.Format("{0:F0}%", HandbrakePercent) : string.Empty,
161+
FrontBrakeHoseConnected ? "I" : "T",
162+
string.Format("A{0} B{1}", AngleCockAOpen ? "+" : "-", AngleCockBOpen ? "+" : "-"),
163+
BleedOffValveOpen ? Simulator.Catalog.GetString("Open") : string.Empty,
164+
};
165+
}
166+
else
167+
{
168+
return new string[] {
146169
DebugType,
147170
string.Format("{0}{1}",FormatStrings.FormatPressure(CylPressurePSI, PressureUnit.PSI, units[BrakeSystemComponent.BrakeCylinder], true), (Car as MSTSWagon).WheelBrakeSlideProtectionActive ? "???" : ""),
148171
FormatStrings.FormatPressure(BrakeLine1PressurePSI, PressureUnit.PSI, units[BrakeSystemComponent.BrakePipe], true),
@@ -156,7 +179,9 @@ public override string[] GetDebugStatus(Dictionary<BrakeSystemComponent, Pressur
156179
FrontBrakeHoseConnected ? "I" : "T",
157180
string.Format("A{0} B{1}", AngleCockAOpen ? "+" : "-", AngleCockBOpen ? "+" : "-"),
158181
BleedOffValveOpen ? Simulator.Catalog.GetString("Open") : string.Empty,
159-
};
182+
};
183+
}
184+
160185
}
161186

162187
public override float GetCylPressurePSI()

Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/Brakes/MSTS/EPBrakeSystem.cs

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using ORTS.Common;
1919
using System;
2020
using System.Collections.Generic;
21+
using ORTS.Scripting.Api;
2122

2223
namespace Orts.Simulation.RollingStocks.SubSystems.Brakes.MSTS
2324
{
@@ -32,32 +33,39 @@ public EPBrakeSystem(TrainCar car)
3233

3334
public override void Update(float elapsedClockSeconds)
3435
{
35-
float demandedAutoCylPressurePSI = 0;
36-
if (BrakeLine3PressurePSI >= 1000f || Car.Train.BrakeLine4 < 0)
37-
{
38-
HoldingValve = ValveState.Release;
39-
}
40-
else if (Car.Train.BrakeLine4 == 0)
41-
{
42-
HoldingValve = ValveState.Lap;
43-
}
44-
else
36+
MSTSLocomotive lead = (MSTSLocomotive)Car.Train.LeadLocomotive;
37+
38+
// Only allow brakes to operate if car is connected to an SME system
39+
if (lead != null && lead.BrakeSystem is EPBrakeSystem && Car.BrakeSystem is EPBrakeSystem && (lead.TrainBrakeController.TrainBrakeControllerState == ControllerState.EPFullServ || lead.TrainBrakeController.TrainBrakeControllerState == ControllerState.EPOnly || lead.TrainBrakeController.TrainBrakeControllerState == ControllerState.EPApply))
4540
{
46-
demandedAutoCylPressurePSI = Math.Min(Math.Max(Car.Train.BrakeLine4, 0), 1) * MaxCylPressurePSI;
47-
HoldingValve = AutoCylPressurePSI <= demandedAutoCylPressurePSI ? ValveState.Lap : ValveState.Release;
48-
}
4941

50-
base.Update(elapsedClockSeconds);
42+
float demandedAutoCylPressurePSI = 0;
43+
if (BrakeLine3PressurePSI >= 1000f || Car.Train.BrakeLine4 < 0)
44+
{
45+
HoldingValve = ValveState.Release;
46+
}
47+
else if (Car.Train.BrakeLine4 == 0)
48+
{
49+
HoldingValve = ValveState.Lap;
50+
}
51+
else
52+
{
53+
demandedAutoCylPressurePSI = Math.Min(Math.Max(Car.Train.BrakeLine4, 0), 1) * MaxCylPressurePSI;
54+
HoldingValve = AutoCylPressurePSI <= demandedAutoCylPressurePSI ? ValveState.Lap : ValveState.Release;
55+
}
5156

52-
if (AutoCylPressurePSI < demandedAutoCylPressurePSI && !Car.WheelBrakeSlideProtectionActive)
53-
{
54-
float dp = elapsedClockSeconds * MaxApplicationRatePSIpS;
55-
if (BrakeLine2PressurePSI - dp * AuxBrakeLineVolumeRatio / AuxCylVolumeRatio < AutoCylPressurePSI + dp)
56-
dp = (BrakeLine2PressurePSI - AutoCylPressurePSI) / (1 + AuxBrakeLineVolumeRatio / AuxCylVolumeRatio);
57-
if (dp > demandedAutoCylPressurePSI - AutoCylPressurePSI)
58-
dp = demandedAutoCylPressurePSI - AutoCylPressurePSI;
59-
BrakeLine2PressurePSI -= dp * AuxBrakeLineVolumeRatio / AuxCylVolumeRatio;
60-
AutoCylPressurePSI += dp;
57+
base.Update(elapsedClockSeconds);
58+
59+
if (AutoCylPressurePSI < demandedAutoCylPressurePSI && !Car.WheelBrakeSlideProtectionActive)
60+
{
61+
float dp = elapsedClockSeconds * MaxApplicationRatePSIpS;
62+
if (BrakeLine2PressurePSI - dp * AuxBrakeLineVolumeRatio / AuxCylVolumeRatio < AutoCylPressurePSI + dp)
63+
dp = (BrakeLine2PressurePSI - AutoCylPressurePSI) / (1 + AuxBrakeLineVolumeRatio / AuxCylVolumeRatio);
64+
if (dp > demandedAutoCylPressurePSI - AutoCylPressurePSI)
65+
dp = demandedAutoCylPressurePSI - AutoCylPressurePSI;
66+
BrakeLine2PressurePSI -= dp * AuxBrakeLineVolumeRatio / AuxCylVolumeRatio;
67+
AutoCylPressurePSI += dp;
68+
}
6169
}
6270
}
6371

Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/Brakes/MSTS/MSTSBrakeSystem.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public static BrakeSystem Create(string type, TrainCar car)
3333
case "air_single_pipe": return new AirSinglePipe(car);
3434
case "ecp":
3535
case "ep": return new EPBrakeSystem(car);
36+
case "sme": return new SMEBrakeSystem(car);
3637
case "air_piped":
3738
case "vacuum_piped": return new SingleTransferPipe(car);
3839
default: return new SingleTransferPipe(car);
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// COPYRIGHT 2009, 2010, 2011, 2012, 2013, 2014 by the Open Rails project.
2+
//
3+
// This file is part of Open Rails.
4+
//
5+
// Open Rails is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU General Public License as published by
7+
// the Free Software Foundation, either version 3 of the License, or
8+
// (at your option) any later version.
9+
//
10+
// Open Rails is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU General Public License
16+
// along with Open Rails. If not, see <http://www.gnu.org/licenses/>.
17+
18+
using ORTS.Common;
19+
using System;
20+
using System.Collections.Generic;
21+
using ORTS.Scripting.Api;
22+
23+
namespace Orts.Simulation.RollingStocks.SubSystems.Brakes.MSTS
24+
{
25+
26+
// Detailed description of the operation of a SME brake system can be found in: "Air brakes, an up-to-date treatise on the Westinghouse air brake as designed for passenger and
27+
// freight service and for electric cars" by Ludy, Llewellyn V., 1875- [from old catalog]; American Technical Society
28+
// https://archive.org/details/airbrakesuptodat00ludy/page/174/mode/2up?q=%22SME+brake%22
29+
30+
public class SMEBrakeSystem : AirTwinPipe
31+
{
32+
public SMEBrakeSystem(TrainCar car)
33+
: base(car)
34+
{
35+
DebugType = "SME";
36+
}
37+
38+
public override void Update(float elapsedClockSeconds)
39+
{
40+
MSTSLocomotive lead = (MSTSLocomotive)Car.Train.LeadLocomotive;
41+
42+
// Only allow brakes to operate if car is connected to an SME system
43+
if (lead != null && lead.BrakeSystem is SMEBrakeSystem && Car.BrakeSystem is SMEBrakeSystem && (lead.TrainBrakeController.TrainBrakeControllerState == ControllerState.SMEFullServ || lead.TrainBrakeController.TrainBrakeControllerState == ControllerState.SMEOnly || lead.TrainBrakeController.TrainBrakeControllerState == ControllerState.SMEReleaseStart || lead.TrainBrakeController.TrainBrakeControllerState == ControllerState.SMESelfLap))
44+
{
45+
46+
float demandedAutoCylPressurePSI = 0;
47+
if (BrakeLine3PressurePSI >= 1000f || Car.Train.BrakeLine4 < 0)
48+
{
49+
HoldingValve = ValveState.Release;
50+
}
51+
else if (Car.Train.BrakeLine4 == 0)
52+
{
53+
HoldingValve = ValveState.Lap;
54+
}
55+
else
56+
{
57+
demandedAutoCylPressurePSI = Math.Min(Math.Max(Car.Train.BrakeLine4, 0), 1) * MaxCylPressurePSI;
58+
HoldingValve = AutoCylPressurePSI <= demandedAutoCylPressurePSI ? ValveState.Lap : ValveState.Release;
59+
}
60+
61+
base.Update(elapsedClockSeconds);
62+
63+
if (AutoCylPressurePSI < demandedAutoCylPressurePSI && !Car.WheelBrakeSlideProtectionActive)
64+
{
65+
float dp = elapsedClockSeconds * MaxApplicationRatePSIpS;
66+
if (BrakeLine2PressurePSI - dp * AuxBrakeLineVolumeRatio / AuxCylVolumeRatio < AutoCylPressurePSI + dp)
67+
dp = (BrakeLine2PressurePSI - AutoCylPressurePSI) / (1 + AuxBrakeLineVolumeRatio / AuxCylVolumeRatio);
68+
if (dp > demandedAutoCylPressurePSI - AutoCylPressurePSI)
69+
dp = demandedAutoCylPressurePSI - AutoCylPressurePSI;
70+
BrakeLine2PressurePSI -= dp * AuxBrakeLineVolumeRatio / AuxCylVolumeRatio;
71+
AutoCylPressurePSI += dp;
72+
}
73+
}
74+
}
75+
76+
public override string GetFullStatus(BrakeSystem lastCarBrakeSystem, Dictionary<BrakeSystemComponent, PressureUnit> units)
77+
{
78+
var s = $" {Simulator.Catalog.GetString("BC")} {FormatStrings.FormatPressure(CylPressurePSI, PressureUnit.PSI, units[BrakeSystemComponent.BrakeCylinder], true)}";
79+
if (HandbrakePercent > 0)
80+
s += $" {Simulator.Catalog.GetString("Handbrake")} {HandbrakePercent:F0}%";
81+
return s;
82+
}
83+
}
84+
}

Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/Controllers/MSTSBrakeController.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ public override void UpdatePressure(ref float pressureBar, float elapsedClockSec
128128
epState = -1;
129129
break;
130130
case ControllerState.FullQuickRelease:
131+
case ControllerState.SMEReleaseStart:
131132
IncreasePressure(ref pressureBar, MaxPressureBar(), QuickReleaseRateBarpS(), elapsedClockSeconds);
132133
DecreasePressure(ref pressureBar, MaxPressureBar(), OverchargeEliminationRateBarpS(), elapsedClockSeconds);
133134
epState = -1;
@@ -184,8 +185,10 @@ public override void UpdatePressure(ref float pressureBar, float elapsedClockSec
184185
break;
185186
case ControllerState.EPApply:
186187
case ControllerState.EPOnly:
188+
case ControllerState.SMEOnly:
187189
case ControllerState.ContServ:
188190
case ControllerState.EPFullServ:
191+
case ControllerState.SMEFullServ:
189192
epState = x;
190193
if (notch.Type == ControllerState.EPApply || notch.Type == ControllerState.ContServ)
191194
{

Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/Controllers/MSTSNotchController.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ public MSTSNotch(float v, int s, string type, STFReader stf)
6969
case "eponlystart": Type = ControllerState.EPOnly; break;
7070
case "epfullservicestart": Type = ControllerState.EPFullServ; break;
7171
case "epholdstart": Type = ControllerState.SelfLap; break;
72+
case "smeholdstart": Type = ControllerState.SMESelfLap; break;
73+
case "smeonlystart": Type = ControllerState.SMEOnly; break;
74+
case "smefullservicestart": Type = ControllerState.SMEFullServ; break;
75+
case "smereleasestart": Type = ControllerState.SMEReleaseStart; break;
7276
case "vacuumcontinuousservicestart": Type = ControllerState.VacContServ; break;
7377
case "vacuumapplycontinuousservicestart": Type = ControllerState.VacApplyContServ; break;
7478
case "manualbrakingstart": Type = ControllerState.ManualBraking; break;

Source/RunActivity/Viewer3D/Popups/HUDWindow.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,35 @@ void TextPageBrakeInfo(TableData table)
956956

957957
}
958958
}
959+
else if ((Viewer.PlayerLocomotive as MSTSLocomotive).BrakeSystem is SMEBrakeSystem)
960+
{
961+
TableSetCells(table, 0,
962+
Viewer.Catalog.GetString("Car"),
963+
Viewer.Catalog.GetString("Type"),
964+
Viewer.Catalog.GetString("BrkCyl"),
965+
Viewer.Catalog.GetString("SrvPipe"),
966+
Viewer.Catalog.GetString("AuxRes"),
967+
Viewer.Catalog.GetString("ErgRes"),
968+
Viewer.Catalog.GetString("StrPipe"),
969+
Viewer.Catalog.GetString("RetValve"),
970+
Viewer.Catalog.GetString("TripleValve"),
971+
Viewer.Catalog.GetString(""),
972+
Viewer.Catalog.GetString("Handbrk"),
973+
Viewer.Catalog.GetString("Conn"),
974+
Viewer.Catalog.GetString("AnglCock"),
975+
Viewer.Catalog.GetString("BleedOff"));
976+
TableAddLine(table);
977+
978+
var n = train.Cars.Count; // Number of lines to show
979+
for (var i = 0; i < n; i++)
980+
{
981+
var j = i < 2 ? i : i * (train.Cars.Count - 1) / (n - 1);
982+
var car = train.Cars[j];
983+
TableSetCell(table, 0, "{0}", car.CarID);
984+
TableSetCells(table, 1, car.BrakeSystem.GetDebugStatus((Viewer.PlayerLocomotive as MSTSLocomotive).BrakeSystemPressureUnits));
985+
TableAddLine(table);
986+
}
987+
}
959988
else // default air braked
960989
{
961990
TableSetCells(table, 0,

0 commit comments

Comments
 (0)