Skip to content

Commit f9aa2ad

Browse files
committed
Set adhesion to switch between Pacha and Polach models if PC performance drops
1 parent 25f5e06 commit f9aa2ad

File tree

1 file changed

+100
-36
lines changed
  • Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/PowerTransmissions

1 file changed

+100
-36
lines changed

Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/PowerTransmissions/Axle.cs

Lines changed: 100 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,11 @@ public float InertiaKgm2
426426
/// </summary>
427427
float forceToAccelerationFactor;
428428

429+
/// <summary>
430+
/// switch between Polach and Pacha adhesion calculation
431+
/// </summary>
432+
bool UsePoalchAdhesion = false;
433+
429434
/// <summary>
430435
/// Pre-calculation of slip characteristics at 0 slip speed
431436
/// </summary>
@@ -587,12 +592,12 @@ public void ComputeWheelSlipThresholdMpS()
587592
// i.e. the point where slope changes from positive (adhesion region)
588593
// to negative (slip region)
589594
double dx = 0.001;
590-
double fa = SlipCharacteristics(a + dx) - SlipCharacteristics(a);
591-
double fb = SlipCharacteristics(b + dx) - SlipCharacteristics(b);
595+
double fa = SlipCharacteristicsPolach(a + dx) - SlipCharacteristicsPolach(a);
596+
double fb = SlipCharacteristicsPolach(b + dx) - SlipCharacteristicsPolach(b);
592597

593598
double SlipSpeedMpS = AxleSpeedMpS - TrainSpeedMpS;
594599

595-
MaximumPolachWheelAdhesion = (float)SlipCharacteristics(WheelSlipThresholdMpS);
600+
MaximumPolachWheelAdhesion = (float)SlipCharacteristicsPolach(WheelSlipThresholdMpS);
596601

597602
if (SlipSpeedMpS == 0)
598603
{
@@ -610,7 +615,7 @@ public void ComputeWheelSlipThresholdMpS()
610615
while (Math.Abs(b - a) > MpS.FromKpH(0.1f))
611616
{
612617
double c = (a + b) / 2;
613-
double fc = SlipCharacteristics(c + dx) - SlipCharacteristics(c);
618+
double fc = SlipCharacteristicsPolach(c + dx) - SlipCharacteristicsPolach(c);
614619
if (fa * fc > 0)
615620
{
616621
a = c;
@@ -813,7 +818,17 @@ public void Save(BinaryWriter outf)
813818
public (double, double, double, double) GetAxleMotionVariation(double axleSpeedMpS, double elapsedClockSeconds)
814819
{
815820
double slipSpeedMpS = axleSpeedMpS - TrainSpeedMpS;
816-
double axleOutForceN = Math.Sign(slipSpeedMpS) * AxleWeightN * SlipCharacteristics(slipSpeedMpS);
821+
double axleOutForceN = 0;
822+
823+
if (UsePoalchAdhesion)
824+
{
825+
axleOutForceN = Math.Sign(slipSpeedMpS) * AxleWeightN * SlipCharacteristicsPolach(slipSpeedMpS);
826+
}
827+
else
828+
{
829+
axleOutForceN = AxleWeightN * SlipCharacteristicsPacha((float)axleSpeedMpS - TrainSpeedMpS, TrainSpeedMpS, AdhesionK, AdhesionLimit);
830+
}
831+
817832
double axleInForceN = 0;
818833
if (DriveType == AxleDriveType.ForceDriven)
819834
axleInForceN = DriveForceN * transmissionEfficiency;
@@ -851,31 +866,9 @@ void Integrate(float elapsedClockSeconds)
851866
if (elapsedClockSeconds <= 0) return;
852867
double prevSpeedMpS = AxleSpeedMpS;
853868

854-
float upperSubStepStartingLimit = 100;
855-
float tempupperSubStepLimit = upperSubStepStartingLimit;
869+
float upperSubStepLimit = 100;
856870
float lowerSubStepLimit = 1;
857871

858-
float screenFrameUpperLimit = 60;
859-
float screenFrameLowerLimit = 40;
860-
861-
var ScreenFrameRate = Simulator.SmoothedFrameRate;
862-
863-
// Reduces the number of substeps if screen FPS drops below a nominal rate of 60 fps
864-
if ( (int)ScreenFrameRate >= screenFrameUpperLimit) // Screen FPS > 60, hold substeps @ maximum value
865-
{
866-
tempupperSubStepLimit = upperSubStepStartingLimit;
867-
}
868-
else if ((int)ScreenFrameRate < screenFrameLowerLimit) // Screen FPS < 40, hold substeps @ minimum value
869-
{
870-
tempupperSubStepLimit = upperSubStepStartingLimit * (screenFrameLowerLimit / screenFrameUpperLimit);
871-
}
872-
else
873-
{
874-
tempupperSubStepLimit = (int) ((ScreenFrameRate / 60) * upperSubStepStartingLimit);
875-
}
876-
877-
var upperSubStepLimit = tempupperSubStepLimit;
878-
879872
// use straight line graph approximation to increase substeps as slipspeed increases towards the threshold speed point
880873
// Points are 1 = (0, upperLimit) and 2 = (threshold, lowerLimit)
881874
var AdhesGrad = ((upperSubStepLimit - lowerSubStepLimit) / (WheelSlipThresholdMpS - 0));
@@ -961,17 +954,44 @@ void Integrate(float elapsedClockSeconds)
961954
/// <param name="timeSpan"></param>
962955
public virtual void Update(float timeSpan)
963956
{
964-
forceToAccelerationFactor = WheelRadiusM * WheelRadiusM / totalInertiaKgm2;
957+
// Test to determine whether to use Polach or Pacha adhesion
958+
var ScreenFrameRate = Simulator.SmoothedFrameRate;
959+
960+
// Switches between Polach (high performance) adhesion model and Pacha (low performance) adhesion model
961+
if(ScreenFrameRate > 59)
962+
{
963+
UsePoalchAdhesion = true;
964+
}
965+
else if(ScreenFrameRate < 55)
966+
{
967+
UsePoalchAdhesion = false;
968+
if (TrainSpeedMpS > 0 )
969+
{
970+
Trace.TraceInformation("Advanced adhesion model switched to low performance option due to low frame rate {0} at ElapsedClockSeconds of {1}", ScreenFrameRate, timeSpan);
971+
}
965972

966-
Polach.Update();
967-
axleStaticForceN = AxleWeightN * SlipCharacteristics(0);
968-
ComputeWheelSlipThresholdMpS();
973+
// Set values for Pacha adhesion
974+
WheelSlipThresholdMpS = MpS.FromKpH(AdhesionK / AdhesionLimit);
975+
WheelAdhesion = 0.99f;
976+
MaximumPolachWheelAdhesion = 0.99f;
969977

970-
if (count < 6 && count++ == 5)
978+
}
979+
980+
forceToAccelerationFactor = WheelRadiusM * WheelRadiusM / totalInertiaKgm2;
981+
982+
if (UsePoalchAdhesion)
971983
{
972-
TrainSpeedMpS = 10 / 3.6f;
984+
973985
Polach.Update();
974-
axleStaticForceN = AxleWeightN * SlipCharacteristics(0);
986+
axleStaticForceN = AxleWeightN * SlipCharacteristicsPolach(0);
987+
ComputeWheelSlipThresholdMpS();
988+
989+
if (count < 6 && count++ == 5)
990+
{
991+
TrainSpeedMpS = 10 / 3.6f;
992+
Polach.Update();
993+
axleStaticForceN = AxleWeightN * SlipCharacteristicsPolach(0);
994+
}
975995
}
976996

977997
#if DEBUG_ADHESION
@@ -1170,6 +1190,7 @@ public double SlipCharacteristics(double slipSpeedMpS)
11701190
}
11711191

11721192
/// <summary>
1193+
/// ***** Polach Adhesion *****
11731194
/// Uses the Polach creep force curves calculation described in the following document
11741195
/// "Creep forces in simulations of traction vehicles running on adhesion limit" by O. Polach 2005 Wear - http://www.sze.hu/~szenasy/VILLVONT/polachslipvizsg.pdf
11751196
///
@@ -1183,12 +1204,55 @@ public double SlipCharacteristics(double slipSpeedMpS)
11831204
/// <param name="slipSpeedMpS">Difference between train speed and wheel speed</param>
11841205
/// <param name="speedMpS">Current speed</param>
11851206
/// <returns>Relative force transmitted to the rail</returns>
1186-
public double SlipCharacteristics(double slipSpeedMpS)
1207+
public double SlipCharacteristicsPolach(double slipSpeedMpS)
11871208
{
11881209
slipSpeedMpS = Math.Abs(slipSpeedMpS);
11891210
double fx = Polach.SlipCharacteristics(slipSpeedMpS);
11901211
WheelAdhesion = (float)fx;
11911212
return fx;
11921213
}
1214+
1215+
1216+
/// <summary>
1217+
/// ***** Pacha Adhesion *****
1218+
/// Slip characteristics computation
1219+
/// - Uses adhesion limit calculated by Curtius-Kniffler formula:
1220+
/// 7.5
1221+
/// umax = --------------------- + 0.161
1222+
/// speed * 3.6 + 44.0
1223+
/// - Computes slip speed
1224+
/// - Computes relative adhesion force as a result of slip characteristics:
1225+
/// 2*K*umax^2*dV
1226+
/// u = ---------------------
1227+
/// umax^2*dv^2 + K^2
1228+
///
1229+
/// For high slip speeds the formula is replaced with an exponentially
1230+
/// decaying function (with smooth coupling) which reaches 40% of
1231+
/// maximum adhesion at infinity. The transition point between equations
1232+
/// is at dV = sqrt(3)*K/umax (inflection point)
1233+
///
1234+
/// </summary>
1235+
/// <param name="slipSpeedMpS">Difference between train speed and wheel speed</param>
1236+
/// <param name="speedMpS">Current speed</param>
1237+
/// <param name="K">Slip speed correction</param>
1238+
/// <param name="umax">Relative weather conditions, usually from 0.2 to 1.0</param>
1239+
/// <returns>Relative force transmitted to the rail</returns>
1240+
public float SlipCharacteristicsPacha(float slipSpeedMpS, float speedMpS, float K, float umax)
1241+
{
1242+
var slipSpeedKpH = MpS.ToKpH(slipSpeedMpS);
1243+
float x = slipSpeedKpH * umax / K; // Slip percentage
1244+
float absx = Math.Abs(x);
1245+
float sqrt3 = (float)Math.Sqrt(3);
1246+
if (absx > sqrt3)
1247+
{
1248+
// At infinity, adhesion is 40% of maximum (Polach, 2005)
1249+
// The value must be lower than 85% for the formula to work
1250+
float inftyFactor = 0.4f;
1251+
return Math.Sign(slipSpeedKpH) * umax * ((sqrt3 / 2 - inftyFactor) * (float)Math.Exp((sqrt3 - absx) / (2 * sqrt3 - 4 * inftyFactor)) + inftyFactor);
1252+
}
1253+
return 2.0f * umax * x / (1 + x * x);
1254+
}
1255+
1256+
11931257
}
11941258
}

0 commit comments

Comments
 (0)