00001 /* -*- mode: C++ -*- 00002 * 00003 * Commander finite state machine interface 00004 * 00005 * Copyright (C) 2007, 2010, Austin Robot Technology 00006 * 00007 * License: Modified BSD Software License Agreement 00008 * 00009 * $Id: FSM.h 615 2010-09-24 16:07:50Z jack.oquin $ 00010 */ 00011 00012 #ifndef __CMDR_FSM_H__ 00013 #define __CMDR_FSM_H__ 00014 00015 // Commander state transition design notes: 00016 // 00017 // States are nodes in a directed graph representation of the 00018 // Commander finite state machine. The arrows in this graph represent 00019 // a transition from one state to a (possibly) different one. Each 00020 // arrow is labelled with an event which triggers that transition, and 00021 // has an associated action method. 00022 // 00023 // Make a matrix of all state transitions indexed by state and event 00024 // containing the action method and a (possibly) new state for each 00025 // arrow in the FSM graph. This table-driven design is complex, but 00026 // it allows adding new states and events with minimal effect on the 00027 // existing implementation. 00028 // 00029 // Commander() logic: 00030 // 00031 // return do_transition(current_event()); 00032 // 00033 // current_event() will prioritize all events, returning the most 00034 // urgent. It will check any timers that are running; timer 00035 // expirations are one set of possible events. The event priorities 00036 // are independent of state. 00037 // 00038 // do_transition() updates the current state, then calls the 00039 // transition-dependent action method from the state transition table. 00040 // Every action method returns a Commander order for this cycle. 00041 // 00042 // Commander could do multiple state transitions in a single cycle. 00043 // Since do_transition() performs the state change before calling the 00044 // action method, in some cases that method may trigger another state 00045 // transition, if necessary. Currently they do not, which is simpler. 00046 00047 #include <iostream> 00048 #include "State.h" 00049 00050 class CmdrFSM 00051 { 00052 public: 00053 00054 // state transition action method pointer 00055 typedef art_msgs::Order (CmdrFSM::*action_t)(CmdrEvent event); 00056 00057 // state transition table entry 00058 typedef struct 00059 { 00060 CmdrState next; 00061 action_t action; 00062 } transtion_t; 00063 00064 CmdrFSM(Commander *cmdr_ptr, int verbosity); 00065 ~CmdrFSM() {}; 00066 00067 art_msgs::Order control(const art_msgs::NavigatorState *_navstate); 00068 00069 CmdrState State(void) 00070 { 00071 return state; 00072 } 00073 00074 private: 00075 ElementID current_way; 00076 00077 int verbose; 00078 Commander *cmdr; 00079 art_msgs::NavigatorState navstate; 00080 CmdrState prev; 00081 CmdrState state; 00082 transtion_t ttable[CmdrEvent::N_events][CmdrState::N_states]; 00083 00084 // Event state variables 00085 ElementID old_replan; 00086 bool was_in_route_network; 00087 00088 // add a transition to the table 00089 void Add(CmdrEvent::event_t event, action_t action, 00090 CmdrState::state_t from_state, CmdrState::state_t to_state); 00091 00092 // return most urgent current event 00093 CmdrEvent current_event(); 00094 00095 00097 // state transition action methods 00099 00100 // error actions 00101 art_msgs::Order ActionError(CmdrEvent event); 00102 art_msgs::Order ActionFail(CmdrEvent event); 00103 art_msgs::Order ActionWait(CmdrEvent event); 00104 00105 // steady state actions 00106 art_msgs::Order ActionInDone(CmdrEvent event); 00107 art_msgs::Order ActionInInit(CmdrEvent event); 00108 art_msgs::Order ActionInRoad(CmdrEvent event); 00109 00110 // state entry actions 00111 art_msgs::Order ActionToDone(CmdrEvent event); 00112 art_msgs::Order ActionToRoad(CmdrEvent event); 00113 00114 // re-planning transitions 00115 art_msgs::Order BlockedInRoad(CmdrEvent event); 00116 art_msgs::Order ReplanInRoad(CmdrEvent event); 00117 art_msgs::Order InitToRoad(CmdrEvent event); 00118 }; 00119 00120 #endif // __CMDR_FSM_H__