public float GetNotchFraction()
        {
            if (Notches.Count == 0)
            {
                return(0);
            }
            MSTSNotch notch = Notches[CurrentNotch];

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

            if (CurrentNotch + 1 < Notches.Count)
            {
                x = Notches[CurrentNotch + 1].Value;
            }
            x = (CurrentValue - notch.Value) / (x - notch.Value);
            if (notch.Type == ControllerState.Release)
            {
                x = 1 - x;
            }
            return(x);
        }
        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].Type == ControllerState.Emergency)
                {
                    v = Notches[Notches.Count - 1].Value * percent / 100;
                }
                for (; ;)
                {
                    MSTSNotch notch = Notches[CurrentNotch];
                    if (CurrentNotch > 0 && v < notch.Value)
                    {
                        MSTSNotch 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)
                    {
                        MSTSNotch next = Notches[CurrentNotch + 1];
                        if (next.Type != 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);
        }
示例#3
0
        public override void UpdateEngineBrakePressure(ref float pressureBar, float elapsedClockSeconds)
        {
            MSTSNotch notch = NotchController.GetCurrentNotch();

            if (notch == null)
            {
                pressureBar = (MaxPressureBar() - FullServReductionBar()) * CurrentValue();
            }
            else
            {
                float x = NotchController.GetNotchFraction();
                switch (notch.Type)
                {
                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:
                    IncreasePressure(ref pressureBar, x * (MaxPressureBar() - FullServReductionBar()), ApplyRateBarpS(), elapsedClockSeconds);
                    break;

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

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

                default:
                    x *= MaxPressureBar() - FullServReductionBar();
                    IncreasePressure(ref pressureBar, x, ApplyRateBarpS(), elapsedClockSeconds);
                    DecreasePressure(ref pressureBar, x, ReleaseRateBarpS(), elapsedClockSeconds);
                    break;
                }
                if (pressureBar > MaxPressureBar())
                {
                    pressureBar = MaxPressureBar();
                }
                if (pressureBar < 0)
                {
                    pressureBar = 0;
                }
            }
        }
        public virtual string GetStatus()
        {
            if (Notches.Count == 0)
            {
                return(string.Format("{0:F0}%", 100 * CurrentValue));
            }
            MSTSNotch notch = Notches[CurrentNotch];

            if (!notch.Smooth && notch.Type == ControllerState.Dummy)
            {
                return(string.Format("{0:F0}%", 100 * CurrentValue));
            }
            if (!notch.Smooth)
            {
                return(notch.GetName());
            }
            if (notch.GetName().Length > 0)
            {
                return(string.Format("{0} {1:F0}%", notch.GetName(), 100 * GetNotchFraction()));
            }
            return(string.Format("{0:F0}%", 100 * GetNotchFraction()));
        }
示例#5
0
        public override float?GetStateFraction()
        {
            if (EmergencyBrakingPushButton() || TCSEmergencyBraking() || TCSFullServiceBraking())
            {
                return(null);
            }
            else if (NotchController != null)
            {
                if (NotchController.NotchCount() == 0)
                {
                    return(NotchController.CurrentValue);
                }
                else
                {
                    MSTSNotch notch = NotchController.GetCurrentNotch();

                    if (!notch.Smooth)
                    {
                        if (notch.Type == ControllerState.Dummy)
                        {
                            return(NotchController.CurrentValue);
                        }
                        else
                        {
                            return(null);
                        }
                    }
                    else
                    {
                        return(NotchController.GetNotchFraction());
                    }
                }
            }
            else
            {
                return(null);
            }
        }
 public MSTSNotch(MSTSNotch other)
 {
     Value  = other.Value;
     Smooth = other.Smooth;
     Type   = other.Type;
 }
示例#7
0
        // Train Brake Controllers
        public override void UpdatePressure(ref float pressureBar, float elapsedClockSeconds, ref float epControllerState)
        {
            var epState = -1f;

            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
            {
                MSTSNotch 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;
                    float x = NotchController.GetNotchFraction();
                    switch (notch.Type)
                    {
                    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.Type == 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.Type == 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.Type == ControllerState.Running || PreviousNotchPosition.Type == ControllerState.Release || PreviousNotchPosition.Type == ControllerState.FullQuickRelease)
                        {
                            pressureBar -= MinReductionBar();
                            epState      = -1;
                        }
                        break;

                    case ControllerState.VacContServ:
                    case ControllerState.VacApplyContServ:
                        // Continuous service position 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.Type == ControllerState.EPApply || notch.Type == ControllerState.ContServ)
                        {
                            epState = x;
                        }
                        x = MaxPressureBar() - MinReductionBar() * (1 - x) - FullServReductionBar() * x;
                        DecreasePressure(ref pressureBar, x, ApplyRateBarpS(), elapsedClockSeconds);
                        if (ForceControllerReleaseGraduated)
                        {
                            IncreasePressure(ref pressureBar, x, ReleaseRateBarpS(), elapsedClockSeconds);
                        }
                        break;

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

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

                    PreviousNotchPosition = NotchController.GetCurrentNotch();
                }
            }

            if (pressureBar > MaxPressureBar())
            {
                pressureBar = MaxPressureBar();
            }
            if (pressureBar < 0)
            {
                pressureBar = 0;
            }
            epControllerState = epState;
        }
示例#8
0
        // Engine Brake Controllers
        public override void UpdateEngineBrakePressure(ref float pressureBar, float elapsedClockSeconds)
        {
            MSTSNotch notch = NotchController.GetCurrentNotch();

            if (notch == null)
            {
                pressureBar = (MaxPressureBar() - FullServReductionBar()) * CurrentValue();
            }
            else
            {
                float x = NotchController.GetNotchFraction();
                switch (notch.Type)
                {
                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:
                    IncreasePressure(ref pressureBar, x * (MaxPressureBar() - FullServReductionBar()), ApplyRateBarpS(), elapsedClockSeconds);
                    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();
                    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();
                    IncreasePressure(ref pressureBar, x, ApplyRateBarpS(), elapsedClockSeconds);
                    DecreasePressure(ref pressureBar, x, ReleaseRateBarpS(), elapsedClockSeconds);
                    break;
                }
                if (pressureBar > MaxPressureBar())
                {
                    pressureBar = MaxPressureBar();
                }
                if (pressureBar < 0)
                {
                    pressureBar = 0;
                }
            }
        }
示例#9
0
        public override void UpdatePressure(ref float pressureBar, float elapsedClockSeconds, ref float epControllerState)
        {
            var epState = -1f;

            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
            {
                MSTSNotch notch = NotchController.GetCurrentNotch();
                if (notch == null)
                {
                    pressureBar = MaxPressureBar() - FullServReductionBar() * CurrentValue();
                }
                else
                {
                    epState = 0;
                    float x = NotchController.GetNotchFraction();
                    switch (notch.Type)
                    {
                    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.Type == ControllerState.FullServ)
                        {
                            epState = x;
                        }
                        pressureBar -= x * ApplyRateBarpS() * elapsedClockSeconds;
                        break;

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

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

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

            if (pressureBar > MaxPressureBar())
            {
                pressureBar = MaxPressureBar();
            }
            if (pressureBar < 0)
            {
                pressureBar = 0;
            }
            epControllerState = epState;
        }
示例#10
0
        // Train Brake Controllers
        public override void UpdatePressure(ref float pressureBar, float elapsedClockSeconds, ref float epControllerState)
        {
            var epState = -1f;

            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
            {
                MSTSNotch 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;
                    float x    = NotchController.GetNotchFraction();
                    var   type = notch.Type;
                    if (OverchargeButtonPressed())
                    {
                        type = ControllerState.Overcharge;
                    }
                    else if (QuickReleaseButtonPressed())
                    {
                        type = ControllerState.FullQuickRelease;
                    }

                    switch (type)
                    {
                    case ControllerState.Hold:
                    case ControllerState.Lap:
                    case ControllerState.MinimalReduction:
                        if (EnforceMinimalReduction)
                        {
                            DecreasePressure(ref pressureBar, MaxPressureBar() - MinReductionBar(), ApplyRateBarpS(), elapsedClockSeconds);
                        }
                        break;

                    default:
                        EnforceMinimalReduction = false;
                        break;
                    }

                    switch (type)
                    {
                    case ControllerState.Release:
                        IncreasePressure(ref pressureBar, MaxPressureBar(), ReleaseRateBarpS(), elapsedClockSeconds);
                        DecreasePressure(ref pressureBar, MaxPressureBar(), OverchargeEliminationRateBarpS(), elapsedClockSeconds);
                        epState = -1;
                        break;

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

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

                    case ControllerState.SlowService:
                        DecreasePressure(ref pressureBar, MaxPressureBar() - FullServReductionBar(), SlowApplicationRateBarpS(), elapsedClockSeconds);
                        break;

                    case ControllerState.StrBrkLap:
                    case ControllerState.StrBrkApply:
                    case ControllerState.StrBrkApplyAll:
                    case ControllerState.StrBrkEmergency:
                        // Nothing is done in these positions, instead they are controlled by the steam ejector in straight brake module
                        break;

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

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

                    case ControllerState.FullServ:
                        epState = x;
                        EnforceMinimalReduction = true;
                        DecreasePressure(ref 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.Type == 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.Type == ControllerState.Running || PreviousNotchPosition.Type == ControllerState.Release || PreviousNotchPosition.Type == ControllerState.FullQuickRelease)
                        {
                            EnforceMinimalReduction = true;
                            epState = -1;
                        }
                        break;

                    case ControllerState.ManualBraking:
                    case ControllerState.VacContServ:
                    case ControllerState.VacApplyContServ:
                        // Continuous service position 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.Type == ControllerState.EPApply || notch.Type == ControllerState.ContServ)
                        {
                            EnforceMinimalReduction = true;
                            x = MaxPressureBar() - MinReductionBar() * (1 - x) - FullServReductionBar() * x;
                            DecreasePressure(ref pressureBar, x, ApplyRateBarpS(), elapsedClockSeconds);
                            if (ForceControllerReleaseGraduated || notch.Type == ControllerState.EPApply)
                            {
                                IncreasePressure(ref pressureBar, x, ReleaseRateBarpS(), elapsedClockSeconds);
                            }
                        }
                        break;

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

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

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

                    PreviousNotchPosition = NotchController.GetCurrentNotch();
                }
            }

            if (pressureBar < 0)
            {
                pressureBar = 0;
            }
            epControllerState = epState;
        }