@@ -102,6 +102,8 @@ public class MSTSSteamLocomotive : MSTSLocomotive
102102 public MSTSNotchController SmallEjectorController = new MSTSNotchController ( 0 , 1 , 0.1f ) ;
103103 public MSTSNotchController LargeEjectorController = new MSTSNotchController ( 0 , 1 , 0.1f ) ;
104104
105+ float DebugTimerS ;
106+
105107 public bool Injector1IsOn ;
106108 bool Injector1SoundIsOn = false ;
107109 public bool Injector2IsOn ;
@@ -2105,29 +2107,7 @@ private void UpdateFX(float elapsedClockSeconds)
21052107 for ( int i = 0 ; i < NumCylinders ; i ++ )
21062108 {
21072109
2108- // Trace.TraceInformation("NumCyl - {0} i {1}", NumCylinders, i);
2109-
2110- // float realCrankAngleRad = (float)(LocomotiveAxle.AxlePositionRad + i * WheelCrankAngleDiffRad[i]);
2111- float realCrankAngleRad = ( float ) ( LocomotiveAxles [ 0 ] . AxlePositionRad ) ;
2112- float normalisedCrankAngleRad = 0 ;
2113-
2114- realCrankAngleRad = ( float ) ( MathHelper . WrapAngle ( realCrankAngleRad ) ) ;
2115-
2116- if ( realCrankAngleRad < 0 )
2117- {
2118- realCrankAngleRad = ( float ) ( 2.0f * Math . PI + realCrankAngleRad ) ; // angle must be maintained in a +ve range, ie 0 - 360
2119- }
2120-
2121- // Normalise crank angle so that it is a value between 0 and 360 starting at the real crank angle difference
2122- if ( realCrankAngleRad >= WheelCrankAngleDiffRad [ i ] )
2123- {
2124- normalisedCrankAngleRad = realCrankAngleRad - WheelCrankAngleDiffRad [ i ] ;
2125- }
2126- else
2127- {
2128- float diff = WheelCrankAngleDiffRad [ i ] - realCrankAngleRad ;
2129- normalisedCrankAngleRad = ( float ) ( 2.0f * Math . PI - diff ) ;
2130- }
2110+ float normalisedCrankAngleRad = NormalisedCrankAngle ( i ) ;
21312111
21322112 // Exhaust crank angle
21332113 float exhaustCrankAngleRad = 0 ;
@@ -5043,7 +5023,6 @@ protected override void UpdateTractiveForce(float elapsedClockSeconds, float t,
50435023 LPslipBackPressureAtmPSI = LPCompPressure_m_AtmPSI ;
50445024 LPslipCompressionPressureAtmPSI = LPCompPressure_n_AtmPSI ;
50455025 LPslipAdmissionPressureAtmPSI = LPCompPressure_q_AtmPSI ;
5046-
50475026 }
50485027 else // Simple mode
50495028 {
@@ -5062,7 +5041,6 @@ protected override void UpdateTractiveForce(float elapsedClockSeconds, float t,
50625041 LPslipBackPressureAtmPSI = LPPressure_d_AtmPSI ;
50635042 LPslipCompressionPressureAtmPSI = LPPressure_e_AtmPSI ;
50645043 LPslipAdmissionPressureAtmPSI = LPPressure_f_AtmPSI ;
5065-
50665044 }
50675045 }
50685046 else // simple locomotive
@@ -5073,29 +5051,26 @@ protected override void UpdateTractiveForce(float elapsedClockSeconds, float t,
50735051 slipBackPressureAtmPSI = Pressure_d_AtmPSI ;
50745052 slipCompressionPressureAtmPSI = Pressure_e_AtmPSI ;
50755053 slipAdmissionPressureAtmPSI = Pressure_f_AtmPSI ;
5076-
5077- // Trace.TraceInformation("Initialise IntialPressure {0} Pressure A {1}", slipInitialPressureAtmPSI, Pressure_a_AtmPSI);
5078-
50795054 }
50805055
50815056 TractiveForceN = 0 ;
50825057 float totalDrvWeightN = 0 ;
50835058 DisplayTangentialWheelTreadForceLbf = 0 ;
5084- float testCrankAngle = 0 ;
5085-
5059+
50865060 for ( int i = 0 ; i < NumCylinders ; i ++ )
50875061 {
5088- float crankAngleRad = ( float ) ( LocomotiveAxles [ 0 ] . AxlePositionRad + i * WheelCrankAngleDiffRad [ i ] ) ;
5062+ // This feature sues some different reference angles as follows:
5063+ // AxlePositionRad - comes from the axle module and is -180 - 0 - 180
5064+ // Crank Angle - converts the above range to 0 - 180 - 0 - this is the principle reference used so that it lines up with reference
5065+ // tables used to buold this function
5066+ // Normalised Crank Angle - converts the above to a 0 - 360 range, this is used for triggering special steam effects, etc.
5067+ float axlePostionRad = LocomotiveAxles [ 0 ] . AxlePositionRad ;
5068+ float crankAngleRad = ( float ) ( axlePostionRad + WheelCrankAngleDiffRad [ i ] ) ;
50895069
5090- testCrankAngle = crankAngleRad ;
5091-
5092- crankAngleRad = ( float ) ( MathHelper . WrapAngle ( crankAngleRad ) ) ;
5093-
5094- // Trace.TraceInformation("Cyl {0} crankAng {1} Position {2} Diff {3}", NumCylinders, MathHelper.ToDegrees(crankAngleRad), MathHelper.ToDegrees(LocomotiveAxle.AxlePositionRad), MathHelper.ToDegrees(WheelCrankAngleDiffRad));
5070+ crankAngleRad = ( float ) ( MathHelper . WrapAngle ( crankAngleRad ) ) ; // Ensures that crank angle is in the range 0 - 180 - 0
50955071
50965072 float crankCylinderPressure = ( MeanEffectivePressurePSI * CylinderEfficiencyRate ) ; // fallback default value
50975073
5098-
50995074 // Calculate cylinder position in relation to crank (and hence wheel) position.
51005075 // For each full wheel revolution, the cylinder will do two storkes (forward and backwards).
51015076 // Each stroke in turn will have a forward component with a corresponding pressure producing a "+ve" force and reverse component producing a "-ve" force.
@@ -5122,9 +5097,7 @@ protected override void UpdateTractiveForce(float elapsedClockSeconds, float t,
51225097 backwardCylinderPosition = crankCylinderPosition ;
51235098 }
51245099
5125- /*
5126- Trace.TraceInformation("Cyl {0} Position {1} testcrankAng {2} crankAngle {3} CrankPosition {4} forwardCrankPosition {5} backwardCrankPosition {6}", i+1, LocomotiveAxle.AxlePositionRad, MathHelper.ToDegrees(testCrankAngle), MathHelper.ToDegrees(crankAngleRad), crankCylinderPosition, forwardCylinderPosition, backwardCylinderPosition);
5127- */
5100+ float normalisedCrankAngleRad = NormalisedCrankAngle ( i ) ;
51285101
51295102 // Crank angles
51305103 float sin = ( float ) Math . Sin ( crankAngleRad ) ;
@@ -5177,13 +5150,6 @@ protected override void UpdateTractiveForce(float elapsedClockSeconds, float t,
51775150 crankCylinderPressure = 0 ;
51785151 }
51795152
5180- #if DEBUG_STEAM_SLIP
5181- if ( throttle > 0.01 && ( absSpeedMpS < 0.2 || absSpeedMpS > 17.9 && absSpeedMpS < 18.1 || absSpeedMpS > 35.5 && absSpeedMpS < 35.9 ) )
5182- {
5183- Trace . TraceInformation ( "Cylinder {0} CrankAngle {1} FwdCylPosition {2} FwdCylPressure {3} BwdCylPosition {4} BwdCylPressure {5} CrankPressure {6} ForwardStroke {7} Speed {8}" , i , MathHelper . ToDegrees ( crankAngleRad ) , forwardCylinderPosition , forwardCylinderPressure , backwardCylinderPosition , backwardCylinderPressure , crankCylinderPressure , forwardStroke , MpS . ToMpH ( absSpeedMpS ) ) ;
5184- }
5185- #endif
5186-
51875153 // Calculate wheel tangential forces = Force applied to wheels
51885154
51895155 float pistonForceLbf = Me2 . ToIn2 ( Me2 . FromFt2 ( CylinderPistonAreaFt2 ) ) * crankCylinderPressure ;
@@ -5192,24 +5158,12 @@ protected override void UpdateTractiveForce(float elapsedClockSeconds, float t,
51925158
51935159 float tangentialForcelbf = tangentialCrankForceFactor * pistonForceLbf ;
51945160
5195-
51965161 float reciprocatingInertiaAngleFactor = 0 ;
51975162 float connectRodInertiaAngleFactor = 0 ;
51985163
51995164 // Calculate the "angle variation factors" for the Inertia
5200- // Account for the position of the crosshead position. In other words it depends upon whether the Rods and Reciporating gear is above or below the axle.
5201- if ( crankAngleRad > 0 && crankAngleRad < Math . PI )
5202- {
5203- // forward stroke
5204- reciprocatingInertiaAngleFactor = ( cos + ( ( CrankRadiusFt / ConnectRodLengthFt ) * ( float ) Math . Cos ( 2 * crankAngleRad ) ) ) ;
5205- connectRodInertiaAngleFactor = ( cos + ( ( CrankRadiusFt * RodCoGFt ) / ( ConnectRodLengthFt * ConnectRodLengthFt ) ) * ( float ) Math . Cos ( 2 * crankAngleRad ) ) ;
5206- }
5207- else
5208- {
5209- // reverse stroke
5210- reciprocatingInertiaAngleFactor = ( cos - ( ( CrankRadiusFt / ConnectRodLengthFt ) * ( float ) Math . Cos ( 2 * crankAngleRad ) ) ) ;
5211- connectRodInertiaAngleFactor = ( cos - ( ( CrankRadiusFt * RodCoGFt ) / ( ConnectRodLengthFt * ConnectRodLengthFt ) ) * ( float ) Math . Cos ( 2 * crankAngleRad ) ) ;
5212- }
5165+ reciprocatingInertiaAngleFactor = ( cos + ( ( CrankRadiusFt / ConnectRodLengthFt ) * ( float ) Math . Cos ( 2 * crankAngleRad ) ) ) ;
5166+ connectRodInertiaAngleFactor = ( cos + ( ( CrankRadiusFt * RodCoGFt ) / ( ConnectRodLengthFt * ConnectRodLengthFt ) ) * ( float ) Math . Cos ( 2 * crankAngleRad ) ) ;
52135167
52145168 // Calculate the speed factor to allow for variation in speed
52155169 // Adjust the above factor to allow for the speed of rotation on the parts - based upon Eq 8 (pg 21)
@@ -5223,7 +5177,8 @@ protected override void UpdateTractiveForce(float elapsedClockSeconds, float t,
52235177 float connectRodInertiaForcelbf = inertiaSpeedCorrectionFactor * connectRodInertiaAngleFactor * ConnectingRodWeightLb ;
52245178
52255179 // Account for the position of the crosshead position. In other words it depends upon whether the Rods and Reciporating gear is above or below the axle.
5226- if ( crankAngleRad > 0 && crankAngleRad < Math . PI )
5180+ // The crosshead will be -ve for normalised angles between 0 - 180, and +ve for normalised angles between 180 - 360
5181+ if ( normalisedCrankAngleRad > 0 && normalisedCrankAngleRad < Math . PI )
52275182 {
52285183 reciprocatingInertiaForcelbf *= - 1 ;
52295184 connectRodInertiaForcelbf *= - 1 ;
@@ -5247,8 +5202,24 @@ protected override void UpdateTractiveForce(float elapsedClockSeconds, float t,
52475202 // To convert the force at the crank to the force at wheel tread = Crank Force * Cylinder Stroke / Diameter of Drive Wheel (inches) - internal friction
52485203 // should be deducted from this as well.
52495204 float tangentialWheelTreadForceLbf = tangentialCrankWheelForceLbf * Me . ToIn ( CylinderStrokeM ) / Me . ToIn ( DrvWheelDiaM ) ;
5205+
5206+ #if DEBUG_STEAM_SLIP
5207+ if ( SpeedMpS > 17.88 && SpeedMpS < 18.5 || SpeedMpS > 34.0 && throttle == 0 )
5208+ {
5209+ Trace . TraceInformation ( "Adhesion Debug - Cyl {0} Time {1} Speed {2} WheelRpM {3} CrankAngle {4} TotalTangForce {5} TangForce {6} TotalInertiaForce {7} TotalTangInertiaForce {8} RecipForce {9} RecipANgleFactor {10} RecipWeight {11} SpeedFactor {12} RodForce {13} RodAngleFactor {14} ForwardCyLPos {15} BackCylPos {16} CrankCylPos {17} NormCrankAngle {18} AxlePosnRad {19}" , i + 1 , DebugTimerS , MpS . ToMpH ( SpeedMpS ) , DrvWheelRevRpS * 60.0f , MathHelper . ToDegrees ( crankAngleRad ) , tangentialWheelTreadForceLbf , tangentialForcelbf , totalInertiaForcelbf , totalTangentialInertiaForcelbf , reciprocatingInertiaForcelbf , reciprocatingInertiaAngleFactor , ReciprocatingWeightLb , inertiaSpeedCorrectionFactor , connectRodInertiaForcelbf , connectRodInertiaAngleFactor , forwardCylinderPosition , backwardCylinderPosition , crankCylinderPosition , normalisedCrankAngleRad , axlePostionRad ) ;
5210+
5211+ DebugTimerS += elapsedClockSeconds ;
5212+ }
5213+
5214+ if ( SpeedMpS > 18.5 && SpeedMpS < 19 )
5215+ {
5216+ DebugTimerS = 0 ;
5217+ }
5218+
5219+ #endif
5220+
52505221 DisplayTangentialWheelTreadForceLbf += tangentialWheelTreadForceLbf ;
5251- TractiveForceN += N . FromLbf ( Math . Max ( tangentialWheelTreadForceLbf , - 1000 ) ) ;
5222+ TractiveForceN += N . FromLbf ( tangentialWheelTreadForceLbf ) ;
52525223
52535224 // ++++ Adhesive Force Calculation ++++++
52545225 // Calculation of components for use in wheel adhesive force calculation
@@ -5266,7 +5237,8 @@ protected override void UpdateTractiveForce(float elapsedClockSeconds, float t,
52665237 float excessBalanceForcelbf = inertiaSpeedCorrectionFactor * excessBalanceWeightLb * sin ;
52675238
52685239 // Account for the position of the crosshead position. In other words it depends upon whether the ExcessBalance is above or below the axle.
5269- if ( crankAngleRad > 0 && crankAngleRad < Math . PI )
5240+ // The crosshead will be -ve for normalised angles between 0 - 180, and +ve for normalised angles between 180 - 360
5241+ if ( normalisedCrankAngleRad > 0 && normalisedCrankAngleRad < Math . PI )
52705242 {
52715243 excessBalanceForcelbf *= - 1 ;
52725244 }
@@ -5289,70 +5261,10 @@ protected override void UpdateTractiveForce(float elapsedClockSeconds, float t,
52895261 {
52905262 totalDrvWeightN += N . FromLbf ( excessBalanceForcelbf - verticalThrustForcelbf ) ;
52915263 }
5292-
5293- /* if (DisplayTangentialWheelTreadForceLbf > SteamStaticWheelForce || WheelSlip)
5294- {
5295- // Trace.TraceInformation("MaxSpeed {0}", MaxLocoSpeedMpH);
5296-
5297- Trace.TraceInformation("Cylinder Pressures - Cylinder {0} CylinderPressure {1} forwardPressure {2} backwardPressure {3} InitialPressure {4} CutoffPressure {5} forwardPosition {6} backwardPosition {7}", i+1, crankCylinderPressure, forwardCylinderPressure, backwardCylinderPressure, slipInitialPressureAtmPSI, slipCutoffPressureAtmPSI, forwardCylinderPosition, backwardCylinderPosition);
5298-
5299- Trace.TraceInformation("Crank Angle {0} Cylinder Position {1} AxlePosition {2} Cylinder {3} CylArea {4} CylPress {5}", MathHelper.ToDegrees(crankAngleRad), crankCylinderPosition, MathHelper.ToDegrees(LocomotiveAxle.AxlePositionRad), i, Me2.ToIn2(Me2.FromFt2(CylinderPistonAreaFt2)), crankCylinderPressure);
5300-
5301- Trace.TraceInformation("Tang.CrankFactor {0} RecInertiaFactor {1}, ConInertiaFactor {2} VerticalForceFactor {3} InertiaSpeedFactor {4}", tangentialCrankForceFactor, reciprocatingInertiaAngleFactor, connectRodInertiaAngleFactor, verticalThrustFactor, inertiaSpeedCorrectionFactor);
5302-
5303- Trace.TraceInformation("PistonForce {0}lbf RodForce {1}lbf RecForce {2}lbf", pistonForceLbf, connectRodInertiaForcelbf, reciprocatingInertiaForcelbf);
5304-
5305- Trace.TraceInformation("VerticalThrustForce {0}lbf ExcessBalanceForce {1}lbf", verticalThrustForcelbf, excessBalanceForcelbf);
5306-
5307- }
5308- */
5309-
5310- #if DEBUG_STEAM_SLIP
5311- if ( throttle > 0.01 && ( absSpeedMpS < 0.2 || absSpeedMpS > 17.7 && absSpeedMpS < 18.2 ) )
5312- {
5313- // Trace.TraceInformation("MaxSpeed {0}", MaxLocoSpeedMpH);
5314-
5315- Trace . TraceInformation ( "Crank Angle {0} Cylinder Position {1} AxlePosition {2} Cylinder {3} CylArea {4} CylPress {5}" , MathHelper . ToDegrees ( crankAngleRad ) , crankCylinderPosition , MathHelper . ToDegrees ( LocomotiveAxle . AxlePositionRad ) , i , Me2 . ToIn2 ( Me2 . FromFt2 ( CylinderPistonAreaFt2 ) ) , crankCylinderPressure ) ;
5316-
5317- Trace . TraceInformation ( "Tang.CrankFactor {0} RecInertiaFactor {1}, ConInertiaFactor {2} VerticalForceFactor {3} InertiaSpeedFactor {4}" , tangentialCrankForceFactor , reciprocatingInertiaFactor , connectRodInertiaFactor , verticalThrustFactor , inertiaSpeedCorrectionFactor ) ;
5318-
5319- Trace . TraceInformation ( "PistonForce {0} RodForce {1} RecForce {2}" , pistonForceLbf , connectRodInertiaForce , reciprocatingInertiaForce ) ;
5320-
5321- Trace . TraceInformation ( "VerticalThrustForce {0} ExcessBalanceForce {1}" , verticalThrustForce , excessBalanceForce ) ;
5322-
5323- }
5324- #endif
53255264 }
53265265
53275266 LocomotiveAxles [ 0 ] . AxleWeightN = totalDrvWeightN + 9.81f * DrvWheelWeightKg ;
53285267 SteamStaticWheelForce = N . ToLbf ( totalDrvWeightN + 9.81f * DrvWheelWeightKg ) * LocomotiveCoefficientFrictionHUD ;
5329- /*
5330- if (DisplayTangentialWheelTreadForceLbf > SteamStaticWheelForce)
5331- {
5332- Trace.TraceInformation("Static Wheel Slip (initiated by static comparison) - TangForce {0}lbf: AdhesiveForce {1}lbf: Speed {2}mph, WheelSpeed {3}mph, CrankAngle {4}deg, AdvSlip {5}, AdvSlipWarn {6}, AxleInput - DriveForceCorrect {7}lbf, TotalDriveW {8}lbf, AxleWeightForce {9}lbf, Friction {10}, throttle {11}, Reverser {12} SlipThresholdSpeed {13}mph, WheelSlipSpeed {14}mph, AxleDriveForce {15}lbf", DisplayTangentialWheelTreadForceLbf, SteamStaticWheelForce, MpS.ToMpH(absSpeedMpS), MpS.ToMpH(WheelSpeedMpS), MathHelper.ToDegrees(testCrankAngle), WheelSlip, WheelSlipWarning, N.ToLbf(totalDrvWeightN), N.ToLbf(9.81f * DrvWheelWeightKg), N.ToLbf(LocomotiveAxle.AxleWeightN), LocomotiveCoefficientFrictionHUD, throttle, cutoff, MpS.ToMpH(LocomotiveAxle.WheelSlipThresholdMpS), MpS.ToMpH(LocomotiveAxle.SlipSpeedMpS), N.ToLbf(LocomotiveAxle.DriveForceN));
5333-
5334- }
5335-
5336- if (WheelSlip && DisplayTangentialWheelTreadForceLbf < SteamStaticWheelForce)
5337- {
5338- Trace.TraceInformation("Static Wheel Slip (initiated by axle model) - TangForce {0}lbf: AdhesiveForce {1}lbf: Speed {2}mph, WheelSpeed {3}mph, CrankAngle {4}deg, AdvSlip {5}, AdvSlipWarn {6}, AxleInput - DriveForceCorrect {7}lbf, TotalDriveW {8}lbf, AxleWeightForce {9}lbf, Friction {10}, throttle {11}, Reverser {12} SlipThresholdSpeed {13}mph, WheelSlipSpeed {14}mph, AxleDriveForce {15}lbf", DisplayTangentialWheelTreadForceLbf, SteamStaticWheelForce, MpS.ToMpH(absSpeedMpS), MpS.ToMpH(WheelSpeedMpS), MathHelper.ToDegrees(testCrankAngle), WheelSlip, WheelSlipWarning, N.ToLbf(totalDrvWeightN), N.ToLbf(9.81f * DrvWheelWeightKg), N.ToLbf(LocomotiveAxle.AxleWeightN), LocomotiveCoefficientFrictionHUD, throttle, cutoff, MpS.ToMpH(LocomotiveAxle.WheelSlipThresholdMpS), MpS.ToMpH(LocomotiveAxle.SlipSpeedMpS), N.ToLbf(LocomotiveAxle.DriveForceN));
5339-
5340- }
5341-
5342- */
5343-
5344- #if DEBUG_STEAM_SLIP
5345-
5346- if ( throttle > 0.01 && ( absSpeedMpS < 0.2 || absSpeedMpS > 17.7 && absSpeedMpS < 18.2 ) )
5347- {
5348- Trace . TraceInformation ( "RotationalForce {0} AdhesiveForce {1}" , N . ToLbf ( TractiveForceN ) , SteamStaticWheelForce ) ;
5349-
5350-
5351- }
5352-
5353- #endif
5354-
5355-
53565268 }
53575269 else // Set wheel speed if "simple" friction is used
53585270 {
@@ -5401,6 +5313,20 @@ protected override void UpdateTractiveForce(float elapsedClockSeconds, float t,
54015313 LocomotiveAxles [ 0 ] . DriveForceN = TractiveForceN ;
54025314 }
54035315
5316+ /// <summary>
5317+ /// Normalise crank angle so that it is a value between 0 and 360 starting at the real crank angle difference
5318+ /// </summary>
5319+ private float NormalisedCrankAngle ( int cylinderNumber )
5320+ {
5321+ float normalisedCrankAngleRad = ( float ) MathHelper . WrapAngle ( LocomotiveAxles [ 0 ] . AxlePositionRad + WheelCrankAngleDiffRad [ cylinderNumber ] ) ;
5322+
5323+ if ( normalisedCrankAngleRad < 0 )
5324+ {
5325+ normalisedCrankAngleRad += ( float ) ( 2 * Math . PI ) ;
5326+ }
5327+ return normalisedCrankAngleRad ;
5328+ }
5329+
54045330
54055331 public override void AdvancedAdhesion ( float elapsedClockSeconds )
54065332 {
0 commit comments