Ejemplo n.º 1
0
        /// <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;
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// This function updates periodically the locomotive's motive force.
        /// </summary>
        protected override void UpdateMotiveForce(double 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 * LocomotiveMaxRailOutputPowerW / AbsWheelSpeedMpS));
                    float maxPowerW = 0.98f * LocomotiveMaxRailOutputPowerW;      //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
                {
                    // Caps throttle setting if more then one diesel engine fitted
                    // As tractive force table is combined output, a ratio of diesel engine powers is used to adjust throttle setting.
                    // In principal, a locomotive with two engines should never exceed 50% throttle if one engine is shut down (if of equal power)
                    if (DieselEngines.Count > 1)
                    {
                        if (t > (DieselEngines.CurrentRailOutputPowerW / DieselEngines.MaximumRailOutputPowerW))
                        {
                            t = (DieselEngines.CurrentRailOutputPowerW / DieselEngines.MaximumRailOutputPowerW);
                        }
                    }

                    MotiveForceN = (float)TractiveForceCurves.Get(t, AbsWheelSpeedMpS) * (1 - PowerReduction);
                    if (MotiveForceN < 0 && !TractiveForceCurves.HasNegativeValues)
                    {
                        MotiveForceN = 0;
                    }
                }

                DieselFlowLps           = DieselEngines.DieselFlowLps;
                partialFuelConsumption += DieselEngines.DieselFlowLps * (float)elapsedClockSeconds;
                if (partialFuelConsumption >= 0.1)
                {
                    DieselLevelL          -= partialFuelConsumption;
                    partialFuelConsumption = 0;
                }
                if (DieselLevelL <= 0.0f)
                {
                    PowerOn = false;
                    SignalEvent(TrainEvent.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 = (float)(ContinuousForceTimeFactor - elapsedClockSeconds) / ContinuousForceTimeFactor;
                if (w < 0)
                {
                    w = 0;
                }
                AverageForceN = w * AverageForceN + (1 - w) * MotiveForceN;
            }
        }
Ejemplo n.º 3
0
        /// <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, AbsWheelSpeedMpS == 0.0f ? (t * MaxForceN) : (t * DieselEngines.MaxOutputPowerW / AbsWheelSpeedMpS));
                    float maxPowerW = 0.98f * DieselEngines.MaxOutputPowerW;      //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);
                    if (MotiveForceN < 0)
                    {
                        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);
                }
                MassKG = InitialMassKg - MaxDieselLevelL * DieselWeightKgpL + DieselLevelL * DieselWeightKgpL;
            }

            if (DynamicBrakePercent > 0 && DynamicBrakeForceCurves != null)
            {
                float f = DynamicBrakeForceCurves.Get(.01f * DynamicBrakePercent, AbsWheelSpeedMpS);
                if (f > 0)
                {
                    MotiveForceN -= (SpeedMpS > 0 ? 1 : -1) * f;
                    switch (Direction)
                    {
                    case Direction.Forward:
                        //MotiveForceN *= 1;     //Not necessary
                        break;

                    case Direction.Reverse:
                        MotiveForceN *= -1;
                        break;

                    case Direction.N:
                    default:
                        MotiveForceN *= 0;
                        break;
                    }
                }
            }

            if (MaxForceN > 0 && MaxContinuousForceN > 0)
            {
                MotiveForceN *= 1 - (MaxForceN - MaxContinuousForceN) / (MaxForceN * MaxContinuousForceN) * AverageForceN;
                float w = (ContinuousForceTimeFactor - elapsedClockSeconds) / ContinuousForceTimeFactor;
                if (w < 0)
                {
                    w = 0;
                }
                AverageForceN = w * AverageForceN + (1 - w) * MotiveForceN;
            }
        }
Ejemplo n.º 4
0
        public override void LoadFromWagFile(string wagFilePath)
        {
            base.LoadFromWagFile(wagFilePath);

            if (Simulator.Settings.VerboseConfigurationMessages)  // Display locomotivve name for verbose error messaging
            {
                Trace.TraceInformation("\n\n ================================================= {0} =================================================", LocomotiveName);
            }

            NormalizeParams();

            // Check to see if Speed of Max Tractive Force has been set - use ORTS value as first priority, if not use MSTS, last resort use an arbitary value.
            if (SpeedOfMaxContinuousForceMpS == 0)
            {
                if (MSTSSpeedOfMaxContinuousForceMpS != 0)
                {
                    SpeedOfMaxContinuousForceMpS = MSTSSpeedOfMaxContinuousForceMpS; // Use MSTS value if present

                    if (Simulator.Settings.VerboseConfigurationMessages)
                    {
                        Trace.TraceInformation("Speed Of Max Continuous Force: set to default value {0}", FormatStrings.FormatSpeedDisplay(SpeedOfMaxContinuousForceMpS, IsMetric));
                    }
                }
                else if (MaxPowerW != 0 && MaxContinuousForceN != 0)
                {
                    SpeedOfMaxContinuousForceMpS = MaxPowerW / MaxContinuousForceN;

                    if (Simulator.Settings.VerboseConfigurationMessages)
                    {
                        Trace.TraceInformation("Speed Of Max Continuous Force: set to 'calculated' value {0}", FormatStrings.FormatSpeedDisplay(SpeedOfMaxContinuousForceMpS, IsMetric));
                    }
                }
                else
                {
                    SpeedOfMaxContinuousForceMpS = 10.0f; // If not defined then set at an "arbitary" value of 22mph

                    if (Simulator.Settings.VerboseConfigurationMessages)
                    {
                        Trace.TraceInformation("Speed Of Max Continuous Force: set to 'arbitary' value {0}", FormatStrings.FormatSpeedDisplay(SpeedOfMaxContinuousForceMpS, IsMetric));
                    }
                }
            }

            if (DieselEngines == null)
            {
                DieselEngines = new DieselEngines(this);
            }

            // Create a diesel engine block if none exits, typically for a MSTS or BASIC configuration
            if (DieselEngines.Count == 0)
            {
                DieselEngines.Add(new DieselEngine());

                DieselEngines[0].InitFromMSTS(this);
                DieselEngines[0].Initialize(true);
            }


            // Check initialization of power values for diesel engines
            for (int i = 0; i < DieselEngines.Count; i++)
            {
                DieselEngines[i].InitDieselRailPowers(this);
            }

            if (GearBox != null && GearBox.IsInitialized)
            {
                GearBox.CopyFromMSTSParams(DieselEngines[0]);
                if (DieselEngines[0].GearBox == null)
                {
                    DieselEngines[0].GearBox = GearBox;
                    DieselEngines[0].GearBox.UseLocoGearBox(DieselEngines[0]);
                }
                for (int i = 1; i < DieselEngines.Count; i++)
                {
                    if (DieselEngines[i].GearBox == null)
                    {
                        DieselEngines[i].GearBox = new GearBox(GearBox, DieselEngines[i]);
                    }
                }

                if (GearBoxController == null)
                {
                    GearBoxController = new MSTSNotchController(GearBox.NumOfGears + 1);
                }
            }

            InitialMassKg = MassKG;

            // If traction force curves not set (BASIC configuration) then check that power values are set, otherwise locomotive will not move.
            if (TractiveForceCurves == null && LocomotiveMaxRailOutputPowerW == 0)
            {
                if (MaxPowerW != 0)
                {
                    LocomotiveMaxRailOutputPowerW = MaxPowerW;  // Set to default power value

                    if (Simulator.Settings.VerboseConfigurationMessages)
                    {
                        Trace.TraceInformation("MaxRailOutputPower (BASIC Config): set to default value = {0}", FormatStrings.FormatPower(LocomotiveMaxRailOutputPowerW, IsMetric, false, false));
                    }
                }
                else
                {
                    LocomotiveMaxRailOutputPowerW = 2500000.0f; // If no default value then set to arbitary value

                    if (Simulator.Settings.VerboseConfigurationMessages)
                    {
                        Trace.TraceInformation("MaxRailOutputPower (BASIC Config): set at arbitary value = {0}", FormatStrings.FormatPower(LocomotiveMaxRailOutputPowerW, IsMetric, false, false));
                    }
                }


                if (MaximumDieselEnginePowerW == 0)
                {
                    MaximumDieselEnginePowerW = LocomotiveMaxRailOutputPowerW;  // If no value set in ENG file, then set the Prime Mover power to same as RailOutputPower (typically the MaxPower value)

                    if (Simulator.Settings.VerboseConfigurationMessages)
                    {
                        Trace.TraceInformation("Maximum Diesel Engine Prime Mover Power set the same as MaxRailOutputPower {0} value", FormatStrings.FormatPower(MaximumDieselEnginePowerW, IsMetric, false, false));
                    }
                }
            }

            // Check force assumptions set for diesel
            if (Simulator.Settings.VerboseConfigurationMessages)
            {
                float ThrottleSetting = 1.0f;    // Must be at full throttle for these calculations
                if (TractiveForceCurves == null) // Basic configuration - ie no force and Power tables, etc
                {
                    float CalculatedMaxContinuousForceN = ThrottleSetting * LocomotiveMaxRailOutputPowerW / SpeedOfMaxContinuousForceMpS;
                    Trace.TraceInformation("Diesel Force Settings (BASIC Config): Max Starting Force {0}, Calculated Max Continuous Force {1} @ speed of {2}", FormatStrings.FormatForce(MaxForceN, IsMetric), FormatStrings.FormatForce(CalculatedMaxContinuousForceN, IsMetric), FormatStrings.FormatSpeedDisplay(SpeedOfMaxContinuousForceMpS, IsMetric));
                    Trace.TraceInformation("Diesel Power Settings (BASIC Config): Prime Mover {0}, Max Rail Output Power {1}", FormatStrings.FormatPower(MaximumDieselEnginePowerW, IsMetric, false, false), FormatStrings.FormatPower(LocomotiveMaxRailOutputPowerW, IsMetric, false, false));

                    if (MaxForceN < MaxContinuousForceN)
                    {
                        Trace.TraceInformation("!!!! Warning: Starting Tractive force {0} is less then Calculated Continuous force {1}, please check !!!!", FormatStrings.FormatForce(MaxForceN, IsMetric), FormatStrings.FormatForce(CalculatedMaxContinuousForceN, IsMetric), FormatStrings.FormatSpeedDisplay(SpeedOfMaxContinuousForceMpS, IsMetric));
                    }
                }
                else // Advanced configuration -
                {
                    float StartingSpeedMpS = 0.1f; // Assumed starting speed for diesel - can't be zero otherwise error will occurr
                    float StartingForceN   = (float)TractiveForceCurves.Get(ThrottleSetting, StartingSpeedMpS);
                    float CalculatedMaxContinuousForceN = (float)TractiveForceCurves.Get(ThrottleSetting, SpeedOfMaxContinuousForceMpS);
                    Trace.TraceInformation("Diesel Force Settings (ADVANCED Config): Max Starting Force {0} Calculated Max Continuous Force {1}, @ speed of {2}", FormatStrings.FormatForce(StartingForceN, IsMetric), FormatStrings.FormatForce(CalculatedMaxContinuousForceN, IsMetric), FormatStrings.FormatSpeedDisplay(SpeedOfMaxContinuousForceMpS, IsMetric));
                    Trace.TraceInformation("Diesel Power Settings (ADVANCED Config): Prime Mover {0}, Max Rail Output Power {1} @ {2} rpm", FormatStrings.FormatPower(DieselEngines.MaxPowerW, IsMetric, false, false), FormatStrings.FormatPower(DieselEngines.MaximumRailOutputPowerW, IsMetric, false, false), MaxRPM);

                    if (StartingForceN < MaxContinuousForceN)
                    {
                        Trace.TraceInformation("!!!! Warning: Calculated Starting Tractive force {0} is less then Calculated Continuous force {1}, please check !!!!", FormatStrings.FormatForce(StartingForceN, IsMetric), FormatStrings.FormatForce(CalculatedMaxContinuousForceN, IsMetric), FormatStrings.FormatSpeedDisplay(SpeedOfMaxContinuousForceMpS, IsMetric));
                    }
                }

                // Check that MaxPower value is realistic - Calculate power - metric - P = F x V
                float CalculatedContinuousPowerW = MaxContinuousForceN * SpeedOfMaxContinuousForceMpS;
                if (MaxPowerW < CalculatedContinuousPowerW)
                {
                    Trace.TraceInformation("!!!! Warning: MaxPower {0} is less then continuous force calculated power {1} @ speed of {2}, please check !!!!", FormatStrings.FormatPower(MaxPowerW, IsMetric, false, false), FormatStrings.FormatPower(CalculatedContinuousPowerW, IsMetric, false, false), FormatStrings.FormatSpeedDisplay(SpeedOfMaxContinuousForceMpS, IsMetric));
                }

                Trace.TraceInformation("===================================================================================================================\n\n");
            }
        }
Ejemplo n.º 5
0
        /// <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;
            }
        }