123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- void fsmbDebugPrint (string s)
- {
- #ifdef FSM_DEBUG
- PrintToRPT("" + s); // comment/uncomment to hide/see debug logs
- #else
- //Print("" + s); // comment/uncomment to hide/see debug logs
- #endif
- }
- void fsmbDebugSpam (string s)
- {
- #ifdef FSM_DEBUG_SPAM
- PrintToRPT("" + s); // comment/uncomment to hide/see debug logs
- #else
- //Print("" + s); // comment/uncomment to hide/see debug logs
- #endif
- }
- /**@class FSMTransition
- * @brief represents transition src ---- event[guard]/action ----|> dst
- **/
- class FSMTransition<Class FSMStateBase, Class FSMEventBase, Class FSMActionBase, Class FSMGuardBase>
- {
- ref FSMStateBase m_srcState;
- ref FSMEventBase m_event; // @NOTE: NULL event means "completion transition" in UML speak
- ref FSMStateBase m_dstState; // @NOTE: NULL dst state == UML terminate pseudonode
- ref FSMActionBase m_action;
- ref FSMGuardBase m_guard;
- void FSMTransition (FSMStateBase src, FSMEventBase e, FSMStateBase dst, FSMActionBase a = NULL, FSMGuardBase g = NULL)
- {
- m_srcState = src;
- m_event = e;
- m_dstState = dst;
- m_action = a;
- m_guard = g;
- }
- };
- enum ProcessEventResult
- {
- FSM_OK,
- FSM_TERMINATED,
- FSM_ABORTED,
- FSM_NO_TRANSITION,
- };
- /**@class FSMBase
- * @brief base class for finite state machine
- *
- * stores current state (m_state) and transition table with possible transitions from each state
- * to another state via event
- **/
- class FSMBase<Class FSMStateBase, Class FSMEventBase, Class FSMActionBase, Class FSMGuardBase>
- {
- protected ref FSMStateBase m_state; /// current fsm state
- protected ref FSMStateBase m_initialState; /// configurable initial state of the machine
- protected ref FSMEventBase m_initialEvent; /// configurable initial event to start the machine (null by default)
- protected ref array<ref FSMTransition<FSMStateBase, FSMEventBase, FSMActionBase, FSMGuardBase>> m_transitions; /// fsm transition table
- void FSMBase ()
- {
- m_transitions = new array<ref FSMTransition<FSMStateBase, FSMEventBase, FSMActionBase, FSMGuardBase>>;
- }
- /**@fn GetCurrentState
- * @brief returns currently active state
- * @return current state the FSM is in (or NULL)
- **/
- FSMStateBase GetCurrentState ()
- {
- return m_state;
- }
- /**@fn SetInitialState
- * @brief sets the initial_state for starting the machine
- **/
- void SetInitialState (FSMStateBase initial_state)
- {
- m_initialState = initial_state;
- }
- /**@fn Start
- * @brief starts the state machine by entering the initial_state (using intial_event as argument to initial state's onEntry)
- * @param[in] e \p optional event for starting the machind
- **/
- void Start (FSMEventBase initial_event = NULL)
- {
- if (LogManager.IsInventoryHFSMLogEnable()) fsmbDebugPrint("[fsm] " + this.ToString() + "::Start(" + initial_event.ToString() + "), init_state=" + m_initialState.ToString());
- m_state = m_initialState;
- m_state.OnEntry(initial_event);
- }
- /**@fn IsRunning
- * @brief returns true if machine is in running state
- **/
- bool IsRunning () { return m_state != NULL; }
- /**@fn Terminate
- * @brief terminates the state machine
- **/
- void Terminate (FSMEventBase terminal_event = NULL)
- {
- if (IsRunning())
- {
- m_state.OnExit(terminal_event);
- m_state = NULL;
- }
- }
- /**@fn Update
- * @brief if machine running, call OnUpdate() on current state
- **/
- void Update (float dt)
- {
- if (IsRunning())
- m_state.OnUpdate(dt);
- }
-
- /**@fn AddTransition
- * @brief adds transition into transition table
- **/
- void AddTransition (FSMTransition<FSMStateBase, FSMEventBase, FSMActionBase, FSMGuardBase> t)
- {
- m_transitions.Insert(t);
- }
- /**@fn ProcessEvent
- * @brief instructs the state machine to process the event e
- * @param[in] e \p event that will be used to find suitable transition from current state
- * @return FSM_OK if transition found and allowed by guard (if any)
- **/
- ProcessEventResult ProcessEvent (FSMEventBase e)
- {
- FSMStateBase curr_state = m_state;
- int count = m_transitions.Count();
- for (int i = 0; i < count; ++i)
- {
- FSMTransition<FSMStateBase, FSMEventBase, FSMActionBase, FSMGuardBase> row = m_transitions.Get(i);
- if (row.m_srcState.Type() == curr_state.Type() && row.m_event.Type() == e.Type())
- {
- FSMTransition<FSMStateBase, FSMEventBase, FSMActionBase, FSMGuardBase> t = m_transitions.Get(i);
- bool hasGuard = t.m_guard != NULL;
- if (!hasGuard || (hasGuard && t.m_guard.GuardCondition(e))) // 1) exec guard (if any)
- {
- ProcessLocalTransition(t, e); // 2) process transition allowed by guard
- }
- }
- }
- return ProcessEventResult.FSM_NO_TRANSITION;
- }
- /**@fn ProcessLocalTransition
- * @brief instructs the state machine to process the event locally - no hierarchy is crossed
- * @param[in] t \p the transition in m_transitions
- * @param[in] e \p event that will be used to process transition from current state
- * @return FSM_OK or FSM_TERMINATED
- **/
- protected ProcessEventResult ProcessLocalTransition (FSMTransition<FSMStateBase, FSMEventBase, FSMActionBase, FSMGuardBase> t, FSMEventBase e)
- {
- if (LogManager.IsInventoryHFSMLogEnable()) fsmbDebugPrint("[fsm] (local) state=" + t.m_srcState.ToString() + "-------- event=" + e.ToString() + "[G=" + t.m_guard.ToString() +"]/A=" + t.m_action.ToString() + " --------|> dst=" + t.m_dstState.ToString());
- m_state.OnExit(e); // 1) call onExit on old state
- if (t.m_action)
- t.m_action.Action(e); // 2) execute transition action (if any)
- m_state = t.m_dstState; // 3) change state to new
- if (t.m_dstState != NULL)
- {
- m_state.OnEntry(e); // 4a) call onEntry on new state
- return ProcessEventResult.FSM_OK;
- }
- else
- {
- if (LogManager.IsInventoryHFSMLogEnable()) fsmbDebugPrint("[fsm] terminating fsm: state=" + t.m_srcState.ToString() + " event=" + e.ToString());
- return ProcessEventResult.FSM_TERMINATED; // 4b) or terminate
- }
- }
- };
|