From 476d67b9a6a27d836b459d99150f97a0a2ce144a Mon Sep 17 00:00:00 2001 From: peternewell Date: Tue, 20 Feb 2024 15:03:25 +1100 Subject: [PATCH] add hammer force calculations --- .../RollingStocks/MSTSSteamLocomotive.cs | 83 +++++++++++++------ .../SubSystems/PowerSupplies/SteamEngine.cs | 25 ++++++ 2 files changed, 83 insertions(+), 25 deletions(-) diff --git a/Source/Orts.Simulation/Simulation/RollingStocks/MSTSSteamLocomotive.cs b/Source/Orts.Simulation/Simulation/RollingStocks/MSTSSteamLocomotive.cs index 198744c08a..56911e2530 100644 --- a/Source/Orts.Simulation/Simulation/RollingStocks/MSTSSteamLocomotive.cs +++ b/Source/Orts.Simulation/Simulation/RollingStocks/MSTSSteamLocomotive.cs @@ -656,8 +656,6 @@ public class MSTSSteamLocomotive : MSTSLocomotive float ReciprocatingWeightLb = 580.0f; // Weight of reciprocating parts of the rod driving gears float ConnectingRodWeightLb = 600.0f; // Weignt of connecting rod - float ConnectingRodBalanceWeightLb = 300.0f; // Balance weight for connecting rods - float ExcessBalanceFactor = 400.0f; // Factor to be included in excess balance formula float CrankRadiusFt = 1.08f; // Assume crank and rod lengths to give a 1:10 ratio - a reasonable av for steam locomotives? float ConnectRodLengthFt = 10.8f; float RodCoGFt = 4.32f; // 0.4 from crank end of rod @@ -1229,25 +1227,6 @@ public override void Initialize() if (ZeroError(BoilerVolumeFT3, "BoilerVolume")) BoilerVolumeFT3 = 1; - // For light locomotives reduce the weight of the various connecting rods, as the default values are for larger locomotives. This will reduce slip on small locomotives - // It is not believed that the weight reduction on the connecting rods is linear with the weight of the locmotive. However this requires futher research, and this section is a - // work around until any further research is undertaken - // "The following code provides a simple 2-step adjustment, as not enough information is currently available for a more flexible one." - if (MassKG < Kg.FromTUS(10)) - { - const float reductionfactor = 0.2f; - ReciprocatingWeightLb = 580.0f * reductionfactor; // Weight of reciprocating parts of the rod driving gears - ConnectingRodWeightLb = 600.0f * reductionfactor; // Weignt of connecting rod - ConnectingRodBalanceWeightLb = 300.0f * reductionfactor; // Balance weight for connecting rods - } - else if (MassKG < Kg.FromTUS(20)) - { - const float reductionfactor = 0.3f; - ReciprocatingWeightLb = 580.0f * reductionfactor; // Weight of reciprocating parts of the rod driving gears - ConnectingRodWeightLb = 600.0f * reductionfactor; // Weignt of connecting rod - ConnectingRodBalanceWeightLb = 300.0f * reductionfactor; // Balance weight for connecting rods - } - #region Initialise additional steam properties WaterDensityPSItoLBpFT3 = SteamTable.WaterDensityInterpolatorPSItoLBpFT3(); @@ -2020,6 +1999,26 @@ public override void Initialize() SteamEngines[i].MaxIndicatedHorsePowerHP = MaxSpeedFactor * (SteamEngines[i].MaxTractiveEffortLbf * MaxLocoSpeedMpH) / 375.0f; // To be checked what MaxTractive Effort is for the purposes of this formula. MaxIndicatedHorsePowerHP += SteamEngines[i].MaxIndicatedHorsePowerHP; } + + if (SteamEngines[i].ExcessWheelBalanceLbs == 0) + { + SteamEngines[i].ExcessWheelBalanceLbs = 440f; // set to a default value. + } + + // For light locomotives reduce the weight of the various connecting rods, as the default values are for larger locomotives. This will reduce slip on small locomotives + // It is not believed that the weight reduction on the connecting rods is linear with the weight of the locmotive. However this requires futher research, and this section is a + // work around until any further research is undertaken + // "The following code provides a simple 2-step adjustment, as not enough information is currently available for a more flexible one." + if (MassKG < Kg.FromTUS(10)) + { + const float reductionfactor = 0.2f; + SteamEngines[i].ExcessWheelBalanceLbs *= reductionfactor; + } + else if (MassKG < Kg.FromTUS(20)) + { + const float reductionfactor = 0.3f; + SteamEngines[i].ExcessWheelBalanceLbs *= reductionfactor; + } } // Check to see if MaxIHP is in fact limited by the boiler @@ -5981,8 +5980,39 @@ private void UpdateSteamTractiveForce(float elapsedClockSeconds, float locomotiv float verticalThrustForcelbf = effectiveRotationalForcelbf * verticalThrustFactor; // Calculate Excess Balance - float excessBalanceWeightLb = (ConnectingRodWeightLb + ReciprocatingWeightLb) - ConnectingRodBalanceWeightLb - (Kg.ToLb(MassKG) / ExcessBalanceFactor); - float excessBalanceForcelbf = inertiaSpeedCorrectionFactor * excessBalanceWeightLb * sin; + float excessBalanceForcelbf = inertiaSpeedCorrectionFactor * SteamEngines[numberofengine].ExcessWheelBalanceLbs * sin; + + // Hammer (dynamic) force due to the rotation of the wheels is calculated + // From The Steam Locomotive by Ralph Johnson (pg 276 ) - + // Hammer force = 1.6047 x stroke (ins) x excessbalancemass (lbf) x speed^2 (mph) / ( Dia of drive wheel^2 (ins)) - This is per wheel + // The excess balance weight is on one side of the locomotive, is spread evenly over the number of wheels (this is not always the + // case for prototypical locomotives) + + if (SteamEngines[numberofengine].AuxiliarySteamEngineType != SteamEngine.AuxiliarySteamEngineTypes.Booster) + { + SteamEngines[numberofengine].HammerForceLbs = (1.6047f * Me.ToIn(SteamEngines[numberofengine].CylindersStrokeM) * SteamEngines[numberofengine].ExcessWheelBalanceLbs * (float)Math.Pow(MpS.ToMpH(absSpeedMpS), 2)) / ((float)Math.Pow(Me.ToIn(2.0f * SteamEngines[numberofengine].AttachedAxle.WheelRadiusM), 2) * SteamEngines[numberofengine].AttachedAxle.NumWheelsetAxles); + + // weight on each individual wheel, rather then each axle + var wheelWeight = SteamEngines[numberofengine].AttachedAxle.WheelWeightKg / (SteamEngines[numberofengine].AttachedAxle.NumWheelsetAxles * 2f); + + if (SteamEngines[numberofengine].HammerForceLbs > wheelWeight) + { + SteamEngines[numberofengine].IsWheelHammerForce = true; + } + else + { + SteamEngines[numberofengine].IsWheelHammerForce = false; + } + + if (SteamEngines[numberofengine].HammerForceLbs > 0.9 * wheelWeight) + { + SteamEngines[numberofengine].IsWheelHammerForceWarning = true; + } + else + { + SteamEngines[numberofengine].IsWheelHammerForceWarning = false; + } + } // Account for the position of the crosshead position. In other words it depends upon whether the ExcessBalance is above or below the axle. // The crosshead will be -ve for normalised angles between 0 - 180, and +ve for normalised angles between 180 - 360 @@ -7935,7 +7965,7 @@ public override string GetDebugStatus() { for (int i = 0; i < SteamEngines.Count; i++) { - status.AppendFormat("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7} \t{8:N0} {9}\n", + status.AppendFormat("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7} \t{8:N0} {9}\t{10} \t{11:N0}{12}\n", Simulator.Catalog.GetString("Force:"), Simulator.Catalog.GetString("Eng#"), i + 1, @@ -7945,7 +7975,10 @@ public override string GetDebugStatus() FormatStrings.FormatForce(SteamEngines[i].DisplayTractiveForceN, IsMetric), Simulator.Catalog.GetString("DrvWhl"), pS.TopM(SteamEngines[i].DriveWheelRevRpS), - FormatStrings.rpm + FormatStrings.rpm, + Simulator.Catalog.GetString("Hammer"), + FormatStrings.FormatForce(N.FromLbf(SteamEngines[i].HammerForceLbs), IsMetric), + SteamEngines[i].IsWheelHammerForce ? "!!!" : SteamEngines[i].IsWheelHammerForceWarning ? "???" : "" ); } diff --git a/Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/PowerSupplies/SteamEngine.cs b/Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/PowerSupplies/SteamEngine.cs index 608dbff947..8c1f79d984 100644 --- a/Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/PowerSupplies/SteamEngine.cs +++ b/Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/PowerSupplies/SteamEngine.cs @@ -366,6 +366,26 @@ public enum AuxiliarySteamEngineTypes /// public float MaxIndicatedHorsePowerHP; + /// + /// Steam Engine unbalanced mass on wheels - per side. + /// + public float ExcessWheelBalanceLbs; + + /// + /// Steam Engine unbalanced wheel warning. + /// + public bool IsWheelHammerForceWarning; + + /// + /// Steam Engine unbalanced large overload. + /// + public bool IsWheelHammerForce; + + /// + /// Steam Engine hammer force per wheel - excessive values of this could cause track deformities. + /// + public float HammerForceLbs; + /// /// Steam Engine drive wheel rev per second /// @@ -699,6 +719,10 @@ public virtual void Parse(STFReader stf) MaxIndicatedHorsePowerHP = stf.ReadFloatBlock(STFReader.UNITS.Power, null); MaxIndicatedHorsePowerHP = W.ToHp(MaxIndicatedHorsePowerHP); // Convert input to HP for use internally in this module break; + case "excesswheelbalance": + var excess = stf.ReadFloatBlock(STFReader.UNITS.Mass, null); + ExcessWheelBalanceLbs = Kg.ToLb(excess); // Convert input to lbs for use internally in this module + break; case "auxiliarysteamenginetype": stf.MustMatch("("); @@ -731,6 +755,7 @@ public void Copy(SteamEngine other) LPCylindersDiameterM = other.LPCylindersDiameterM; BoosterCutoff = other.BoosterCutoff; MaxIndicatedHorsePowerHP = other.MaxIndicatedHorsePowerHP; + ExcessWheelBalanceLbs = other.ExcessWheelBalanceLbs; BoosterThrottleCutoff = other.BoosterThrottleCutoff; BoosterGearRatio = other.BoosterGearRatio; AttachedAxleId = other.AttachedAxleId;