Skip to content

Commit 560c07c

Browse files
committed
Update slip adhesion
1 parent 11a2563 commit 560c07c

File tree

2 files changed

+70
-10
lines changed

2 files changed

+70
-10
lines changed

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

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,14 @@ public float CurrentLocomotiveSteamHeatBoilerWaterCapacityL
215215

216216
// Adhesion parameters
217217
float BaseFrictionCoefficientFactor; // Factor used to adjust Curtius formula depending upon weather conditions
218+
float SlipFrictionCoefficientFactor;
218219
public float SteamStaticWheelForce;
219220
public float SteamTangentialWheelForce;
220221
public float SteamDrvWheelWeightLbs; // Weight on each drive axle
221222
public float PreviousThrottleSetting = 0.0f; // Holds the value of the previous throttle setting for calculating the correct antislip speed
223+
float WheelSlipTimeS;
224+
float WheelStopSlipTimeS;
225+
float CurrentWheelSlipAdhesionMultiplier;
222226

223227
// parameters for Track Sander based upon compressor air and abrasive table for 1/2" sand blasting nozzle @ 50psi
224228
public float MaxTrackSandBoxCapacityM3 = Me3.FromFt3(40.0f); // Capacity of sandbox - assume 40.0 cu ft
@@ -3016,13 +3020,54 @@ public virtual void UpdateFrictionCoefficient(float elapsedClockSeconds)
30163020

30173021
}
30183022

3019-
if (WheelSlip && ThrottlePercent > 0.2f && !BrakeSkid) // Test to see if loco wheel is slipping, then coeff of friction will be decreased below static value. Sanding will override this somewhat
3023+
// When wheel slips or skids, then dynamic (kinetic) coeff of friction will be decreased below static value. Sanding will override this somewhat.
3024+
// The transition between static and dynamic friction appears to decrease at an exponential rate until it reaches a steady state dynamic value.
3025+
//
3026+
3027+
3028+
// Test to see if loco wheel is slipping or skidding due to brake application
3029+
if (WheelSlip && ((ThrottlePercent > 0.2f && !BrakeSkid) || (ThrottlePercent < 0.1f && BrakeSkid)))
30203030
{
3021-
BaseFrictionCoefficientFactor *= 0.5f; // Descrease friction to take into account dynamic (kinetic) friction, typically kinetic friction is approximately 50% of static friction.
3031+
3032+
WheelStopSlipTimeS = 0; // Reset stop slip time if wheel slip starts
3033+
3034+
// Exponential curve is used to transition between static friction and dynamic friction when wheel slips
3035+
// Exponential constant calculated between two points, using this tool - https://mathcracker.com/exponential-function-calculator#results
3036+
// Google search suggests that Steel on steel has a static coeff = 0.74, and a dynamic coeff = 0.57. Hence reduction = 0.77.
3037+
// Constant points facilitate a decrease from 1 to 0.7 in 3 seconds - P1 = (0, 1), P2 = (3, 0.77). Hence exp constant = −0.0871
3038+
var expAdhesion = -0.0871;
3039+
WheelSlipTimeS += elapsedClockSeconds;
3040+
WheelSlipTimeS = MathHelper.Clamp(WheelSlipTimeS, 0.0f, 3.0f); // Ensure that time to transition between the two friction cases is maintained - currently set to 3 secs
3041+
3042+
float adhesionMultiplier = (float) Math.Exp(expAdhesion * WheelSlipTimeS);
3043+
CurrentWheelSlipAdhesionMultiplier = adhesionMultiplier;
3044+
3045+
BaseFrictionCoefficientFactor *= adhesionMultiplier; // Descrease friction to take into account dynamic (kinetic) friction, typically kinetic friction is approximately 50% of static friction.
3046+
SlipFrictionCoefficientFactor = BaseFrictionCoefficientFactor;
3047+
3048+
BaseFrictionCoefficientFactor = MathHelper.Clamp(BaseFrictionCoefficientFactor, 0.05f, 1.0f); // Ensure friction coefficient never exceeds a "reasonable" value
30223049
}
3023-
else if (WheelSlip && ThrottlePercent < 0.1f && BrakeSkid) // Test to see if loco wheel is skidding due to brake application
3050+
else
30243051
{
3025-
BaseFrictionCoefficientFactor *= 0.5f; // Descrease friction to take into account dynamic (kinetic) friction, typically kinetic friction is approximately 50% of static friction.
3052+
WheelSlipTimeS = 0; // Reset slip time if wheel slip stops
3053+
3054+
if (SlipFrictionCoefficientFactor < BaseFrictionCoefficientFactor && SlipFrictionCoefficientFactor != 0) // Once these two are equal then assume that wheels have stopped slipping.
3055+
{
3056+
// Trace.TraceInformation("SlipFriction {0} Base {1}", SlipFrictionCoefficientFactor, BaseFrictionCoefficientFactor);
3057+
// Exponential curve is used to transition between dynamic friction and static friction when wheel stops slipping
3058+
// Constant points facilitate an increase from 0.7 to 1 in 3 seconds - P1 = (3, 0.77), P2 = (0, 1). Hence exp constant = 0.0871
3059+
var expAdhesion = 0.0871;
3060+
WheelStopSlipTimeS += elapsedClockSeconds;
3061+
WheelStopSlipTimeS = MathHelper.Clamp(WheelStopSlipTimeS, 0.0f, 3.0f); // Ensure that time to transition between the two friction cases is maintained - currently set to 3 secs
3062+
3063+
float adhesionMultiplier = CurrentWheelSlipAdhesionMultiplier * (float)Math.Exp(expAdhesion * WheelStopSlipTimeS);
3064+
3065+
// Trace.TraceInformation("adhesion {0} StopTime {1} Base {2} Current {3}", adhesionMultiplier, WheelStopSlipTimeS, BaseFrictionCoefficientFactor, CurrentWheelSlipAdhesionMultiplier);
3066+
3067+
BaseFrictionCoefficientFactor *= adhesionMultiplier; // Descrease friction to take into account dynamic (kinetic) friction, typically kinetic friction is approximately 50% of static friction.
3068+
SlipFrictionCoefficientFactor = BaseFrictionCoefficientFactor;
3069+
BaseFrictionCoefficientFactor = MathHelper.Clamp(BaseFrictionCoefficientFactor, 0.05f, 1.0f); // Ensure friction coefficient never exceeds a "reasonable" value
3070+
}
30263071
}
30273072

30283073
var AdhesionMultiplier = Simulator.Settings.AdhesionFactor / 100.0f; // Convert to a factor where 100% = no change to adhesion

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

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4652,7 +4652,7 @@ protected override void UpdateTractiveForce(float elapsedClockSeconds, float t,
46524652

46534653
#region - Steam Adhesion Model Input for Steam Locomotives
46544654

4655-
// Based upon information presented in "Locomotive Operation - A Technical and Practical Analysis" by G. R. Henderson - https://archive.org/details/locomotiveoperat00hend
4655+
// Based upon information presented on pg 276 of "Locomotive Operation - A Technical and Practical Analysis" by G. R. Henderson - https://archive.org/details/locomotiveoperat00hend
46564656
// At its simplest slip occurs when the wheel tangential force exceeds the static frictional force
46574657
// Static frictional force = weight on the locomotive driving wheels * frictional co-efficient
46584658
// Tangential force = Effective force (Interia + Piston force) * Tangential factor (sin (crank angle) + (crank radius / connecting rod length) * sin (crank angle) * cos (crank angle))
@@ -4979,29 +4979,36 @@ protected override void UpdateTractiveForce(float elapsedClockSeconds, float t,
49794979
// If locomotive slip is occuring, set parameters to reduce motive force (pulling power), and set wheel rotational speed for wheel viewers
49804980
if (IsLocoSlip)
49814981
{
4982-
4982+
// Based upon information presented in "Locomotive Operation - A Technical and Practical Analysis" by G. R. Henderson - https://archive.org/details/locomotiveoperat00hend
49834983
// This next section caluclates the turning speed for the wheel if slip occurs. It is based upon the force applied to the wheel and the moment of inertia for the wheel
49844984
// A Generic wheel profile is used, so results may not be applicable to all locomotive, but should provide a "reasonable" guestimation
49854985
// Generic wheel assumptions are - 80 inch drive wheels ( 2.032 metre), a pair of drive wheels weighs approx 6,000lbs, axle weighs 1,000 lbs, and has a diameter of 8 inches.
49864986
// Moment of Inertia (Wheel and axle) = (Mass x Radius) / 2.0
4987+
// Reference model assumption
49874988
float WheelRadiusAssumptM = Me.FromIn(80.0f / 2.0f);
49884989
float WheelWeightKG = Kg.FromLb(6000.0f);
49894990
float AxleWeighKG = Kg.FromLb(1000.0f);
49904991
float AxleRadiusM = Me.FromIn(8.0f / 2.0f);
4992+
4993+
// Take into account the actual lcomotive that we are modelling, and vary the above values by the ratio of drive wheel size.
4994+
var wheelSizeRatio = DriverWheelRadiusM / WheelRadiusAssumptM;
4995+
WheelRadiusAssumptM *= wheelSizeRatio;
4996+
WheelWeightKG *= wheelSizeRatio;
4997+
AxleWeighKG *= wheelSizeRatio;
4998+
AxleRadiusM *= wheelSizeRatio;
4999+
49915000
float WheelMomentInertia = (WheelWeightKG * WheelRadiusAssumptM * WheelRadiusAssumptM) / 2.0f;
49925001
float AxleMomentInertia = (WheelWeightKG * AxleRadiusM * AxleRadiusM) / 2.0f;
49935002
float TotalWheelMomentofInertia = WheelMomentInertia + AxleMomentInertia; // Total MoI for generic wheel
49945003

4995-
// The moment of inertia will be adjusted up or down compared to the size of the wheel on the player locomotive compared to the Generic wheel
4996-
TotalWheelMomentofInertia *= DriverWheelRadiusM / WheelRadiusAssumptM;
4997-
49985004
// The moment of inertia needs to be increased by the number of wheel sets
49995005
TotalWheelMomentofInertia *= LocoNumDrvAxles;
50005006

50015007
// the inertia of the coupling rods can also be added
50025008
// Assume rods weigh approx 1500 lbs
50035009
// // MoI = rod weight x stroke radius (ie stroke / 2)
50045010
float RodWeightKG = Kg.FromLb(1500.0f);
5011+
RodWeightKG *= wheelSizeRatio;
50055012
// ???? For both compound and simple??????
50065013
float RodStrokeM = CylinderStrokeM / 2.0f;
50075014
float RodMomentInertia = RodWeightKG * RodStrokeM * RodStrokeM;
@@ -5010,11 +5017,19 @@ protected override void UpdateTractiveForce(float elapsedClockSeconds, float t,
50105017

50115018
// angular acceleration = (sum of forces * wheel radius) / moment of inertia
50125019
float AngAccRadpS2 = (N.FromLbf(SteamTangentialWheelForce - SteamStaticWheelForce) * DriverWheelRadiusM) / TotalMomentInertia;
5020+
5021+
// Trace.TraceInformation("AngAcc {0} Tang {1} Static {2} Radius {3} Inertia {4} WheelSpeed {5}", AngAccRadpS2, N.FromLbf(SteamTangentialWheelForce), N.FromLbf(SteamStaticWheelForce), DriverWheelRadiusM, TotalMomentInertia, FrictionWheelSpeedMpS);
50135022
// tangential acceleration = angular acceleration * wheel radius
50145023
// tangential speed = angular acceleration * time
50155024
PrevFrictionWheelSpeedMpS = FrictionWheelSpeedMpS; // Save current value of wheelspeed
50165025
// Speed = current velocity + acceleration * time
5017-
FrictionWheelSpeedMpS += (AngAccRadpS2 * DriverWheelRadiusM * elapsedClockSeconds); // increase wheel speed whilever wheel accelerating
5026+
var wheelSpeedRadpS = (AngAccRadpS2 * elapsedClockSeconds);
5027+
// Convert from radpS to MpS for the wheel size
5028+
var revsPs = wheelSpeedRadpS / (2.0f * (float)Math.PI); // Convert rads to revs
5029+
var diffWheelSpeedMpS = revsPs * 2.0f * (float)Math.PI * DriverWheelRadiusM;
5030+
5031+
// each wheel rev will travel the circumference of the wheel
5032+
FrictionWheelSpeedMpS += diffWheelSpeedMpS; // change wheel speed whilever wheel accelerating/decelerating
50185033
FrictionWheelSpeedMpS = MathHelper.Clamp(FrictionWheelSpeedMpS, 0.0f, 62.58f); // Clamp wheel speed at maximum of 140mph (62.58 m/s)
50195034

50205035
WheelSlip = true; // Set wheel slip if locomotive is slipping

0 commit comments

Comments
 (0)