31
31
using SharpDX . Direct3D9 ;
32
32
using Orts . Formats . OR ;
33
33
using static Orts . Simulation . RollingStocks . SubSystems . PowerTransmissions . Axle ;
34
+ using MonoGame . Framework . Utilities . Deflate ;
34
35
35
36
namespace Orts . Simulation . RollingStocks . SubSystems . PowerTransmissions
36
37
{
@@ -345,19 +346,32 @@ public void Copy(Axles other)
345
346
public void Initialize ( )
346
347
{
347
348
ResetTime = Car . Simulator . GameTime ;
349
+ int numForce = 0 ;
350
+ int numMotor = 0 ;
348
351
foreach ( var axle in AxleList )
349
352
{
350
- if ( Car is MSTSLocomotive locomotive )
353
+ if ( ! ( Car is MSTSLocomotive ) ) axle . DriveType = AxleDriveType . NotDriven ;
354
+ else if ( axle . DriveType == AxleDriveType . ForceDriven ) numForce ++ ;
355
+ else if ( axle . DriveType == AxleDriveType . MotorDriven ) numMotor ++ ;
356
+ }
357
+ foreach ( var axle in AxleList )
358
+ {
359
+ if ( numMotor > 0 && axle . DriveType == AxleDriveType . ForceDriven ) axle . DriveType = AxleDriveType . NotDriven ;
360
+ else if ( axle . DriveType == AxleDriveType . ForceDriven ) axle . TractiveForceFraction = 1.0f / numForce ;
361
+ else if ( axle . DriveType == AxleDriveType . MotorDriven ) axle . TractiveForceFraction = 1.0f / numMotor ;
362
+ int numDriven = numMotor > 0 ? numMotor : numForce ;
363
+ int numNotDriven = AxleList . Count - numDriven ;
364
+ var locomotive = Car as MSTSLocomotive ;
365
+ if ( locomotive != null )
351
366
{
352
- if ( axle . InertiaKgm2 <= 0 ) axle . InertiaKgm2 = locomotive . AxleInertiaKgm2 / AxleList . Count ;
353
- if ( axle . WheelWeightKg <= 0 ) axle . WheelWeightKg = locomotive . DrvWheelWeightKg / AxleList . Count ;
354
- if ( axle . AxleWeightN <= 0 ) axle . AxleWeightN = 9.81f * axle . WheelWeightKg ; //remains fixed for diesel/electric locomotives, but varies for steam locomotives
355
- if ( axle . NumWheelsetAxles <= 0 ) axle . NumWheelsetAxles = locomotive . LocoNumDrvAxles ;
356
- if ( axle . WheelRadiusM <= 0 ) axle . WheelRadiusM = locomotive . DriverWheelRadiusM ;
357
- if ( axle . WheelFlangeAngleRad <= 0 ) axle . WheelFlangeAngleRad = locomotive . MaximumWheelFlangeAngleRad ;
358
- if ( axle . DampingNs <= 0 ) axle . DampingNs = locomotive . MassKG / 1000.0f / AxleList . Count ;
359
- if ( axle . FrictionN <= 0 ) axle . FrictionN = locomotive . MassKG / 1000.0f / AxleList . Count ;
360
-
367
+ if ( axle . DriveType != AxleDriveType . NotDriven )
368
+ {
369
+ axle . BrakeForceFraction = 1.0f / ( locomotive . DriveWheelOnlyBrakes ? numDriven : AxleList . Count ) ;
370
+ if ( axle . WheelWeightKg <= 0 ) axle . WheelWeightKg = locomotive . DrvWheelWeightKg / numDriven ;
371
+ if ( axle . NumWheelsetAxles <= 0 ) axle . NumWheelsetAxles = locomotive . LocoNumDrvAxles / numDriven ;
372
+ if ( axle . WheelRadiusM <= 0 ) axle . WheelRadiusM = locomotive . DriverWheelRadiusM ;
373
+ }
374
+
361
375
// set the wheel slip threshold times for different types of locomotives
362
376
// Because of the irregular force around the wheel for a steam engine during a revolution, "response" time for warnings needs to be lower
363
377
if ( locomotive . EngineType == TrainCar . EngineTypes . Steam )
@@ -371,6 +385,23 @@ public void Initialize()
371
385
axle . WheelSlipWarningThresholdTimeS = 1 ;
372
386
}
373
387
}
388
+ if ( axle . DriveType == AxleDriveType . NotDriven )
389
+ {
390
+ var wagon = Car as MSTSWagon ;
391
+ axle . BrakeForceFraction = locomotive != null && locomotive . DriveWheelOnlyBrakes ? 0 : 1.0f / AxleList . Count ;
392
+ if ( axle . WheelWeightKg <= 0 )
393
+ {
394
+ if ( locomotive != null ) axle . WheelWeightKg = Math . Max ( ( Car . MassKG - locomotive . DrvWheelWeightKg ) / numNotDriven , 500 ) ;
395
+ else axle . WheelWeightKg = Car . MassKG / numNotDriven ;
396
+ }
397
+ if ( axle . NumWheelsetAxles <= 0 ) axle . NumWheelsetAxles = Math . Max ( Car . GetWagonNumAxles ( ) / numNotDriven , 1 ) ;
398
+ if ( axle . WheelRadiusM <= 0 ) axle . WheelRadiusM = wagon . WheelRadiusM ;
399
+ }
400
+ if ( axle . InertiaKgm2 <= 0 ) axle . InertiaKgm2 = ( Car as MSTSWagon ) . AxleInertiaKgm2 / AxleList . Count ;
401
+ if ( axle . WheelFlangeAngleRad <= 0 ) axle . WheelFlangeAngleRad = Car . MaximumWheelFlangeAngleRad ;
402
+ if ( axle . AxleWeightN <= 0 ) axle . AxleWeightN = 9.81f * axle . WheelWeightKg ; //remains fixed for diesel/electric locomotives, but varies for steam locomotives
403
+ if ( axle . DampingNs <= 0 ) axle . DampingNs = axle . WheelWeightKg / 1000.0f ;
404
+ if ( axle . FrictionN <= 0 ) axle . FrictionN = axle . WheelWeightKg / 1000.0f ;
374
405
axle . Initialize ( ) ;
375
406
}
376
407
}
@@ -529,6 +560,15 @@ public class Axle : ISubSystem<Axle>
529
560
{
530
561
public int NumOfSubstepsPS { get ; set ; }
531
562
563
+ /// <summary>
564
+ /// Contribution of this axle to the total tractive force
565
+ /// </summary>
566
+ public float TractiveForceFraction ;
567
+ /// <summary>
568
+ /// Contribution of this axle to the total brake force
569
+ /// </summary>
570
+ public float BrakeForceFraction ;
571
+
532
572
/// <summary>
533
573
/// Positive only brake force to the individual axle, in Newtons
534
574
/// </summary>
@@ -1261,6 +1301,7 @@ void Integrate(float elapsedClockSeconds)
1261
1301
public virtual void Update ( float elapsedSeconds )
1262
1302
{
1263
1303
bool advancedAdhesion = Car is MSTSLocomotive locomotive && locomotive . AdvancedAdhesionModel ;
1304
+ advancedAdhesion &= DriveType != AxleDriveType . NotDriven ; // Skip integrator for undriven axles to save CPU
1264
1305
forceToAccelerationFactor = WheelRadiusM * WheelRadiusM / totalInertiaKgm2 ;
1265
1306
if ( ! advancedAdhesion )
1266
1307
{
@@ -1390,8 +1431,25 @@ public void UpdateSimpleAdhesion(float elapsedClockSeconds)
1390
1431
if ( Math . Abs ( axleOutForceN ) > maxAdhesionForceN )
1391
1432
{
1392
1433
axleOutForceN = MathHelper . Clamp ( axleOutForceN , - maxAdhesionForceN , maxAdhesionForceN ) ;
1393
- if ( Car is MSTSLocomotive locomotive && ! locomotive . AntiSlip && locomotive . SlipControlSystem == MSTSLocomotive . SlipControlType . None ) axleOutForceN *= locomotive . Adhesion1 ;
1394
- //else if (!(Car is MSTSLocomotive) && Car.Simulator.UseAdvancedAdhesion && !Car.Simulator.Settings.SimpleControlPhysics && Car.IsPlayerTrain) axleOutForceN = MathHelper.Clamp(axleOutForceN, -);
1434
+ if ( ! Car . Simulator . UseAdvancedAdhesion || Car . Simulator . Settings . SimpleControlPhysics || ! Car . Train . IsPlayerDriven )
1435
+ {
1436
+ if ( Car is MSTSLocomotive locomotive && ! locomotive . AntiSlip ) axleOutForceN *= locomotive . Adhesion1 ;
1437
+ }
1438
+ else
1439
+ {
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
+ }
1451
+ axleOutForceN = MathHelper . Clamp ( axleOutForceN , - adhesionForceN , adhesionForceN ) ;
1452
+ }
1395
1453
1396
1454
HuDIsWheelSlip = HuDIsWheelSlipWarning = IsWheelSlip = IsWheelSlipWarning = true ;
1397
1455
@@ -1418,7 +1476,7 @@ public void UpdateSimpleAdhesion(float elapsedClockSeconds)
1418
1476
}
1419
1477
AxlePositionRad += AxleSpeedMpS / WheelRadiusM * elapsedClockSeconds ;
1420
1478
1421
- if ( Math . Abs ( TrainSpeedMpS ) < 0.001f && Math . Abs ( axleInForceN ) < frictionForceN )
1479
+ if ( Math . Abs ( TrainSpeedMpS ) < 0.001f && Math . Abs ( axleInForceN ) < totalFrictionForceN )
1422
1480
{
1423
1481
axleOutForceN = 0 ;
1424
1482
}
0 commit comments