Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

BehaviorBase.cc

Go to the documentation of this file.
00001 #include "BehaviorBase.h"
00002 #include "Events/EventRouter.h"
00003 #include "IPC/SharedObject.h"
00004 #include "Shared/string_util.h"
00005 #include "Motion/MotionManager.h"
00006 #include "Shared/MarkScope.h"
00007 
00008 BehaviorBase::BehaviorBase()
00009   : ReferenceCounter(), EventListener(), autoMotions(), started(false), instanceName(), event(NULL)
00010 {
00011   getRegistryInstance().insert(this);
00012 }
00013 
00014 BehaviorBase::BehaviorBase(const std::string& name)
00015   : ReferenceCounter(), EventListener(), autoMotions(), started(false), instanceName(name), event(NULL)
00016 {
00017   getRegistryInstance().insert(this);
00018 }
00019 
00020 BehaviorBase::BehaviorBase(const BehaviorBase& b)
00021   : ReferenceCounter(b), EventListener(b), autoMotions(), started(b.started), instanceName(b.instanceName), event(NULL)
00022 {
00023   getRegistryInstance().insert(this);
00024 }
00025 
00026 BehaviorBase&
00027 BehaviorBase::operator=(const BehaviorBase& b) {
00028   ReferenceCounter::operator=(b);
00029   EventListener::operator=(b);
00030   started=b.started;
00031   instanceName=b.instanceName;
00032   return *this;
00033 }
00034 
00035 BehaviorBase::~BehaviorBase() {
00036   setAutoDelete(false);
00037   if(started)
00038     std::cerr << "Behavior " << getName() << " deleted while running: use 'removeReference', not 'delete'" << std::endl;
00039   if(erouter!=NULL)
00040     erouter->removeListener(this);
00041   autoMotions.clear(); // this actually removes the motions via MonitorMotion's destructors
00042   getRegistryInstance().erase(this);
00043 }
00044 
00045 void
00046 BehaviorBase::start() {
00047   //std::cout << getName() << " started " << this << std::endl;
00048   if(!started) {
00049     started=true;
00050     addReference();
00051     try {
00052       preStart();
00053       if(started) // re-verify flag in case the subclass called stop()
00054         doStart();
00055       if(started)
00056         postStart();
00057     } catch(...) {
00058       // abort our reference... don't delete on dereference
00059       bool prevAD = getAutoDelete();
00060       setAutoDelete(false);
00061       removeReference();
00062       setAutoDelete(prevAD);
00063       throw;
00064     }
00065   }
00066 }
00067 
00068 void
00069 BehaviorBase::stop() {
00070   //std::cout << getName() << " stopped " << this << std::endl;
00071   if(started) {
00072     doStop();
00073     autoMotions.clear(); // this actually removes the motions via MonitorMotion's destructors
00074     started=false;
00075     erouter->remove(this);
00076     removeReference();
00077   }
00078 }
00079 
00080 void BehaviorBase::processEvent(const EventBase& curEvent) {
00081   const EventBase* prevEvent = event; // in case of recursive events triggered by doEvent
00082   event=&curEvent;
00083   if(prevEvent==event) { // prevent recursive looping on the same event (is this good or no?)
00084     std::cerr << "Warning: blocking recursive event posting of " << event->getDescription() << " to behavior " << getName() << std::endl;
00085   } else {
00086     doEvent();
00087     event=prevEvent;
00088   }
00089 }
00090 
00091 void BehaviorBase::doEvent() {
00092   if(event->getGeneratorID()==EventBase::textmsgEGID && event->getSourceID()==1)
00093     erouter->postEvent(*event);
00094 }
00095 
00096 std::string BehaviorBase::getClassName() const {
00097   return string_util::demangle(typeid(*this).name());
00098 }
00099 
00100 std::set<BehaviorBase*>&
00101 BehaviorBase::getRegistryInstance() {
00102   static std::set<BehaviorBase*> registry;
00103   return registry;
00104 }
00105 
00106 std::string
00107 BehaviorBase::humanifyClassName(const std::string& name) {
00108   std::string name2 = /*(string_util::endsWith(name,"Behavior") && name.size()>10) ? name.substr(0,name.size()-8) :*/ name;
00109   std::string name3;
00110   unsigned int rightEdge = name2.size();
00111   if ( rightEdge == 0 ) return name3;
00112   while ( !isalpha(name2[rightEdge-1]) && (--rightEdge > 0) );
00113   for(unsigned int i=0; i<rightEdge; ++i) {
00114     /*! a rough heuristic for inserting spaces... before any non-lowercase letter (i.e. caps or nums) where previous or next is lower, but not within a digit string or before a final digit string
00115      - ASCIIVision → ASCII Vision
00116      - Aibo3DController → Aibo3D Controller
00117      - EStopController → EStop Controller
00118      - Test32 → Test32
00119      - FlashIPAddr → Flash IP Addr
00120      */
00121   if(!islower(name2[i]) && i>1 && 
00122      ( (i+1<rightEdge && islower(name2[i+1]) && isalpha(name2[i-1])) || islower(name2[i-1]) ))
00123       name3.append(1,' ');
00124     name3.append(1,name2[i]);
00125   }
00126   name3.append(name2.substr(rightEdge));
00127   return name3;
00128 }
00129 
00130 // this version calls out to the other addMotion (instead of using optional argument)
00131 // to avoid dependence on MotionManager.h just for the kStdPriority
00132 BehaviorBase::MC_ID
00133 BehaviorBase::addMotion(const SharedObjectBase& mc, Prunability_t prune/*=PERSISTENT*/) {
00134   return addMotion(mc,prune,MotionManager::kStdPriority);
00135 }
00136 
00137 BehaviorBase::MC_ID
00138 BehaviorBase::addMotion(const SharedObjectBase& mc, Prunability_t prune, float priority/*=MotionManager::kStdPriority*/) {
00139   MotionManager::MC_ID mcid = MotionManager::invalid_MC_ID;
00140   if(prune==PERSISTENT)
00141     mcid = motman->addPersistentMotion(mc, priority);
00142   else if(prune==PRUNABLE)
00143     mcid = motman->addPrunableMotion(mc, priority);
00144   else
00145     throw std::runtime_error("Invalid prunability value for BehaviorBase::addMotion");
00146   if(mcid!=MotionManager::invalid_MC_ID)
00147     autoMotions[mcid].monitor(*this,mcid,mc.getRegion());
00148   return mcid;
00149 }
00150 
00151 void
00152 BehaviorBase::removeMotion(MotionManager::MC_ID mcid) {
00153   autoMotions.erase(mcid); // removes motion via MonitorMotion destructor
00154 }
00155 
00156 BehaviorBase::MonitorMotion::~MonitorMotion() {
00157   if(mcid!=MotionManager::invalid_MC_ID) {
00158     erouter->removeListener(this,EventBase::motmanEGID,mcid,EventBase::deactivateETID);
00159     motman->removeMotion(mcid);
00160   }
00161   if(mcregion!=NULL)
00162     mcregion->RemoveReference();
00163 }
00164 void BehaviorBase::MonitorMotion::monitor(BehaviorBase& parent, MotionManager::MC_ID mc_id, RCRegion* region) {
00165   owner=&parent; mcid=mc_id; mcregion=region;
00166   if(mcregion!=NULL)
00167     mcregion->AddReference();
00168   if(mcid!=MotionManager::invalid_MC_ID)
00169     erouter->addListener(this,EventBase::motmanEGID,mcid,EventBase::deactivateETID);
00170 }
00171 void BehaviorBase::MonitorMotion::processEvent(const EventBase&) {
00172   // we have received notification that the motion was removed/pruned
00173   MotionManager::MC_ID tmp = mcid; // backup original
00174   mcid=MotionManager::invalid_MC_ID; // clear mcid *before* erasing the entry, so the destructor won't try to remove the mcid a second time
00175   mcregion->RemoveReference();
00176   mcregion=NULL;
00177   owner->autoMotions.erase(tmp);
00178   // by erasing the map entry, this instance should now be destructed!
00179 }
00180 
00181 
00182 /*! @file
00183  * @brief Implements BehaviorBase from which all Behaviors should inherit
00184  * @author ejt (Creator)
00185  */
00186 

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