StateMachine.h
Go to the documentation of this file.
00001 /*******************************************************************************
00002  *  StateMachine.h
00003  *
00004  *  (C) 2007 AG Aktives Sehen <agas@uni-koblenz.de>
00005  *           Universitaet Koblenz-Landau
00006  *
00007  *  Additional information:
00008  *  $Id: $
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


robbie_architecture
Author(s): Viktor Seib
autogenerated on Mon Oct 6 2014 02:53:09