Skip to content

Commit e626a4f

Browse files
committed
Fix initialization not working correctly after first pass
1 parent 6b9fca4 commit e626a4f

File tree

1 file changed

+66
-55
lines changed
  • Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/Brakes/MSTS

1 file changed

+66
-55
lines changed

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

Lines changed: 66 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -602,70 +602,81 @@ public override void Initialize()
602602
CylAreaM2 = (float)((Math.PI * (CylDiameterM * CylDiameterM) / 4.0f));
603603
CylVolumeM3 = CylAreaM2 * CylStrokeM;
604604

605-
// Estimate the piping volume that results in the intended full service cylinder pressure
606-
if (CylPipeVolumeM3 <= 0 && AuxCylVolumeRatio > 0)
605+
// Estimate the piping volume if it has not been defined yet
606+
// Piping volume cannot be 0 as this can cause division by 0
607+
if (CylPipeVolumeM3 <= 0)
607608
{
608-
// Assuming 70 psi as brake pipe pressure
609-
float nomPipePressurePSI = 70.0f;
610-
float nomCylPressurePSI = nomPipePressurePSI * (AuxCylVolumeRatio / (AuxCylVolumeRatio + 1.0f));
611-
612-
float tempPipeVolumeM3 = (-(CylVolumeM3 * OneAtmospherePSI) - nomCylPressurePSI * (CylVolumeM3 + AuxResVolumeM3) + (nomPipePressurePSI * AuxResVolumeM3))
613-
/ (CylCount * nomCylPressurePSI);
614-
615-
CylPipeVolumeM3 = Math.Max(tempPipeVolumeM3, 0.05f * CylVolumeM3);
616-
617-
// Produce a warning if the brake configuration will be unable to achieve desired pressure due to aux res too small
618-
// If car has a supply res or a main res, aux res size doesn't matter
619-
if (tempPipeVolumeM3 < 0.05f * CylVolumeM3 && !((Car as MSTSWagon).SupplyReservoirPresent || Car is MSTSLocomotive))
620-
Trace.TraceWarning($"Auxiliary reservoir on car {Car.WagFilePath} appears to be too small for the brake cylinder(s). " +
621-
$"Consider increasing the auxiliary reservoir size, reducing cylinder size, or using a supply reservoir to provide sufficient cylinder pressures.");
609+
if (AuxCylVolumeRatio > 0 && !((Car as MSTSWagon).SupplyReservoirPresent || Car is MSTSLocomotive))
610+
{ // User has defined a triple valve ratio and the cylinder will be drawing air from the aux res
611+
// Set piping volume to produce expected pressure for the triple valve ratio
612+
// Assuming 70 psi as brake pipe pressure
613+
float nomPipePressurePSI = 70.0f;
614+
float nomCylPressurePSI = nomPipePressurePSI * (AuxCylVolumeRatio / (AuxCylVolumeRatio + 1.0f));
615+
616+
float tempPipeVolumeM3 = (-(CylVolumeM3 * OneAtmospherePSI) - nomCylPressurePSI * (CylVolumeM3 + AuxResVolumeM3) + (nomPipePressurePSI * AuxResVolumeM3))
617+
/ (CylCount * nomCylPressurePSI);
618+
619+
// Piping volume must be at least 5% of full cylinder volume
620+
CylPipeVolumeM3 = Math.Max(tempPipeVolumeM3, 0.05f * CylVolumeM3);
621+
622+
// Produce a warning if the brake configuration will be unable to achieve desired pressure due to aux res too small
623+
// If car has a supply res or a main res, aux res size doesn't matter
624+
if (tempPipeVolumeM3 < 0.05f * CylVolumeM3)
625+
Trace.TraceWarning($"Auxiliary reservoir on car {Car.WagFilePath} appears to be too small for the brake cylinder(s). " +
626+
$"Consider increasing the auxiliary reservoir size, reducing cylinder size, or using a supply reservoir to provide sufficient cylinder pressures.");
627+
}
628+
else // Assume piping volume is 20% of full cylinder volume
629+
CylPipeVolumeM3 = 0.20f * CylVolumeM3;
622630
}
623631

624632
// Advanced brake cylinder sim needs a spring pressure defined, otherwise it can remain 0
625633
if (BrakeCylinderSpringPressurePSI <= 0)
626634
BrakeCylinderSpringPressurePSI = 5.0f;
627635

628636
// Precalculate the relationship between air in cylinder lines and cylinder travel
637+
if (CylTravelTab == null) // May have been initialized already
638+
{
639+
// Assumptions from PRR characteristic curve:
640+
// pg 40: https://ia600906.us.archive.org/24/items/braketestsreport00penn/braketestsreport00penn.pdf
641+
// Brake cylinder reaches rated travel at 50 psi
642+
// Brake cylinder travel is 80% of nominal when pressure reaches the spring counter-pressure
643+
// Other assumptions:
644+
// Brake cylinder travel remains at 0 until reaching half the spring counter-pressure
645+
// Brake cylinder travel is linear w.r.t. total air in the cylinder line, not entirely accurate but greatly simplifies code
646+
float[] airPV = new float[5];
647+
float[] cylTravel = new float[5];
648+
649+
float nomPSI = 50.0f;
650+
651+
// Prevent interpolator error. Max cyl pressure and nominal pressure need to be slightly offset
652+
if (ReferencePressurePSI == nomPSI)
653+
nomPSI -= 5.0f;
654+
// Prevent interpolator error. Spring pressure should never be this large
655+
if (BrakeCylinderSpringPressurePSI >= nomPSI)
656+
BrakeCylinderSpringPressurePSI = nomPSI - 5.0f;
657+
658+
// 0 cylinder travel with 0 air in cylinder
659+
cylTravel[0] = 0;
660+
airPV[0] = AdvancedBrakeCylinderAir(0, true);
661+
// 0 cylinder travel when pressure is insufficient to budge spring
662+
cylTravel[1] = 0;
663+
airPV[1] = AdvancedBrakeCylinderAir(BrakeCylinderSpringPressurePSI / 2.0f, true);
664+
// 80% cylinder travel when spring pressure is fully overcome
665+
cylTravel[2] = CylStrokeM * 0.8f;
666+
airPV[2] = AdvancedBrakeCylinderAir(BrakeCylinderSpringPressurePSI, true);
667+
// 100% cylinder travel at 50 psi, with linear change in travel between 50 psi and max pressure
668+
// This will work whether the max cylinder pressure is above or below 50 psi
669+
float strokePerPsi = (CylStrokeM - cylTravel[2]) / (50.0f - BrakeCylinderSpringPressurePSI);
670+
671+
cylTravel[3] = (strokePerPsi * (Math.Min(nomPSI, ReferencePressurePSI) - 50.0f)) + CylStrokeM;
672+
airPV[3] = AdvancedBrakeCylinderAir(Math.Min(nomPSI, ReferencePressurePSI), true);
673+
674+
cylTravel[4] = (strokePerPsi * (Math.Max(nomPSI, ReferencePressurePSI) - 50.0f)) + CylStrokeM;
675+
airPV[4] = AdvancedBrakeCylinderAir(Math.Max(nomPSI, ReferencePressurePSI), true);
676+
677+
CylTravelTab = new Interpolator(airPV, cylTravel);
629678

630-
// Assumptions from PRR characteristic curve:
631-
// pg 40: https://ia600906.us.archive.org/24/items/braketestsreport00penn/braketestsreport00penn.pdf
632-
// Brake cylinder reaches rated travel at 50 psi
633-
// Brake cylinder travel is 80% of nominal when pressure reaches the spring counter-pressure
634-
// Other assumptions:
635-
// Brake cylinder travel remains at 0 until reaching half the spring counter-pressure
636-
// Brake cylinder travel is linear w.r.t. total air in the cylinder line, not entirely accurate but greatly simplifies code
637-
float[] airPV = new float[5];
638-
float[] cylTravel = new float[5];
639-
640-
float nomPSI = 50.0f;
641-
642-
// Prevent interpolator error. Max cyl pressure and nominal pressure need to be slightly offset
643-
if (ReferencePressurePSI == nomPSI)
644-
nomPSI -= 5.0f;
645-
// Prevent interpolator error. Spring pressure should never be this large
646-
if (BrakeCylinderSpringPressurePSI >= nomPSI)
647-
BrakeCylinderSpringPressurePSI = nomPSI - 5.0f;
648-
649-
// 0 cylinder travel with 0 air in cylinder
650-
cylTravel[0] = 0;
651-
airPV[0] = AdvancedBrakeCylinderAir(0, true);
652-
// 0 cylinder travel when pressure is insufficient to budge spring
653-
cylTravel[1] = 0;
654-
airPV[1] = AdvancedBrakeCylinderAir(BrakeCylinderSpringPressurePSI / 2.0f, true);
655-
// 80% cylinder travel when spring pressure is fully overcome
656-
cylTravel[2] = CylStrokeM * 0.8f;
657-
airPV[2] = AdvancedBrakeCylinderAir(BrakeCylinderSpringPressurePSI, true);
658-
// 100% cylinder travel at 50 psi, with linear change in travel between 50 psi and max pressure
659-
// This will work whether the max cylinder pressure is above or below 50 psi
660-
float strokePerPsi = (CylStrokeM - cylTravel[2]) / (50.0f - BrakeCylinderSpringPressurePSI);
661-
662-
cylTravel[3] = (strokePerPsi * (Math.Min(nomPSI, ReferencePressurePSI) - 50.0f)) + CylStrokeM;
663-
airPV[3] = AdvancedBrakeCylinderAir(Math.Min(nomPSI, ReferencePressurePSI), true);
664-
665-
cylTravel[4] = (strokePerPsi * (Math.Max(nomPSI, ReferencePressurePSI) - 50.0f)) + CylStrokeM;
666-
airPV[4] = AdvancedBrakeCylinderAir(Math.Max(nomPSI, ReferencePressurePSI), true);
667-
668-
CylTravelTab = new Interpolator(airPV, cylTravel);
679+
}
669680
}
670681
if (CylVolumeM3 <= 0 && AuxCylVolumeRatio > 0)
671682
CylVolumeM3 = AuxResVolumeM3 / AuxCylVolumeRatio / CylCount;

0 commit comments

Comments
 (0)