Advanced Distributed Systems module at HSLU
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

133 lines
6.7 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RaspiControl {
public enum ProcessState {
Startup,
Init,
Ready,
StartMoveManual,
ResumeMoveManual,
MoveManual,
MoveManualF,
MoveManualB,
MoveManualL,
MoveManualR,
StopManual,
Auto,
Final,
Error
}
public enum Command {
Connected,
InitDone,
JoystickUp,
JoystickDown,
JoystickLeft,
JoystickRight,
JoystickCenter,
autoMode,
finished,
failure,
none
}
internal class StateMachine {
class StateTransition {
readonly ProcessState CurrentState;
readonly Command Command;
public StateTransition(ProcessState currentState, Command command) {
CurrentState = currentState;
Command = command;
}
public override int GetHashCode() {
return 17 + 31 * CurrentState.GetHashCode() + 31 * Command.GetHashCode();
}
public override bool Equals(object obj) {
StateTransition other = obj as StateTransition;
return other != null && this.CurrentState == other.CurrentState && this.Command == other.Command;
}
}
Dictionary<StateTransition, ProcessState> transitions;
public ProcessState CurrentState { get; private set; }
public StateMachine() {
CurrentState = ProcessState.Startup;
transitions = new Dictionary<StateTransition, ProcessState> {
{new StateTransition(ProcessState.Startup,Command.Connected), ProcessState.Init },
{new StateTransition(ProcessState.Init,Command.JoystickCenter), ProcessState.Ready },
{new StateTransition(ProcessState.Ready,Command.JoystickUp), ProcessState.StartMoveManual },
{new StateTransition(ProcessState.Ready,Command.JoystickDown), ProcessState.StartMoveManual },
{new StateTransition(ProcessState.Ready,Command.JoystickLeft), ProcessState.StartMoveManual },
{new StateTransition(ProcessState.Ready,Command.JoystickRight), ProcessState.StartMoveManual },
{new StateTransition(ProcessState.StartMoveManual,Command.none), ProcessState.MoveManual },
{new StateTransition(ProcessState.StartMoveManual, Command.autoMode), ProcessState.Auto },
{new StateTransition(ProcessState.MoveManualF, Command.none), ProcessState.MoveManual },
{new StateTransition(ProcessState.MoveManualF, Command.autoMode), ProcessState.Auto },
{new StateTransition(ProcessState.MoveManualB, Command.none), ProcessState.MoveManual },
{new StateTransition(ProcessState.MoveManualB, Command.autoMode), ProcessState.Auto },
{new StateTransition(ProcessState.MoveManualL, Command.none), ProcessState.MoveManual },
{new StateTransition(ProcessState.MoveManualL, Command.autoMode), ProcessState.Auto },
{new StateTransition(ProcessState.MoveManualR, Command.none), ProcessState.MoveManual },
{new StateTransition(ProcessState.MoveManualR, Command.autoMode), ProcessState.Auto },
{new StateTransition(ProcessState.MoveManual, Command.JoystickUp), ProcessState.MoveManualF },
{new StateTransition(ProcessState.MoveManual, Command.JoystickDown), ProcessState.MoveManualB },
{new StateTransition(ProcessState.MoveManual, Command.JoystickLeft), ProcessState.MoveManualL },
{new StateTransition(ProcessState.MoveManual, Command.JoystickRight), ProcessState.MoveManualR },
{new StateTransition(ProcessState.MoveManual, Command.JoystickCenter), ProcessState.StopManual },
{new StateTransition(ProcessState.MoveManual, Command.autoMode), ProcessState.Auto },
{new StateTransition(ProcessState.StopManual,Command.JoystickUp), ProcessState.ResumeMoveManual },
{new StateTransition(ProcessState.StopManual,Command.JoystickDown), ProcessState.ResumeMoveManual },
{new StateTransition(ProcessState.StopManual,Command.JoystickLeft), ProcessState.ResumeMoveManual },
{new StateTransition(ProcessState.StopManual,Command.JoystickRight), ProcessState.ResumeMoveManual },
{new StateTransition(ProcessState.StopManual, Command.autoMode), ProcessState.Auto },
{new StateTransition(ProcessState.ResumeMoveManual, Command.none),ProcessState.MoveManual },
{new StateTransition(ProcessState.ResumeMoveManual, Command.autoMode), ProcessState.Auto },
{new StateTransition(ProcessState.Auto, Command.finished), ProcessState.Final },
{new StateTransition(ProcessState.Auto, Command.JoystickUp), ProcessState.StartMoveManual },
{new StateTransition(ProcessState.Auto, Command.JoystickDown), ProcessState.StartMoveManual },
{new StateTransition(ProcessState.Auto, Command.JoystickLeft), ProcessState.StartMoveManual },
{new StateTransition(ProcessState.Auto, Command.JoystickRight), ProcessState.StartMoveManual },
{new StateTransition(ProcessState.Auto, Command.JoystickCenter), ProcessState.StartMoveManual },
{new StateTransition(ProcessState.Auto, Command.failure), ProcessState.Error },
{new StateTransition(ProcessState.Error, Command.JoystickUp), ProcessState.StartMoveManual },
{new StateTransition(ProcessState.Error, Command.JoystickDown), ProcessState.StartMoveManual },
{new StateTransition(ProcessState.Error, Command.JoystickLeft), ProcessState.StartMoveManual },
{new StateTransition(ProcessState.Error, Command.JoystickRight), ProcessState.StartMoveManual },
{new StateTransition(ProcessState.Error, Command.JoystickCenter), ProcessState.StartMoveManual },
};
}
public ProcessState GetNext(Command command) {
StateTransition transition = new StateTransition(CurrentState, command);
ProcessState nextState;
if (!transitions.TryGetValue(transition, out nextState))
throw new Exception("Invalid transition: " + CurrentState + " -> " + command);
return nextState;
}
public ProcessState MoveNext(Command command) {
CurrentState = GetNext(command);
return CurrentState;
}
}
}