@@ -574,6 +574,11 @@ public float TenderCoalMassKG // Decreased by firing and increased
574574 0.0f, MathHelper.Pi/2, 0.0f, 0.0f // default 2 cylinder locomotive
575575 };
576576
577+ static float[] BoosterWheelCrankAngleDiffRad = new float[]
578+ {
579+ 0.0f, MathHelper.Pi/2, 0.0f, 0.0f // default 2 cylinder locomotive
580+ };
581+
577582 public float IndicatedHorsePowerHP; // Indicated Horse Power (IHP), theoretical power of the locomotive, it doesn't take into account the losses due to friction, etc. Typically output HP will be 70 - 90% of the IHP
578583 public float DrawbarHorsePowerHP; // Drawbar Horse Power (DHP), maximum power available at the wheels.
579584 public float DrawBarPullLbsF; // Drawbar pull in lbf
@@ -2136,7 +2141,6 @@ public override void InitializeMoving()
21362141 public override void Update(float elapsedClockSeconds)
21372142 {
21382143 base.Update(elapsedClockSeconds);
2139- UpdateFX(elapsedClockSeconds);
21402144
21412145#if INDIVIDUAL_CONTROL
21422146 //this train is remote controlled, with mine as a helper, so I need to send the controlling information, but not the force.
@@ -2454,8 +2458,8 @@ private void UpdateFX(float elapsedClockSeconds)
24542458 // Find
24552459 for (int i = 0; i < MSTSNumCylinders; i++)
24562460 {
2457-
2458- float normalisedCrankAngleRad = NormalisedCrankAngle(i);
2461+ var crankAngleDiffRad = WheelCrankAngleDiffRad[i];
2462+ float normalisedCrankAngleRad = NormalisedCrankAngle(i, crankAngleDiffRad );
24592463
24602464 // Exhaust crank angle
24612465 float exhaustCrankAngleRad = 0;
@@ -2518,7 +2522,6 @@ private void UpdateFX(float elapsedClockSeconds)
25182522 }
25192523 }
25202524
2521-
25222525 if (MSTSNumCylinders == 4)
25232526 {
25242527 // Cylinder Cocks
@@ -2586,8 +2589,6 @@ private void UpdateFX(float elapsedClockSeconds)
25862589 CylinderCock42On = true;
25872590 }
25882591 }
2589-
2590-
25912592 }
25922593 else if (MSTSNumCylinders == 3)
25932594 {
@@ -2639,7 +2640,6 @@ private void UpdateFX(float elapsedClockSeconds)
26392640 CylinderCock32On = true;
26402641 }
26412642 }
2642-
26432643 }
26442644 else // 2 Cylinders
26452645 {
@@ -2675,12 +2675,8 @@ private void UpdateFX(float elapsedClockSeconds)
26752675 CylinderCock22On = true;
26762676 }
26772677 }
2678-
2679-
26802678 }
26812679 }
2682-
2683-
26842680 }
26852681 else if (Cylinder2SteamEffects) // For MSTS locomotives with one cylinder cock ignore calculation of cock opening times.
26862682 // Currently retained as a legacy issue, and eventually both this and the MSTS version should be removed
@@ -2709,58 +2705,87 @@ private void UpdateFX(float elapsedClockSeconds)
27092705 // Booster steam exhaust
27102706 if (BoosterCylinderSteamExhaustOn) // For Booster engine
27112707 {
2712- var BoosterCylinderSteamExhaustTimePeriodS = 0.5f * 1.0f / DrvWheelRevRpS; // Calculate how long cylinder cocks open @ speed = Time (sec) / (Drv Wheel RpS ) - assume two cylinder strokes per rev, ie each cock will only be open for 1/2 rev
2713- BoosterCylinderSteamExhaustTimerS += elapsedClockSeconds;
2714- if (BoosterCylinderSteamExhaustTimerS > BoosterCylinderSteamExhaustTimePeriodS)
2708+
2709+ for (int i = 0; i < 1; i++)
27152710 {
2716- if (BoosterCylinderSteamExhaust01On)
2711+ var crankAngleDiffRad = BoosterWheelCrankAngleDiffRad[i];
2712+ float normalisedCrankAngleRad = NormalisedCrankAngle(i, crankAngleDiffRad);
2713+
2714+ // Exhaust crank angle
2715+ float exhaustCrankAngleRad = 0;
2716+ if (normalisedCrankAngleRad <= MathHelper.Pi)
2717+ {
2718+ exhaustCrankAngleRad = CylinderExhaustOpenFactor * (float)Math.PI;
2719+ }
2720+ else
27172721 {
2718- BoosterCylinderSteamExhaust01On = false;
2719- BoosterCylinderSteamExhaust02On = true;
2720- BoosterCylinderSteamExhaustTimerS = 0.0f; // Reset timer
2722+ exhaustCrankAngleRad = CylinderExhaustOpenFactor * (float)Math.PI + (float)Math.PI;
27212723 }
2722- else if (BoosterCylinderSteamExhaust02On)
2724+
2725+ if (absSpeedMpS > 0.001)
27232726 {
2724- BoosterCylinderSteamExhaust01On = true;
2725- BoosterCylinderSteamExhaust02On = false;
2726- BoosterCylinderSteamExhaustTimerS = 0.0f; // Reset timer
2727+ if (i == 0 && ((normalisedCrankAngleRad <= MathHelper.Pi && normalisedCrankAngleRad >= exhaustCrankAngleRad) || (normalisedCrankAngleRad < 2 * MathHelper.Pi && normalisedCrankAngleRad >= exhaustCrankAngleRad)))
2728+ {
2729+ BoosterCylinderSteamExhaust01On = true;
2730+ }
2731+ else if (i == 0)
2732+ {
2733+ BoosterCylinderSteamExhaust01On = false;
2734+ }
27272735
2736+ else if (i == 1 && ((normalisedCrankAngleRad <= MathHelper.Pi && normalisedCrankAngleRad >= exhaustCrankAngleRad) || (normalisedCrankAngleRad < 2 * MathHelper.Pi && normalisedCrankAngleRad >= exhaustCrankAngleRad)))
2737+ {
2738+ BoosterCylinderSteamExhaust02On = true;
2739+ }
2740+ else if (i == 1)
2741+ {
2742+ BoosterCylinderSteamExhaust02On = false;
2743+ }
27282744 }
27292745 }
27302746 }
27312747
27322748 // Booster steam cylinder cock exhaust
27332749 if (BoosterCylinderCocksOn) // For Booster engine
27342750 {
2735- var BoosterCylinderCockOpenTimePeriodS = 0.5f * 1.0f / DrvWheelRevRpS; // Calculate how long cylinder cocks open @ speed = Time (sec) / (Drv Wheel RpS ) - assume two cylinder strokes per rev, ie each cock will only be open for 1/2 rev
2736- BoosterCylinderCockTimerS += elapsedClockSeconds;
2737- if (BoosterCylinderCockTimerS > BoosterCylinderCockOpenTimePeriodS)
2751+
2752+ for (int i = 0; i < 1; i++)
27382753 {
2739- if (BoosterCylinderCock11On)
2754+
2755+ var crankAngleDiffRad = BoosterWheelCrankAngleDiffRad[i];
2756+ float normalisedCrankAngleRad = NormalisedCrankAngle(i, crankAngleDiffRad);
2757+
2758+ if (i == 0)
27402759 {
2741- BoosterCylinderCock11On = false;
2742- BoosterCylinderCock12On = true;
2743- BoosterCylinderCockTimerS = 0.0f; // Reset timer
2760+ if (normalisedCrankAngleRad <= MathHelper.Pi)
2761+ {
2762+ BoosterCylinderCock11On = true;
2763+ BoosterCylinderCock12On = false;
2764+ }
27442765 }
2745- else if (BoosterCylinderCock12On)
2766+ else
27462767 {
2747- BoosterCylinderCock11On = true;
2748- BoosterCylinderCock12On = false;
2749- BoosterCylinderCockTimerS = 0.0f; // Reset timer
2750-
2768+ if (normalisedCrankAngleRad > MathHelper.Pi)
2769+ {
2770+ BoosterCylinderCock11On = false;
2771+ BoosterCylinderCock12On = true;
2772+ }
27512773 }
2752-
2753- if (BoosterCylinderCock21On)
2774+ if (i == 1)
27542775 {
2755- BoosterCylinderCock21On = false;
2756- BoosterCylinderCock22On = true;
2757- // BoosterCylinderCockTimerS = 0.0f; // Reset timer
2776+ if (normalisedCrankAngleRad <= MathHelper.Pi)
2777+ {
2778+ BoosterCylinderCock21On = true;
2779+ BoosterCylinderCock22On = false;
2780+ }
27582781 }
2759- else if (BoosterCylinderCock22On)
2782+ else
27602783 {
2761- BoosterCylinderCock21On = true;
2762- BoosterCylinderCock22On = false;
2763- // BoosterCylinderCockTimerS = 0.0f; // Reset timer
2784+ if (normalisedCrankAngleRad > MathHelper.Pi)
2785+ {
2786+ BoosterCylinderCock21On = false;
2787+ BoosterCylinderCock22On = true;
2788+ }
27642789 }
27652790 }
27662791 }
@@ -5455,8 +5480,9 @@ private void UpdateSteamTractiveForce(float elapsedClockSeconds, float locomotiv
54555480 backwardCylinderPosition = crankCylinderPosition;
54565481 }
54575482
5458- float normalisedCrankAngleRad = NormalisedCrankAngle(i);
5459-
5483+ var crankAngleDiffRad = WheelCrankAngleDiffRad[i];
5484+ float normalisedCrankAngleRad = NormalisedCrankAngle(i, crankAngleDiffRad);
5485+
54605486 // Crank angles
54615487 float sin = (float)Math.Sin(crankAngleRad);
54625488 float cos = (float)Math.Cos(crankAngleRad);
@@ -5776,8 +5802,6 @@ private void UpdateSteamTractiveForce(float elapsedClockSeconds, float locomotiv
57765802 {
57775803 IsCritTELimit = false; // Reset flag if limiting TE
57785804 }
5779-
5780- SteamEngines[numberofengine].AttachedAxle.DriveForceN = SteamEngines[numberofengine].TractiveForceN / SteamEngines[numberofengine].AttachedAxle.NumberWheelAxles;
57815805 }
57825806
57835807 /// <summary>
@@ -5795,10 +5819,13 @@ protected override void UpdateTractiveForce(float elapsedClockSeconds, float loc
57955819 // Update tractive effort across all steam engines
57965820 for (int i = 0; i < SteamEngines.Count; i++)
57975821 {
5822+ ApplyDirectionToTractiveForce(ref SteamEngines[i].TractiveForceN);
5823+
57985824 TractiveForceN += SteamEngines[i].TractiveForceN;
57995825
58005826 if (Simulator.UseAdvancedAdhesion && !Simulator.Settings.SimpleControlPhysics)
58015827 {
5828+ SteamEngines[i].AttachedAxle.DriveForceN = SteamEngines[i].TractiveForceN / SteamEngines[i].AttachedAxle.NumberWheelAxles;
58025829 UpdateAxleDriveForce();
58035830 MotiveForceN += SteamEngines[i].AttachedAxle.CompensatedAxleForceN;
58045831 }
@@ -5816,14 +5843,11 @@ protected override void UpdateTractiveForce(float elapsedClockSeconds, float loc
58165843 IndicatedHorsePowerHP += SteamEngines[i].IndicatedHorsePowerHP;
58175844 IndicatedHorsePowerHP = MathHelper.Clamp(IndicatedHorsePowerHP, 0, IndicatedHorsePowerHP);
58185845
5819-
58205846 //TODO - identify the maximum value for display??
58215847 PistonSpeedFtpMin = SteamEngines[0].PistonSpeedFtpMin;
58225848
58235849 }
58245850
5825- ApplyDirectionToTractiveForce(ref TractiveForceN);
5826-
58275851 // Find the maximum TE for debug i.e. @ start and full throttle
58285852 if (absSpeedMpS < 1.0)
58295853 {
@@ -5860,9 +5884,9 @@ protected override void UpdateTractiveForce(float elapsedClockSeconds, float loc
58605884 /// <summary>
58615885 /// Normalise crank angle so that it is a value between 0 and 360 starting at the real crank angle difference
58625886 /// </summary>
5863- private float NormalisedCrankAngle(int cylinderNumber)
5887+ private float NormalisedCrankAngle(int cylinderNumber, float crankAngleRad )
58645888 {
5865- float normalisedCrankAngleRad = (float)MathHelper.WrapAngle((float)LocomotiveAxles[0].AxlePositionRad + WheelCrankAngleDiffRad[cylinderNumber] );
5889+ float normalisedCrankAngleRad = (float)MathHelper.WrapAngle((float)LocomotiveAxles[0].AxlePositionRad + crankAngleRad );
58665890
58675891 if (normalisedCrankAngleRad < 0)
58685892 {
0 commit comments