Skip to content

Commit d6bd4e3

Browse files
committed
European brake mass calculations
1 parent 8566519 commit d6bd4e3

File tree

5 files changed

+66
-16
lines changed

5 files changed

+66
-16
lines changed

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

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,13 @@ public void Load()
381381
float LoadFullRelayValveRatio;
382382
float LoadFullInshotPSI;
383383

384+
// Used to avoid unnecessary brake mode changes. No need to Copy/Save/Restore them
385+
BrakeModes PrevBrakeMode;
386+
float PrevBrakeMass = -1;
387+
388+
// These settings may preceed the brake system type definition, which would cause them not to be parsed, that's why this workaround is needed.
389+
(float MaxBrakeForceN, float MaxHandbrakeForceN, float MaxBrakeShoeForceN) ParsetimeBrakeForces;
390+
384391
/// <summary>
385392
/// This initializer is called when we haven't loaded this type of car before
386393
/// and must read it new from the wag file.
@@ -642,11 +649,38 @@ public virtual void LoadFromWagFile(string wagFilePath)
642649
if (!BrakeModeNames.Contains(key.BrakeMode.ToString()))
643650
BrakeSystems.Remove(key);
644651
}
645-
else
652+
BrakeModeNames = BrakeSystems.Keys.Select(k => k.BrakeMode.ToString()).Distinct().ToArray();
653+
BrakeSystem = BrakeSystem ?? MSTSBrakeSystem.Create(CarBrakeSystemType, this);
654+
655+
BrakeSystem.InitialMaxBrakeForceN = ParsetimeBrakeForces.MaxBrakeForceN;
656+
BrakeSystem.InitialMaxHandbrakeForceN = ParsetimeBrakeForces.MaxHandbrakeForceN;
657+
BrakeSystem.MaxBrakeShoeForceN = ParsetimeBrakeForces.MaxBrakeShoeForceN;
658+
659+
if (BrakeSystem is AirSinglePipe airBrake)
646660
{
647-
BrakeModeNames = BrakeSystems.Keys.Select(k => k.ToString()).ToArray();
661+
if (BrakeSystems?.Count > 0)
662+
{
663+
foreach (var key in BrakeSystems.Keys)
664+
{
665+
if (BrakeSystems[key] is AirSinglePipe subSystem)
666+
{
667+
BrakeSystems.TryGetValue((BrakeModes.P, key.MinMass), out var pMode);
668+
var pModeBrakeMass = (pMode as AirSinglePipe)?.BrakeMass;
669+
if (subSystem.BrakeMass == 0 && (pModeBrakeMass == null || pModeBrakeMass == 0))
670+
{
671+
// We will reverse calculate the brake mass from the brake forces
672+
subSystem.MaxBrakeShoeForceN = BrakeSystem.MaxBrakeShoeForceN;
673+
subSystem.InitialMaxBrakeForceN = BrakeSystem.InitialMaxBrakeForceN;
674+
}
675+
subSystem.BrakeMassToShoeForce(pModeBrakeMass);
676+
}
677+
}
678+
}
679+
else
680+
{
681+
airBrake.BrakeMassToShoeForce(null);
682+
}
648683
}
649-
BrakeSystem = BrakeSystem ?? MSTSBrakeSystem.Create(CarBrakeSystemType, this);
650684

651685
var (brakeMode, maxMass) = BrakeSystems?.Count > 0 ? BrakeSystems.Keys.FirstOrDefault() : default;
652686
SetBrakeSystemMode(brakeMode, maxMass, forceSwitch: true);
@@ -988,6 +1022,8 @@ public virtual void LoadFromWagFile(string wagFilePath)
9881022
hiStageAir.RelayValveRatio = LoadFullRelayValveRatio;
9891023
loStageAir.RelayValveInshotPSI = LoadEmptyInshotPSI;
9901024
hiStageAir.RelayValveInshotPSI = LoadFullInshotPSI;
1025+
loStageAir.BrakeMassToShoeForce(null);
1026+
hiStageAir.BrakeMassToShoeForce(null);
9911027
}
9921028

9931029
BrakeSystems.Add((BrakeSystem.BrakeMode, LoadEmptyMassKg), loStage);
@@ -1008,9 +1044,12 @@ public virtual void LoadFromWagFile(string wagFilePath)
10081044

10091045
public void SetBrakeSystemMode(BrakeModes mode, float massKg, bool forceSwitch = false)
10101046
{
1011-
if (Math.Abs(SpeedMpS) > .1 && !forceSwitch)
1047+
if ((Math.Abs(SpeedMpS) > 0.1 || mode == PrevBrakeMode && massKg == PrevBrakeMass) && !forceSwitch)
10121048
return;
10131049

1050+
PrevBrakeMode = mode;
1051+
PrevBrakeMass = massKg;
1052+
10141053
if (BrakeSystems?.Count > 0)
10151054
{
10161055
// 1) First get the values from the zero load stage / base stage
@@ -1025,7 +1064,7 @@ public void SetBrakeSystemMode(BrakeModes mode, float massKg, bool forceSwitch =
10251064
foreach (var key in BrakeSystems.Keys)
10261065
if (key.BrakeMode == mode && key.MinMass <= massKg)
10271066
max = Math.Max(max, key.MinMass);
1028-
if ((BrakeSystem.BrakeMode, BrakeSystem.LoadStageMinMassKg) != (mode, max) && BrakeSystems.TryGetValue((mode, max), out brakeSystem))
1067+
if (BrakeSystems.TryGetValue((mode, max), out brakeSystem))
10291068
{
10301069
HandleIncompatibleBrakesystems(brakeSystem);
10311070
BrakeSystem.InitializeFromCopy(brakeSystem, true);
@@ -1327,6 +1366,9 @@ public virtual void Parse(string lowercasetoken, STFReader stf)
13271366
FrictionE2 = stf.ReadFloat(STFReader.UNITS.None, null);
13281367
stf.SkipRestOfBlock();
13291368
; break;
1369+
case "wagon(maxbrakeforce": ParsetimeBrakeForces.MaxBrakeForceN = stf.ReadFloatBlock(STFReader.UNITS.Force, null); break;
1370+
case "wagon(maxhandbrakeforce": ParsetimeBrakeForces.MaxHandbrakeForceN = stf.ReadFloatBlock(STFReader.UNITS.Force, null); break;
1371+
case "wagon(ortsmaxbrakeshoeforce": ParsetimeBrakeForces.MaxBrakeShoeForceN = stf.ReadFloatBlock(STFReader.UNITS.Force, null); break;
13301372
case "wagon(brakesystemtype":
13311373
CarBrakeSystemType = stf.ReadStringBlock(null).ToLower();
13321374
BrakeSystem = MSTSBrakeSystem.Create(CarBrakeSystemType, this);

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

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ public enum BrakeValveType
164164
protected float BrakePipeChangePSIpS;
165165
protected SmoothedData SmoothedBrakePipeChangePSIpS;
166166

167-
protected float BrakeMass;
167+
public float BrakeMass;
168168

169169
/// <summary>
170170
/// EP brake holding valve. Needs to be closed (Lap) in case of brake application or holding.
@@ -409,8 +409,8 @@ public override string[] GetDebugStatus(Dictionary<BrakeSystemComponent, Pressur
409409
FrontBrakeHoseConnected ? "I" : "T",
410410
string.Format("A{0} B{1}", AngleCockAOpenAmount >= 1 ? "+" : AngleCockAOpenAmount <= 0 ? "-" : "/", AngleCockBOpenAmount >= 1 ? "+" : AngleCockBOpenAmount <= 0 ? "-" : "/"),
411411
BleedOffValveOpen ? Simulator.Catalog.GetString("Open") : string.Empty,
412+
string.Format("{0}t-{1}%", (int)Kg.ToTonne(BrakeMass), GetBrakePercent()),
412413
};
413-
414414
}
415415

416416
public override float GetCylPressurePSI()
@@ -564,9 +564,9 @@ public override void Parse(string lowercasetoken, STFReader stf)
564564
case "wagon(ortssupplyrescapacity": SupplyResVolumeM3 = Me3.FromFt3(stf.ReadFloatBlock(STFReader.UNITS.VolumeDefaultFT3, null)); break;
565565
case "engine(ortssupplyreschargingrate":
566566
case "wagon(ortssupplyreschargingrate": SupplyResChargingRatePSIpS = stf.ReadFloatBlock(STFReader.UNITS.PressureRateDefaultPSIpS, null); break;
567-
case "wagon(ortsmaxbrakeshoeforce": MaxBrakeShoeForceN = stf.ReadFloatBlock(STFReader.UNITS.Force, null); break;
568-
case "wagon(maxhandbrakeforce": InitialMaxHandbrakeForceN = stf.ReadFloatBlock(STFReader.UNITS.Force, null); break;
569567
case "wagon(maxbrakeforce": InitialMaxBrakeForceN = stf.ReadFloatBlock(STFReader.UNITS.Force, null); break;
568+
case "wagon(maxhandbrakeforce": InitialMaxHandbrakeForceN = stf.ReadFloatBlock(STFReader.UNITS.Force, null); break;
569+
case "wagon(ortsmaxbrakeshoeforce": MaxBrakeShoeForceN = stf.ReadFloatBlock(STFReader.UNITS.Force, null); break;
570570
case "wagon(ortsbrakemass": BrakeMass = stf.ReadFloatBlock(STFReader.UNITS.Mass, null); break;
571571
}
572572
}
@@ -2596,7 +2596,7 @@ public void BrakeMassToShoeForce(float? brakeMassWithoutAccelerator)
25962596
if (Car == null)
25972597
return;
25982598

2599-
if (MaxBrakeShoeForceN > 0)
2599+
if (MaxBrakeShoeForceN > 0 && BrakeMass > 0)
26002600
{
26012601
Trace.TraceInformation("Brake mode {0}-{1} has both BrakeMass and MaxBrakeShoeForceN set. BrakeMass will be ignored: {2}", BrakeMode, LoadStageMinMassKg, Car.WagFilePath);
26022602
return;
@@ -2652,9 +2652,16 @@ public void BrakeMassToShoeForce(float? brakeMassWithoutAccelerator)
26522652
else
26532653
{
26542654
var force = MaxBrakeShoeForceN > 0 ? MaxBrakeShoeForceN : InitialMaxBrakeForceN;
2655-
var brakePercentage = MathHelper.Clamp((force / referenceMass / 10 + d - c * referenceSpeed) / (a - b * referenceSpeed), 40, 250);
2656-
BrakeMass = referenceMass * brakePercentage / 100;
2655+
var brakePercentage = MathHelper.Clamp((force / referenceMass / 10 + d - c * referenceSpeed) / (a - b * referenceSpeed), 0, 250);
2656+
BrakeMass = Kg.FromTonne(referenceMass) * brakePercentage / 100;
2657+
if (modeIsAccelerated)
2658+
BrakeMass /= 0.7f;
26572659
}
26582660
}
2661+
2662+
public float GetBrakePercent()
2663+
{
2664+
return (int)MathHelper.Clamp(BrakeMass / Car.MassKG * 100, 0, 250);
2665+
}
26592666
}
26602667
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,9 +307,9 @@ public override void Parse(string lowercasetoken, STFReader stf)
307307
case "wagon(ortsbrakecylinderdiameter": CylDiameterM = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); break;
308308
case "wagon(ortsbrakecylinderpistontravel": CylStrokeM = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); break;
309309
case "wagon(ortsnumberbrakecylinders": CylCount = stf.ReadIntBlock(null); break;
310-
case "wagon(ortsmaxbrakeshoeforce": MaxBrakeShoeForceN = stf.ReadFloatBlock(STFReader.UNITS.Force, null); break;
311-
case "wagon(maxhandbrakeforce": InitialMaxHandbrakeForceN = stf.ReadFloatBlock(STFReader.UNITS.Force, null); break;
312310
case "wagon(maxbrakeforce": InitialMaxBrakeForceN = stf.ReadFloatBlock(STFReader.UNITS.Force, null); break;
311+
case "wagon(maxhandbrakeforce": InitialMaxHandbrakeForceN = stf.ReadFloatBlock(STFReader.UNITS.Force, null); break;
312+
case "wagon(ortsmaxbrakeshoeforce": MaxBrakeShoeForceN = stf.ReadFloatBlock(STFReader.UNITS.Force, null); break;
313313
}
314314
}
315315

Source/RunActivity/Viewer3D/Popups/CarOperationsWindow.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public bool RearBrakeHoseChanged
5858
set;
5959
get;
6060
}
61-
protected override ControlLayout Layout(ControlLayout layout)
61+
protected override ControlLayout Layout(ControlLayout layout)
6262
{
6363
Label ID, buttonHandbrake, buttonTogglePower, buttonToggleMU, buttonToggleBatterySwitch, buttonToggleElectricTrainSupplyCable, buttonToggleFrontBrakeHose, buttonToggleRearBrakeHose, buttonToggleAngleCockA, buttonToggleAngleCockB, buttonToggleBleedOffValve, buttonClose;
6464

Source/RunActivity/Viewer3D/Popups/HUDWindow.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1125,7 +1125,8 @@ void TextPageBrakeInfo(TableData table)
11251125
Viewer.Catalog.GetString("Handbrk"),
11261126
Viewer.Catalog.GetString("Conn"),
11271127
Viewer.Catalog.GetString("AnglCock"),
1128-
Viewer.Catalog.GetString("BleedOff"));
1128+
Viewer.Catalog.GetString("BleedOff"),
1129+
Viewer.Catalog.GetString("BrkM-%"));
11291130
TableAddLine(table);
11301131

11311132
var n = train.Cars.Count; // Number of lines to show

0 commit comments

Comments
 (0)