Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

BehaviorBase.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_BehaviorBase_h_
00003 #define INCLUDED_BehaviorBase_h_
00004 
00005 #include "Events/EventListener.h"
00006 #include "Shared/ReferenceCounter.h"
00007 #include <string>
00008 #include <set>
00009 
00010 //! The basis from which all other Behaviors should inherit
00011 /*! 
00012  *  For complex behaviors, it may be helpful to break aspects of the behaviors into independent 'states', and
00013  *  use a state machine formalism to control them.  See StateNode and Transition for more information.
00014  *
00015  *  Quick-start boilerplate is included in the distribution: <a href="http://cvs.tekkotsu.org/cgi/viewcvs.cgi/Tekkotsu/project/templates/behavior.h?rev=HEAD&content-type=text/vnd.viewcvs-markup"><i>project</i><tt>/templates/behavior.h</tt></a>:
00016  * 
00017  *  Tutorials:
00018  *  - <a href="../FirstBehavior.html">Tekkotsu's "First Behavior" Tutorial</a>
00019  *  - <a href="http://www.cs.cmu.edu/~dst/Tekkotsu/Tutorial/behaviors.shtml">David Touretzky's "Behaviors" Chapter</a>
00020  *  - <a href="http://www.cs.cmu.edu/afs/cs/academic/class/15494-s06/www/lectures/behaviors.pdf">CMU's Cognitive Robotics course slides</a>
00021  *  
00022  *  REMEMBER: If/when you override DoStart() / DoStop(), make sure that your own implementation calls BehaviorBase's implementation to allow
00023  *  proper reference counting... otherwise you'll get memory leaks and other odd issues. (see boilerplate link above for example usage)
00024  *
00025  *  Also, if you instantiate a behavior on the stack instead of the heap (this is very rarely done), remember to call 
00026  *  SetAutoDelete(false) (provided from the ReferenceCounter base class) -- don't want it to try to free memory
00027  *  on the stack when the behavior is stopped!  (The stack limits the allocation of the behavior
00028  *  to the current scope, which overrides the reference counting.)
00029  */
00030 class BehaviorBase : public ReferenceCounter, public EventListener {
00031 public:
00032   //! destructor - if is active when deleted, will display a warning (don't delete directly - use RemoveReference())
00033   virtual ~BehaviorBase();
00034   
00035   //! By default, merely adds to the reference counter (through AddReference()); Note you should still call this from your overriding methods
00036   virtual void DoStart();
00037 
00038   //! By default, subtracts from the reference counter (RemoveReference()), and thus may deletex if zero;  Don't forget to still call this when you override this; <b>Warning:</b> call this at the <i>end</i> of your DoStop(), not beginning (it might @c delete @c this )
00039   virtual void DoStop();
00040   
00041   //! By defining here, allows you to get away with not supplying a processEvent() function for the EventListener interface.  By default, does nothing.
00042   virtual void processEvent(const EventBase& /*event*/) {}
00043 
00044   //! Identifies the behavior in menus and such
00045   virtual std::string getName() const { return instanceName; }
00046 
00047   //! Allows dynamic renaming of behaviors
00048   virtual void setName(const std::string& name) { instanceName=name; }
00049 
00050   //! Gives a short description of what this particular instantiation does (in case a more specific description is needed on an individual basis)
00051   /*! By default simply returns getName(), because any calls from a
00052    *  BehaviorBase function to getClassDescription() are going to call
00053    *  BehaviorBase::getClassDescription(), not
00054    *  ~YourSubClass~::getClassDescription(), because static functions
00055    *  can't be virtual in C++ (doh!)
00056    *
00057    *  This means that getDescription called on a pointer to a
00058    *  BehaviorBase of unknown subtype would always return an empty
00059    *  string, which is pretty useless.  So instead we return the name
00060    *  in this situation.  If you want getDescription to return
00061    *  getClassDescription, you'll have to override it in your subclass
00062    *  to do so. */
00063   virtual std::string getDescription() const {
00064     std::string d=getClassDescription();
00065     return (d.size()==0)?getName():d;
00066   }
00067 
00068   //! Returns the name of the class of this behavior (aka its type)
00069   /*! Note that this isn't static to avoid the problems we found with
00070    *  getDescription/getClassDescription.  So instead we wind up
00071    *  wasting some memory in each instance of the class to store the
00072    *  className, but at least it will work the way you expect. */
00073   virtual std::string getClassName() const { return className; }
00074   
00075   //! Gives a short description of what this class of behaviors does... you should override this (but don't have to)
00076   /*! If you do override this, also consider overriding getDescription() to return it */
00077   static std::string getClassDescription() { return ""; }
00078 
00079   //! Returns true if the behavior is currently running
00080   virtual bool isActive() const { return started; }
00081   
00082   //! This read-only set allows us list all the currently instantiated behaviors
00083   /*! Not all of these behaviors are necessarily active, this is everything that has been allocated and not yet deallocated */
00084   static const std::set<BehaviorBase*>& getRegistry() { return getRegistryInstance(); }
00085 
00086   // Just some debugging stuff in stasis
00087   /*  virtual void AddReference() {
00088       std::cout << getName() << " AddReference()==" << GetReferences() << ' ' << this << std::endl;
00089       ReferenceCounter::AddReference();
00090       }
00091       
00092       virtual void RemoveReference() {
00093       std::cout << getName() << " RemoveReference()==" << GetReferences() << ' ' << this << std::endl;
00094       ReferenceCounter::RemoveReference();
00095       }
00096   */
00097   
00098 protected:
00099   //! static function to provide well-defined initialization order
00100   static std::set<BehaviorBase*>& getRegistryInstance();
00101 
00102   //! constructor, @a name is used as both instance name and class name
00103   explicit BehaviorBase(const std::string& name);
00104   //! constructor, allows different initial values for class name and instance name
00105   BehaviorBase(const std::string& classname, const std::string& instancename);
00106   //! copy constructor; assumes subclass handles copying approriately - i.e. if @a b is active, the copy will be as well, even though DoStart was never called..
00107   BehaviorBase(const BehaviorBase& b);
00108   //! assignment operator; assumes subclass handles assignment appropriately - i.e. if @a b is active, the copy will be as well, even though DoStart was never called..
00109   BehaviorBase& operator=(const BehaviorBase& b);
00110 
00111   bool started; //!< true when the behavior is active
00112   std::string instanceName; //!< holds the name of this instance of behavior
00113   const std::string className; //!< holds the type of the subclass of this behavior as a string
00114 };
00115 
00116 /*! @file
00117  * @brief Describes BehaviorBase from which all Behaviors should inherit
00118  * @author ejt (Creator)
00119  *
00120  * $Author: ejt $
00121  * $Name: tekkotsu-4_0 $
00122  * $Revision: 1.28 $
00123  * $State: Exp $
00124  * $Date: 2006/10/03 22:09:40 $
00125  */
00126 
00127 #endif

Tekkotsu v4.0
Generated Thu Nov 22 00:54:51 2007 by Doxygen 1.5.4