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); }
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())); }
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; }
// 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; }
// 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; } } }
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; }
// 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; }