Orocos Real-Time Toolkit  2.5.0
StateMachineService.cpp
00001 /***************************************************************************
00002   tag: Peter Soetens  Wed Jan 18 14:11:40 CET 2006  StateMachineService.cpp
00003 
00004                         StateMachineService.cpp -  description
00005                            -------------------
00006     begin                : Wed January 18 2006
00007     copyright            : (C) 2006 Peter Soetens
00008     email                : peter.soetens@mech.kuleuven.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 
00040 #include "StateMachineService.hpp"
00041 
00042 #include "../Attribute.hpp"
00043 #include "../FactoryExceptions.hpp"
00044 #include "../TaskContext.hpp"
00045 #include "../OperationCaller.hpp"
00046 
00047 namespace RTT
00048 {
00049 
00050     using namespace detail;
00051 
00052         void StateMachineService::createOperationFactory() {
00053             // Add the state specific methods :
00054             // Special trick : we store the 'this' pointer in a DataSource, such that when
00055             // the created commands are copied, they also get the new this pointer.
00056             // This requires template specialisations on the TemplateFactory level.
00057             DataSource<StateMachinePtr>* ptr = _this.get();
00058 
00059             // I had to make activate() a command because the entry {}
00060             // may contain commands upon which the state machine is
00061             // not strictly active (entry executed and no transition
00062             // in progress) when activate() returns, hence activate()
00063             // takes time and is thus a method. This is however in
00064             // violation with the concept of 'initialisation of the
00065             // SM' which may contain non-rt safe code. When activate() is
00066             // called directly upon the SM in C++, it _is_ a method, but
00067             // with the same deficiencies.
00068             addOperationDS("trace", &StateMachine::trace,ptr).doc("Trace the execution of this StateMachine. *Not* Real-Time.");
00069             addOperationDS("activate", &StateMachine::activate,ptr).doc("Activate this StateMachine to initial state and enter request Mode.");
00070             addOperationDS("deactivate", &StateMachine::deactivate,ptr).doc("Deactivate this StateMachine");
00071             addOperationDS("start", &StateMachine::automatic,ptr).doc("Start this StateMachine, enter automatic Mode.");
00072             addOperationDS("automatic", &StateMachine::automatic,ptr).doc("Start this StateMachine, enter automatic Mode.");
00073             addOperationDS("pause", &StateMachine::pause,ptr).doc("Pause this StateMachine, enter paused Mode.");
00074             addOperationDS("step", &StateMachine::step,ptr).doc(
00075                                  "Step this StateMachine. When paused, step a single instruction or transition evaluation. \n"
00076                                  "When in reactive mode, evaluate transitions and go to a next state, or if none, run handle.");
00077             addOperationDS("reset", &StateMachine::reset,ptr).doc("Reset this StateMachine to the initial state");
00078             addOperationDS("stop", &StateMachine::stop,ptr).doc("Stop this StateMachine to the final state and enter request Mode.");
00079             addOperationDS("reactive", &StateMachine::reactive,ptr).doc("Enter reactive mode (see requestState() and step() ).\n OperationCaller is done if ready for requestState() or step() method.");
00080             addOperationDS("requestState", &StateMachine::requestState,ptr).doc("Request to go to a particular state. Will succeed if there exists a valid transition from this state to the requested state.").arg("State", "The state to make the transition to.");
00081 
00082             addOperationDS("inState", &StateMachine::inState,ptr).doc("Is the StateMachine in a given state ?").arg("State", "State Name");
00083             addOperationDS("inError", &StateMachine::inError,ptr).doc("Is this StateMachine in error ?");
00084             addOperationDS("getState", &StateMachine::getCurrentStateName,ptr).doc("The name of the current state. An empty string if not active.");
00085             addOperationDS("isActive", &StateMachine::isActive,ptr).doc("Is this StateMachine activated (possibly in transition) ?");
00086             addOperationDS("isRunning", &StateMachine::isAutomatic,ptr).doc("Is this StateMachine running in automatic mode ?");
00087             addOperationDS("isReactive", &StateMachine::isReactive,ptr).doc("Is this StateMachine ready and waiting for requests or events ?");
00088             addOperationDS("isPaused", &StateMachine::isPaused,ptr).doc("Is this StateMachine paused ?");
00089             addOperationDS("inInitialState", &StateMachine::inInitialState,ptr).doc("Is this StateMachine in the initial state ?");
00090             addOperationDS("inFinalState", &StateMachine::inFinalState,ptr).doc("Is this StateMachine in the final state ?");
00091             addOperationDS("inTransition", &StateMachine::inTransition,ptr).doc("Is this StateMachine executing a entry|handle|exit program ?");
00092         }
00093 
00094         StateMachineServicePtr StateMachineService::copy(ParsedStateMachinePtr newsc, std::map<const DataSourceBase*, DataSourceBase*>& replacements, bool instantiate )
00095         {
00096             // if this gets copied, all created methods will use the new instance of StateMachineService to
00097             // call the member functions. Further more, all future methods for the copy will also call the new instance
00098             // while future methods for the original will still call the original.
00099             StateMachineServicePtr tmp( new StateMachineService( newsc, this->mtc ) );
00100             replacements[ _this.get() ] = tmp->_this.get(); // put 'newsc' in map
00101 
00102             ConfigurationInterface* dummy = ConfigurationInterface::copy( replacements, instantiate );
00103             tmp->loadValues( dummy->getValues());
00104             delete dummy;
00105 
00106             return tmp;
00107         }
00108 
00109         StateMachineService::StateMachineService(ParsedStateMachinePtr statem, TaskContext* tc)
00110             : Service( statem->getName() ),
00111               _this( new ValueDataSource<StateMachinePtr>( statem ) ),
00112               statemachine(statem),
00113               mtc(tc)
00114         {
00115             this->createOperationFactory();
00116             this->setOwner( tc );
00117         }
00118 
00119     StateMachineService::~StateMachineService()
00120     {
00121         // When the this Service is deleted, make sure the program does not reference us.
00122         if ( statemachine ) {
00123             statemachine->setService( StateMachineServicePtr() );
00124         }
00125     }
00126     //ExecutionEngine* StateMachineService::engine() const { return mtc->engine(); }
00127 
00128 }
00129