diff --git a/Source/Orts.Simulation/Simulation/RollingStocks/MSTSDieselLocomotive.cs b/Source/Orts.Simulation/Simulation/RollingStocks/MSTSDieselLocomotive.cs index 1c2a4709cc..416466d01e 100644 --- a/Source/Orts.Simulation/Simulation/RollingStocks/MSTSDieselLocomotive.cs +++ b/Source/Orts.Simulation/Simulation/RollingStocks/MSTSDieselLocomotive.cs @@ -758,6 +758,10 @@ public override void ChangeGearUp() DieselEngines[0].GearBox.AutoGearUp(); GearBoxController.SetValue((float)DieselEngines[0].GearBox.NextGearIndex); } + else if (DieselEngines[0].GearBox.GearBoxOperation == GearBoxOperation.Manual) + { + DieselEngines[0].GearBox.ManualGearUp = true; + } } } @@ -771,6 +775,11 @@ public override void ChangeGearDown() DieselEngines[0].GearBox.AutoGearDown(); GearBoxController.SetValue((float)DieselEngines[0].GearBox.NextGearIndex); } + else if (DieselEngines[0].GearBox.GearBoxOperation == GearBoxOperation.Manual) + { + DieselEngines[0].GearBox.ManualGearDown = true; + } + } } diff --git a/Source/Orts.Simulation/Simulation/RollingStocks/MSTSLocomotive.cs b/Source/Orts.Simulation/Simulation/RollingStocks/MSTSLocomotive.cs index 3a2e8b3459..042018abe4 100644 --- a/Source/Orts.Simulation/Simulation/RollingStocks/MSTSLocomotive.cs +++ b/Source/Orts.Simulation/Simulation/RollingStocks/MSTSLocomotive.cs @@ -294,6 +294,7 @@ public bool LargeEjectorSoundOn // Set values for display in HUD public float WagonCoefficientFrictionHUD; public float LocomotiveCoefficientFrictionHUD; + public float HuDGearMaximumTractiveForce; public PressureUnit MainPressureUnit = PressureUnit.None; public Dictionary BrakeSystemPressureUnits = new Dictionary diff --git a/Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/PowerSupplies/DieselEngine.cs b/Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/PowerSupplies/DieselEngine.cs index ccaa1a614a..4ca161e519 100644 --- a/Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/PowerSupplies/DieselEngine.cs +++ b/Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/PowerSupplies/DieselEngine.cs @@ -992,6 +992,22 @@ public void Update(float elapsedClockSeconds) } else // for gear box type 2 & 3 { + // When a manual gear change is initiated, then reduce motive to zero (done in gear box class) whilst gear change is occurring, allow time delay for gears to change + if (GearBox.ManualGearChange && !GearBox.ManualGearBoxChangeOn) // Initially set gear change + { + GearBox.ManualGearBoxChangeOn = true; + } + else if (GearBox.ManualGearBoxChangeOn && GearBox.ManualGearTimerS < GearBox.ManualGearTimerResetS) + { + GearBox.ManualGearTimerS += elapsedClockSeconds; // Increment timer + } + else if (GearBox.ManualGearBoxChangeOn && GearBox.ManualGearTimerS > GearBox.ManualGearTimerResetS) + { + GearBox.ManualGearBoxChangeOn = false; + GearBox.ManualGearTimerS = 0; // Reset timer + } + + if (RealRPM > 0) GearBox.ClutchPercent = (RealRPM - GearBox.ShaftRPM) / RealRPM * 100f; else @@ -1013,8 +1029,10 @@ public void Update(float elapsedClockSeconds) } } - if (RealRPM < 0.8f * IdleRPM && ThrottlePercent > 0) + // Simulate stalled engine if RpM decreases too far, by stopping engine + if (RealRPM < 0.9f * IdleRPM) { + Trace.TraceInformation("Diesel Engine has stalled"); HandleEvent(PowerSupplyEvent.StopEngine); Simulator.Confirmer.Message(ConfirmLevel.Warning, Simulator.Catalog.GetString("Diesel Engine has stalled.")); } diff --git a/Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/PowerTransmissions/GearBox.cs b/Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/PowerTransmissions/GearBox.cs index e244962644..f41d55c3e6 100644 --- a/Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/PowerTransmissions/GearBox.cs +++ b/Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/PowerTransmissions/GearBox.cs @@ -157,6 +157,12 @@ public class GearBox : ISubSystem protected MSTSGearBoxParams GearBoxParams => Locomotive.DieselEngines.MSTSGearBoxParams; public List Gears = new List(); + public float ManualGearTimerResetS = 1; // Allow gear change to take 1 seconds + public float ManualGearTimerS; // Time for gears to change + public bool ManualGearBoxChangeOn = false; + public bool ManualGearUp = false; + public bool ManualGearDown = false; + public Gear CurrentGear { get @@ -409,14 +415,25 @@ public float TractiveForceN } float tractiveForceN = DieselEngine.DieselTorqueTab[dieselRpM] / DieselEngine.DieselTorqueTab.MaxY() * CurrentGear.MaxTractiveForceN; + Locomotive.HuDGearMaximumTractiveForce = CurrentGear.MaxTractiveForceN; - // Limit tractive force if engine is governed, ie speed cannot exceed the governed speed - if (DieselEngine.RealRPM >= DieselEngine.GovenorRPM && ShaftRPM > DieselEngine.GovenorRPM) + // Limit tractive force if engine is governed, ie speed cannot exceed the governed speed or the throttled speed + + if ((DieselEngine.RealRPM >= DieselEngine.GovenorRPM && ShaftRPM > DieselEngine.GovenorRPM) || (DieselEngine.RealRPM < DieselEngine.GovenorRPM && DieselEngine.RealRPM > DieselEngine.ThrottleRPMTab[DieselEngine.DemandedThrottlePercent])) { // use decay function to decrease tractive effort if RpM exceeds governed RpM value. // y = original amount ( 1 - decay rate)^length of prediction + float decayRpM = 0; - var decayRpM = ShaftRPM - DieselEngine.GovenorRPM; + if (DieselEngine.RealRPM < DieselEngine.GovenorRPM && DieselEngine.RealRPM > DieselEngine.ThrottleRPMTab[DieselEngine.DemandedThrottlePercent]) + { + decayRpM = ShaftRPM - DieselEngine.ThrottleRPMTab[DieselEngine.DemandedThrottlePercent]; + } + else + { + decayRpM = ShaftRPM - DieselEngine.GovenorRPM; + } + var teDecline = Math.Pow((1.0f - 0.05f), decayRpM); tractiveForceN = (float)Math.Abs(CurrentGear.MaxTractiveForceN * teDecline); @@ -434,8 +451,8 @@ public float TractiveForceN } - // When a manual gear change is initiated, then reduce motive to zero whilst gear change is occurring - if (ManualGearChange) + // Set TE to zero if gear change happening + if (ManualGearBoxChangeOn) { tractiveForceN = 0; } @@ -573,20 +590,44 @@ public void InitializeMoving() public void Update(float elapsedClockSeconds) { - if ((clutch <= 0.05) || (clutch >= 1f)) + if (GearBoxOperation == GearBoxOperation.Automatic || GearBoxOperation == GearBoxOperation.Semiautomatic) { - if (currentGearIndex < nextGearIndex) + if ((clutch <= 0.05) || (clutch >= 1f)) { - DieselEngine.Locomotive.SignalEvent(Event.GearUp); - currentGearIndex = nextGearIndex; + if (currentGearIndex < nextGearIndex) + { + DieselEngine.Locomotive.SignalEvent(Event.GearUp); + currentGearIndex = nextGearIndex; + } + } + if ((clutch <= 0.05) || (clutch >= 0.5f)) + { + if (currentGearIndex > nextGearIndex) + { + DieselEngine.Locomotive.SignalEvent(Event.GearDown); + currentGearIndex = nextGearIndex; + } } } - if ((clutch <= 0.05) || (clutch >= 0.5f)) + else if (GearBoxOperation == GearBoxOperation.Manual) { - if (currentGearIndex > nextGearIndex) + if (ManualGearUp) { - DieselEngine.Locomotive.SignalEvent(Event.GearDown); - currentGearIndex = nextGearIndex; + if (currentGearIndex < nextGearIndex) + { + DieselEngine.Locomotive.SignalEvent(Event.GearUp); + currentGearIndex = nextGearIndex; + ManualGearUp = false; + } + } + if (ManualGearDown) + { + if (currentGearIndex > nextGearIndex) + { + DieselEngine.Locomotive.SignalEvent(Event.GearDown); + currentGearIndex = nextGearIndex; + ManualGearDown = false; + } } } diff --git a/Source/RunActivity/Viewer3D/Popups/HUDWindow.cs b/Source/RunActivity/Viewer3D/Popups/HUDWindow.cs index 1938967608..66979e843c 100644 --- a/Source/RunActivity/Viewer3D/Popups/HUDWindow.cs +++ b/Source/RunActivity/Viewer3D/Popups/HUDWindow.cs @@ -204,8 +204,27 @@ public override void PrepareFrame(RenderFrame frame, ElapsedTime elapsedTime, bo if (Visible && TextPages[TextPage] == TextPageForceInfo) { var loco = Viewer.PlayerLocomotive as MSTSLocomotive; - ForceGraphMotiveForce.AddSample(loco.MotiveForceN / loco.MaxForceN); - ForceGraphDynamicForce.AddSample(-loco.MotiveForceN / loco.MaxForceN); + var locoD = Viewer.PlayerLocomotive as MSTSDieselLocomotive; + + // For geared locomotives the Max Force base value needs to change for each gear. + if (locoD != null && locoD.DieselEngines.HasGearBox) + { + ForceGraphMotiveForce.AddSample(loco.MotiveForceN / loco.HuDGearMaximumTractiveForce); + } + else + { + ForceGraphMotiveForce.AddSample(loco.MotiveForceN / loco.MaxForceN); + } + + if (locoD != null && locoD.DieselEngines.HasGearBox) + { + ForceGraphDynamicForce.AddSample(-loco.MotiveForceN / loco.HuDGearMaximumTractiveForce); + } + else + { + ForceGraphDynamicForce.AddSample(-loco.MotiveForceN / loco.MaxForceN); + } + ForceGraphNumOfSubsteps.AddSample((float)loco.LocomotiveAxle.AxleRevolutionsInt.NumOfSubstepsPS / (float)loco.LocomotiveAxle.AxleRevolutionsInt.MaxSubsteps); ForceGraphs.PrepareFrame(frame);