Skip to content

Commit 89833d4

Browse files
authored
Merge pull request #878 from peternewell/adhesion_polach_#1
Implement Polach Adhesion
2 parents 9d41208 + 9347dcf commit 89833d4

File tree

14 files changed

+628
-176
lines changed

14 files changed

+628
-176
lines changed

Source/Documentation/Manual/physics.rst

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,23 @@ simplicity, only one axle model is computed (and animated). A tilting
254254
feature and the independent axle adhesion model will be introduced in the
255255
future.
256256

257-
The heart of the model is the slip characteristics (picture below).
257+
The advanced adhesion model uses two alternate algorithms to calculate the
258+
wheel adhesion. The first model is based upon an algorithm by Pacha, whilst the second
259+
uses an algorithm developed by Polach. The Polach algorithm provides
260+
a more accurate outcome and facilitates the future inclusion of track conditions.
261+
However due to the number of algorithm steps required to calculate the wheel adhesion
262+
value, it is more CPU load intensive then the Pacha one. This can produce low
263+
frame rates for the screen display in machines with low performance specifications.
264+
265+
Hence OR automatically senses the CPU load, and switches to the Pacha algorithm at
266+
high loads and to the Polach algorithm under lower CPU loads. In this way OR attempts
267+
to support the operation of lower specification computers. When OR is using the
268+
Pacha algorithm, the "Wheel Adh (Max)" values will both read 99%, whereas when the
269+
Polach algorithm is being used these values will be around the expected values of 30-55%.
270+
271+
272+
273+
The heart of the adhesion algorithm is the slip characteristics (pictured below).
258274

259275
.. image:: images/physics-adhesion-slip.png
260276
:align: center

Source/ORTS.Common/Conversions.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,15 @@ public static string FormatSpeedDisplay(float speed, bool isMetric)
595595
"{0:F1} {1}", MpS.FromMpS(speed, isMetric), isMetric ? kmph : mph);
596596
}
597597

598+
/// <summary>
599+
/// Formatted localized speed string, used to display tracking speed, with 2 decimal precision
600+
/// </summary>
601+
public static string FormatVeryLowSpeedDisplay(float speed, bool isMetric)
602+
{
603+
return String.Format(CultureInfo.CurrentCulture,
604+
"{0:F2} {1}", MpS.FromMpS(speed, isMetric), isMetric ? kmph : mph);
605+
}
606+
598607
/// <summary>
599608
/// Formatted localized speed string, used to display speed limits, with 0 decimal precision
600609
/// </summary>

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

Lines changed: 45 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -301,10 +301,9 @@ public override void LoadFromWagFile(string wagFilePath)
301301
{
302302
Trace.TraceInformation("MaxRailOutputPower (BASIC Config): set at arbitary value = {0}", FormatStrings.FormatPower(LocomotiveMaxRailOutputPowerW, IsMetric, false, false));
303303
}
304-
305304
}
306305

307-
306+
308307
if (MaximumDieselEnginePowerW == 0)
309308
{
310309
MaximumDieselEnginePowerW = LocomotiveMaxRailOutputPowerW; // If no value set in ENG file, then set the Prime Mover power to same as RailOutputPower (typically the MaxPower value)
@@ -313,7 +312,6 @@ public override void LoadFromWagFile(string wagFilePath)
313312
Trace.TraceInformation("Maximum Diesel Engine Prime Mover Power set the same as MaxRailOutputPower {0} value", FormatStrings.FormatPower(MaximumDieselEnginePowerW, IsMetric, false, false));
314313

315314
}
316-
317315
}
318316

319317
// Check that maximum force value has been set
@@ -330,40 +328,42 @@ public override void LoadFromWagFile(string wagFilePath)
330328
}
331329
else
332330
{
333-
float ThrottleSetting = 1.0f; // Must be at full throttle for these calculations
331+
float throttleSetting = 1.0f; // Must be at full throttle for these calculations
334332
float StartingSpeedMpS = 0.1f; // Assumed starting speed for diesel - can't be zero otherwise error will occurr
335-
float MaxForceN = TractiveForceCurves.Get(ThrottleSetting, StartingSpeedMpS);
333+
MaxForceN = TractiveForceCurves.Get(throttleSetting, StartingSpeedMpS);
336334

337335
if (Simulator.Settings.VerboseConfigurationMessages)
338336
Trace.TraceInformation("Maximum Force set to {0} value, calcuated from Tractive Force Tables", FormatStrings.FormatForce(MaxForceN, IsMetric));
339337
}
340-
341-
342338
}
343339

344340

345-
// Check force assumptions set for diesel
346-
if (Simulator.Settings.VerboseConfigurationMessages)
341+
// Check force assumptions set for diesel
342+
CalculatedMaxContinuousForceN = 0;
343+
float ThrottleSetting = 1.0f; // Must be at full throttle for these calculations
344+
if (TractiveForceCurves == null) // Basic configuration - ie no force and Power tables, etc
347345
{
348-
CalculatedMaxContinuousForceN = 0;
349-
float ThrottleSetting = 1.0f; // Must be at full throttle for these calculations
350-
if (TractiveForceCurves == null) // Basic configuration - ie no force and Power tables, etc
346+
CalculatedMaxContinuousForceN = ThrottleSetting * LocomotiveMaxRailOutputPowerW / SpeedOfMaxContinuousForceMpS;
347+
348+
if (Simulator.Settings.VerboseConfigurationMessages)
351349
{
352-
CalculatedMaxContinuousForceN = ThrottleSetting * LocomotiveMaxRailOutputPowerW / SpeedOfMaxContinuousForceMpS;
353350
Trace.TraceInformation("Diesel Force Settings (BASIC Config): Max Starting Force {0}, Calculated Max Continuous Force {1} @ speed of {2}", FormatStrings.FormatForce(MaxForceN, IsMetric), FormatStrings.FormatForce(CalculatedMaxContinuousForceN, IsMetric), FormatStrings.FormatSpeedDisplay(SpeedOfMaxContinuousForceMpS, IsMetric));
354351
Trace.TraceInformation("Diesel Power Settings (BASIC Config): Prime Mover {0}, Max Rail Output Power {1}", FormatStrings.FormatPower(MaximumDieselEnginePowerW, IsMetric, false, false), FormatStrings.FormatPower(LocomotiveMaxRailOutputPowerW, IsMetric, false, false));
355352

356353
if (MaxForceN < MaxContinuousForceN)
357354
{
358355
Trace.TraceInformation("!!!! Warning: Starting Tractive force {0} is less then Calculated Continuous force {1}, please check !!!!", FormatStrings.FormatForce(MaxForceN, IsMetric), FormatStrings.FormatForce(CalculatedMaxContinuousForceN, IsMetric), FormatStrings.FormatSpeedDisplay(SpeedOfMaxContinuousForceMpS, IsMetric));
359356
}
360-
361357
}
362-
else // Advanced configuration -
358+
359+
}
360+
else // Advanced configuration -
361+
{
362+
float StartingSpeedMpS = 0.1f; // Assumed starting speed for diesel - can't be zero otherwise error will occurr
363+
float StartingForceN = TractiveForceCurves.Get(ThrottleSetting, StartingSpeedMpS);
364+
CalculatedMaxContinuousForceN = TractiveForceCurves.Get(ThrottleSetting, SpeedOfMaxContinuousForceMpS);
365+
if (Simulator.Settings.VerboseConfigurationMessages)
363366
{
364-
float StartingSpeedMpS = 0.1f; // Assumed starting speed for diesel - can't be zero otherwise error will occurr
365-
float StartingForceN = TractiveForceCurves.Get(ThrottleSetting, StartingSpeedMpS);
366-
CalculatedMaxContinuousForceN = TractiveForceCurves.Get(ThrottleSetting, SpeedOfMaxContinuousForceMpS);
367367
Trace.TraceInformation("Diesel Force Settings (ADVANCED Config): Max Starting Force {0}, Calculated Max Continuous Force {1}, @ speed of {2}", FormatStrings.FormatForce(StartingForceN, IsMetric), FormatStrings.FormatForce(CalculatedMaxContinuousForceN, IsMetric), FormatStrings.FormatSpeedDisplay(SpeedOfMaxContinuousForceMpS, IsMetric));
368368
Trace.TraceInformation("Diesel Power Settings (ADVANCED Config): Prime Mover {0}, Max Rail Output Power {1} @ {2} rpm", FormatStrings.FormatPower(DieselEngines.MaxPowerW, IsMetric, false, false), FormatStrings.FormatPower(DieselEngines.MaximumRailOutputPowerW, IsMetric, false, false), MaxRPM);
369369

@@ -372,34 +372,43 @@ public override void LoadFromWagFile(string wagFilePath)
372372
Trace.TraceInformation("!!!! Warning: Calculated Starting Tractive force {0} is less then Calculated Continuous force {1}, please check !!!!", FormatStrings.FormatForce(StartingForceN, IsMetric), FormatStrings.FormatForce(CalculatedMaxContinuousForceN, IsMetric), FormatStrings.FormatSpeedDisplay(SpeedOfMaxContinuousForceMpS, IsMetric));
373373
}
374374
}
375+
}
376+
377+
// Check that MaxPower value is realistic - Calculate power - metric - P = F x V
378+
float CalculatedContinuousPowerW = MaxContinuousForceN * SpeedOfMaxContinuousForceMpS;
379+
if (MaxPowerW < CalculatedContinuousPowerW && Simulator.Settings.VerboseConfigurationMessages)
380+
{
381+
Trace.TraceInformation("!!!! Warning: MaxPower {0} is less then continuous force calculated power {1} @ speed of {2}, please check !!!!", FormatStrings.FormatPower(MaxPowerW, IsMetric, false, false), FormatStrings.FormatPower(CalculatedContinuousPowerW, IsMetric, false, false), FormatStrings.FormatSpeedDisplay(SpeedOfMaxContinuousForceMpS, IsMetric));
382+
}
375383

376-
// Check that MaxPower value is realistic - Calculate power - metric - P = F x V
377-
float CalculatedContinuousPowerW = MaxContinuousForceN * SpeedOfMaxContinuousForceMpS;
378-
if (MaxPowerW < CalculatedContinuousPowerW)
384+
if (!DieselEngines.HasGearBox)
385+
{
386+
// Check Adhesion values
387+
var calculatedmaximumpowerw = CalculatedMaxContinuousForceN * SpeedOfMaxContinuousForceMpS;
388+
var maxforcekN = MaxForceN / 1000.0f;
389+
var designadhesionzerospeed = maxforcekN / (Kg.ToTonne(DrvWheelWeightKg) * 10);
390+
if (Simulator.Settings.VerboseConfigurationMessages)
379391
{
380-
Trace.TraceInformation("!!!! Warning: MaxPower {0} is less then continuous force calculated power {1} @ speed of {2}, please check !!!!", FormatStrings.FormatPower(MaxPowerW, IsMetric, false, false), FormatStrings.FormatPower(CalculatedContinuousPowerW, IsMetric, false, false), FormatStrings.FormatSpeedDisplay(SpeedOfMaxContinuousForceMpS, IsMetric));
392+
Trace.TraceInformation("Zero Adhesion - zeroadhesion {0} maxForcekN {1} Driveweight {2}", designadhesionzerospeed, maxforcekN, DrvWheelWeightKg);
381393
}
382-
383-
if (!DieselEngines.HasGearBox)
394+
var calculatedmaxcontinuousforcekN = CalculatedMaxContinuousForceN / 1000.0f;
395+
var designadhesionmaxcontspeed = calculatedmaxcontinuousforcekN / (Kg.ToTonne(DrvWheelWeightKg) * 10);
396+
var zerospeed = 0;
397+
var configuredadhesionzerospeed = (Curtius_KnifflerA / (zerospeed + Curtius_KnifflerB) + Curtius_KnifflerC);
398+
var configuredadhesionmaxcontinuousspeed = (Curtius_KnifflerA / (SpeedOfMaxContinuousForceMpS + Curtius_KnifflerB) + Curtius_KnifflerC);
399+
var dropoffspeed = calculatedmaximumpowerw / (MaxForceN);
400+
var configuredadhesiondropoffspeed = (Curtius_KnifflerA / (dropoffspeed + Curtius_KnifflerB) + Curtius_KnifflerC);
401+
if (Simulator.Settings.VerboseConfigurationMessages)
384402
{
385-
// Check Adhesion values
386-
var calculatedmaximumpowerw = CalculatedMaxContinuousForceN * SpeedOfMaxContinuousForceMpS;
387-
var maxforcekN = MaxForceN / 1000.0f;
388-
var designadhesionzerospeed = maxforcekN / (Kg.ToTonne(DrvWheelWeightKg) * 10);
389-
var calculatedmaxcontinuousforcekN = CalculatedMaxContinuousForceN / 1000.0f;
390-
var designadhesionmaxcontspeed = calculatedmaxcontinuousforcekN / (Kg.ToTonne(DrvWheelWeightKg) * 10);
391-
var zerospeed = 0;
392-
var configuredadhesionzerospeed = (Curtius_KnifflerA / (zerospeed + Curtius_KnifflerB) + Curtius_KnifflerC);
393-
var configuredadhesionmaxcontinuousspeed = (Curtius_KnifflerA / (SpeedOfMaxContinuousForceMpS + Curtius_KnifflerB) + Curtius_KnifflerC);
394-
var dropoffspeed = calculatedmaximumpowerw / (MaxForceN);
395-
var configuredadhesiondropoffspeed = (Curtius_KnifflerA / (dropoffspeed + Curtius_KnifflerB) + Curtius_KnifflerC);
396-
397403
Trace.TraceInformation("Slip control system: {0}, Traction motor type: {1}", SlipControlSystem.ToString(), TractionMotorType.ToString()); // Slip control
398404

399405
Trace.TraceInformation("Apparent (Design) Adhesion: Zero - {0:N2} @ {1}, Max Continuous Speed - {2:N2} @ {3}, Drive Wheel Weight - {4}", designadhesionzerospeed, FormatStrings.FormatSpeedDisplay(zerospeed, IsMetric), designadhesionmaxcontspeed, FormatStrings.FormatSpeedDisplay(SpeedOfMaxContinuousForceMpS, IsMetric), FormatStrings.FormatMass(DrvWheelWeightKg, IsMetric));
400406
Trace.TraceInformation("OR Calculated Adhesion Setting: Zero Speed - {0:N2} @ {1}, Dropoff Speed - {2:N2} @ {3}, Max Continuous Speed - {4:N2} @ {5}", configuredadhesionzerospeed, FormatStrings.FormatSpeedDisplay(zerospeed, IsMetric), configuredadhesiondropoffspeed, FormatStrings.FormatSpeedDisplay(dropoffspeed, IsMetric), configuredadhesionmaxcontinuousspeed, FormatStrings.FormatSpeedDisplay(SpeedOfMaxContinuousForceMpS, IsMetric));
401407
}
408+
}
402409

410+
if (Simulator.Settings.VerboseConfigurationMessages)
411+
{
403412
Trace.TraceInformation("===================================================================================================================\n\n");
404413
}
405414

0 commit comments

Comments
 (0)