コード例 #1
0
        public float GetNotchFraction()
        {
            if (Notches.Count == 0)
            {
                return(0);
            }
            INotchController notch = Notches[CurrentNotch];

            if (!notch.Smooth)
            {
                // Respect British 3-wire EP brake configurations
                return((notch.NotchStateType == ControllerState.EPApply || notch.NotchStateType == ControllerState.EPOnly)? CurrentValue : 1);
            }
            float x = 1;

            if (CurrentNotch + 1 < Notches.Count)
            {
                x = Notches[CurrentNotch + 1].Value;
            }
            x = (CurrentValue - notch.Value) / (x - notch.Value);
            if (notch.NotchStateType == ControllerState.Release)
            {
                x = 1 - x;
            }
            return(x);
        }
コード例 #2
0
        public virtual string GetStatus()
        {
            if (Notches.Count == 0)
            {
                return(string.Format("{0:F0}%", 100 * CurrentValue));
            }
            INotchController notch = Notches[CurrentNotch];
            //TODO translation via (static?) Catalog
            //also if NotchStateType == ControllerState.Running, need to use GetParticularString using ControllerState enum description attribute for context
            string name = EnumExtension.GetDescription(notch.NotchStateType);

            if (!notch.Smooth && notch.NotchStateType == ControllerState.Dummy)
            {
                return(string.Format("{0:F0}%", 100 * CurrentValue));
            }
            if (!notch.Smooth)
            {
                return(name);
            }
            if (!string.IsNullOrEmpty(name))
            {
                return(string.Format("{0} {1:F0}%", name, 100 * GetNotchFraction()));
            }
            return(string.Format("{0:F0}%", 100 * GetNotchFraction()));
        }
コード例 #3
0
        public float SetPercent(float percent)
        {
            float v = (MinimumValue < 0 && percent < 0 ? -MinimumValue : MaximumValue) * percent / 100;

            CurrentValue = MathHelper.Clamp(v, MinimumValue, MaximumValue);

            if (CurrentNotch >= 0)
            {
                if (Notches[Notches.Count - 1].NotchStateType == ControllerState.Emergency)
                {
                    v = Notches[Notches.Count - 1].Value * percent / 100;
                }
                for (; ;)
                {
                    INotchController notch = Notches[CurrentNotch];
                    if (CurrentNotch > 0 && v < notch.Value)
                    {
                        INotchController prev = Notches[CurrentNotch - 1];
                        if (!notch.Smooth && !prev.Smooth && v - prev.Value > .45 * (notch.Value - prev.Value))
                        {
                            break;
                        }
                        CurrentNotch--;
                        continue;
                    }
                    if (CurrentNotch < Notches.Count - 1)
                    {
                        INotchController next = Notches[CurrentNotch + 1];
                        if (next.NotchStateType != ControllerState.Emergency)
                        {
                            if ((notch.Smooth || next.Smooth) && v < next.Value)
                            {
                                break;
                            }
                            if (!notch.Smooth && !next.Smooth && v - notch.Value < .55 * (next.Value - notch.Value))
                            {
                                break;
                            }
                            CurrentNotch++;
                            continue;
                        }
                    }
                    break;
                }
                if (Notches[CurrentNotch].Smooth)
                {
                    CurrentValue = v;
                }
                else
                {
                    CurrentValue = Notches[CurrentNotch].Value;
                }
            }
            IntermediateValue = CurrentValue;
            return(100 * CurrentValue);
        }
コード例 #4
0
        public override float?GetStateFraction()
        {
            if (EmergencyBrakingPushButton() || TCSEmergencyBraking() || TCSFullServiceBraking() || QuickReleaseButtonPressed() || OverchargeButtonPressed())
            {
                return(null);
            }
            else if (NotchController != null)
            {
                if (NotchController.NotchCount() == 0)
                {
                    return(NotchController.CurrentValue);
                }
                else
                {
                    INotchController notch = NotchController.GetCurrentNotch();

                    if (!notch.Smooth)
                    {
                        if (notch.NotchStateType == ControllerState.Dummy)
                        {
                            return(NotchController.CurrentValue);
                        }
                        else
                        {
                            return(null);
                        }
                    }
                    else
                    {
                        return(NotchController.GetNotchFraction());
                    }
                }
            }
            else
            {
                return(null);
            }
        }
コード例 #5
0
        public virtual string GetStatus()
        {
            if (Notches.Count == 0)
            {
                return($"{100 * CurrentValue:F0}%");
            }
            INotchController notch = Notches[CurrentNotch];
            string           name  = notch.NotchStateType.GetLocalizedDescription();

            if (!notch.Smooth && notch.NotchStateType == ControllerState.Dummy)
            {
                return($"{100 * CurrentValue:F0}%");
            }
            if (!notch.Smooth)
            {
                return(name);
            }
            if (!string.IsNullOrEmpty(name))
            {
                return($"{name} {100 * GetNotchFraction():F0}%");
            }
            return($"{100 * GetNotchFraction():F0}%");
        }
コード例 #6
0
 public MSTSNotch(INotchController other)
 {
     Value          = other.Value;
     Smooth         = other.Smooth;
     NotchStateType = other.NotchStateType;
 }
コード例 #7
0
        // Train Brake Controllers
        public override Tuple <double, double> UpdatePressure(double pressureBar, double epPressureBar, double elapsedClockSeconds)
        {
            double epState = -1.0;

            if (EmergencyBrakingPushButton() || TCSEmergencyBraking())
            {
                pressureBar -= EmergencyRateBarpS() * elapsedClockSeconds;
            }
            else if (TCSFullServiceBraking())
            {
                if (pressureBar > MaxPressureBar() - FullServReductionBar())
                {
                    pressureBar -= ApplyRateBarpS() * elapsedClockSeconds;
                }
                else if (pressureBar < MaxPressureBar() - FullServReductionBar())
                {
                    pressureBar = MaxPressureBar() - FullServReductionBar();
                }
            }
            else
            {
                INotchController notch = NotchController.GetCurrentNotch();

                if (!brakeControllerInitialised) // The first time around loop, PreviousNotchPosition will be set up front with current value, this will stop crashes due to vsalue not being initialised.
                {
                    previousNotchPosition      = NotchController.GetCurrentNotch();
                    brakeControllerInitialised = true;
                }
                if (notch == null)
                {
                    pressureBar = MaxPressureBar() - FullServReductionBar() * CurrentValue();
                }
                else
                {
                    epState = 0;
                    double          x         = NotchController.GetNotchFraction();
                    ControllerState notchType = notch.NotchStateType;
                    if (OverchargeButtonPressed())
                    {
                        notchType = ControllerState.Overcharge;
                    }
                    else if (QuickReleaseButtonPressed())
                    {
                        switch (notchType)
                        {
                        case ControllerState.Hold:
                        case ControllerState.Lap:
                        case ControllerState.MinimalReduction:
                            if (EnforceMinimalReduction)
                            {
                                pressureBar = DecreasePressure(pressureBar, MaxPressureBar() - MinReductionBar(), ApplyRateBarpS(), elapsedClockSeconds);
                            }
                            break;

                        default:
                            EnforceMinimalReduction = false;
                            break;
                        }
                    }
                    switch (notchType)
                    {
                    case ControllerState.Release:
                        pressureBar = IncreasePressure(pressureBar, MaxPressureBar(), ReleaseRateBarpS(), elapsedClockSeconds);
                        pressureBar = DecreasePressure(pressureBar, MaxPressureBar(), OverchargeEliminationRateBarpS(), elapsedClockSeconds);
                        epState     = -1;
                        break;

                    case ControllerState.FullQuickRelease:
                    case ControllerState.SMEReleaseStart:
                        pressureBar = IncreasePressure(pressureBar, MaxPressureBar(), QuickReleaseRateBarpS(), elapsedClockSeconds);
                        pressureBar = DecreasePressure(pressureBar, MaxPressureBar(), OverchargeEliminationRateBarpS(), elapsedClockSeconds);
                        epState     = -1;
                        break;

                    case ControllerState.Overcharge:
                        pressureBar = IncreasePressure(pressureBar, Math.Min(MaxOverchargePressureBar(), MainReservoirPressureBar()), QuickReleaseRateBarpS(), elapsedClockSeconds);
                        epState     = -1;
                        break;

                    case ControllerState.SlowService:
                        if (pressureBar > MaxPressureBar() - MinReductionBar())
                        {
                            pressureBar = MaxPressureBar() - MinReductionBar();
                        }
                        pressureBar = DecreasePressure(pressureBar, MaxPressureBar() - FullServReductionBar(), SlowApplicationRateBarpS(), elapsedClockSeconds);
                        break;

                    case ControllerState.StraightLap:
                    case ControllerState.StraightApply:
                    case ControllerState.StraightApplyAll:
                    case ControllerState.StraightEmergency:
                        // Nothing is done in these positions, instead they are controlled by the steam ejector in straight brake module
                        break;

                    case ControllerState.StraightRelease:
                    case ControllerState.StraightReleaseOn:
                        // This position is an on position so pressure will be zero (reversed due to vacuum brake operation)
                        pressureBar = 0;
                        break;

                    case ControllerState.StraightReleaseOff:     //(reversed due to vacuum brake operation)
                    case ControllerState.Apply:
                        pressureBar -= x * ApplyRateBarpS() * elapsedClockSeconds;
                        break;

                    case ControllerState.FullServ:
                        epState = x;
                        EnforceMinimalReduction = true;
                        if (pressureBar > MaxPressureBar() - MinReductionBar())
                        {
                            pressureBar = MaxPressureBar() - MinReductionBar();
                        }
                        pressureBar = DecreasePressure(pressureBar, MaxPressureBar() - FullServReductionBar(), ApplyRateBarpS(), elapsedClockSeconds);
                        break;

                    case ControllerState.Lap:
                        // Lap position applies min service reduction when first selected, and previous contoller position was Running, then no change in pressure occurs
                        if (previousNotchPosition.NotchStateType == ControllerState.Running)
                        {
                            EnforceMinimalReduction = true;
                            epState = -1;
                        }
                        break;

                    case ControllerState.MinimalReduction:
                        // Lap position applies min service reduction when first selected, and previous contoller position was Running or Release, then no change in pressure occurs
                        if (previousNotchPosition.NotchStateType == ControllerState.Running || previousNotchPosition.NotchStateType == ControllerState.Release || previousNotchPosition.NotchStateType == ControllerState.FullQuickRelease)
                        {
                            EnforceMinimalReduction = true;
                            epState = -1;
                        }
                        break;

                    case ControllerState.ManualBraking:
                    case ControllerState.VacContServ:
                        // Continuous service positions for vacuum brakes - allows brake to be adjusted up and down continuously between the ON and OFF position
                        pressureBar = (1 - x) * MaxPressureBar();
                        epState     = -1;
                        break;

                    case ControllerState.EPApply:
                    case ControllerState.EPOnly:
                    case ControllerState.SMEOnly:
                    case ControllerState.ContServ:
                    case ControllerState.EPFullServ:
                    case ControllerState.SMEFullServ:
                        epState = x;
                        if (notch.NotchStateType == ControllerState.EPApply || notch.NotchStateType == ControllerState.ContServ)
                        {
                            EnforceMinimalReduction = true;
                            x = MaxPressureBar() - MinReductionBar() * (1 - x) - FullServReductionBar() * x;
                            if (pressureBar > MaxPressureBar() - MinReductionBar())
                            {
                                pressureBar = MaxPressureBar() - MinReductionBar();
                            }
                            pressureBar = DecreasePressure(pressureBar, x, ApplyRateBarpS(), elapsedClockSeconds);
                            if (ForceControllerReleaseGraduated || notch.NotchStateType == ControllerState.EPApply)
                            {
                                pressureBar = IncreasePressure(pressureBar, x, ReleaseRateBarpS(), elapsedClockSeconds);
                            }
                        }
                        break;

                    case ControllerState.GSelfLapH:
                    case ControllerState.Suppression:
                    case ControllerState.GSelfLap:
                        EnforceMinimalReduction = true;
                        x           = MaxPressureBar() - MinReductionBar() * (1 - x) - FullServReductionBar() * x;
                        pressureBar = DecreasePressure(pressureBar, x, ApplyRateBarpS(), elapsedClockSeconds);
                        if (ForceControllerReleaseGraduated || notch.NotchStateType == ControllerState.GSelfLap)
                        {
                            pressureBar = IncreasePressure(pressureBar, x, ReleaseRateBarpS(), elapsedClockSeconds);
                        }
                        break;

                    case ControllerState.Emergency:
                        pressureBar -= EmergencyRateBarpS() * elapsedClockSeconds;
                        epState      = 1;
                        break;

                    case ControllerState.Dummy:
                        x           = MaxPressureBar() - FullServReductionBar() * (notch.Smooth ? x : CurrentValue());
                        pressureBar = IncreasePressure(pressureBar, x, ReleaseRateBarpS(), elapsedClockSeconds);
                        pressureBar = DecreasePressure(pressureBar, x, ApplyRateBarpS(), elapsedClockSeconds);
                        epState     = -1;
                        break;
                    }

                    previousNotchPosition = NotchController.GetCurrentNotch();
                }
            }

            if (pressureBar < 0)
            {
                pressureBar = 0;
            }
            return(new Tuple <double, double>(pressureBar, epState));
        }
コード例 #8
0
        // Engine Brake Controllers
        public override double UpdateEngineBrakePressure(double pressureBar, double elapsedClockSeconds)
        {
            INotchController notch = NotchController.GetCurrentNotch();

            if (notch == null)
            {
                pressureBar = (MaxPressureBar() - FullServReductionBar()) * CurrentValue();
            }
            else
            {
                double x = NotchController.GetNotchFraction();
                switch (notch.NotchStateType)
                {
                case ControllerState.Neutral:
                case ControllerState.Running:
                case ControllerState.Lap:
                    break;

                case ControllerState.FullQuickRelease:
                    pressureBar -= x * QuickReleaseRateBarpS() * elapsedClockSeconds;
                    break;

                case ControllerState.Release:
                    pressureBar -= x * ReleaseRateBarpS() * elapsedClockSeconds;
                    break;

                case ControllerState.Apply:
                case ControllerState.FullServ:
                    pressureBar = IncreasePressure(pressureBar, x * (MaxPressureBar() - FullServReductionBar()), ApplyRateBarpS(), elapsedClockSeconds);
                    break;

                case ControllerState.ManualBraking:
                case ControllerState.VacContServ:
                    // Continuous service positions for vacuum brakes - allows brake to be adjusted up and down continuously between the ON and OFF position
                    pressureBar = (1 - x) * MaxPressureBar();
                    break;

                case ControllerState.BrakeNotch:
                    // Notch position for brakes - allows brake to be adjusted up and down continuously between specified notches
                    pressureBar = (1 - x) * MaxPressureBar();
                    break;

                case ControllerState.Emergency:
                    pressureBar += EmergencyRateBarpS() * elapsedClockSeconds;
                    break;

                case ControllerState.Dummy:
                    pressureBar = (MaxPressureBar() - FullServReductionBar()) * CurrentValue();
                    break;

                default:
                    x          *= MaxPressureBar() - FullServReductionBar();
                    pressureBar = IncreasePressure(pressureBar, x, ApplyRateBarpS(), elapsedClockSeconds);
                    pressureBar = DecreasePressure(pressureBar, x, ReleaseRateBarpS(), elapsedClockSeconds);
                    break;
                }
                if (pressureBar > MaxPressureBar())
                {
                    pressureBar = MaxPressureBar();
                }
                if (pressureBar < 0)
                {
                    pressureBar = 0;
                }
            }
            return(pressureBar);
        }
コード例 #9
0
        // Train Brake Controllers
        public override Tuple <double, double> UpdatePressure(double pressureBar, double epPressureBar, double elapsedClockSeconds)
        {
            double epState = -1.0;

            if (EmergencyBrakingPushButton() || TCSEmergencyBraking())
            {
                pressureBar -= EmergencyRateBarpS() * elapsedClockSeconds;
            }
            else if (TCSFullServiceBraking())
            {
                if (pressureBar > MaxPressureBar() - FullServReductionBar())
                {
                    pressureBar -= ApplyRateBarpS() * elapsedClockSeconds;
                }
                else if (pressureBar < MaxPressureBar() - FullServReductionBar())
                {
                    pressureBar = MaxPressureBar() - FullServReductionBar();
                }
            }
            else
            {
                INotchController notch = NotchController.GetCurrentNotch();

                if (!BrakeControllerInitialised) // The first time around loop, PreviousNotchPosition will be set up front with current value, this will stop crashes due to vsalue not being initialised.
                {
                    PreviousNotchPosition      = NotchController.GetCurrentNotch();
                    BrakeControllerInitialised = true;
                }

                if (notch == null)
                {
                    pressureBar = MaxPressureBar() - FullServReductionBar() * CurrentValue();
                }
                else
                {
                    epState = 0;
                    double x = NotchController.GetNotchFraction();
                    switch (notch.NotchStateType)
                    {
                    case ControllerState.Release:
                        pressureBar += x * ReleaseRateBarpS() * elapsedClockSeconds;
                        epState      = -1;
                        break;

                    case ControllerState.FullQuickRelease:
                        pressureBar += x * QuickReleaseRateBarpS() * elapsedClockSeconds;
                        epState      = -1;
                        break;

                    case ControllerState.Apply:
                    case ControllerState.FullServ:
                        if (notch.NotchStateType == ControllerState.FullServ)
                        {
                            epState = x;
                        }
                        pressureBar -= x * ApplyRateBarpS() * elapsedClockSeconds;
                        break;

                    case ControllerState.Lap:
                        // Lap position applies min service reduction when first selected, and previous contoller position was Running, then no change in pressure occurs
                        if (PreviousNotchPosition.NotchStateType == ControllerState.Running)
                        {
                            pressureBar -= MinReductionBar();
                            epState      = -1;
                        }
                        break;

                    case ControllerState.MinimalReduction:
                        // Lap position applies min service reduction when first selected, and previous contoller position was Running or Release, then no change in pressure occurs
                        if (PreviousNotchPosition.NotchStateType == ControllerState.Running || PreviousNotchPosition.NotchStateType == ControllerState.Release || PreviousNotchPosition.NotchStateType == ControllerState.FullQuickRelease)
                        {
                            pressureBar -= MinReductionBar();
                            epState      = -1;
                        }
                        break;

                    case ControllerState.VacContServ:
                        // Continuous service positions for vacuum brakes - allows brake to be adjusted up and down continuously between the ON and OFF position
                        pressureBar = (1 - x) * MaxPressureBar();
                        epState     = -1;
                        break;

                    case ControllerState.EPApply:
                    case ControllerState.GSelfLapH:
                    case ControllerState.Suppression:
                    case ControllerState.ContServ:
                    case ControllerState.GSelfLap:
                        if (notch.NotchStateType == ControllerState.EPApply || notch.NotchStateType == ControllerState.ContServ)
                        {
                            epState = x;
                        }
                        x           = MaxPressureBar() - MinReductionBar() * (1 - x) - FullServReductionBar() * x;
                        pressureBar = DecreasePressure(pressureBar, x, ApplyRateBarpS(), elapsedClockSeconds);
                        if (ForceControllerReleaseGraduated)
                        {
                            pressureBar = IncreasePressure(pressureBar, x, ReleaseRateBarpS(), elapsedClockSeconds);
                        }
                        break;

                    case ControllerState.Emergency:
                        pressureBar -= EmergencyRateBarpS() * elapsedClockSeconds;
                        epState      = 1;
                        break;

                    case ControllerState.Dummy:
                        x          *= MaxPressureBar() - FullServReductionBar();
                        pressureBar = IncreasePressure(pressureBar, x, ReleaseRateBarpS(), elapsedClockSeconds);
                        pressureBar = DecreasePressure(pressureBar, x, ApplyRateBarpS(), elapsedClockSeconds);
                        epState     = -1;
                        break;
                    }

                    PreviousNotchPosition = NotchController.GetCurrentNotch();
                }
            }

            if (pressureBar > MaxPressureBar())
            {
                pressureBar = MaxPressureBar();
            }
            if (pressureBar < 0)
            {
                pressureBar = 0;
            }
            return(new Tuple <double, double>(pressureBar, epState));
        }