diff --git a/src/Devices/AtcDimetronic.cs b/src/Devices/AtcDimetronic.cs
index 1060fe6..09c778f 100644
--- a/src/Devices/AtcDimetronic.cs
+++ b/src/Devices/AtcDimetronic.cs
@@ -86,6 +86,9 @@ namespace OpenbveFcmbTrainPlugin
/// The delay before ATO changes notches.
private readonly double AtoNotchDelay = 250;
+ /// The deceleration considered by ATO to calculate braking curves, in m/s2.
+ private readonly double AtoDeceleration = 0.33;
+
/// The counter for the ATO notch delay.
private double AtoNotchDelayCounter;
@@ -107,6 +110,9 @@ namespace OpenbveFcmbTrainPlugin
/// The maximum speed in YARD mode.
private readonly Speed YardMaximumSpeed;
+ /// The maximum speed when ATO mode is first initialized.
+ private readonly Speed AtoInitSpeed = new Speed(25 / 3.6);
+
/// The distance after which the runback protection is triggered.
private readonly double RunbackDistance;
@@ -418,7 +424,6 @@ namespace OpenbveFcmbTrainPlugin
}
}
-
/// Is called when the state of a key changes.
/// The key.
/// Whether the key is pressed or released.
@@ -545,14 +550,17 @@ namespace OpenbveFcmbTrainPlugin
switch (type)
{
case -16777215:
+ // ATC track state
+ if (!(beacon.Optional >= 0 & beacon.Optional <= 3))
{
- if (!(beacon.Optional >= 0 & beacon.Optional <= 3))
- {
- break;
- }
- TrackState = (TrackStates)beacon.Optional;
- return;
+ break;
}
+ TrackState = (TrackStates)beacon.Optional;
+ return;
+ case 36900:
+ // ATC Dimetronic ATO beacon
+ AtoPositionKnown = true;
+ return;
}
}
@@ -704,10 +712,18 @@ namespace OpenbveFcmbTrainPlugin
double speed = train.State.Speed.KilometersPerHour;
bool stopped = speed < 0.05;
- Speed limit = CurrentSpeedCode.CurrentLimit;
- Speed target = CurrentSpeedCode.TargetLimit;
+ // Set limits from speed code, unless position is unknown
+ Speed limit = AtoPositionKnown ? CurrentSpeedCode.CurrentLimit : AtoInitSpeed;
+ Speed target = AtoPositionKnown ? CurrentSpeedCode.TargetLimit : AtoInitSpeed;
double distance = CurrentSpeedCode.TargetPosition - TrainLocation;
+ // Calculate required deceleration
+ double requiredDeceleration = 0;
+ if (target.KilometersPerHour < limit.KilometersPerHour)
+ {
+ requiredDeceleration = (train.State.Speed.MetersPerSecond - target.MetersPerSecond) / (distance - 8) * 10;
+ }
+
// Pitch multiplier, used to alter when state changes occur
double pitchMulti = train.State.Pitch / 20;
@@ -724,7 +740,7 @@ namespace OpenbveFcmbTrainPlugin
AtoStartupPosition = TrainLocation;
// If the train is stopped, doors are closed and signal is clear, change to startup state
- if (stopped && train.DoorState == DoorStates.None && target.KilometersPerHour > 0)
+ if (stopped && train.DoorState == DoorStates.None && limit.KilometersPerHour > 0)
{
AtoState = AtoStates.AwaitingStartup;
}
@@ -749,10 +765,16 @@ namespace OpenbveFcmbTrainPlugin
}
AtoNotchDelayCounter = 0;
}
- if (train.State.Speed.KilometersPerHour >= target.KilometersPerHour - 5 + pitchMulti)
+ if (train.State.Speed.KilometersPerHour >= limit.KilometersPerHour - 5 + pitchMulti)
{
+ // Train is near the limit, maintain speed
AtoState = AtoStates.MaintainSpeed;
}
+ if (requiredDeceleration >= AtoDeceleration)
+ {
+ // Train is near a speed change, reduce speed
+ AtoState = AtoStates.ReduceSpeed;
+ }
break;
case AtoStates.MaintainSpeed:
if ((train.Acceleration > 0 || (AtoPowerNotch > 0 && train.State.Pitch <= 0)) && AtoNotchDelayCounter >= AtoNotchDelay)
@@ -769,10 +791,45 @@ namespace OpenbveFcmbTrainPlugin
AtoNotchDelayCounter = 0;
}
}
- if (train.State.Speed.KilometersPerHour <= target.KilometersPerHour - 7 + pitchMulti)
+ if (train.State.Speed.KilometersPerHour <= limit.KilometersPerHour - 7 + pitchMulti && target.KilometersPerHour >= limit.KilometersPerHour)
{
+ // Train is far below the limit, increase speed
AtoState = AtoStates.IncreaseSpeed;
}
+ if (requiredDeceleration >= AtoDeceleration)
+ {
+ // Train is near a speed change, reduce speed
+ AtoState = AtoStates.ReduceSpeed;
+ }
+ break;
+ case AtoStates.ReduceSpeed:
+ if (train.Acceleration > -requiredDeceleration && AtoNotchDelayCounter >= AtoNotchDelay)
+ {
+ // Train is travelling too fast, reduce speed
+ if (AtoPowerNotch > 0)
+ {
+ AtoPowerNotch--;
+ AtoNotchDelayCounter = 0;
+ }
+ else if (AtoBrakeNotch < train.Specs.BrakeNotches)
+ {
+ AtoBrakeNotch++;
+ AtoNotchDelayCounter = 0;
+ }
+ }
+ else if (train.Acceleration < -requiredDeceleration && AtoNotchDelayCounter >= AtoNotchDelay)
+ {
+ // Reducing speed too fast, release brakes
+ if (AtoBrakeNotch > 0)
+ {
+ AtoBrakeNotch--;
+ AtoNotchDelayCounter = 0;
+ }
+ }
+ if (train.State.Speed.KilometersPerHour <= target.KilometersPerHour - 3 + pitchMulti)
+ {
+ AtoState = AtoStates.MaintainSpeed;
+ }
break;
}
@@ -783,8 +840,8 @@ namespace OpenbveFcmbTrainPlugin
// ATO is driving but does not know the position of the train, unselect driving mode and set alarm state
if (TrainLocation - AtoStartupPosition > 400 && !AtoPositionKnown)
{
- //AtoState = AtoStates.Alarm;
- //DeviceState = DeviceStates.NoMode;
+ AtoState = AtoStates.Alarm;
+ DeviceState = DeviceStates.NoMode;
}
}
}
diff --git a/src/Train/Train.cs b/src/Train/Train.cs
index 4b67e22..1925bda 100644
--- a/src/Train/Train.cs
+++ b/src/Train/Train.cs
@@ -143,7 +143,6 @@ namespace OpenbveFcmbTrainPlugin
AccelerationTimer = 0;
AccelerationSpeed = data.Vehicle.Speed;
}
- data.DebugMessage = Acceleration.ToString();
// Retrieve data from all devices
foreach (Device dev in Devices)