internal override void DoorChange(DoorStates oldState, DoorStates newState) { if (oldState == DoorStates.None && newState != DoorStates.None) { atoState = AtoStates.Stopped; } else if (oldState != DoorStates.None && newState == DoorStates.None) { //Door closed atoState = AtoStates.Ready; readyTimer = ATO_READY_TIMER; } }
internal override int? Elapse(ElapseData data) { train.debugMessage = ""; //Is train in Auto? if (train.trainModeActual != Train.TrainModes.Auto) { atoState = AtoStates.Stopped; return null; } //Calculate current acceleration rate if (data.TotalTime.Seconds - accelerationLastPoll.Seconds >= ACCELERATION_POLL_RATE) { UpdateAcceleration(data); } //Calculate distance to stop double? distanceToNextStop = null; if (atoStoppingPosition != null) { distanceToNextStop = atoStoppingPosition - data.Vehicle.Location; } train.debugMessage = $"{atoState}"; if (atoState == AtoStates.Ready) { //At station counting down to departure atoDemands = -train.specs.BrakeNotches; readyTimer -= data.ElapsedTime.Seconds; if (train.doorState != DoorStates.None) { atoState = AtoStates.Stopped; } else if (readyTimer <= 0.0) { atoState = AtoStates.Enroute; } } else if (atoState == AtoStates.Enroute) { //Travelling to next station //Get the train to stick to the ATP Target Speed int atoTargetSpeedDemand = CalculateTargetSpeedNotchChange(data); //Run function for stopping at station int? atoStoppingDemand = null; if (atoStoppingPosition != null) { //Call a function that returns the desired brake/power notch (or null if none) atoStoppingDemand = CalculateStationStopNotchChange(data, distanceToNextStop ?? 0); } //Select the lowest notch between "TASC" and the target speed code above int notch = (atoDemands ?? 0) + Math.Min(atoStoppingDemand ?? train.specs.PowerNotches, atoTargetSpeedDemand); //Call ChangeAtoDemands with appropriate time between notch ChangeAtoDemands(data, notch, ATO_TIME_BETWEEN_NOTCH_CHANGE, true, true); train.debugMessage = $"Enroute. TS {atoTargetSpeedDemand}, TASC {atoStoppingDemand}. Req {notch}. Actual {atoDemands}. Target speed {train.atpTargetSpeed}"; //If doors open if (train.doorState != DoorStates.None) { atoState = AtoStates.Stopped; } } else if (atoState == AtoStates.Stopped) { atoStoppingPosition = null; atoDemands = -train.specs.BrakeNotches; if (train.doorState == DoorStates.None) { atoState = AtoStates.Ready; readyTimer = ATO_READY_TIMER; } } if (atoReceivedData != null) { atoStoppingPosition = atoReceivedData + data.Vehicle.Location; atoReceivedData = null; } //train.debugMessage = $" Ato: {atoState} demanding {atoDemands} for {train.atpTargetSpeed}"; return atoDemands; }
internal override int?Elapse(ElapseData data) { train.debugMessage = ""; //Detect jump to station if (lastFrameTrackPosition != null) { if (Math.Abs(lastFrameTrackPosition.Value - data.Vehicle.Location) > STATION_JUMP_THRESHOLD_DISTANCE) { //Reset ATO stopping pos atoStoppingPosition = null; } } lastFrameTrackPosition = data.Vehicle.Location; //Is train in Auto? if (train.trainModeSelected != Train.TrainModes.Auto) { atoState = AtoStates.Stopped; return(null); } if (atoState == AtoStates.Stopped) { atoStoppingPosition = null; return(-train.specs.BrakeNotches); } //Calculate current acceleration rate if (data.TotalTime.Seconds - accelerationLastPoll.Seconds >= ACCELERATION_POLL_RATE) { UpdateAcceleration(data); } //Calculate distance to stop double?distanceToNextStop = null; if (atoStoppingPosition != null) { distanceToNextStop = atoStoppingPosition - data.Vehicle.Location; } train.debugMessage = $"{atoState}"; if (atoState == AtoStates.Ready) { //At station counting down to departure atoDemands = -train.specs.BrakeNotches; readyTimer -= data.ElapsedTime.Seconds; if (readyTimer <= 0.0) { atoState = AtoStates.Enroute; } //Reset stop pos if closer than 25m else if (atoStoppingPosition != null && distanceToNextStop < 25) { atoStoppingPosition = null; } } else if (atoState == AtoStates.Enroute) { //Travelling to next station //Get the train to stick to the ATP Target Speed int atoTargetSpeedDemand = CalculateTargetSpeedNotchChange(data); //Run function for stopping at station int?atoStoppingDemand = null; if (atoStoppingPosition != null) { //Call a function that returns the desired brake/power notch (or null if none) atoStoppingDemand = CalculateStationStopNotchChange(data, distanceToNextStop ?? 0); } //Select the lowest notch between "TASC" and the target speed code above int notch = (atoDemands ?? 0) + Math.Min(atoStoppingDemand ?? train.specs.PowerNotches, atoTargetSpeedDemand); //Limit powering below 2km/h if (data.Vehicle.Speed.KilometersPerHour < 2.0) { notch = Math.Min(notch, 1); } //Call ChangeAtoDemands with appropriate time between notch ChangeAtoDemands(data, notch, ATO_TIME_BETWEEN_NOTCH_CHANGE, true, true); train.debugMessage = $"Enroute. TS {atoTargetSpeedDemand}, TASC {atoStoppingDemand}. Req {notch}. Actual {atoDemands}. Target speed {train.atpTargetSpeed}"; } if (atoReceivedData != null) { atoStoppingPosition = atoReceivedData + data.Vehicle.Location; atoReceivedData = null; } //train.debugMessage = $" Ato: {atoState} demanding {atoDemands} for {train.atpTargetSpeed}"; return(atoDemands); }