From 5477d7389cb9c25502ea52c8f87a0489bc0f33e8 Mon Sep 17 00:00:00 2001 From: Marc Riera Date: Mon, 23 Dec 2024 01:25:25 +0100 Subject: [PATCH] ATC Dimetronic: Implement double signal codes --- src/Devices/AtcDimetronic.cs | 78 ++++++++++++++++++++++++----------- src/Managers/ConfigManager.cs | 18 +++++++- src/Train/Train.cs | 2 +- 3 files changed, 70 insertions(+), 28 deletions(-) diff --git a/src/Devices/AtcDimetronic.cs b/src/Devices/AtcDimetronic.cs index 6ce85e1..fbf2f16 100644 --- a/src/Devices/AtcDimetronic.cs +++ b/src/Devices/AtcDimetronic.cs @@ -51,15 +51,15 @@ namespace OpenbveFcmbTrainPlugin /// The current state of the track. private TrackStates TrackState; + /// The current position of the train. + private double TrainLocation; + + /// The length of the train. + private readonly double TrainLength; + /// The maximum speed in YARD mode. private readonly Speed YardMaximumSpeed; - /// The speed limit for each signal aspect. - private readonly Speed[] AspectLimit = { new Speed(0), new Speed(25 / 3.6), new Speed(25 / 3.6), new Speed(25 / 3.6), new Speed(25 / 3.6), new Speed(45 / 3.6), new Speed(45 / 3.6), new Speed(45 / 3.6), new Speed(45 / 3.6), new Speed(70 / 3.6), new Speed(70 / 3.6), new Speed(70 / 3.6), new Speed(70 / 3.6) }; - - /// The target speed limit for each signal aspect. - private readonly Speed[] AspectTargetLimit = { new Speed(0), new Speed(0), new Speed(0), new Speed(25 / 3.6), new Speed(25 / 3.6), new Speed(0), new Speed(0), new Speed(45 / 3.6), new Speed(45 / 3.6), new Speed(0), new Speed(0), new Speed(70 / 3.6), new Speed(70 / 3.6) }; - /// Whether ATO is available or not on the train. private readonly bool AtoAvailable; @@ -113,26 +113,38 @@ namespace OpenbveFcmbTrainPlugin internal int Aspect; internal Speed Limit; internal Speed Target; + internal Speed EntryTarget; internal SignalCode(int aspect, string data) { Aspect = aspect; Limit = new Speed(0); Target = new Speed(0); + EntryTarget = new Speed(0); if (data.Contains("/")) { - int separator = data.IndexOf('/'); - string a = data.Substring(0, separator); - string b = data.Substring(separator + 1); - if (double.TryParse(a, NumberStyles.Float, CultureInfo.InvariantCulture, out double an) && double.TryParse(b, NumberStyles.Float, CultureInfo.InvariantCulture, out double bn)) + string[] speeds = data.Split('/'); + if (speeds.Length > 1) { - if (an >= bn && an >= 0) + string a = speeds[0]; + string b = speeds[1]; + if (double.TryParse(a, NumberStyles.Float, CultureInfo.InvariantCulture, out double an) && double.TryParse(b, NumberStyles.Float, CultureInfo.InvariantCulture, out double bn)) { - Limit = new Speed(an / 3.6); - } - if (bn <= an && bn >= 0) - { - Target = new Speed(bn / 3.6); + if (an >= bn && an >= 0) + { + Limit = new Speed(an / 3.6); + } + if (bn <= an && bn >= 0) + { + Target = new Speed(bn / 3.6); + } + if (speeds.Length > 2) + { + if (double.TryParse(speeds[2], NumberStyles.Float, CultureInfo.InvariantCulture, out double cn)) + { + EntryTarget = new Speed(cn / 3.6); + } + } } } } @@ -145,6 +157,12 @@ namespace OpenbveFcmbTrainPlugin /// The aspect of the current signal in the route. private int CurrentSignalAspect; + /// The start position of the current signal. + private double CurrentSignalStartLocation; + + /// The end position of the current signal. + private double CurrentSignalEndLocation; + /// The ideal power notch for the AI. private int AiPowerNotch; @@ -155,8 +173,9 @@ namespace OpenbveFcmbTrainPlugin /// The maximum speed in YARD mode, in km/h. /// The list of signal codes recognised by the device. /// Whether ATO is available or not. - internal AtcDimetronic(Speed yardMaxSpeed, List signalCodes, bool atoAvailable) + internal AtcDimetronic(double trainLength, Speed yardMaxSpeed, List signalCodes, bool atoAvailable) { + TrainLength = trainLength; YardMaximumSpeed = yardMaxSpeed; SignalCodes = signalCodes; AtoAvailable = atoAvailable; @@ -175,6 +194,10 @@ namespace OpenbveFcmbTrainPlugin DeviceState = DeviceStates.NoMode; } + // Update train location + // TODO: implement runback/rollfoward protection + TrainLocation = train.State.Location; + double speed = train.State.Speed.KilometersPerHour; bool stopped = speed < 0.05; @@ -252,13 +275,13 @@ namespace OpenbveFcmbTrainPlugin case DeviceStates.ATP: train.ContinuousProtection = true; train.VigilanceOverride = false; - CurrentSpeedCode = GetSpeedCodeFromAspect(SignalCodes, CurrentSignalAspect); + CurrentSpeedCode = GetSpeedCodeFromAspect(); break; // ATC device is in ATO driving mode case DeviceStates.ATO: train.ContinuousProtection = true; train.VigilanceOverride = true; - CurrentSpeedCode = GetSpeedCodeFromAspect(SignalCodes, CurrentSignalAspect); + CurrentSpeedCode = GetSpeedCodeFromAspect(); break; } @@ -376,6 +399,8 @@ namespace OpenbveFcmbTrainPlugin internal override void SetSignal(SignalData[] signal) { CurrentSignalAspect = signal[0].Aspect; + CurrentSignalStartLocation = signal[0].Distance + TrainLocation; + CurrentSignalEndLocation = signal.Length > 1 ? signal[1].Distance + TrainLocation : double.MaxValue; } /// Is called when a beacon is passed. @@ -511,15 +536,18 @@ namespace OpenbveFcmbTrainPlugin } /// Generates the corresponding speed code from a signal aspect. - /// The list of signal codes. - /// The current signal aspect. - private SpeedCode GetSpeedCodeFromAspect(List signalCodes, int aspect) + private SpeedCode GetSpeedCodeFromAspect() { - foreach (SignalCode signal in signalCodes) + foreach (SignalCode signal in SignalCodes) { - if (signal.Aspect == aspect) + if (signal.Aspect == CurrentSignalAspect) { - return new SpeedCode(signal.Limit, signal.Target); + if (TrainLocation - TrainLength < CurrentSignalStartLocation && signal.EntryTarget.MetersPerSecond > 0) + { + // The train has not fully entered the signal section, use the entry target speed + return new SpeedCode(signal.Limit, signal.EntryTarget, CurrentSignalEndLocation); + } + return new SpeedCode(signal.Limit, signal.Target, CurrentSignalEndLocation); } } return new SpeedCode(new Speed(0), new Speed(0)); diff --git a/src/Managers/ConfigManager.cs b/src/Managers/ConfigManager.cs index 4d1ebe7..a3a1754 100644 --- a/src/Managers/ConfigManager.cs +++ b/src/Managers/ConfigManager.cs @@ -11,6 +11,8 @@ namespace OpenbveFcmbTrainPlugin /// Represents a collection of plugin settings. internal class SettingsCollection { + internal double TrainLength; + internal bool DoorSelectionDeviceEnabled; internal bool DoorClosingSoundDeviceEnabled; internal bool DoorTractionCutDeviceEnabled; @@ -75,6 +77,19 @@ namespace OpenbveFcmbTrainPlugin } switch (Section) { + case "train": + switch (Key) + { + case "length": + { + if (double.TryParse(Value, NumberStyles.Float, CultureInfo.InvariantCulture, out double a)) + { + PluginSettings.TrainLength = a; + } + } + break; + } + break; case "doorselection": switch (Key) { @@ -211,8 +226,7 @@ namespace OpenbveFcmbTrainPlugin PluginSettings.AtcDimetronicAtoAvailable = string.Compare(Value, "false", StringComparison.OrdinalIgnoreCase) != 0; break; default: - int aspect; - if (int.TryParse(Key, NumberStyles.Integer, CultureInfo.InvariantCulture, out aspect)) + if (int.TryParse(Key, NumberStyles.Integer, CultureInfo.InvariantCulture, out int aspect)) { AtcDimetronic.SignalCode signalCode = new AtcDimetronic.SignalCode(aspect, Value); if (signalCode != null) diff --git a/src/Train/Train.cs b/src/Train/Train.cs index e9e1fb8..00aa189 100644 --- a/src/Train/Train.cs +++ b/src/Train/Train.cs @@ -98,7 +98,7 @@ namespace OpenbveFcmbTrainPlugin } if (settings.AtcDimetronicDeviceEnabled) { - Devices.Add(new AtcDimetronic(settings.AtcDimetronicYardSpeedLimit, settings.AtcDimetronicSignalCodes, settings.AtcDimetronicAtoAvailable)); + Devices.Add(new AtcDimetronic(settings.TrainLength, settings.AtcDimetronicYardSpeedLimit, settings.AtcDimetronicSignalCodes, settings.AtcDimetronicAtoAvailable)); } }