ATC Dimetronic: ATO init

This commit is contained in:
Marc Riera 2024-12-28 13:06:54 +01:00
parent a836a0e438
commit be7003669e

View file

@ -53,6 +53,23 @@ namespace OpenbveFcmbTrainPlugin
/// <summary>The current state of the track.</summary> /// <summary>The current state of the track.</summary>
private TrackStates TrackState; private TrackStates TrackState;
/// <summary>Represents the state of ATO.</summary>
private enum AtoStates
{
Inactive,
AwaitingStartup,
IncreaseSpeed,
MaintainSpeed,
ReduceSpeed,
StopApproach
}
/// <summary>The current state of ATO.</summary>
private AtoStates AtoState;
/// <summary>Whether ATO knows the precise position of the train or not.</summary>
private bool AtoPositionKnown;
/// <summary>The current position of the train.</summary> /// <summary>The current position of the train.</summary>
private double TrainLocation; private double TrainLocation;
@ -90,13 +107,13 @@ namespace OpenbveFcmbTrainPlugin
internal Speed WarningOn { get; private set; } internal Speed WarningOn { get; private set; }
internal Speed WarningOff { get; private set; } internal Speed WarningOff { get; private set; }
internal Speed TargetLimit { get; private set; } internal Speed TargetLimit { get; private set; }
internal double TargetDistance { get; private set; } internal double TargetPosition { get; private set; }
internal SpeedCode(Speed limit, Speed target, double distance) internal SpeedCode(Speed limit, Speed target, double distance)
{ {
CurrentLimit = limit; CurrentLimit = limit;
TargetLimit = target; TargetLimit = target;
TargetDistance = distance; TargetPosition = distance;
if (limit == target) if (limit == target)
{ {
// Constant speed // Constant speed
@ -116,10 +133,10 @@ namespace OpenbveFcmbTrainPlugin
} }
/// <summary>Updates the ATC speed code.</summary> /// <summary>Updates the ATC speed code.</summary>
/// <param name="distance">The distance to the end of the signalling block.</param> /// <param name="position">The position of the end of the signalling block.</param>
internal void Update(double distance) internal void Update(double position)
{ {
TargetDistance = distance; TargetPosition = position;
} }
} }
@ -227,13 +244,19 @@ namespace OpenbveFcmbTrainPlugin
// Update train location // Update train location
TrainLocation = train.State.Location; TrainLocation = train.State.Location;
// If ATO is not the current mode, it should be in inactive state
if (DeviceState != DeviceStates.ATO)
{
AtoState = AtoStates.Inactive;
}
double speed = train.State.Speed.KilometersPerHour; double speed = train.State.Speed.KilometersPerHour;
bool stopped = speed < 0.05; bool stopped = speed < 0.05;
if (DeviceState == DeviceStates.YARD || DeviceState == DeviceStates.ATP || DeviceState == DeviceStates.ATO) if (DeviceState == DeviceStates.YARD || DeviceState == DeviceStates.ATP || DeviceState == DeviceStates.ATO)
{ {
// Speed limit enforcement // Speed limit enforcement
if (AtcControlState == AtcControlStates.Released && speed > CurrentSpeedCode.WarningOn.KilometersPerHour) if (AtcControlState == AtcControlStates.Released && speed > CurrentSpeedCode.WarningOn.KilometersPerHour && DeviceState != DeviceStates.ATO)
{ {
// Cut power above warning on threshold and play alarm // Cut power above warning on threshold and play alarm
AtcControlState = AtcControlStates.NoPowerAlarm; AtcControlState = AtcControlStates.NoPowerAlarm;
@ -278,6 +301,16 @@ namespace OpenbveFcmbTrainPlugin
// The train is rolling unintendedly, reset driving mode // The train is rolling unintendedly, reset driving mode
DeviceState = DeviceStates.NoMode; DeviceState = DeviceStates.NoMode;
} }
// Accidental door opening protection
if (train.DoorState != DoorStates.None)
{
RequestedBrakeNotch = stopped ? train.Specs.BrakeNotches + 1 : train.ServiceBrakeNotch;
}
else
{
RequestedBrakeNotch = -1;
}
} }
// Brake application // Brake application
@ -320,28 +353,29 @@ namespace OpenbveFcmbTrainPlugin
case DeviceStates.YARD: case DeviceStates.YARD:
train.ContinuousProtection = false; train.ContinuousProtection = false;
train.VigilanceOverride = false; train.VigilanceOverride = false;
// Apply brake if any door opens
if (train.DoorState != DoorStates.None)
{
RequestedBrakeNotch = stopped ? train.Specs.BrakeNotches + 1 : train.ServiceBrakeNotch;
}
// If the train is not moving, brakes are released
if (stopped)
{
AtcControlState = AtcControlStates.Released;
}
break; break;
// ATC device is in ATP (M+ATP) driving mode // ATC device is in ATP (M+ATP) driving mode
case DeviceStates.ATP: case DeviceStates.ATP:
train.ContinuousProtection = true; train.ContinuousProtection = true;
train.VigilanceOverride = false; train.VigilanceOverride = false;
CurrentSpeedCode = GetSpeedCodeFromAspect(); CurrentSpeedCode = GetSpeedCodeFromAspect();
// If reverser is not forward, unselect mode
if (train.PhysicalHandles.Reverser != 1)
{
DeviceState = DeviceStates.NoMode;
}
break; break;
// ATC device is in ATO driving mode // ATC device is in ATO driving mode
case DeviceStates.ATO: case DeviceStates.ATO:
train.ContinuousProtection = true; train.ContinuousProtection = true;
train.VigilanceOverride = true; train.VigilanceOverride = true;
CurrentSpeedCode = GetSpeedCodeFromAspect(); CurrentSpeedCode = GetSpeedCodeFromAspect();
ProcessAto(train, route);
// If reverser is not forward or emergency brake is applied, unselect mode
if (train.PhysicalHandles.Reverser != 1 || train.PhysicalHandles.BrakeNotch > train.Specs.BrakeNotches)
{
DeviceState = DeviceStates.NoMode;
}
break; break;
} }
@ -389,6 +423,7 @@ namespace OpenbveFcmbTrainPlugin
if (train.PhysicalHandles.Reverser == 1 || train.PhysicalHandles.Reverser == -1) if (train.PhysicalHandles.Reverser == 1 || train.PhysicalHandles.Reverser == -1)
{ {
DeviceState = DeviceStates.YARD; DeviceState = DeviceStates.YARD;
AtcControlState = AtcControlStates.Released;
// Update ATC speed code // Update ATC speed code
CurrentSpeedCode = new SpeedCode(YardMaximumSpeed, YardMaximumSpeed); CurrentSpeedCode = new SpeedCode(YardMaximumSpeed, YardMaximumSpeed);
} }
@ -416,7 +451,7 @@ namespace OpenbveFcmbTrainPlugin
// Allow change when the train is stopped in ATP mode // Allow change when the train is stopped in ATP mode
if (DeviceState == DeviceStates.ATP && stopped && AtoAvailable) if (DeviceState == DeviceStates.ATP && stopped && AtoAvailable)
{ {
if (train.PhysicalHandles.Reverser == 1 && TrackState > TrackStates.Unprotected) if (train.PhysicalHandles.Reverser == 1 && TrackState > TrackStates.Unprotected && train.PhysicalHandles.BrakeNotch <= train.Specs.BrakeNotches)
{ {
DeviceState = DeviceStates.ATO; DeviceState = DeviceStates.ATO;
} }
@ -510,6 +545,16 @@ namespace OpenbveFcmbTrainPlugin
{ {
data.Handles.Reverser = 1; data.Handles.Reverser = 1;
data.Response = AIResponse.Short; data.Response = AIResponse.Short;
return;
}
// Acknowledge overspeed alarm
if (AtcControlState == AtcControlStates.NoPowerAlarm)
{
KeyChange(VirtualKeys.B1, true, train);
data.Response = AIResponse.Long;
KeyChange(VirtualKeys.B1, false, train);
return;
} }
switch (DeviceState) switch (DeviceState)
@ -524,6 +569,7 @@ namespace OpenbveFcmbTrainPlugin
KeyChange(VirtualKeys.I, true, train); KeyChange(VirtualKeys.I, true, train);
data.Response = AIResponse.Short; data.Response = AIResponse.Short;
KeyChange(VirtualKeys.I, false, train); KeyChange(VirtualKeys.I, false, train);
return;
} }
break; break;
case DeviceStates.YARD: case DeviceStates.YARD:
@ -537,7 +583,7 @@ namespace OpenbveFcmbTrainPlugin
KeyChange(VirtualKeys.J, true, train); KeyChange(VirtualKeys.J, true, train);
data.Response = AIResponse.Short; data.Response = AIResponse.Short;
KeyChange(VirtualKeys.J, false, train); KeyChange(VirtualKeys.J, false, train);
break; return;
} }
} }
CalculateAiNotches(data, train, route); CalculateAiNotches(data, train, route);
@ -553,7 +599,7 @@ namespace OpenbveFcmbTrainPlugin
KeyChange(VirtualKeys.I, true, train); KeyChange(VirtualKeys.I, true, train);
data.Response = AIResponse.Short; data.Response = AIResponse.Short;
KeyChange(VirtualKeys.I, false, train); KeyChange(VirtualKeys.I, false, train);
break; return;
} }
} }
CalculateAiNotches(data, train, route); CalculateAiNotches(data, train, route);
@ -626,5 +672,31 @@ namespace OpenbveFcmbTrainPlugin
} }
return new SpeedCode(new Speed(0), new Speed(0)); return new SpeedCode(new Speed(0), new Speed(0));
} }
/// <summary>Processes ATO orders.</summary>
private void ProcessAto(Train train, Route route)
{
double speed = train.State.Speed.KilometersPerHour;
bool stopped = speed < 0.05;
Speed limit = CurrentSpeedCode.CurrentLimit;
Speed target = CurrentSpeedCode.TargetLimit;
double distance = CurrentSpeedCode.TargetPosition - TrainLocation;
switch (AtoState)
{
case AtoStates.Inactive:
// Keep train still
RequestedPowerNotch = 0;
RequestedBrakeNotch = train.Specs.BrakeNotches + 1;
// 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)
{
AtoState = AtoStates.AwaitingStartup;
}
break;
}
}
} }
} }