Orocos Real-Time Toolkit  2.8.3
ParsedStateMachine.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: Peter Soetens Tue Jul 20 17:32:42 CEST 2004 ParsedStateMachine.cxx
3 
4  ParsedStateMachine.cxx - description
5  -------------------
6  begin : Tue July 20 2004
7  copyright : (C) 2004 Peter Soetens
8  email : peter.soetens@mech.kuleuven.ac.be
9 
10  ***************************************************************************
11  * This library is free software; you can redistribute it and/or *
12  * modify it under the terms of the GNU Lesser General Public *
13  * License as published by the Free Software Foundation; either *
14  * version 2.1 of the License, or (at your option) any later version. *
15  * *
16  * This library is distributed in the hope that it will be useful, *
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
19  * Lesser General Public License for more details. *
20  * *
21  * You should have received a copy of the GNU Lesser General Public *
22  * License along with this library; if not, write to the Free Software *
23  * Foundation, Inc., 59 Temple Place, *
24  * Suite 330, Boston, MA 02111-1307 USA *
25  * *
26  ***************************************************************************/
27 
28 #include "ParsedStateMachine.hpp"
29 #include "../internal/DataSource.hpp"
30 #include "../ExecutionEngine.hpp"
31 #include "StateDescription.hpp"
32 
33 #include "../Service.hpp"
34 #include "StateMachineService.hpp"
35 #include "../TaskContext.hpp"
36 #include "../internal/mystd.hpp"
37 
38 #include <cassert>
39 
40 #include <boost/lambda/lambda.hpp>
41 
42 namespace RTT {
43  using namespace detail;
44  using namespace std;
45  using boost::tuples::get;
54  ParsedStateMachinePtr ParsedStateMachine::copy( std::map<const DataSourceBase*, DataSourceBase*>& replacements, bool instantiate ) const
55  {
56  /* Recursive copy :
57  * First copy this SC, then its child SC's
58  */
59  std::map<const StateInterface*, StateInterface*> statemapping;
61  ret->_text = this->_text;
62  ret->setName( this->_name, false);
63 
64  if (instantiate)
65  Logger::log() <<Logger::Debug <<"Creating an instance of "<< this->_name << Logger::endl;
66 
67  // First copy the task such that commands and attributes can be correctly
68  // copied. This also sets the EventProcessor for the SM.
69  ret->setService( this->object->copy(ret, replacements, instantiate) );
70 
71  // the parameters of the SC, similar to FunctionGraph's Arguments.
72  for ( VisibleWritableValuesMap::const_iterator i = parametervalues.begin();
73  i != parametervalues.end(); ++i )
74  {
75  // What is sure, is that each param
76  // must also be in the ConfigurationInterface.
77  assert( ret->getService()->getValue( i->first ) );
78  ret->parametervalues[i->first] = ret->getService()->getValue( i->first );
79  }
80 
81  //**********************
82  // TODO add copy method to StateMachine itself where all stuff below belongs :
83  // but, not so easy since copy makes new instance...
84  for ( ChildList::const_iterator i = getChildren().begin(); i != getChildren().end(); ++i )
85  {
86  // copy the submachines....
87  assert( dynamic_cast<ParsedStateMachine*>( i->get() ) == static_cast<ParsedStateMachine*>( i->get() ));
88  ParsedStateMachinePtr oldmachine = boost::dynamic_pointer_cast<ParsedStateMachine>( *i );
89  ParsedStateMachinePtr newmachine(oldmachine->copy( replacements, instantiate ));
90  // I would think that providing 'instantiate' would not hurt...
91  // XXX? previously, the instantiate flag was not given to copy, does it now break apps ?
92 
93  ret->addChild( newmachine ); // also copy tree info to StateMachine !
94  newmachine->setParent( ret );
95  }
96 
97  // Copy the InitCommand :
98  if (this->getInitCommand()) {
99  ret->setInitCommand( this->getInitCommand()->copy(replacements) );
100  // test :
101  //ret->getInitCommand()->execute();
102  }
103 
104  // First make a copy of all states. All states are either
105  // known by their name or by a transition from or to them...
106  statemapping[0] = 0; // insert null element.
107  for ( TransitionMap::const_iterator i = stateMap.begin(); i != stateMap.end(); ++i )
108  {
109  if( statemapping.find( i->first ) == statemapping.end() && i->first != 0 ) {
110  StateInterface* cpy = i->first->copy( replacements );
111  ret->addState( cpy );
112  statemapping[i->first] = cpy;
113  }
114  }
115 
116  // next, copy the transitions
117  for ( TransitionMap::const_iterator i = stateMap.begin(); i != stateMap.end(); ++i )
118  {
119  assert( statemapping.find( i->first ) != statemapping.end() );
120  StateInterface* fromState = statemapping[i->first];
121  for ( TransList::const_iterator j = i->second.begin(); j != i->second.end(); ++j )
122  {
123  ConditionInterface* condition = j->get<0>()->copy( replacements );
124  assert( statemapping.find( j->get<1>() ) != statemapping.end() );
125  StateInterface* toState = statemapping[j->get<1>()];
126  int rank = j->get<2>();
127  int line = j->get<3>();
128  boost::shared_ptr<ProgramInterface> transprog( j->get<4>() );
129  if (transprog)
130  transprog.reset( j->get<4>()->copy(replacements) );
131  ret->transitionSet(fromState, toState, condition, transprog, rank, line );
132  }
133  }
134 
135  // next, copy/recreate the events
136  for ( EventMap::const_iterator i = eventMap.begin(); i != eventMap.end(); ++i )
137  {
138  assert( statemapping.find( i->first ) != statemapping.end() );
139  StateInterface* fromState = statemapping[i->first];
140  for ( EventList::const_iterator j = i->second.begin(); j != i->second.end(); ++j )
141  {
142  ServicePtr sp = j->get<0>();
143  string ename = j->get<1>();
144  vector<DataSourceBase::shared_ptr> origargs( j->get<2>() );
145  vector<DataSourceBase::shared_ptr> newargs;
146  for ( vector<DataSourceBase::shared_ptr>::const_iterator vit = origargs.begin();
147  vit != origargs.end(); ++vit)
148  newargs.push_back( (*vit)->copy(replacements) );
149  StateInterface* toState = statemapping[j->get<3>()];
150  ConditionInterface* condition = j->get<4>()->copy( replacements );
151  ProgramInterfacePtr tprog;
152  ProgramInterfacePtr tgraph( j->get<5>() );
153  if (tgraph)
154  tprog.reset( tgraph->copy(replacements) );
155  StateInterface* elseState = statemapping[j->get<7>()];
156  ProgramInterfacePtr eprog;
157  ProgramInterfacePtr egraph( j->get<8>() );
158  if (egraph)
159  eprog.reset( egraph->copy(replacements) );
160 #ifndef NDEBUG
161  bool eresult =
162 #endif
163  ret->createEventTransition(sp, ret->getService()->getOwner()->engine(), ename, newargs, fromState, toState, condition, tprog, elseState, eprog );
164  assert( eresult );
165  }
166  }
167 
168  // finally, copy the preconditions
169  for ( PreConditionMap::const_iterator i = precondMap.begin(); i != precondMap.end(); ++i )
170  {
171  assert( statemapping.find( i->first ) != statemapping.end() );
172  StateInterface* tgtState = statemapping[i->first];
173  ConditionInterface* condition = i->second.first->copy( replacements );
174  int line = i->second.second;
175  ret->preconditionSet( tgtState, condition, line );
176  }
177 
178  // init the StateMachine itself :
179  ret->setFinalState( statemapping[ getFinalState() ]);
180  ret->setInitialState( statemapping[ getInitialState() ]);
181 
182  return ret;
183  }
184 
186  this->smStatus = Status::unloaded;
187  if ( this->isLoaded() ){
188  getEngine()->removeFunction(this);
189  }
190 
191  // we own our states...
192  for ( TransitionMap::iterator i = stateMap.begin();
193  i != stateMap.end(); ++i )
194  delete i->first;
195  // we own our conditions...
196  for ( TransitionMap::iterator i = stateMap.begin();
197  i != stateMap.end(); ++i )
198  for ( TransList::iterator i2 = i->second.begin(); i2 != i->second.end(); ++i2 )
199  delete get<0>( *i2 ); // delete the condition.
200 
201  // we own our event guards...
202  for ( EventMap::iterator i = eventMap.begin();
203  i != eventMap.end(); ++i )
204  for ( EventList::iterator i2 = i->second.begin(); i2 != i->second.end(); ++i2 )
205  delete get<4>( *i2 ); // delete the condition.
206 
207  }
208 
210  : StateMachine( StateMachinePtr() ) // no parent, no task
211  {
212  _text.reset( new string("No Text Set.") );
213  }
214 
216  {
218  // just kill off the interface.
219  if ( !object )
220  return;
221  if ( object->getParent() && object->getParent()->hasService( object->getName() ) ){
222  assert( object == object->getParent()->getService( object->getName() ) );
223  object->getParent()->removeService( object->getName() );
224  }
225  object.reset();
226  }
227 
228  void ParsedStateMachine::addParameter( const std::string& name, AttributeBase* var )
229  {
230  assert( parametervalues.find( name ) == parametervalues.end() );
231  parametervalues[name] = var;
232  // every parameter is also a readonly var...
233  // visiblereadonlyvalues[name] = var->toDataSource();
234  }
235 
236  AttributeBase* ParsedStateMachine::getParameter( const std::string& name ) const
237  {
238  if( parametervalues.find( name ) == parametervalues.end() )
239  return 0;
240  return parametervalues.find(name)->second;
241  }
242 
243  ParsedStateMachine::VisibleWritableValuesMap ParsedStateMachine::getParameters() const
244  {
245  return parametervalues;
246  }
247 
248  std::vector<std::string> ParsedStateMachine::getParameterNames() const
249  {
250  return keys( parametervalues );
251  }
252 
253  void ParsedStateMachine::setName( const std::string& name, bool recursive )
254  {
255  // XXX BIG NOTE :
256  // this function should me named 'instantiate' or so because it does more than
257  // settting the name, it also recursively arranges names of children and
258  // sets the parent-child TC connections. Reed the 'recursive' flag as 'instantiate'.
259  // it is used only recursively for instantiating root contexts.
260  //cerr << "Setting name "<< _name << " to " << name<<" rec: "<<recursive<<endl;
261  // set the StateMachine name
262  this->_name = name;
263  // set the datasource's name
264  //nameds->set( name );
265 
266  if ( recursive == false )
267  return;
268  //this->getService()->addPeer( this->getService()->getPeer("states")->getPeer("task") );
269  for ( ChildList::const_iterator i = getChildren().begin(); i != getChildren().end(); ++i )
270  {
271  std::string subname = name + "." + (*i)->getName();
272  ParsedStateMachine* psc = static_cast<ParsedStateMachine*>( i->get() );
273  psc->setName( subname, true );
274  // we own our child:
275  psc->getService()->setOwner( 0 );
276  this->getService()->addService( psc->getService() );
277  }
278  }
279 
280  std::string ParsedStateMachine::getText() const
281  {
282  return *_text;
283  }
284 
285  void ParsedStateMachine::setText( std::string text)
286  {
287  *_text = text;
288  }
289 
291  return object;
292  }
294  object = tc;
295  }
296 
297  bool ParsedStateMachine::inState( const std::string& name ) {
298  StateInterface* copy = this->currentState();
299  if (copy == 0)
300  return false;
301  return copy->getName() == name;
302  }
303 
305  {
306  }
307 
308 }
bool inState(const std::string &name)
A hierarchical StateMachine which is loaded in the Program Processor.
boost::shared_ptr< StateMachineService > StateMachineServicePtr
boost::shared_ptr< ParsedStateMachine > ParsedStateMachinePtr
void finish()
Call this function if the state machine is parsed.
std::string getText() const
Return the text to which getLineNumber() refers.
void setName(const std::string &name, bool recursive)
Set the name of this machine.
This interface represents the concept of a condition which can be evaluated and return true or false...
STL namespace.
virtual const std::string & getName() const =0
Get the name of this state.
virtual ConditionInterface * copy(std::map< const base::DataSourceBase *, base::DataSourceBase * > &alreadyCloned) const
When copying an Orocos program, we want identical internal::DataSource&#39;s to be mapped to identical Da...
boost::shared_ptr< ProgramInterface > ProgramInterfacePtr
std::vector< std::string > getParameterNames() const
void addParameter(const std::string &name, base::AttributeBase *var)
void setService(boost::shared_ptr< StateMachineService > tc)
An attribute is a minimalistic, named placeholder for data.
boost::shared_ptr< Service > ServicePtr
Definition: rtt-fwd.hpp:86
boost::shared_ptr< StateMachineService > getService() const
StateInterface * currentState() const
Retrieve the current state of the state machine.
static std::ostream & endl(std::ostream &__os)
Definition: Logger.cpp:383
void unloading()
Informs this object that it got unloaded from an ExecutionEngine.
ParsedStateMachinePtr copy(std::map< const base::DataSourceBase *, base::DataSourceBase * > &replacements, bool instantiate=false) const
Create a copy, set instantiate to &#39;true&#39; if instantiating a RootMachine.
boost::shared_ptr< StateMachine > StateMachinePtr
virtual StateInterface * copy(std::map< const base::DataSourceBase *, base::DataSourceBase * > &replacementdss) const =0
std::vector< typename MapT::key_type > keys(const MapT &map)
Definition: mystd.hpp:151
void addChild(StateMachinePtr child)
static Logger & log()
As Instance(), but more userfriendly.
Definition: Logger.cpp:117
base::AttributeBase * getParameter(const std::string &name) const
VisibleWritableValuesMap getParameters() const
virtual void unloading()
Informs this object that it got unloaded from an ExecutionEngine.
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:51
State machine created by the scripting engine which represents a parsed state machine.
A State contains an entry, run, handle and exit program.
const ChildList & getChildren() const
Get a list of all child state machines.