Tekkotsu Homepage | Demos | Overview | Downloads | Dev. Resources | Reference | Credits |
BehaviorBase.hGo 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 |