/// <summary> /// This function updates periodically the locomotive's motive force. /// </summary> protected override void UpdateMotiveForce(float elapsedClockSeconds, float t, float AbsSpeedMpS, float AbsWheelSpeedMpS) { if (PowerOn) { if (TractiveForceCurves == null) { float maxForceN = Math.Min(t * MaxForceN * (1 - PowerReduction), AbsWheelSpeedMpS == 0.0f ? (t * MaxForceN * (1 - PowerReduction)) : (t * DieselEngines.CurrentRailOutputPowerW / AbsWheelSpeedMpS)); float maxPowerW = 0.98f * DieselEngines.MaximumRailOutputPowerW; //0.98 added to let the diesel engine handle the adhesion-caused jittering if (DieselEngines.HasGearBox) { MotiveForceN = DieselEngines.MotiveForceN; } else { if (maxForceN * AbsWheelSpeedMpS > maxPowerW) { maxForceN = maxPowerW / AbsWheelSpeedMpS; } if (AbsSpeedMpS > MaxSpeedMpS - 0.05f) { maxForceN = 20 * (MaxSpeedMpS - AbsSpeedMpS) * maxForceN; } if (AbsSpeedMpS > (MaxSpeedMpS)) { maxForceN = 0; } MotiveForceN = maxForceN; } } else { if (t > (DieselEngines.MaxOutputPowerW / DieselEngines.MaxPowerW)) { t = (DieselEngines.MaxOutputPowerW / DieselEngines.MaxPowerW); } MotiveForceN = TractiveForceCurves.Get(t, AbsWheelSpeedMpS) * (1 - PowerReduction); if (MotiveForceN < 0 && !TractiveForceCurves.AcceptsNegativeValues()) { MotiveForceN = 0; } } DieselFlowLps = DieselEngines.DieselFlowLps; partialFuelConsumption += DieselEngines.DieselFlowLps * elapsedClockSeconds; if (partialFuelConsumption >= 0.1) { DieselLevelL -= partialFuelConsumption; partialFuelConsumption = 0; } if (DieselLevelL <= 0.0f) { PowerOn = false; SignalEvent(Event.EnginePowerOff); foreach (DieselEngine de in DieselEngines) { if (de.EngineStatus != DieselEngine.Status.Stopping || de.EngineStatus != DieselEngine.Status.Stopped) { de.Stop(); } } } // MassKG = InitialMassKg - MaxDieselLevelL * DieselWeightKgpL + DieselLevelL * DieselWeightKgpL; } if (MaxForceN > 0 && MaxContinuousForceN > 0 && PowerReduction < 1) { MotiveForceN *= 1 - (MaxForceN - MaxContinuousForceN) / (MaxForceN * MaxContinuousForceN) * AverageForceN * (1 - PowerReduction); float w = (ContinuousForceTimeFactor - elapsedClockSeconds) / ContinuousForceTimeFactor; if (w < 0) { w = 0; } AverageForceN = w * AverageForceN + (1 - w) * MotiveForceN; } }
/// <summary> /// This function updates periodically the locomotive's motive force. /// </summary> protected override void UpdateMotiveForce(float elapsedClockSeconds, float t, float AbsSpeedMpS, float AbsWheelSpeedMpS) { // This section calculates the motive force of the locomotive as follows: // Basic configuration (no TF table) - uses P = F /speed relationship - requires power and force parameters to be set in the ENG file. // Advanced configuration (TF table) - use a user defined tractive force table // With Simple adhesion apart from correction for rail adhesion, there is no further variation to the motive force. // With Advanced adhesion the raw motive force is fed into the advanced (axle) adhesion model, and is corrected for wheel slip and rail adhesion if (PowerOn) { if (TractiveForceCurves == null) { float maxForceN = Math.Min(t * MaxForceN * (1 - PowerReduction), AbsSpeedMpS == 0.0f ? (t * MaxForceN * (1 - PowerReduction)) : (t * LocomotiveMaxRailOutputPowerW / AbsSpeedMpS)); float maxPowerW = LocomotiveMaxRailOutputPowerW * (DieselEngines.ApparentThrottleSetting / 100.0f); if (DieselEngines.HasGearBox) { MotiveForceN = DieselEngines.MotiveForceN; } else { if (maxForceN * AbsSpeedMpS > maxPowerW) { maxForceN = maxPowerW / AbsSpeedMpS; } // CTN - Not sure what impact that these following have??? if (AbsSpeedMpS > MaxSpeedMpS - 0.05f) { maxForceN = 20 * (MaxSpeedMpS - AbsSpeedMpS) * maxForceN; } // CTN - Sets power to zero, which I don't think is correct if (AbsSpeedMpS > (MaxSpeedMpS)) { maxForceN = 0; } MotiveForceN = maxForceN; } } else { MotiveForceN = TractiveForceCurves.Get((DieselEngines.ApparentThrottleSetting / 100.0f), AbsSpeedMpS) * (1 - PowerReduction); if (MotiveForceN < 0 && !TractiveForceCurves.AcceptsNegativeValues()) { MotiveForceN = 0; } } DieselFlowLps = DieselEngines.DieselFlowLps; partialFuelConsumption += DieselEngines.DieselFlowLps * elapsedClockSeconds; if (partialFuelConsumption >= 0.1) { DieselLevelL -= partialFuelConsumption; partialFuelConsumption = 0; } if (DieselLevelL <= 0.0f) { PowerOn = false; SignalEvent(Event.EnginePowerOff); foreach (DieselEngine de in DieselEngines) { if (de.EngineStatus != DieselEngine.Status.Stopping || de.EngineStatus != DieselEngine.Status.Stopped) { de.Stop(); } } } } if (MaxForceN > 0 && MaxContinuousForceN > 0 && PowerReduction < 1) { MotiveForceN *= 1 - (MaxForceN - MaxContinuousForceN) / (MaxForceN * MaxContinuousForceN) * AverageForceN * (1 - PowerReduction); float w = (ContinuousForceTimeFactor - elapsedClockSeconds) / ContinuousForceTimeFactor; if (w < 0) { w = 0; } AverageForceN = w * AverageForceN + (1 - w) * MotiveForceN; } }