Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

StateNode.cc

Go to the documentation of this file.
00001 #include "StateNode.h"
00002 #include "Transition.h"
00003 #include "Events/EventRouter.h"
00004 #include "Sound/SoundManager.h"
00005 #include "Wireless/Wireless.h"
00006 #include "Shared/debuget.h"
00007 
00008 StateNode::~StateNode() {
00009   ASSERT(!isActive(), "Destructing while active?")
00010   for(std::vector<Transition*>::iterator it=transitions.begin(); it!=transitions.end(); it++)
00011     (*it)->removeReference();
00012   if(issetup) {
00013     teardown();
00014     if(issetup) {
00015       serr->printf("WARNING %s doesn't seem to call StateNode::teardown() in its\n"
00016                    "        implementation of the function: issetup=%d, nodes.size()=%lu\n"
00017                    "        Attempting to recover...\n",getClassName().c_str(),issetup,(unsigned long)nodes.size());
00018       StateNode::teardown();
00019     }
00020   }
00021 }
00022 
00023 Transition* StateNode::addTransition(Transition* trans) {
00024   transitions.push_back(trans);
00025   trans->addReference();
00026   trans->addSource(this);
00027   return trans;
00028 }
00029 
00030 StateNode* StateNode::addNode(StateNode* node) {
00031   nodes.push_back(node);
00032   node->addReference();
00033   if ( node->parent == NULL )
00034     node->parent = this;
00035   return node;
00036 }
00037 
00038 StateNode* StateNode::getChild(const std::string& name) const {
00039     for (std::vector<StateNode*>::const_iterator it = nodes.begin(); it != nodes.end(); it++)
00040       if ( name == (*it)->getName() ) return *it;
00041     return NULL;
00042 }
00043 
00044 StateNode* StateNode::getSibling(const std::string& name) const {
00045     if ( parent == NULL )
00046       return parent;
00047     for (std::vector<StateNode*>::const_iterator it = parent->nodes.begin(); it != parent->nodes.end(); it++)
00048       if ( name == (*it)->getName() ) return *it;
00049     return parent->getSibling(name);
00050 }
00051 
00052 struct ScopeReference {
00053   ScopeReference(ReferenceCounter& rc) : ref(rc) { ref.addReference(); }
00054   ~ScopeReference() { ref.removeReference(); }
00055   ReferenceCounter& ref;
00056 };
00057 
00058 /*! This could be implemented slightly more simply as a pre/postStart() pair, but
00059  *  keeping our specialization in start() itself allows us to keep pre/postStart empty
00060  *  (thus more robust to subclass overrides forgetting to call their superclass version,
00061  *  but also avoids any potential subclass mis-handling of transition fire while in preStart) */
00062 void StateNode::start() {
00063   if(started)
00064     return;
00065   started=true; // use started to watch for immediate transition
00066   ScopeReference ref(*this); // keep a self-reference for this scope, releases automatically on throw/return
00067   postStateStart();
00068 #ifdef PLATFORM_APERIOS
00069   if ( !speechText.empty() )
00070     sout->printf("Speak: %s\n",speechText.c_str());
00071 #else
00072   if ( !speechText.empty() )
00073     sndman->speak(speechText);
00074 #endif
00075   if ( parent == NULL && transitions.size() > 0 )
00076     serr->printf("WARNING StateNode '%s' has transitions but no parent; you probably forgot to call addNode().\n",getName().c_str());
00077   if ( ! issetup ) {
00078     setup();
00079     issetup = true;
00080   }
00081   // Must start the transitions before we start the behavior, because the behavior could
00082   // post something that triggers a transition.  But if a transition fires and tries to
00083   // shut the behavior down, we must detect that and not try to start the behavior afterward.
00084   for(std::vector<Transition*>::iterator it=transitions.begin(); it!=transitions.end(); it++) {
00085     if ( !(*it)->isActive()  )
00086       (*it)->start();
00087     if(!isActive()) //a transition fired upon its start
00088       return;
00089   }
00090   started=false; // reset flag otherwise BehaviorBase::start() will be a no-op
00091   BehaviorBase::start();
00092   if ( isActive() && startnode )
00093     startnode->start();
00094 }
00095 
00096 void StateNode::stop() {
00097   for(std::vector<Transition*>::iterator it=transitions.begin(); it!=transitions.end(); it++) {
00098     if((*it)->isActive())
00099       (*it)->stop();
00100   }
00101   for(std::vector<StateNode*>::iterator it=nodes.begin(); it!=nodes.end(); it++)
00102     if((*it)->isActive())
00103       (*it)->stop();
00104   if(!retain && issetup) {
00105     teardown();
00106     if(issetup) {
00107       serr->printf("WARNING %s doesn't seem to call StateNode::teardown() in its\n"
00108                    "        implementation of the function: issetup=%d, nodes.size()=%lu\n"
00109                    "        Attempting to recover...\n",getClassName().c_str(),issetup,(unsigned long)nodes.size());
00110       StateNode::teardown();
00111     }
00112   }
00113   postStateStop();
00114   BehaviorBase::stop();
00115 }
00116 
00117 void StateNode::teardown() {
00118   for(std::vector<StateNode*>::iterator it=nodes.begin(); it!=nodes.end(); it++)
00119     (*it)->removeReference();
00120   startnode = NULL;
00121   nodes.clear();
00122   issetup=false;
00123   /*std::cout << "Teardown!!!!!!!!" << std::endl;*/
00124 }
00125 
00126 void StateNode::postStateStart() {
00127   erouter->postEvent(EventBase::stateMachineEGID,reinterpret_cast<size_t>(this),EventBase::activateETID,0,getName(),1);
00128 }
00129 
00130 void StateNode::postStateStop() {
00131   erouter->postEvent(EventBase::stateMachineEGID,reinterpret_cast<size_t>(this),EventBase::deactivateETID,get_time()-startedTime,getName(),0);
00132 }
00133 
00134 void StateNode::postStateCompletion(float magnitude/*=0*/) {
00135   erouter->postEvent(EventBase::stateMachineEGID,reinterpret_cast<size_t>(this),EventBase::statusETID,get_time()-startedTime,getName(),magnitude);
00136 }
00137 
00138 
00139 /*! @file 
00140  * @brief Describes StateNode, which is both a state machine controller as well as a node within a state machine itself
00141  * @author ejt (Creator)
00142  */
00143 

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:51 2016 by Doxygen 1.6.3