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