Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef StateMachine_H
00012 #define StateMachine_H
00013
00014 #include <string>
00015 #include <map>
00016 #include <sstream>
00017 #include <deque>
00018 #include <typeinfo>
00019
00020 #include "ros/ros.h"
00021 #include "../../Architecture/Singleton/Clock.h"
00022
00023 #define ADD_MACHINE_STATE( STATE_MACHINE, STATE ) { STATE_MACHINE.addState( STATE, #STATE ); }
00024
00030 template<typename StateEnumT>
00031 class StateMachine
00032 {
00033 public:
00034
00036 StateMachine( );
00037
00039 ~StateMachine();
00040
00042 void setName( std::string name ) { m_Name=name; }
00043
00045 void setHistoryLength( unsigned historyLength ) { m_HistoryLength=historyLength; }
00046
00048 void addState( StateEnumT state, std::string name ) { m_StateNames[ state ] = name; }
00049
00051 StateEnumT state() { return m_State; }
00052
00054 StateEnumT historyState( unsigned steps );
00055
00057 std::string stateString() { return m_Name + ": " + stateString( m_State ); }
00058
00060 std::string stateString( StateEnumT state );
00061
00063 void setState( StateEnumT state );
00064
00066 void setLastState();
00067
00069 unsigned timeSinceStateChange();
00070
00072 std::string info();
00073
00074 private:
00075
00076 StateEnumT m_State;
00077
00078 std::map< StateEnumT, std::string > m_StateNames;
00079
00080 std::string m_Name;
00081
00082 unsigned m_LastStateChange;
00083
00084 std::deque<StateEnumT> m_StateHistory;
00085 unsigned m_HistoryLength;
00086
00087 };
00088
00089
00090 template<typename StateEnumT> unsigned StateMachine<StateEnumT>::timeSinceStateChange( )
00091 {
00092 return Clock::getInstance()->getTimestamp() - m_LastStateChange;
00093 }
00094
00095
00096 template<typename StateEnumT> StateMachine<StateEnumT>::StateMachine( )
00097 {
00098 m_Name = "Unnamed State Machine";
00099 m_State = StateEnumT(0);
00100 m_LastStateChange = Clock::getInstance()->getTimestamp();
00101 m_HistoryLength=20;
00102 }
00103
00104
00105 template<typename StateEnumT> StateMachine<StateEnumT>::~StateMachine( )
00106 {
00107 }
00108
00109
00110 template<typename StateEnumT> std::string StateMachine<StateEnumT>::stateString( StateEnumT state )
00111 {
00112 if ( m_StateNames.find( state ) == m_StateNames.end() )
00113 {
00114 std::ostringstream stream;
00115 stream << "Invalid state (" << state << ")";
00116 return stream.str();
00117 }
00118 return m_StateNames[ state ];
00119 }
00120
00121
00122 template<typename StateEnumT> StateEnumT StateMachine<StateEnumT>::historyState( unsigned steps )
00123 {
00124 if ( steps < m_StateHistory.size() )
00125 {
00126 return m_StateHistory[ m_StateHistory.size()-1-steps ];
00127 }
00128 else if ( m_StateHistory.size() != 0 )
00129 {
00130 return m_StateHistory.front();
00131 }
00132 else
00133 {
00134 return m_State;
00135 }
00136 }
00137
00138
00139 template<typename StateEnumT> void StateMachine<StateEnumT>::setState( StateEnumT state )
00140 {
00141 if ( m_State != state )
00142 {
00143
00144 if ( m_StateNames.find( state ) == m_StateNames.end() )
00145 {
00146 std::ostringstream stream;
00147 stream << "Invalid state (" << state << ")!" << std::endl << info();
00148 ROS_ERROR_STREAM( stream.str() );
00149 }
00150
00151 std::ostringstream stream;
00152 stream << "Setting state of '" << m_Name << "' to " << stateString( state );
00153 stream << " after " << float(timeSinceStateChange())/1000.0 << "s";
00154 ROS_INFO_STREAM( stream.str() );
00155
00156 m_StateHistory.push_back( m_State );
00157 if ( m_StateHistory.size() > m_HistoryLength )
00158 {
00159 m_StateHistory.pop_front();
00160 }
00161
00162 m_State = state;
00163 m_LastStateChange = Clock::getInstance()->getTimestamp();
00164 }
00165 }
00166
00167
00168 template<typename StateEnumT> void StateMachine<StateEnumT>::setLastState()
00169 {
00170 std::ostringstream stream;
00171 stream << "Reversing state of '" << m_Name << "' to " << m_StateHistory.back();
00172 stream << " after " << float(timeSinceStateChange())/1000.0 << "s";
00173 ROS_INFO_STREAM( stream.str() );
00174
00175 m_State = m_StateHistory.back();
00176 m_StateHistory.pop_back();
00177
00178 m_LastStateChange = Clock::getInstance()->getTimestamp();
00179 }
00180
00181
00182 template<typename StateEnumT> std::string StateMachine<StateEnumT>::info()
00183 {
00184 std::ostringstream stream;
00185 stream << "State machine: " << m_Name << std::endl;
00186 stream << "Current state: " << stateString( m_State ) << std::endl;
00187 stream << "State type: " << typeid( StateEnumT ).name() << std::endl;
00188
00189 stream << "Registered states: ";
00190 typename std::map< StateEnumT, std::string >::iterator it;
00191 it=m_StateNames.begin();
00192 while ( it != m_StateNames.end() )
00193 {
00194 if ( it != m_StateNames.begin() ) { stream << ", "; }
00195 stream << it->second << "(" << it->first << ")";
00196 it++;
00197 };
00198
00199 stream << "Previous states: ";
00200 for( unsigned i=0; i<m_StateHistory.size(); i++ )
00201 {
00202 if ( i!=0 ) { stream << " -> "; }
00203 stream << stateString( m_StateHistory[i] );
00204 }
00205
00206 return stream.str();
00207 }
00208
00209 #endif