123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- /**@class OFSMBase
- * @brief base class for Orthogonal Finite State Machine
- *
- * stores current states (m_states) and transition table with possible transitions from each state
- * to another state via event
- **/
- class OFSMBase<Class FSMStateBase, Class FSMEventBase, Class FSMActionBase, Class FSMGuardBase>
- {
- protected ref array<ref FSMStateBase> m_States; /// current fsm state
- protected ref array<ref FSMStateBase> m_InitialStates; /// configurable initial state of the machine
- protected ref array<ref FSMTransition<FSMStateBase, FSMEventBase, FSMActionBase, FSMGuardBase>> m_Transitions; /// fsm transition table
- void OFSMBase ()
- {
- m_States = new array<ref FSMStateBase>;
- m_InitialStates = new array<ref FSMStateBase>;
- m_Transitions = new array<ref FSMTransition<FSMStateBase, FSMEventBase, FSMActionBase, FSMGuardBase>>;
- }
- /**@fn GetCurrentStates
- * @brief returns currently active state
- * @return current state the FSM is in (or NULL)
- **/
- array<ref FSMStateBase> GetCurrentState ()
- {
- return m_States;
- }
- /**@fn SetInitialState
- * @brief sets the initial_state for starting the machine
- **/
- void SetInitialStates (array<ref FSMStateBase> initial_states)
- {
- m_InitialStates = initial_states;
- for (int s = 0; s < initial_states.Count(); ++s)
- m_States.Insert(initial_states[s]);
- }
- /**@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 (array<ref FSMEventBase> initial_events = null)
- {
- if (LogManager.IsInventoryHFSMLogEnable()) fsmbDebugPrint("[ofsm] " + this.ToString() + "::Start(" + initial_events.ToString() + "), init_state=" + m_InitialStates.ToString());
- for (int s = 0; s < m_States.Count(); ++s)
- {
- m_States[s] = m_InitialStates[s];
- if (initial_events)
- m_States[s].OnEntry(initial_events[s]);
- else
- m_States[s].OnEntry(null);
- }
- }
- /**@fn IsRunning
- * @brief returns true if machine is in running state
- **/
- bool IsRunning ()
- {
- int sc = m_States.Count();
- if (sc)
- {
- for (int s = 0; s < sc; ++s)
- if (m_States[s] != null)
- return true;
- }
- return false;
- }
- /**@fn Terminate
- * @brief terminates the state machine
- **/
- void Terminate (array<ref FSMEventBase> terminal_events = null)
- {
- if (IsRunning())
- {
- for (int s = 0; s < m_States.Count(); ++s)
- {
- if (terminal_events)
- m_States[s].OnExit(terminal_events[s]);
- else
- m_States[s].OnExit(null);
- m_States[s] = null;
- }
- }
- }
- /**@fn Update
- * @brief if machine running, call OnUpdate() on current state
- **/
- void Update (float dt)
- {
- if (IsRunning())
- {
- for (int s = 0; s < m_States.Count(); ++s)
- {
- m_States[s].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)
- {
- 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_event.Type() == e.Type())
- {
- for (int s = 0; s < m_States.Count(); ++s)
- {
- if (row.m_srcState.Type() == m_States[s].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(s, 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 (int s, FSMTransition<FSMStateBase, FSMEventBase, FSMActionBase, FSMGuardBase> t, FSMEventBase e)
- {
- if (LogManager.IsInventoryHFSMLogEnable()) fsmbDebugPrint("[ofsm] (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_States[s].OnExit(e); // 1) call onExit on old state
- if (t.m_action)
- t.m_action.Action(e); // 2) execute transition action (if any)
- m_States[s] = t.m_dstState; // 3) change state to new
- if (t.m_dstState != NULL)
- {
- m_States[s].OnEntry(e); // 4a) call onEntry on new state
- return ProcessEventResult.FSM_OK;
- }
- else
- {
- if (LogManager.IsInventoryHFSMLogEnable()) fsmbDebugPrint("[ofsm] terminating fsm: state=" + t.m_srcState.ToString() + " event=" + e.ToString());
- return ProcessEventResult.FSM_TERMINATED; // 4b) or terminate
- }
- }
- };
|