@@ -936,6 +936,11 @@ public float SlipSpeedPercent
936936 }
937937 }
938938
939+ /// <summary>
940+ /// Percentage of wheelslip (different models use different observables to calculate it)
941+ /// </summary>
942+ public float SlipPercent ;
943+
939944 /// <summary>
940945 /// Slip speed rate of change value, in metric (meters per second) per second
941946 /// </summary>
@@ -1097,7 +1102,7 @@ public void Save(BinaryWriter outf)
10971102 {
10981103 double slipSpeedMpS = axleSpeedMpS - TrainSpeedMpS ;
10991104 // Compute force transmitted to rail according to adhesion curves
1100- double axleOutForceN = 0 ;
1105+ double axleOutForceN ;
11011106 if ( Axles . UsePolachAdhesion )
11021107 {
11031108 axleOutForceN = Math . Sign ( slipSpeedMpS ) * AxleWeightN * SlipCharacteristicsPolach ( slipSpeedMpS ) ;
@@ -1361,51 +1366,52 @@ public virtual void Update(float elapsedSeconds)
13611366 if ( advancedAdhesion )
13621367 {
13631368 Integrate ( elapsedSeconds ) ;
1364- if ( SlipSpeedPercent > ( Car is MSTSLocomotive loco && loco . SlipControlSystem == MSTSLocomotive . SlipControlType . Full ? ( 200 - SlipWarningTresholdPercent ) : 100 ) )
1365- {
1366- // Wheel slip internally happens instantaneously, but may correct itself in a short period, so HuD indication has a small time delay to eliminate "false" indications
1367- IsWheelSlip = IsWheelSlipWarning = true ;
13681369
1369- // Wait some time before indicating the HuD wheelslip to avoid false triggers
1370- // TODO: set an increased HUD wheelslip threshold if a slip control system is fitted, as it operates close to the wheelslip threshold
1371- if ( WheelSlipTimeS > WheelSlipThresholdTimeS )
1372- {
1373- HuDIsWheelSlip = HuDIsWheelSlipWarning = true ;
1374- }
1375- WheelSlipTimeS += elapsedSeconds ;
1376- }
1377- else if ( Math . Abs ( SlipSpeedPercent ) > SlipWarningTresholdPercent )
1378- {
1379- // Wheel slip internally happens instantaneously, but may correct itself in a short period, so HuD indication has a small time delay to eliminate "false" indications
1380- IsWheelSlipWarning = true ;
1381- IsWheelSlip = false ;
1382-
1383- // Wait some time before indicating wheelslip to avoid false triggers
1384- if ( WheelSlipWarningTimeS > WheelSlipWarningThresholdTimeS ) HuDIsWheelSlipWarning = true ;
1385- HuDIsWheelSlip = false ;
1386- WheelSlipWarningTimeS += elapsedSeconds ;
1387- }
1388- else
1370+ SlipPercent = SlipSpeedPercent ;
1371+
1372+ if ( elapsedSeconds > 0.0f )
13891373 {
1390- HuDIsWheelSlipWarning = false ;
1391- HuDIsWheelSlip = false ;
1392- IsWheelSlipWarning = false ;
1393- IsWheelSlip = false ;
1394- WheelSlipWarningTimeS = WheelSlipTimeS = 0 ;
1374+ slipDerivationMpSS = ( SlipSpeedMpS - previousSlipSpeedMpS ) / elapsedSeconds ;
1375+ previousSlipSpeedMpS = SlipSpeedMpS ;
1376+
1377+ slipDerivationPercentpS = ( SlipSpeedPercent - previousSlipPercent ) / elapsedSeconds ;
1378+ previousSlipPercent = SlipSpeedPercent ;
13951379 }
13961380 }
13971381 else
13981382 {
13991383 UpdateSimpleAdhesion ( elapsedSeconds ) ;
14001384 }
1385+ if ( SlipPercent > ( Car is MSTSLocomotive loco && loco . SlipControlSystem == MSTSLocomotive . SlipControlType . Full && Math . Abs ( DriveForceN ) > BrakeRetardForceN ? ( 200 - SlipWarningTresholdPercent ) : 100 ) )
1386+ {
1387+ // Wheel slip internally happens instantaneously, but may correct itself in a short period, so HuD indication has a small time delay to eliminate "false" indications
1388+ IsWheelSlip = IsWheelSlipWarning = true ;
14011389
1402- if ( elapsedSeconds > 0.0f )
1390+ // Wait some time before indicating the HuD wheelslip to avoid false triggers
1391+ if ( WheelSlipTimeS > WheelSlipThresholdTimeS )
1392+ {
1393+ HuDIsWheelSlip = HuDIsWheelSlipWarning = true ;
1394+ }
1395+ WheelSlipTimeS += elapsedSeconds ;
1396+ }
1397+ else if ( SlipPercent > SlipWarningTresholdPercent )
14031398 {
1404- slipDerivationMpSS = ( SlipSpeedMpS - previousSlipSpeedMpS ) / elapsedSeconds ;
1405- previousSlipSpeedMpS = SlipSpeedMpS ;
1399+ // Wheel slip internally happens instantaneously, but may correct itself in a short period, so HuD indication has a small time delay to eliminate "false" indications
1400+ IsWheelSlipWarning = true ;
1401+ IsWheelSlip = false ;
14061402
1407- slipDerivationPercentpS = ( SlipSpeedPercent - previousSlipPercent ) / elapsedSeconds ;
1408- previousSlipPercent = SlipSpeedPercent ;
1403+ // Wait some time before indicating wheelslip to avoid false triggers
1404+ if ( WheelSlipWarningTimeS > WheelSlipWarningThresholdTimeS ) HuDIsWheelSlipWarning = true ;
1405+ HuDIsWheelSlip = false ;
1406+ WheelSlipWarningTimeS += elapsedSeconds ;
1407+ }
1408+ else
1409+ {
1410+ HuDIsWheelSlipWarning = false ;
1411+ HuDIsWheelSlip = false ;
1412+ IsWheelSlipWarning = false ;
1413+ IsWheelSlip = false ;
1414+ WheelSlipWarningTimeS = WheelSlipTimeS = 0 ;
14091415 }
14101416 }
14111417
@@ -1427,56 +1433,45 @@ public void UpdateSimpleAdhesion(float elapsedClockSeconds)
14271433 AxleFrictionForceN = frictionForceN ;
14281434 AxleSpeedMpS = TrainSpeedMpS ;
14291435
1430- float maxAdhesionForceN = AxleWeightN * AdhesionLimit ;
1431- if ( Math . Abs ( axleOutForceN ) > maxAdhesionForceN )
1436+ float adhesionForceN = AxleWeightN * AdhesionLimit ;
1437+ SlipPercent = Math . Abs ( axleOutForceN ) / adhesionForceN * 100 ;
1438+ if ( SlipPercent > 100 )
14321439 {
1433- axleOutForceN = MathHelper . Clamp ( axleOutForceN , - maxAdhesionForceN , maxAdhesionForceN ) ;
1434- if ( ! Car . Simulator . UseAdvancedAdhesion || Car . Simulator . Settings . SimpleControlPhysics || ! Car . Train . IsPlayerDriven )
1440+ axleOutForceN = MathHelper . Clamp ( axleOutForceN , - adhesionForceN , adhesionForceN ) ;
1441+ // Simple adhesion, simple wheelslip conditions
1442+ if ( Car is MSTSLocomotive locomotive && ! locomotive . AdvancedAdhesionModel )
14351443 {
1436- if ( Car is MSTSLocomotive locomotive && ! locomotive . AntiSlip ) axleOutForceN *= locomotive . Adhesion1 ;
1444+ if ( ! locomotive . AntiSlip ) axleOutForceN *= locomotive . Adhesion1 ;
1445+ else SlipPercent = 100 ;
14371446 }
1447+ else if ( ! Car . Simulator . UseAdvancedAdhesion || Car . Simulator . Settings . SimpleControlPhysics || ! Car . Train . IsPlayerDriven )
1448+ {
1449+ // No wagon skid in simple adhesion
1450+ SlipPercent = 100 ;
1451+ }
1452+ // Semi-advanced adhesion. Used in non-driven axles when advanced adhesion is enabled, to avoid running the integrator
14381453 else
14391454 {
1440- float adhesionForceN ;
1441- if ( ( TrainSpeedMpS > 0 && axleOutForceN < 0 ) || ( TrainSpeedMpS < 0 && axleOutForceN > 0 ) )
1442- {
1443- // Compute adhesion as if wheel is fully locked
1444- adhesionForceN = AxleWeightN * SlipCharacteristicsPacha ( - TrainSpeedMpS , TrainSpeedMpS , AdhesionK , AdhesionLimit ) ;
1445- }
1446- else
1447- {
1448- // Get asymptotic (dynamic) adhesion coefficient
1449- adhesionForceN = AxleWeightN * SlipCharacteristicsPacha ( 1000.0f , Math . Abs ( TrainSpeedMpS ) , AdhesionK , AdhesionLimit ) ;
1450- }
1455+ // For non-driven axles, only brake skid is possible (no wheel slip). Consider wheels to be fully locked
1456+ AxleSpeedMpS = 0 ;
1457+ // Use the advanced adhesion coefficient
1458+ adhesionForceN = AxleWeightN * SlipCharacteristicsPacha ( SlipSpeedMpS , TrainSpeedMpS , AdhesionK , AdhesionLimit ) ;
14511459 axleOutForceN = MathHelper . Clamp ( axleOutForceN , - adhesionForceN , adhesionForceN ) ;
14521460 }
1453-
1454- HuDIsWheelSlip = HuDIsWheelSlipWarning = IsWheelSlip = IsWheelSlipWarning = true ;
1455-
1456- if ( ( TrainSpeedMpS > 0 && axleOutForceN < 0 ) || ( TrainSpeedMpS < 0 && axleOutForceN > 0 ) )
1461+ // In case of wheel skid, reduce indicated brake force
1462+ if ( ( ( TrainSpeedMpS > 0 && axleOutForceN < 0 ) || ( TrainSpeedMpS < 0 && axleOutForceN > 0 ) ) && Math . Abs ( DriveForceN ) < BrakeRetardForceN && Math . Sign ( TrainSpeedMpS ) * ( - axleOutForceN + axleInForceN ) - frictionForceN > 0 )
14571463 {
1458- if ( Math . Abs ( axleInForceN ) < BrakeRetardForceN && Math . Sign ( TrainSpeedMpS ) * ( - axleOutForceN + axleInForceN ) - frictionForceN > 0 )
1459- {
1460- AxleBrakeForceN = Math . Sign ( TrainSpeedMpS ) * ( - axleOutForceN + axleInForceN ) - frictionForceN ;
1461- AxleSpeedMpS = 0 ;
1462- }
1463- else
1464- {
1465- AxleMotiveForceN = axleOutForceN + Math . Sign ( TrainSpeedMpS ) * totalFrictionForceN ;
1466- }
1464+ AxleBrakeForceN = Math . Sign ( TrainSpeedMpS ) * ( - axleOutForceN + axleInForceN ) - frictionForceN ;
14671465 }
1466+ // Otherwise, indicate that slip is reducing motive force
14681467 else
14691468 {
14701469 AxleMotiveForceN = axleOutForceN + Math . Sign ( TrainSpeedMpS ) * totalFrictionForceN ;
14711470 }
14721471 }
1473- else
1474- {
1475- HuDIsWheelSlip = HuDIsWheelSlipWarning = IsWheelSlip = IsWheelSlipWarning = false ;
1476- }
14771472 AxlePositionRad += AxleSpeedMpS / WheelRadiusM * elapsedClockSeconds ;
14781473
1479- if ( Math . Abs ( TrainSpeedMpS ) < 0.001f && Math . Abs ( axleInForceN ) < totalFrictionForceN )
1474+ if ( Math . Abs ( TrainSpeedMpS ) < 0.001f && Math . Abs ( DriveForceN ) < totalFrictionForceN )
14801475 {
14811476 axleOutForceN = 0 ;
14821477 }
0 commit comments