Skip to content

Commit cca2bd5

Browse files
committed
Further adjustments
1 parent d331d9d commit cca2bd5

File tree

5 files changed

+111
-68
lines changed

5 files changed

+111
-68
lines changed

Source/Orts.Simulation/Simulation/RollingStocks/MSTSControlTrailerCar.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ public override string GetStatus()
225225
/// <summary>
226226
/// This function updates periodically the locomotive's motive force.
227227
/// </summary>
228-
protected override void UpdateTractiveForce(float elapsedClockSeconds, float t, float AbsSpeedMpS, float AbsWheelSpeedMpS, int numberofengine)
228+
protected override void UpdateTractiveForce(float elapsedClockSeconds, float t, float AbsSpeedMpS, float AbsWheelSpeedMpS)
229229
{
230230
}
231231

Source/Orts.Simulation/Simulation/RollingStocks/MSTSDieselLocomotive.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,7 @@ protected override void UpdateControllers(float elapsedClockSeconds)
624624
/// <summary>
625625
/// This function updates periodically the locomotive's motive force.
626626
/// </summary>
627-
protected override void UpdateTractiveForce(float elapsedClockSeconds, float t, float AbsSpeedMpS, float AbsWheelSpeedMpS, int numberofengine)
627+
protected override void UpdateTractiveForce(float elapsedClockSeconds, float t, float AbsSpeedMpS, float AbsWheelSpeedMpS)
628628
{
629629
// This section calculates the motive force of the locomotive as follows:
630630
// Basic configuration (no TF table) - uses P = F /speed relationship - requires power and force parameters to be set in the ENG file.

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2012,7 +2012,7 @@ public override void Update(float elapsedClockSeconds)
20122012
// TODO this is a wild simplification for electric and diesel electric
20132013
if (EngineType == EngineTypes.Diesel || EngineType == EngineTypes.Electric)
20142014
{
2015-
UpdateTractiveForce(elapsedClockSeconds, ThrottlePercent / 100f, AbsSpeedMpS, AbsWheelSpeedMpS, 0);
2015+
UpdateTractiveForce(elapsedClockSeconds, ThrottlePercent / 100f, AbsSpeedMpS, AbsWheelSpeedMpS);
20162016
}
20172017

20182018
foreach (MultiPositionController mpc in MultiPositionControllers)
@@ -2375,7 +2375,7 @@ protected virtual void UpdateControllers(float elapsedClockSeconds)
23752375
/// <summary>
23762376
/// This function updates periodically the locomotive's motive force.
23772377
/// </summary>
2378-
protected virtual void UpdateTractiveForce(float elapsedClockSeconds, float t, float AbsSpeedMpS, float AbsWheelSpeedMpS, int numberofengine)
2378+
protected virtual void UpdateTractiveForce(float elapsedClockSeconds, float t, float AbsSpeedMpS, float AbsWheelSpeedMpS)
23792379
{
23802380
// Method to set force and power info
23812381
// An alternative method in the steam locomotive will override this and input force and power info for it.

Source/Orts.Simulation/Simulation/RollingStocks/MSTSSteamLocomotive.cs

Lines changed: 91 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -2203,8 +2203,6 @@ public override void Update(float elapsedClockSeconds)
22032203
UpdateAuxiliaries(elapsedClockSeconds, absSpeedMpS);
22042204
UpdateSuperHeat();
22052205

2206-
TractiveForceN = 0; // reset tractiveforceN in preparation to calculating a new value
2207-
MotiveForceN = 0;
22082206
CylinderSteamUsageLBpS = 0;
22092207
CylCockSteamUsageLBpS = 0;
22102208
MeanEffectivePressurePSI = 0;
@@ -2310,41 +2308,11 @@ public override void Update(float elapsedClockSeconds)
23102308
tractiveforcethrottle = throttle;
23112309
}
23122310

2313-
UpdateTractiveForce(elapsedClockSeconds, tractiveforcethrottle, 0, 0, i);
2314-
2315-
TractiveForceN += SteamEngines[i].TractiveForceN;
2316-
2317-
MotiveForceN += SteamEngines[i].AttachedAxle.CompensatedAxleForceN;
2318-
}
2311+
UpdateSteamTractiveForce(elapsedClockSeconds, tractiveforcethrottle, 0, 0, i);
23192312

2320-
// Find the maximum TE for debug i.e. @ start and full throttle
2321-
if (absSpeedMpS < 1.0)
2322-
{
2323-
if (Math.Abs(TractiveForceN) > absStartTractiveEffortN && Math.Abs(TractiveForceN) < MaxForceN)
2324-
{
2325-
absStartTractiveEffortN = Math.Abs(TractiveForceN); // update to new maximum TE
2326-
}
23272313
}
23282314

2329-
DisplayTractiveForceN = TractiveForceN;
2330-
2331-
MotiveForceSmoothN.Update(elapsedClockSeconds, MotiveForceN);
2332-
MotiveForceSmoothedN = MotiveForceSmoothN.SmoothedValue;
2333-
if (float.IsNaN(MotiveForceN))
2334-
MotiveForceN = 0;
2335-
2336-
DrawBarPullLbsF = N.ToLbf(Math.Abs(MotiveForceSmoothedN) - LocoTenderFrictionForceN); // Locomotive drawbar pull is equal to motive force of locomotive (+ tender) - friction forces of locomotive (+ tender)
2337-
DrawBarPullLbsF = MathHelper.Clamp(DrawBarPullLbsF, 0, DrawBarPullLbsF); // clamp value so it doesn't go negative
2338-
2339-
DrawbarHorsePowerHP = (DrawBarPullLbsF * MpS.ToMpH(absSpeedMpS)) / 375.0f; // TE in this instance is a maximum, and not at the wheel???
2340-
DrawbarHorsePowerHP = MathHelper.Clamp(DrawbarHorsePowerHP, 0, DrawbarHorsePowerHP); // clamp value so it doesn't go negative
2341-
2342-
2343-
// Calculate IHP
2344-
// IHP = (MEP x CylStroke(ft) x cylArea(sq in) x No Strokes (/min)) / 33000) - this is per cylinder
2345-
2346-
IndicatedHorsePowerHP = (N.ToLbf(MotiveForceSmoothedN) * pS.TopH(Me.ToMi(absSpeedMpS))) / 375.0f;
2347-
IndicatedHorsePowerHP = MathHelper.Clamp(IndicatedHorsePowerHP, 0, IndicatedHorsePowerHP);
2315+
UpdateTractiveForce(elapsedClockSeconds, ThrottlePercent / 100f, AbsSpeedMpS, AbsWheelSpeedMpS);
23482316

23492317
#endregion
23502318

@@ -5130,21 +5098,20 @@ private void UpdateCylinders(float elapsedClockSeconds, float throttle, float cu
51305098
SteamReleasePressure_AtmPSI = SteamEngines[numberofengine].Pressure_c_AtmPSI; // for steam and smoke effects
51315099

51325100
}
5133-
protected override void UpdateTractiveForce(float elapsedClockSeconds, float locomotivethrottle, float AbsSpeedMpS, float AbsWheelSpeedMpS, int numberofengine)
5134-
{
5135-
// Pass force and power information to MSTSLocomotive file by overriding corresponding method there
51365101

5137-
// Set Max Power equal to max IHP
5138-
MaxPowerW = W.FromHp(SteamEngines[numberofengine].MaxIndicatedHorsePowerHP);
51395102

5140-
// Set maximum force for the locomotive
5141-
MaxForceN = N.FromLbf(SteamEngines[numberofengine].MaxTractiveEffortLbf * CylinderEfficiencyRate);
5142-
5143-
// Set Max Velocity of locomotive
5144-
MaxSpeedMpS = Me.FromMi(pS.FrompH(MaxLocoSpeedMpH)); // Note this is not the true max velocity of the locomotive, but the speed at which max HP is reached
5103+
/// <summary>
5104+
/// Calculate the tractive forces for each steam engine
5105+
/// </summary>
5106+
private void UpdateSteamTractiveForce(float elapsedClockSeconds, float locomotivethrottle, float AbsSpeedMpS, float AbsWheelSpeedMpS, int numberofengine)
5107+
{
51455108

51465109
#region - Steam Adhesion Model Input for Steam Locomotives
51475110

5111+
// Caculate the current piston speed - purely for display purposes at the moment
5112+
// Piston Speed (Ft p Min) = (Stroke length x 2) x (Ft in Mile x Train Speed (mph) / ( Circum of Drv Wheel x 60))
5113+
SteamEngines[numberofengine].PistonSpeedFtpMin = Me.ToFt(pS.TopM(SteamEngines[numberofengine].CylindersStrokeM * 2.0f * DrvWheelRevRpS)) * SteamGearRatio;
5114+
51485115
// Based upon information presented on pg 276 of "Locomotive Operation - A Technical and Practical Analysis" by G. R. Henderson -
51495116
// https://archive.org/details/locomotiveoperat00hend/page/276/mode/2up
51505117
// At its simplest slip occurs when the wheel tangential force exceeds the static frictional force
@@ -5459,11 +5426,7 @@ protected override void UpdateTractiveForce(float elapsedClockSeconds, float loc
54595426
else // Adjust tractive force if "simple" friction is used, or is a geared steam locomotive
54605427
{
54615428
// This section updates the force calculations and maintains them at the current values.
5462-
5463-
// Caculate the current piston speed - purely for display purposes at the moment
5464-
// Piston Speed (Ft p Min) = (Stroke length x 2) x (Ft in Mile x Train Speed (mph) / ( Circum of Drv Wheel x 60))
5465-
PistonSpeedFtpMin = Me.ToFt(pS.TopM(SteamEngines[numberofengine].CylindersStrokeM * 2.0f * DrvWheelRevRpS)) * SteamGearRatio;
5466-
5429+
54675430
if (SteamEngineType == SteamEngineTypes.Compound)
54685431
{
54695432
// Calculate tractive effort if set for compounding - tractive effort in each cylinder will need to be calculated
@@ -5482,21 +5445,20 @@ protected override void UpdateTractiveForce(float elapsedClockSeconds, float loc
54825445
// Calculate IHP
54835446
// IHP = (MEP x Speed (mph)) / 375.0) - this is per cylinder
54845447

5485-
HPIndicatedHorsePowerHP = (HPTractiveEffortLbsF * pS.TopH(Me.ToMi(absSpeedMpS))) / 375.0f;
5486-
LPIndicatedHorsePowerHP = (LPTractiveEffortLbsF * pS.TopH(Me.ToMi(absSpeedMpS))) / 375.0f;
5448+
SteamEngines[numberofengine].HPIndicatedHorsePowerHP = (HPTractiveEffortLbsF * pS.TopH(Me.ToMi(absSpeedMpS))) / 375.0f;
5449+
SteamEngines[numberofengine].LPIndicatedHorsePowerHP = (LPTractiveEffortLbsF * pS.TopH(Me.ToMi(absSpeedMpS))) / 375.0f;
54875450

54885451
float WheelRevs = pS.TopM(DrvWheelRevRpS);
5489-
IndicatedHorsePowerHP += HPIndicatedHorsePowerHP + LPIndicatedHorsePowerHP;
5490-
IndicatedHorsePowerHP = MathHelper.Clamp(IndicatedHorsePowerHP, 0, IndicatedHorsePowerHP);
5452+
54915453
}
54925454
else // if simple or geared locomotive calculate tractive effort
54935455
{
54945456

54955457
// If the steam piston is exceeding the maximum design piston rate then decrease efficiency of mep
5496-
if (SteamEngineType == SteamEngineTypes.Geared && PistonSpeedFtpMin > MaxSteamGearPistonRateFtpM)
5458+
if (SteamEngineType == SteamEngineTypes.Geared && SteamEngines[numberofengine].PistonSpeedFtpMin > MaxSteamGearPistonRateFtpM)
54975459
{
54985460
// use straight line curve to decay mep to zero by 2 x piston speed
5499-
float pistonforcedecay = 1.0f - (1.0f / MaxSteamGearPistonRateFtpM) * (PistonSpeedFtpMin - MaxSteamGearPistonRateFtpM);
5461+
float pistonforcedecay = 1.0f - (1.0f / MaxSteamGearPistonRateFtpM) * (SteamEngines[numberofengine].PistonSpeedFtpMin - MaxSteamGearPistonRateFtpM);
55005462
pistonforcedecay = MathHelper.Clamp(pistonforcedecay, 0.0f, 1.0f); // Clamp decay within bounds
55015463

55025464
SteamEngines[numberofengine].MeanEffectivePressurePSI *= pistonforcedecay; // Decrease mep once piston critical speed is exceeded
@@ -5575,22 +5537,88 @@ protected override void UpdateTractiveForce(float elapsedClockSeconds, float loc
55755537
IsCritTELimit = false; // Reset flag if limiting TE
55765538
}
55775539

5578-
ApplyDirectionToTractiveForce(ref SteamEngines[numberofengine].TractiveForceN);
5540+
SteamEngines[numberofengine].AttachedAxle.DriveForceN = SteamEngines[numberofengine].TractiveForceN;
5541+
}
5542+
5543+
/// <summary>
5544+
/// Update the tractive force for the complete steam locomotive
5545+
/// </summary>
5546+
protected override void UpdateTractiveForce(float elapsedClockSeconds, float locomotivethrottle, float AbsSpeedMpS, float AbsWheelSpeedMpS)
5547+
{
5548+
TractiveForceN = 0; // reset tractiveforceN in preparation to calculating a new value
5549+
MotiveForceN = 0;
5550+
IndicatedHorsePowerHP = 0;
5551+
PistonSpeedFtpMin = 0;
5552+
5553+
// Update tractive effort across all steam engines
5554+
for (int i = 0; i < SteamEngines.Count; i++)
5555+
{
5556+
TractiveForceN += SteamEngines[i].TractiveForceN;
5557+
5558+
MotiveForceN += SteamEngines[i].AttachedAxle.CompensatedAxleForceN;
5559+
5560+
// Set Max Power equal to max IHP
5561+
MaxPowerW = W.FromHp(SteamEngines[i].MaxIndicatedHorsePowerHP);
5562+
5563+
// Set maximum force for the locomotive
5564+
MaxForceN = N.FromLbf(SteamEngines[i].MaxTractiveEffortLbf * CylinderEfficiencyRate);
5565+
5566+
if (SteamEngineType == SteamEngineTypes.Compound)
5567+
{
5568+
IndicatedHorsePowerHP += HPIndicatedHorsePowerHP + LPIndicatedHorsePowerHP;
5569+
IndicatedHorsePowerHP = MathHelper.Clamp(IndicatedHorsePowerHP, 0, IndicatedHorsePowerHP);
5570+
}
5571+
else
5572+
{
5573+
IndicatedHorsePowerHP += SteamEngines[i].IndicatedHorsePowerHP;
5574+
}
5575+
5576+
//TODO - identify the maximum value for display??
5577+
PistonSpeedFtpMin = SteamEngines[0].PistonSpeedFtpMin;
5578+
5579+
}
5580+
5581+
ApplyDirectionToTractiveForce(ref TractiveForceN);
5582+
5583+
// Find the maximum TE for debug i.e. @ start and full throttle
5584+
if (absSpeedMpS < 1.0)
5585+
{
5586+
if (Math.Abs(TractiveForceN) > absStartTractiveEffortN && Math.Abs(TractiveForceN) < MaxForceN)
5587+
{
5588+
absStartTractiveEffortN = Math.Abs(TractiveForceN); // update to new maximum TE
5589+
}
5590+
}
5591+
5592+
DisplayTractiveForceN = TractiveForceN;
5593+
5594+
MotiveForceSmoothN.Update(elapsedClockSeconds, MotiveForceN);
5595+
MotiveForceSmoothedN = MotiveForceSmoothN.SmoothedValue;
5596+
if (float.IsNaN(MotiveForceN))
5597+
MotiveForceN = 0;
5598+
5599+
DrawBarPullLbsF = N.ToLbf(Math.Abs(MotiveForceSmoothedN) - LocoTenderFrictionForceN); // Locomotive drawbar pull is equal to motive force of locomotive (+ tender) - friction forces of locomotive (+ tender)
5600+
DrawBarPullLbsF = MathHelper.Clamp(DrawBarPullLbsF, 0, DrawBarPullLbsF); // clamp value so it doesn't go negative
5601+
5602+
DrawbarHorsePowerHP = (DrawBarPullLbsF * MpS.ToMpH(absSpeedMpS)) / 375.0f; // TE in this instance is a maximum, and not at the wheel???
5603+
DrawbarHorsePowerHP = MathHelper.Clamp(DrawbarHorsePowerHP, 0, DrawbarHorsePowerHP); // clamp value so it doesn't go negative
5604+
5605+
// Set Max Velocity of locomotive
5606+
MaxSpeedMpS = Me.FromMi(pS.FrompH(MaxLocoSpeedMpH)); // Note this is not the true max velocity of the locomotive, but the speed at which max HP is reached
5607+
5608+
55795609

55805610
// Set tractive force to zero if throttle is closed
55815611
if (locomotivethrottle < 0.001)
55825612
{
5583-
SteamEngines[numberofengine].TractiveForceN = 0;
5613+
TractiveForceN = 0;
55845614
}
55855615

5586-
5587-
SteamEngines[numberofengine].AttachedAxle.DriveForceN = SteamEngines[numberofengine].TractiveForceN;
55885616
}
55895617

5590-
/// <summary>
5591-
/// Normalise crank angle so that it is a value between 0 and 360 starting at the real crank angle difference
5592-
/// </summary>
5593-
private float NormalisedCrankAngle(int cylinderNumber)
5618+
/// <summary>
5619+
/// Normalise crank angle so that it is a value between 0 and 360 starting at the real crank angle difference
5620+
/// </summary>
5621+
private float NormalisedCrankAngle(int cylinderNumber)
55945622
{
55955623
float normalisedCrankAngleRad = (float)MathHelper.WrapAngle((float)LocomotiveAxles[0].AxlePositionRad + WheelCrankAngleDiffRad[cylinderNumber]);
55965624

Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/PowerSupplies/SteamEngine.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -543,10 +543,25 @@ public enum AuxiliarySteamEngineTypes
543543
public float CylCockSteamUsageLBpS;
544544

545545
/// <summary>
546-
/// Indicated Horse Power
546+
/// Indicated HP Horse Power for Compound
547+
/// </summary>
548+
public float HPIndicatedHorsePowerHP;
549+
550+
/// <summary>
551+
/// Indicated LP Horse Power for Compound
552+
/// </summary>
553+
public float LPIndicatedHorsePowerHP;
554+
555+
/// <summary>
556+
/// Indicated Horse Power for single expansion
547557
/// </summary>
548558
public float IndicatedHorsePowerHP;
549559

560+
/// <summary>
561+
/// Speed of Piston
562+
/// </summary>
563+
public float PistonSpeedFtpMin;
564+
550565
/// <summary>
551566
/// Calculated Factor of Adhesion
552567
/// </summary>

0 commit comments

Comments
 (0)