Orocos Real-Time Toolkit
2.5.0
|
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