Skip to content

Commit adf9260

Browse files
committed
Proportional relay valve
1 parent 51d4cd9 commit adf9260

File tree

4 files changed

+68
-38
lines changed

4 files changed

+68
-38
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1819,7 +1819,7 @@ public void DynamicBrakeBlending(float elapsedClockSeconds)
18191819
&& ThrottlePercent == 0 && !(DynamicBrakeController != null && DynamicBrakeBlendingOverride && DynamicBrakeController.CurrentValue > 0))
18201820
{
18211821
float maxCylPressurePSI = airPipeSystem.GetMaxCylPressurePSI();
1822-
float target = airPipeSystem.AutoCylPressurePSI / maxCylPressurePSI;
1822+
float target = airPipeSystem.AutoCylPressurePSI * airPipeSystem.RelayValveRatio / maxCylPressurePSI;
18231823

18241824
if (!DynamicBrakeBlended)
18251825
{

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

Lines changed: 65 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public class AirSinglePipe : MSTSBrakeSystem
4141
protected float ControlResPressurePSI = 64;
4242
protected float FullServPressurePSI = 50;
4343
protected float MaxCylPressurePSI = 64;
44+
protected float MaxTripleValveCylPressurePSI;
4445
protected float AuxCylVolumeRatio = 2.5f;
4546
protected float AuxBrakeLineVolumeRatio;
4647
protected float EmergResVolumeM3 = 0.07f;
@@ -53,6 +54,10 @@ public class AirSinglePipe : MSTSBrakeSystem
5354
protected float EmergencyValveActuationRatePSIpS = 0;
5455
protected float EmergResChargingRatePSIpS = 1.684f;
5556
protected float EmergAuxVolumeRatio = 1.4f;
57+
protected bool RelayValveFitted = false;
58+
public float RelayValveRatio { get; protected set; } = 1;
59+
protected float RelayValveApplicationRatePSIpS = 50;
60+
protected float RelayValveReleaseRatePSIpS = 50;
5661
protected string DebugType = string.Empty;
5762
protected string RetainerDebugState = string.Empty;
5863
protected bool MRPAuxResCharging;
@@ -121,6 +126,11 @@ public override void InitializeFromCopy(BrakeSystem copy)
121126
TwoPipes = thiscopy.TwoPipes;
122127
MRPAuxResCharging = thiscopy.MRPAuxResCharging;
123128
HoldingValve = thiscopy.HoldingValve;
129+
RelayValveFitted = thiscopy.RelayValveFitted;
130+
RelayValveRatio = thiscopy.RelayValveRatio;
131+
RelayValveApplicationRatePSIpS = thiscopy.RelayValveApplicationRatePSIpS;
132+
RelayValveReleaseRatePSIpS = thiscopy.RelayValveReleaseRatePSIpS;
133+
MaxTripleValveCylPressurePSI = thiscopy.MaxTripleValveCylPressurePSI;
124134
}
125135

126136
// Get the brake BC & BP for EOT conditions
@@ -233,6 +243,21 @@ public override void Parse(string lowercasetoken, STFReader stf)
233243
case "wagon(ortsbrakeinsensitivity": BrakeInsensitivityPSIpS = stf.ReadFloatBlock(STFReader.UNITS.PressureRateDefaultPSIpS, 0.07f); break;
234244
case "wagon(ortsemergencyvalveactuationrate": EmergencyValveActuationRatePSIpS = stf.ReadFloatBlock(STFReader.UNITS.PressureRateDefaultPSIpS, 15f); break;
235245
case "wagon(ortsmainrespipeauxrescharging": MRPAuxResCharging = this is AirTwinPipe && stf.ReadBoolBlock(true); break;
246+
case "wagon(ortsbrakerelayvalveratio":
247+
RelayValveRatio = stf.ReadFloatBlock(STFReader.UNITS.None, null);
248+
if (RelayValveRatio != 0)
249+
{
250+
RelayValveFitted = true;
251+
}
252+
else
253+
{
254+
RelayValveRatio = 1;
255+
RelayValveFitted = false;
256+
}
257+
break;
258+
case "wagon(ortsbrakerelayvalveapplicationrate": RelayValveApplicationRatePSIpS = stf.ReadFloatBlock(STFReader.UNITS.PressureRateDefaultPSIpS, null); break;
259+
case "wagon(ortsbrakerelayvalvereleaserate": RelayValveReleaseRatePSIpS = stf.ReadFloatBlock(STFReader.UNITS.PressureRateDefaultPSIpS, null); break;
260+
case "wagon(ortsmaxtriplevalvecylinderpressure": MaxTripleValveCylPressurePSI = stf.ReadFloatBlock(STFReader.UNITS.PressureDefaultPSI, null); break;
236261
}
237262
}
238263

@@ -298,13 +323,16 @@ public override void Initialize(bool handbrakeOn, float maxPressurePSI, float fu
298323
if (Car.Simulator.Settings.SimpleControlPhysics && EmergResVolumeM3 > 2.0)
299324
EmergResVolumeM3 = 0.7f;
300325

326+
if (MaxTripleValveCylPressurePSI == 0) MaxTripleValveCylPressurePSI = MaxCylPressurePSI / RelayValveRatio;
327+
301328
BrakeLine1PressurePSI = Car.Train.EqualReservoirPressurePSIorInHg;
302329
BrakeLine2PressurePSI = Car.Train.BrakeLine2PressurePSI;
303330
BrakeLine3PressurePSI = 0;
304331
if (maxPressurePSI > 0)
305332
ControlResPressurePSI = maxPressurePSI;
306333
FullServPressurePSI = fullServPressurePSI;
307-
CylPressurePSI = AutoCylPressurePSI = immediateRelease ? 0 : Math.Min((maxPressurePSI - BrakeLine1PressurePSI) * AuxCylVolumeRatio, MaxCylPressurePSI);
334+
AutoCylPressurePSI = immediateRelease ? 0 : Math.Min((maxPressurePSI - BrakeLine1PressurePSI) * AuxCylVolumeRatio, MaxCylPressurePSI);
335+
CylPressurePSI = AutoCylPressurePSI * RelayValveRatio;
308336
AuxResPressurePSI = Math.Max(TwoPipes ? maxPressurePSI : maxPressurePSI - AutoCylPressurePSI / AuxCylVolumeRatio, BrakeLine1PressurePSI);
309337
if ((Car as MSTSWagon).EmergencyReservoirPresent)
310338
EmergResPressurePSI = Math.Max(AuxResPressurePSI, maxPressurePSI);
@@ -324,6 +352,8 @@ public override void Initialize(bool handbrakeOn, float maxPressurePSI, float fu
324352
AuxBrakeLineVolumeRatio = 3.1f;
325353

326354
CylVolumeM3 = EmergResVolumeM3 / EmergAuxVolumeRatio / AuxCylVolumeRatio;
355+
356+
RelayValveFitted |= (loco != null && (loco.DynamicBrakeAutoBailOff || loco.DynamicBrakePartialBailOff)) || (Car as MSTSWagon).BrakeValve == MSTSWagon.BrakeValveType.DistributingValve;
327357
}
328358

329359
/// <summary>
@@ -420,8 +450,8 @@ public override void Update(float elapsedClockSeconds)
420450
dp = (AuxResPressurePSI - AutoCylPressurePSI) * AuxCylVolumeRatio / (1 + AuxCylVolumeRatio);
421451
if (((Car as MSTSWagon).BrakeValve == MSTSWagon.BrakeValveType.Distributor) && TripleValveState != ValveState.Emergency && dp > threshold - AutoCylPressurePSI)
422452
dp = threshold - AutoCylPressurePSI;
423-
if (AutoCylPressurePSI + dp > MaxCylPressurePSI)
424-
dp = MaxCylPressurePSI - AutoCylPressurePSI;
453+
if (AutoCylPressurePSI + dp > MaxTripleValveCylPressurePSI)
454+
dp = MaxTripleValveCylPressurePSI - AutoCylPressurePSI;
425455
if (BrakeLine1PressurePSI > AuxResPressurePSI - dp / AuxCylVolumeRatio && !BleedOffValveOpen)
426456
dp = (AuxResPressurePSI - BrakeLine1PressurePSI) * AuxCylVolumeRatio;
427457
if (dp < 0)
@@ -527,11 +557,12 @@ public override void Update(float elapsedClockSeconds)
527557
if (AutoCylPressurePSI < 0)
528558
AutoCylPressurePSI = 0;
529559

530-
if (Car is MSTSLocomotive && (Car as MSTSWagon).BrakeValve == MSTSWagon.BrakeValveType.DistributingValve)
560+
float demandedPressurePSI = 0;
561+
var loco = Car as MSTSLocomotive;
562+
if (loco != null && (Car as MSTSWagon).BrakeValve == MSTSWagon.BrakeValveType.DistributingValve)
531563
{
532564
// For distributing valves, we use AutoCylPressurePSI as "Application Chamber/Pipe" pressure
533565
// CylPressurePSI is the actual pressure applied to cylinders
534-
var loco = Car as MSTSLocomotive;
535566
var engineBrakeStatus = loco.EngineBrakeController.Notches[loco.EngineBrakeController.CurrentNotch].Type;
536567
var trainBrakeStatus = loco.TrainBrakeController.Notches[loco.TrainBrakeController.CurrentNotch].Type;
537568
// BailOff
@@ -544,8 +575,8 @@ public override void Update(float elapsedClockSeconds)
544575
if (trainBrakeStatus == ControllerState.Emergency)
545576
{
546577
float dp = elapsedClockSeconds * MaxApplicationRatePSIpS;
547-
if (dp > MaxCylPressurePSI - AutoCylPressurePSI)
548-
dp = MaxCylPressurePSI - AutoCylPressurePSI;
578+
if (dp > MaxCylPressurePSI / RelayValveRatio - AutoCylPressurePSI)
579+
dp = MaxCylPressurePSI / RelayValveRatio - AutoCylPressurePSI;
549580
AutoCylPressurePSI += dp;
550581
}
551582
// Release pipe open
@@ -558,15 +589,13 @@ public override void Update(float elapsedClockSeconds)
558589
loco.Train.BrakeLine3PressurePSI = AutoCylPressurePSI;
559590

560591
// Equalization between application chamber and brake cylinders
561-
// TODO: Drain air from main reservoir
562-
CylPressurePSI = AutoCylPressurePSI;
592+
demandedPressurePSI = AutoCylPressurePSI;
563593
}
564594
else
565595
{
566-
if (Car is MSTSLocomotive loco && loco.EngineType != TrainCar.EngineTypes.Control) // TODO - Control cars ned to be linked to power suppy requirements.
596+
demandedPressurePSI = Math.Max(AutoCylPressurePSI, BrakeLine3PressurePSI);
597+
if (loco != null && loco.EngineType != TrainCar.EngineTypes.Control) // TODO - Control cars ned to be linked to power suppy requirements.
567598
{
568-
float demandedPressurePSI = Math.Max(AutoCylPressurePSI, BrakeLine3PressurePSI);
569-
// if (Car is MSTSLocomotive loco && loco.LocomotivePowerSupply.MainPowerSupplyOn)
570599
if (loco.LocomotivePowerSupply.MainPowerSupplyOn)
571600
{
572601
if (loco.Train.LeadLocomotiveIndex >= 0)
@@ -600,6 +629,7 @@ public override void Update(float elapsedClockSeconds)
600629
{
601630
demandedPressurePSI = CylPressurePSI;
602631
}
632+
demandedPressurePSI /= RelayValveRatio;
603633
if (demandedPressurePSI < BrakeLine3PressurePSI)
604634
demandedPressurePSI = BrakeLine3PressurePSI;
605635
}
@@ -621,34 +651,35 @@ public override void Update(float elapsedClockSeconds)
621651
}
622652
}
623653
}
624-
// TODO: this first clause is intended for locomotives fitted with some sort of proportional valve
625-
// i.e. the triple valve is not directly attached to the physical brake cylinder
626-
// This allows e.g. blending, variable load, or higher pressures than provided by triple valves
627-
if (loco.DynamicBrakeAutoBailOff || loco.DynamicBrakeAutoBailOff)
628-
{
629-
if (demandedPressurePSI > CylPressurePSI)
630-
{
631-
float dp = elapsedClockSeconds * loco.EngineBrakeApplyRatePSIpS;
632-
if (dp > demandedPressurePSI - CylPressurePSI)
633-
dp = demandedPressurePSI - CylPressurePSI;
634-
/* TODO: Proportional valves need air from the main reservoir
635-
if (BrakeLine2PressurePSI - dp * AuxBrakeLineVolumeRatio / AuxCylVolumeRatio < CylPressurePSI + dp)
636-
dp = (BrakeLine2PressurePSI - CylPressurePSI) / (1 + AuxBrakeLineVolumeRatio / AuxCylVolumeRatio);
637-
BrakeLine2PressurePSI -= dp * AuxBrakeLineVolumeRatio / AuxCylVolumeRatio;*/
638-
CylPressurePSI += dp;
639-
}
640-
else if (demandedPressurePSI < CylPressurePSI) CylPressurePSI = Math.Max(demandedPressurePSI, CylPressurePSI - elapsedClockSeconds * loco.EngineBrakeReleaseRatePSIpS);
641-
}
642-
else // Rest of cases
654+
}
655+
}
656+
if (RelayValveFitted)
657+
{
658+
demandedPressurePSI *= RelayValveRatio;
659+
if (demandedPressurePSI > CylPressurePSI)
660+
{
661+
float dp = elapsedClockSeconds * RelayValveApplicationRatePSIpS;
662+
if (dp > demandedPressurePSI - CylPressurePSI)
663+
dp = demandedPressurePSI - CylPressurePSI;
664+
if (TwoPipes)
643665
{
644-
CylPressurePSI = Math.Max(AutoCylPressurePSI, BrakeLine3PressurePSI);
666+
if (BrakeLine2PressurePSI - dp * AuxBrakeLineVolumeRatio / AuxCylVolumeRatio < CylPressurePSI + dp)
667+
dp = (BrakeLine2PressurePSI - CylPressurePSI) / (1 + AuxBrakeLineVolumeRatio / AuxCylVolumeRatio);
668+
BrakeLine2PressurePSI -= dp * AuxBrakeLineVolumeRatio / AuxCylVolumeRatio;
645669
}
670+
if (MaxCylPressurePSI < CylPressurePSI + dp)
671+
dp = MaxCylPressurePSI - CylPressurePSI;
672+
CylPressurePSI += dp;
646673
}
647-
else
674+
else if (demandedPressurePSI < CylPressurePSI)
648675
{
649-
CylPressurePSI = Math.Max(AutoCylPressurePSI, BrakeLine3PressurePSI);
676+
CylPressurePSI = Math.Max(Math.Max(demandedPressurePSI, CylPressurePSI - elapsedClockSeconds * RelayValveReleaseRatePSIpS), 0);
650677
}
651678
}
679+
else
680+
{
681+
CylPressurePSI = demandedPressurePSI;
682+
}
652683

653684
// During braking wheelslide control is effected throughout the train by additional equipment on each vehicle. In the piping to each pair of brake cylinders are fitted electrically operated
654685
// dump valves. When axle rotations which are sensed electrically, differ by a predetermined speed the dump valves are operated releasing brake cylinder pressure to both axles of the affected
@@ -670,7 +701,6 @@ public override void Update(float elapsedClockSeconds)
670701
{
671702
Car.WheelBrakeSlideProtectionActive = true;
672703
AutoCylPressurePSI -= elapsedClockSeconds * MaxReleaseRatePSIpS;
673-
CylPressurePSI = AutoCylPressurePSI;
674704
Car.WheelBrakeSlideProtectionTimerS -= elapsedClockSeconds;
675705

676706
// Lockout WSP dump valve if it is open for greater then 7 seconds continuously

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public override void Update(float elapsedClockSeconds)
9797
}
9898
else
9999
{
100-
demandedAutoCylPressurePSI = Math.Min(Math.Max(Car.Train.BrakeLine4, 0), 1) * MaxCylPressurePSI;
100+
demandedAutoCylPressurePSI = Math.Min(Math.Max(Car.Train.BrakeLine4, 0), 1) * MaxTripleValveCylPressurePSI;
101101
HoldingValve = AutoCylPressurePSI <= demandedAutoCylPressurePSI ? ValveState.Lap : ValveState.Release;
102102
}
103103

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public override void Update(float elapsedClockSeconds)
5656
}
5757
else
5858
{
59-
demandedAutoCylPressurePSI = Math.Min(Math.Max(Car.Train.BrakeLine4, 0), 1) * MaxCylPressurePSI;
59+
demandedAutoCylPressurePSI = Math.Min(Math.Max(Car.Train.BrakeLine4, 0), 1) * MaxTripleValveCylPressurePSI;
6060
HoldingValve = AutoCylPressurePSI <= demandedAutoCylPressurePSI ? ValveState.Lap : ValveState.Release;
6161
}
6262

0 commit comments

Comments
 (0)