Skip to content

Commit df8a6f3

Browse files
committed
Tune zero-speed adhesion
1 parent e5815eb commit df8a6f3

File tree

2 files changed

+38
-38
lines changed

2 files changed

+38
-38
lines changed

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

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -416,34 +416,23 @@ public void Save(BinaryWriter outf)
416416
}
417417

418418
/// <summary>
419-
/// Compute variation in axle dynamics. Calculates axle speed, axle angular position and rail force.
419+
/// Compute variation in axle dynamics. Calculates axle speed, axle angular position and in/out forces.
420420
/// </summary>
421-
public (float, float, float) GetAxleMotionVariation(float axleSpeedMpS)
421+
public (float, float, float, float) GetAxleMotionVariation(float axleSpeedMpS)
422422
{
423-
float axleForceN = AxleWeightN * SlipCharacteristics(axleSpeedMpS - TrainSpeedMpS, TrainSpeedMpS, AdhesionK, AdhesionLimit);
423+
float axleOutForceN = AxleWeightN * SlipCharacteristics(axleSpeedMpS - TrainSpeedMpS, TrainSpeedMpS, AdhesionK, AdhesionLimit);
424424

425-
float motiveAxleForceN = -axleForceN - dampingNs * (axleSpeedMpS - TrainSpeedMpS); // Force transmitted to rail + heat losses
425+
float axleInForceN = 0;
426426
if (DriveType == AxleDriveType.ForceDriven)
427-
motiveAxleForceN += DriveForceN * transmissionEfficiency;
427+
axleInForceN = DriveForceN * transmissionEfficiency;
428428
else if (DriveType == AxleDriveType.MotorDriven)
429-
motiveAxleForceN += motor.GetDevelopedTorqueNm(axleSpeedMpS * transmissionRatio / WheelRadiusM) * transmissionEfficiency / WheelRadiusM;
429+
axleInForceN = motor.GetDevelopedTorqueNm(axleSpeedMpS * transmissionRatio / WheelRadiusM) * transmissionEfficiency / WheelRadiusM;
430430

431-
// Dissipative forces: they will never increase wheel speed
432-
float frictionalForceN = BrakeRetardForceN + frictionN;
433-
434-
float totalAxleForceN = motiveAxleForceN - Math.Sign(axleSpeedMpS) * frictionalForceN;
435-
if (Math.Abs(axleSpeedMpS) < 0.01f)
436-
{
437-
if (motiveAxleForceN > frictionalForceN) totalAxleForceN = motiveAxleForceN - frictionalForceN;
438-
else if (motiveAxleForceN < -frictionalForceN) totalAxleForceN = motiveAxleForceN + frictionalForceN;
439-
else
440-
{
441-
totalAxleForceN = 0;
442-
axleForceN = 0;
443-
frictionalForceN -= Math.Abs(motiveAxleForceN);
444-
}
445-
}
446-
return (totalAxleForceN * forceToAccelerationFactor, axleSpeedMpS / WheelRadiusM, axleForceN);
431+
float totalAxleForceN = axleInForceN - axleOutForceN - dampingNs * (axleSpeedMpS - TrainSpeedMpS); // Force transmitted to rail + heat losses
432+
433+
totalAxleForceN -= Math.Sign(axleSpeedMpS) * (BrakeRetardForceN + frictionN); // Dissipative forces: they will never increase wheel speed
434+
435+
return (totalAxleForceN * forceToAccelerationFactor, axleSpeedMpS / WheelRadiusM, axleOutForceN, axleInForceN);
447436
}
448437

449438
/// <summary>
@@ -473,30 +462,40 @@ void Integrate(float elapsedClockSeconds)
473462
NumOfSubstepsPS = Math.Max(Math.Min(NumOfSubstepsPS, 50), 1);
474463
float dt = elapsedClockSeconds / NumOfSubstepsPS;
475464
float hdt = dt / 2.0f;
476-
float axleForceSumN = 0;
465+
float axleInForceSumN = 0;
466+
float axleOutForceSumN = 0;
477467
for (int i=0; i<NumOfSubstepsPS; i++)
478468
{
479469
var k1 = GetAxleMotionVariation(AxleSpeedMpS);
480-
if (i == 0 && k1.Item1 * dt > Math.Max((Math.Abs(SlipSpeedMpS) - 1) * 10, 1) / 100)
470+
if (i == 0)
481471
{
482-
NumOfSubstepsPS = Math.Min(NumOfSubstepsPS + 5, 50);
483-
dt = elapsedClockSeconds / NumOfSubstepsPS;
484-
hdt = dt / 2;
472+
if (k1.Item1 * dt > Math.Max((Math.Abs(SlipSpeedMpS) - 1) * 10, 1) / 100)
473+
{
474+
NumOfSubstepsPS = Math.Min(NumOfSubstepsPS + 5, 50);
475+
dt = elapsedClockSeconds / NumOfSubstepsPS;
476+
hdt = dt / 2;
477+
}
478+
if (Math.Sign(AxleSpeedMpS + k1.Item1 * dt) != Math.Sign(AxleSpeedMpS) && BrakeRetardForceN + frictionN > Math.Abs(driveForceN - k1.Item3))
479+
{
480+
AxlePositionRad += AxleSpeedMpS * hdt;
481+
AxlePositionRad = MathHelper.WrapAngle(AxlePositionRad);
482+
AxleSpeedMpS = 0;
483+
AxleForceN = 0;
484+
DriveForceN = k1.Item4;
485+
return;
486+
}
485487
}
486488
var k2 = GetAxleMotionVariation(AxleSpeedMpS + k1.Item1 * hdt);
487489
var k3 = GetAxleMotionVariation(AxleSpeedMpS + k2.Item1 * hdt);
488490
var k4 = GetAxleMotionVariation(AxleSpeedMpS + k3.Item1 * dt);
489491
AxleSpeedMpS += (integratorError = (k1.Item1 + 2 * (k2.Item1 + k3.Item1) + k4.Item1) * dt / 6.0f);
490492
AxlePositionRad += (k1.Item2 + 2 * (k2.Item2 + k3.Item2) + k4.Item2) * dt / 6.0f;
491-
axleForceSumN += (k1.Item3 + 2 * (k2.Item3 + k3.Item3) + k4.Item3);
493+
axleOutForceSumN += (k1.Item3 + 2 * (k2.Item3 + k3.Item3) + k4.Item3);
494+
axleInForceSumN += (k1.Item4 + 2 * (k2.Item4 + k3.Item4) + k4.Item4);
492495
}
493-
AxleForceN = axleForceSumN / (NumOfSubstepsPS * 6);
496+
AxleForceN = axleOutForceSumN / (NumOfSubstepsPS * 6);
497+
DriveForceN = axleInForceSumN / (NumOfSubstepsPS * 6);
494498
AxlePositionRad = MathHelper.WrapAngle(AxlePositionRad);
495-
496-
if ((prevSpeedMpS > 0 && AxleSpeedMpS <= 0) || (prevSpeedMpS < 0 && AxleSpeedMpS >= 0))
497-
{
498-
if (Math.Max(BrakeRetardForceN, frictionN) > Math.Abs(driveForceN - AxleForceN)) Reset();
499-
}
500499
}
501500

502501
/// <summary>
@@ -540,6 +539,9 @@ void StationaryCalculation(float elapsedClockSeconds)
540539
public virtual void Update(float timeSpan)
541540
{
542541
forceToAccelerationFactor = WheelRadiusM * WheelRadiusM / totalInertiaKgm2;
542+
543+
motor?.Update(timeSpan);
544+
543545
Integrate(timeSpan);
544546
// TODO: We should calculate brake force here
545547
// Adding and substracting the brake force is correct for normal operation,
@@ -551,8 +553,6 @@ public virtual void Update(float timeSpan)
551553
CompensatedAxleForceN = AxleForceN + Math.Sign(TrainSpeedMpS) * BrakeRetardForceN;
552554
if (AxleForceN == 0) CompensatedAxleForceN = 0;
553555

554-
motor?.Update(timeSpan);
555-
556556
if (timeSpan > 0.0f)
557557
{
558558
slipDerivationMpSS = (SlipSpeedMpS - previousSlipSpeedMpS) / timeSpan;

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ public override void Update(float timeSpan)
5050
float linToAngFactor = AxleConnected.TransmissionRatio / AxleConnected.WheelRadiusM;
5151
if (SlipControl)
5252
{
53-
if (TargetForceN > 0) DriveSpeedRadpS = (AxleConnected.TrainSpeedMpS + AxleConnected.WheelSlipThresholdMpS * 0.99f) * linToAngFactor + OptimalAsyncSpeedRadpS;
54-
else if (TargetForceN < 0) DriveSpeedRadpS = (AxleConnected.TrainSpeedMpS - AxleConnected.WheelSlipThresholdMpS * 0.99f) * linToAngFactor - OptimalAsyncSpeedRadpS;
53+
if (TargetForceN > 0) DriveSpeedRadpS = (AxleConnected.TrainSpeedMpS + AxleConnected.WheelSlipThresholdMpS * 0.95f) * linToAngFactor + OptimalAsyncSpeedRadpS;
54+
else if (TargetForceN < 0) DriveSpeedRadpS = (AxleConnected.TrainSpeedMpS - AxleConnected.WheelSlipThresholdMpS * 0.95f) * linToAngFactor - OptimalAsyncSpeedRadpS;
5555
}
5656
else
5757
{

0 commit comments

Comments
 (0)