StateMachine.hpp

00001 /***************************************************************************
00002   tag: Peter Soetens  Tue Dec 21 22:43:07 CET 2004  StateMachineTree.hpp
00003 
00004                         StateMachineTree.hpp -  description
00005                            -------------------
00006     begin                : Tue December 21 2004
00007     copyright            : (C) 2004 Peter Soetens
00008     email                : peter.soetens@mech.kuleuven.ac.be
00009 
00010  ***************************************************************************
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU General Public                   *
00013  *   License as published by the Free Software Foundation;                 *
00014  *   version 2 of the License.                                             *
00015  *                                                                         *
00016  *   As a special exception, you may use this file as part of a free       *
00017  *   software library without restriction.  Specifically, if other files   *
00018  *   instantiate templates or use macros or inline functions from this     *
00019  *   file, or you compile this file and link it with other files to        *
00020  *   produce an executable, this file does not by itself cause the         *
00021  *   resulting executable to be covered by the GNU General Public          *
00022  *   License.  This exception does not however invalidate any other        *
00023  *   reasons why the executable file might be covered by the GNU General   *
00024  *   Public License.                                                       *
00025  *                                                                         *
00026  *   This library is distributed in the hope that it will be useful,       *
00027  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00028  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00029  *   Lesser General Public License for more details.                       *
00030  *                                                                         *
00031  *   You should have received a copy of the GNU General Public             *
00032  *   License along with this library; if not, write to the Free Software   *
00033  *   Foundation, Inc., 59 Temple Place,                                    *
00034  *   Suite 330, Boston, MA  02111-1307  USA                                *
00035  *                                                                         *
00036  ***************************************************************************/
00037 
00038 
00039 #ifndef HIERARCHICAL_STATE_MACHINE_HPP
00040 #define HIERARCHICAL_STATE_MACHINE_HPP
00041 
00042 #include "StateInterface.hpp"
00043 #include "ConditionInterface.hpp"
00044 #include "CommandInterface.hpp"
00045 #include "DataSourceBase.hpp"
00046 #include "Handle.hpp"
00047 #include "EventProcessor.hpp"
00048 
00049 #include <map>
00050 #include <vector>
00051 #include <string>
00052 #include <utility>
00053 #include <boost/tuple/tuple.hpp>
00054 #include <boost/weak_ptr.hpp>
00055 #include <boost/shared_ptr.hpp>
00056 
00057 namespace RTT
00058 {
00059 
00060 
00061 
00062     class TaskContext;
00063     class EventService;
00064     class StateMachineProcessor;
00065 
00066     class StateMachine;
00067     typedef boost::shared_ptr<StateMachine> StateMachinePtr;
00068     typedef boost::weak_ptr<StateMachine> StateMachineWPtr;
00069 
00078     class RTT_API StateMachine
00079     {
00080         enum PrivateStatus { nill, gostop, goreset, pausing } smpStatus;
00081 
00082         static std::string emptyString;
00083     public:
00087         struct RTT_API Status {
00088             enum StateMachineStatus {inactive, activating, active, requesting, running, stopping, stopped, resetting, deactivating, paused, error, unloaded };
00089         };
00090     protected:
00095         typedef std::vector< boost::tuple<ConditionInterface*, StateInterface*, int, int, boost::shared_ptr<ProgramInterface> > > TransList;
00096         typedef std::map< StateInterface*, TransList > TransitionMap;
00097         typedef std::multimap< StateInterface*, std::pair<ConditionInterface*, int> > PreConditionMap;
00098         typedef std::vector< boost::tuple<EventService*,
00099                                           std::string, std::vector<DataSourceBase::shared_ptr>,
00100                                           StateInterface*,
00101                                           ConditionInterface*, boost::shared_ptr<ProgramInterface>,
00102                                           Handle,
00103                                           StateInterface*, boost::shared_ptr<ProgramInterface> > > EventList;
00104         typedef std::map< StateInterface*, EventList > EventMap;
00105         std::vector<StateMachinePtr> _children;
00106         typedef boost::weak_ptr<StateMachine> StateMachineParentPtr;
00107         StateMachineParentPtr _parent;
00108 
00109         std::string _name;
00110         EventProcessor* eproc;
00111         Status::StateMachineStatus smStatus;
00112         StateMachineProcessor* smp;
00113 
00114         // Hook to denote to subclasses that we are unloaded.
00115         virtual void handleUnload();
00116     public:
00117 
00118         typedef std::vector<StateMachinePtr> ChildList;
00119 
00124         virtual ~StateMachine();
00125 
00131         StateMachine(StateMachinePtr parent, const std::string& name="Default");
00132 
00139         StateMachine(StateMachinePtr parent, EventProcessor* ep, const std::string& name="Default");
00140 
00141         void setStateMachineProcessor(StateMachineProcessor* smproc) {
00142             smp = smproc;
00143             if (smp)
00144                 smStatus = Status::inactive;
00145             else {
00146                 smStatus = Status::unloaded;
00147                 this->handleUnload();
00148             }
00149         }
00150 
00151         void setEventProcessor(EventProcessor* smproc) {
00152             eproc = smproc;
00153         }
00154 
00158         bool requestState(const std::string& statename) {
00159             StateInterface* tmp = this->getState(statename);
00160             if (tmp) {
00161                 return this->requestStateChange( tmp );
00162             }
00163             return false;
00164         }
00165 
00169         bool inState(const std::string& state) const {
00170             StateInterface* copy = this->currentState();
00171             if (copy == 0)
00172                 return false;
00173             return copy->getName() == state;
00174         }
00175 
00180         bool inStrictState(const std::string& state) const {
00181             StateInterface* copy = this->currentState();
00182             if (copy == 0)
00183                 return false;
00184             return copy->getName() == state && !this->inTransition();
00185         }
00186 
00190         const std::string& getCurrentStateName() const {
00191             StateInterface* copy = this->currentState();
00192             if (copy == 0)
00193                 return emptyString;
00194             return copy->getName();
00195         }
00196 
00200         inline bool isStrictlyActive() const {
00201             return this->isActive() && !this->inTransition();
00202         }
00203 
00207         inline bool inInitialState() const {
00208             return initstate == current;// && !_sc->inTransition();
00209         }
00210 
00214         inline bool inFinalState() const {
00215             return finistate == current;// && !this->inTransition();
00216         }
00217 
00222         bool stepDone() const {
00223             if ( isPaused() )
00224                 return !mstep;
00225             return isStrictlyActive();
00226         }
00227 
00231         inline bool isActive() const { return current != 0; }
00232 
00237         inline bool isStopped() const { return smStatus == Status::stopped; }
00238 
00242         inline bool inError() const { return smStatus == Status::error; }
00243 
00247         inline bool isReactive() const { return current != 0 && smStatus != Status::running; }
00248 
00253         inline bool isAutomatic() const { return smStatus == Status::running; }
00254 
00258         inline bool isPaused() const { return smStatus == Status::paused; }
00259 
00263         bool activate();
00264 
00268         bool pause();
00269 
00274         bool step();
00275 
00279         bool automatic();
00280 
00284         bool start();
00285 
00290         bool stop();
00291 
00296         bool reset();
00297 
00301         bool reactive();
00302 
00306         bool deactivate();
00307 
00312         bool execute();
00313 
00329         StateInterface* requestNextState(bool stepping = false);
00330 
00335         StateInterface* requestNextStateStep();
00336 
00341         bool requestFinalState();
00342 
00353         bool requestInitialState();
00354 
00363         StateInterface* nextState();
00364 
00368         std::vector<std::string> getStateList() const;
00369 
00373         StateInterface* getState( const std::string & name ) const;
00374 
00378         Status::StateMachineStatus getStatus() const;
00379 
00383         void addState( StateInterface* s );
00384 
00397         bool requestStateChange( StateInterface * s_n );
00398 
00412         bool executePending( bool stepping = false );
00413 
00431         void preconditionSet( StateInterface* state, ConditionInterface* cnd, int line);
00432 
00452         void transitionSet( StateInterface* from, StateInterface* to, ConditionInterface* cnd, int priority, int line);
00453 
00476         void transitionSet( StateInterface* from, StateInterface* to,
00477                             ConditionInterface* cnd, boost::shared_ptr<ProgramInterface> transprog,
00478                             int priority, int line);
00479 
00499         bool createEventTransition( EventService* es,
00500                                     const std::string& ename, std::vector<DataSourceBase::shared_ptr> args,
00501                                     StateInterface* from, StateInterface* to,
00502                                     ConditionInterface* guard, boost::shared_ptr<ProgramInterface> transprog,
00503                                     StateInterface* elseto = 0, boost::shared_ptr<ProgramInterface> elseprog =
00504                                     boost::shared_ptr<ProgramInterface>() );
00505 
00509         void setInitialState( StateInterface* s );
00510 
00514         void setFinalState( StateInterface* s );
00515 
00520         StateInterface* currentState() const;
00521 
00526         ProgramInterface* currentProgram() const;
00527 
00531         StateInterface* getInitialState() const {
00532             return initstate;
00533         }
00534 
00538         StateInterface* getFinalState() const {
00539             return finistate;
00540         }
00541 
00549         void setInitCommand( CommandInterface* c)
00550         {
00551             initc = c;
00552         }
00553 
00554         CommandInterface* getInitCommand() const
00555         {
00556             return initc;
00557         }
00558 
00562         StateMachinePtr getParent() const
00563         {
00564             return _parent.lock();
00565         }
00566 
00567         void setParent(StateMachinePtr parent)
00568         {
00569             _parent = parent;
00570         }
00571 
00575         const ChildList& getChildren() const
00576         {
00577             return _children;
00578         }
00579 
00580         void addChild( StateMachinePtr child ) {
00581             _children.push_back( child );
00582         }
00583 
00588         const std::string& getName() const {
00589             return _name;
00590         }
00591 
00596         int getLineNumber() const;
00597 
00601         virtual std::string getText() const;
00602 
00609         bool inTransition() const;
00610 
00616         bool interruptible() const;
00617 
00618     protected:
00624         TransitionMap stateMap;
00625 
00630         PreConditionMap precondMap;
00631 
00636         EventMap eventMap;
00637 
00638 
00639         void changeState( StateInterface* s, ProgramInterface* tprog, bool stepping = false );
00640 
00641         void leaveState( StateInterface* s );
00642 
00643         void enterState( StateInterface* s );
00644 
00645         void runState( StateInterface* s );
00646 
00647         void handleState( StateInterface* s );
00648 
00649         bool executeProgram(ProgramInterface*& cp, bool stepping);
00650 
00651         int checkConditions( StateInterface* state, bool stepping = false );
00652 
00653         void enableEvents( StateInterface* s );
00654         void disableEvents( StateInterface* s );
00655     private:
00656 
00661         void eventTransition( StateInterface* from, ConditionInterface* c,
00662                               ProgramInterface* p, StateInterface* to,
00663                               ProgramInterface* elsep, StateInterface* elseto );
00664 
00668         StateInterface* initstate;
00669 
00673         StateInterface* finistate;
00674 
00679         StateInterface* current;
00680 
00684         StateInterface* next;
00685 
00686         CommandInterface* initc;
00687 
00688         ProgramInterface* currentProg;
00689         ProgramInterface* currentExit;
00690         ProgramInterface* currentHandle;
00691         ProgramInterface* currentEntry;
00692         ProgramInterface* currentRun;
00693         ProgramInterface* currentTrans;
00694 
00695         TransList::iterator reqstep;
00696         TransList::iterator reqend;
00697 
00698         std::pair<PreConditionMap::const_iterator,PreConditionMap::const_iterator> prec_it;
00699         bool checking_precond;
00700         bool mstep;
00701 
00702         int evaluating;
00703     };
00704 }
00705 
00706 #endif
Generated on Thu Dec 23 13:22:38 2010 for Orocos Real-Time Toolkit by  doxygen 1.6.3