Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

EventBase.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_EventBase_h
00003 #define INCLUDED_EventBase_h
00004 
00005 #include "Shared/XMLLoadSave.h"
00006 #include "Shared/FamilyFactory.h"
00007 #include <string>
00008 
00009 //! Forms the basis of communication between modules/behaviors in the framework
00010 /*! 
00011  *  Events are defined by a 3-tuple:
00012  *  - The @b generator indicates the class of the creator of the event, and in practice also generally implies the type (i.e. subclass) of the event itself.
00013  *  - The @b source indicates the instance of the creator of the event, which differentiates when more than one generator is available.
00014  *  - The @b type indicates the role of the event among other events from the source.
00015  *
00016  *  Each of these is represented by an ID, the #EventGeneratorID_t (EGID) and #EventTypeID_t (ETID) are
00017  *  defined here in EventBase.  Source IDs (SID) are defined separately by each generator, so the
00018  *  documentation in each entry of EventGeneratorID_t describes how to interpret the source field.
00019  *
00020  *  So for example, the button event which results from initially pressing the head button on an ERS-7
00021  *  robot would be:
00022  *  <center>(EventBase::buttonEGID, ERS7Info::HeadButOffset, EventBase::activateETID)</center>
00023  *
00024  *  While the button is held down, additional #statusETID events are used to report varying pressure values (if the button
00025  *  is pressure sensitive), and an event with #deactivateETID is sent when the button is released.
00026  *  Alternatively, an SID value from a vision detector (say #visObjEGID) refers to seeing a particular object, a completely
00027  *  different domain, values of which may overlap with other generators' source IDs.
00028  *  Thus, interpreting the source field requires knowing the generator as well.
00029  *
00030  *  When the generator doesn't have groups of activity with a 'begin' or 'end', it will use #statusETID
00031  *  for all of its events.  (in other words, not all generators necessarily have to use activate or deactivate)
00032  *  For example, sensor updates are continuously occuring, so you will only ever see
00033  *  <center>(EventBase::sensorEGID,SensorSrcID::UpdatedSID,EventBase::statusETID)</center>
00034  *  
00035  *  The #duration field is also generator specific - some may refer to
00036  *  the time since the last activation event (e.g. button events)
00037  *  where as others refer to time since last status (e.g. sensors
00038  *  updates)
00039  *
00040  *  If you want to make a new generator, all you have to do is add a new entry
00041  *  to the ID list (#EventGeneratorID_t) and then put its name in the 
00042  *  #EventGeneratorNames[] array.  Alternatively, there is an 'unlicensed spectrum' available under
00043  *  #unknownEGID.  You can send out events from that generator just
00044  *  like any other, but it should only be used for quick tests and hacking
00045  *  around...
00046  *
00047  *  The generator ID number is only that -- an ID number.  
00048  *  Events can be posted to the EventRouter anywhere, anytime,
00049  *  and do not require anything of the sender.  However, there is an EventGeneratorBase which
00050  *  can simplify some aspects of behaviors whose sole purpose is processing information
00051  *  and generating events.
00052  *
00053  *  If more information needs to be sent along with the event, the
00054  *  cleanest solution is to create a subclass of EventBase to hold the
00055  *  additional information.  For example, you can see the existing
00056  *  subclasses in the inheritance diagram above.  If you want to use a
00057  *  quick hack however, you could just pass a pointer to data as the SID if you
00058  *  don't need that field for something else, or use a DataEvent.
00059  *
00060  *  @note All subclasses must override getClassTypeID() and provide
00061  *  a unique value to allow fast polymorphic serialization for inter-process
00062  *  communication.  Implementing the load/save functions
00063  *  ({load,save}BinaryBuffer and {load,save}XML) for your addtional data fields
00064  *  would also be necessary in order to allow your event to be sent between
00065  *  processes, or eventually, between robots.
00066  * 
00067  *  @see EventRouter for discussion on sending and receiving of events
00068  *  @see Tutorials:
00069  *    - <a href="../FirstBehavior2.html">Steps 3, 4, & 5 of Tekkotsu's First Behavior Tutorial</a>
00070  *    - <a href="http://www.cs.cmu.edu/~dst/Tekkotsu/Tutorial/events.shtml">David Touretzky's Events Chapter</a>
00071  *    - <a href="http://www.cs.cmu.edu/afs/cs/academic/class/15494-s06/www/lectures/behaviors.pdf">CMU's Cognitive Robotics course slides</a>
00072  *    - <a href="../media/TekkotsuQuickReference_ERS7.pdf">ERS-7 Quick Reference Sheet</a>
00073  */
00074 class EventBase : public XMLLoadSave {
00075  public:
00076   //! Lists all possible event generator ids
00077   /*! An event generator is a abstract source of events, used for listening to and parsing certain classes of events
00078    *
00079    *  IF YOU ADD AN EVENT GENERATOR, DON'T FORGET TO NAME IT (EventBase::EventGeneratorNames, actual names are in EventBase.cc)*/
00080   enum EventGeneratorID_t {
00081     unknownEGID=0,    //!< default EGID, used if you forget to set it, probably not a good idea to use this for anything except errors or testing quick hacks
00082     aiEGID,           //!< not being used, yet (might use this when AI makes decisions?)
00083     audioEGID,        //!< Sends an event when a sound starts/ends playback, status events as chained sounds end; SID is SoundManager::Play_ID; duration is playtime
00084     buttonEGID,       //!< Sends activate event for button down, deactivate for button up.  Status events only for when pressure sensitive buttons' reading changes. (on sensorEGID updates); SIDs are from ButtonOffset_t in the namespace of the target model (e.g. ERS210Info::ButtonOffset_t); duration is button down time
00085     cameraResolutionEGID, //!< Sends a status event whenever the camera's resolution changes, such as a different camera than predicted by RobotInfo is being used, or a camera is hotswapped.  SID corresponds to the visOFbkEGID for that camera.
00086     erouterEGID,      //!< Sends activate event on first listener, deactivate on last listener, and status on other listener changes.; SID is the generator ID affected
00087     estopEGID,        //!< Sends an event when the estop is turned on or off; SID is the MotionManager::MC_ID of the EmergencyStopMC; duration is length of estop activation
00088     grasperEGID,  //!< Sends events when the Grasper processes a user request
00089         koduEGID,       //!< Sends events when a kodu event occurs
00090     locomotionEGID,   //!< Sends events regarding transportation in the world; you can/should assume these will all be LocomotionEvent classes; SID is MotionManager::MC_ID of posting MotionCommand; duration is the time since last velocity change of that MC. (You could generate these for things other than walking...)
00091     lookoutEGID,      //!< Sends an event when Lookout request is complete; SID is the id for lookout request
00092     mapbuilderEGID,  //!< Sends a status event when map is completed
00093     micOSndEGID,      //!< Sends a DataEvent<OSoundVectorData> for every audio buffer received from the system; SID and duration are always 0 (This is generated by the MainObj instantiation of MMCombo)
00094     micRawEGID,       //!< reserved for future use
00095     micFFTEGID,       //!< reserved for future use
00096     micPitchEGID,       //!< Sends a PitchEvent when a particular frequency is detected; SID is a pointer to the PitchDetector, magnitude is product of amplitude and confidence
00097     mocapEGID,        //!< Sends a MoCapEvent for "motion capture" or GPS type updates from an external localization source.  Used for position/orientation feedback from simulation as well.
00098     motmanEGID,       //!< Sends events when a MotionCommand is added or removed, SID is is the MotionManager::MC_ID, duration is always 0; individual MotionCommands may throw status events to signal intermediary status
00099     pilotEGID,        //!< Sends events when position of agent is updated or pilot request is completed
00100     powerEGID,        //!< Sends events for low power warnings, temperature, etc. see PowerSrcID::PowerSourceID_t
00101     remoteStateEGID,  //!< Sent when remote state is updated
00102     runtimeEGID,     //!< Sends an activate upon completion of startup, and a deactivate event upon shutdown; source ID undefined (currently 0)
00103     sensorEGID,       //!< Sends a status event when new sensor readings are available. see SensorSrcID::SensorSourceID_t
00104     servoEGID,        //!< Sends notifications of servo errors; the source id is the Tekkotsu output offset
00105     stateMachineEGID, //!< Sends an event upon entering and leaving a StateNode; SID is pointer to the StateNode; duration is always 0; some state will throw a status event when they have completed their task and are now idling
00106     stateSignalEGID,  //!< Sends a DataEvent that can be monitored by a SignalTrans for triggering a state transition
00107     stateTransitionEGID, //!< Sends an event each time a transition is triggered; SID is a pointer to the transition; type is activate at start of firing and deactivate when firing is complete; duration is always 0; activate guaranteed to occur immediately *before* the transition actually occurs
00108     textmsgEGID,      //!< Sends status events when a text msg is received on console; generated by the Controller, SID is 0 if broadcast from ControllerGUI, 1 if "private" from BehaviorSwitchControl; duration is always 0 (see Controller for more information)
00109     timerEGID,        //!< Sends timer events; you set timers explicitly, you don't have to listen as well. (See EventRouter::addTimer()) There's no cross-talk, only the listener which requested the timer will receive it; SID is whatever you requested it to be; duration is the time (since boot, in ms) that the timer was supposed to go off; these are always status
00110     userEGID,        //!< Reserved for user-generated events
00111     visInterleaveEGID,//!< Sends a FilterBankEvent when new interleaved images are available; SID is whatever value you gave during setup (typically in StartupBehavior_SetupVision.cc), duration is always 0
00112     visJPEGEGID,      //!< Sends a FilterBankEvent when JPEG compressed images are available; SID is whatever value you gave during setup (typically in StartupBehavior_SetupVision.cc), duration is always 0
00113     visObjEGID,       //!< Sends VisionObjectEvents for objects detected in camera images; SID is whatever value you gave during setup (typically in StartupBehavior_SetupVision.cc), duration is always 0
00114     visOFbkEGID,      //!< Sends a DataEvent < OFbkImageVectorData > for every camera image received from the system; SID and duration are always 0 (This is generated by the MainObj instantiation of MMCombo)
00115     visPNGEGID,      //!< Sends a FilterBankEvent when PNG compressed images are available; SID is whatever value you gave during setup (typically in StartupBehavior_SetupVision.cc), duration is always 0
00116     visRawCameraEGID, //!< Sends a FilterBankEvent when new raw camera images are available; SID is whatever value you gave during setup (typically in StartupBehavior_SetupVision.cc), duration is always 0
00117     visRawDepthEGID,     //!< Sends FilterBankEvent when new depth images are available
00118     visRegionEGID,    //!< Sends a SegmentedColorFilterBankEvent when color regions are available; SID is whatever value you gave during setup (typically in StartupBehavior_SetupVision.cc), duration is always 0
00119     visRLEEGID,       //!< Sends a SegmentedColorFilterBankEvent when RLE encoded color segmentated images are available; SID is whatever value you gave during setup (typically in StartupBehavior_SetupVision.cc), duration is always 0
00120     visSegmentEGID,   //!< Sends a SegmentedColorFilterBankEvent when color segmentated images are available; SID is whatever value you gave during setup (typically in StartupBehavior_SetupVision.cc), duration is always 0
00121     wmVarEGID,        //!< Sends an event when a watched memory is changed; source id is pointer to WMEntry
00122     worldModelEGID,   //!< not being used, yet (for when objects are detected/lost?)
00123     numEGIDs          //!< the number of generators available
00124   };
00125 
00126   //! Holds string versions of each of the generator's names, handy for debugging so you can output the events as readable strings (you'll find this in EventBase.cc since it can't go in the header or we get multiply-defined errors during linking)
00127   static const char* const EventGeneratorNames[numEGIDs+1];
00128   
00129   //! an event type id is used to denote whether it's the first in a sequence (button down), in a sequence (button still down), or last (button up)
00130   enum EventTypeID_t {
00131     activateETID,   //!< Start of an event sequence, e.g. button down
00132     statusETID,     //!< Indicates a value has changed, e.g. new sensor readings
00133     deactivateETID, //!< Last of a series of events, e.g. button up
00134     numETIDs        //!< the number of different event types
00135   };
00136   
00137   //! holds string versions of EventTypeID_t
00138   static const char* const EventTypeNames[numETIDs+1];
00139   
00140   //! holds abbreviated string versions of EventTypeID_t
00141   static const char* const EventTypeAbbr[numETIDs];
00142   
00143   //! type used for class ids in the type registry (see getTypeRegistry())
00144   typedef unsigned int classTypeID_t;
00145   
00146   //! type used for the type registry
00147   typedef FamilyFactory<EventBase,classTypeID_t> registry_t;
00148 
00149   //! returns a FamilyFactory with which you can look up classTypeID_t's to make new instances from serialized data
00150   static registry_t& getTypeRegistry();
00151   
00152   /*! @name Constructors/Destructors */
00153   //! constructor
00154   /*! @see EventRouter::postEvent() */
00155   EventBase(); 
00156   EventBase(EventGeneratorID_t gid, size_t sid, EventTypeID_t tid, unsigned int dur=0);
00157   EventBase(EventGeneratorID_t gid, size_t sid, EventTypeID_t tid, unsigned int dur, const std::string& n);
00158   EventBase(EventGeneratorID_t gid, size_t sid, EventTypeID_t tid, unsigned int dur, const std::string& n, float mag);
00159   virtual ~EventBase() {} //!< destructor
00160 
00161   //! allows a copy to be made of an event, supporting polymorphism
00162   /*! Must be overridden by all subclasses to allow this to happen
00163    * 
00164    *  I would like to switch this over to the cloneable interface once
00165    *  the compiler gets updated out of the 3.3 branch... see
00166    *  Cloneable::clone() for a discussion of the issue and
00167    *  implementation notes. */
00168   virtual EventBase* clone() const { return new EventBase(*this); }
00169   //@}
00170 
00171   template<typename T>
00172   operator const T&() const {
00173     const T* recastEvent = dynamic_cast<const T*>(this);
00174     if ( recastEvent == NULL )
00175       std::cerr << "Attempt to dynamic_cast an EventBase to the wrong type\n";
00176     return *recastEvent;
00177   }
00178 
00179   /*! @name Methods */
00180   virtual const std::string& getName() const { return stim_id; } //!< gets the name of the event - useful for debugging output, see also getDescription()
00181   virtual EventBase& setName(const std::string& n); //!< sets name to a given string, prevents overwriting by generated names
00182 
00183   virtual float getMagnitude() const { return magnitude; } //!< gets "strength" of event - by default 1 for activate and status events, 0 for deactivate events
00184   virtual EventBase& setMagnitude(float m) { magnitude=m; return *this; }//!< sets "strength" of event - you may want to override the default values (see getMagnitude())
00185 
00186   virtual unsigned int getTimeStamp() const { return timestamp; } //!< time event was created
00187   virtual void setTimeStamp(unsigned int t) { timestamp=t; } //!< resets time event was created
00188 
00189   virtual EventGeneratorID_t getGeneratorID() const { return genID; } /*!< @brief gets the generator ID for this event @see EventGeneratorID_t */
00190   virtual EventBase& setGeneratorID(EventGeneratorID_t gid) { genID=gid; genName(); return *this; } /*!< @brief sets the generator ID for this event @see EventGeneratorID_t */
00191   
00192   virtual size_t getSourceID() const { return sourceID; } /*!< @brief gets the source ID for this event @see sourceID */
00193   virtual EventBase& setSourceID(size_t sid) { sourceID=sid; genName(); return *this; } /*!< @brief sets the source ID for this event @see sourceID */
00194   
00195   virtual EventTypeID_t getTypeID() const { return typeID; } /*!< @brief gets the type ID @see EventTypeID_t */
00196   virtual EventBase& setTypeID(EventTypeID_t tid) { typeID=tid; unsigned int n=strlen(EventTypeAbbr[typeID]); stim_id.replace(stim_id.size()-n-1,n,EventTypeAbbr[typeID]); return *this; } /*!< @brief sets the type ID @see EventTypeID_t */
00197 
00198 
00199   virtual int getHostID() const { return hostID; }  //!< ID of the host that generated this event (-1U for localhost)
00200   virtual EventBase& setHostID(int host) { hostID = host; genName(); return *this; }  //!< sets the ID of the host associated with this event
00201   
00202   virtual unsigned int getDuration() const { return duration; } /*!< @brief gets the time since the beginning of this sequence (the timestamp of the activate event) @see duration */
00203   virtual EventBase& setDuration(unsigned int d) { duration = d; return *this; }/*!< @brief sets the time since the beginning of this sequence (the timestamp of the activate event) @see duration */
00204 
00205   virtual const std::string& resetName() { nameisgen=true; genName(); return stim_id; } //!< resets name to generated form, overwriting any previous name
00206   virtual bool isCustomName() const { return !nameisgen; } //!< returns true if not using the generated name
00207 
00208   //! generates a description of the event with variable verbosity 
00209   /*! @param showTypeSpecific should be read by subclasses to add additional information
00210    *  @param verbosity can be one of the following values:
00211    *    - 0 - Basic: <i>event_name</i> \\t <i>generator_id</i> \\t <i>source_id</i> \\t <i>type_id</i>
00212    *    - 1 - Numerics: <i>event_name</i> \\t <i>generator_id</i> \\t <i>source_id</i> \\t <i>type_id</i>
00213    *    - 2 - Timing: <i>event_name</i> \\t <i>generator_id</i> \\t <i>source_id</i> \\t <i>type_id</i> \\t <i>duration</i> \\t <i>timestamp</i>
00214    *    - 3 and above - Full: <i>event_name</i> \\t <i>generator_id</i> \\t <i>source_id</i> \\t <i>type_id</i> \\t <i>duration</i> \\t <i>timestamp</i> \\t <i>magnitude</i>
00215    *  if showTypeSpecific, additional fields will be added after the common fields listed above. */
00216   virtual std::string getDescription(bool showTypeSpecific=true, unsigned int verbosity=0) const; 
00217 
00218   inline bool operator<(const EventBase& e) const { return timestamp<e.timestamp; }
00219 
00220   //! is true if the genID, typeID, and sourceID's all match
00221   virtual bool operator==(const EventBase& eb) const {
00222     return (sourceID==eb.sourceID && genID==eb.genID && typeID==eb.typeID);
00223   }
00224   //!tests to see if events have the same generator and source IDs
00225   bool sameGenSource(const EventBase& eb) const { return genID==eb.genID && sourceID==eb.sourceID; }
00226   
00227   bool longerThan(const EventBase& eb) const { return duration>eb.duration && *this==eb; } //!< compares event duration and ensures same event generator, source, and type - useful for event masks
00228   bool shorterThan(const EventBase& eb) const { return duration<eb.duration && *this==eb; }//!< compares event duration and ensures same event generator, source, and type - useful for event masks
00229   bool equalOrLongerThan(const EventBase& eb) const { return duration>=eb.duration && *this==eb; }//!< compares event duration and ensures same event generator, source, and type - useful for event masks
00230   bool equalOrShorterThan(const EventBase& eb) const { return duration<=eb.duration && *this==eb; }//!< compares event duration and ensures same event generator, source, and type - useful for event masks
00231   
00232   static bool isValidGeneratorID(unsigned int egid) { return egid<numEGIDs; }
00233   //@}
00234 
00235   //! Useful for serializing events to send between processes
00236   /*! @name LoadSave interface */
00237 
00238   //! All subclasses should override this and return a unique ID for their class.
00239   /*! All IDs corresponding to all-capital letters are reserved for future
00240    *  framework expansion.  (Thus, user subclasses should contain at least one
00241    *  lower-case letter.)  This code can be used when serializing to allow quick
00242    *  identification of the class type by the receiver. */
00243   virtual classTypeID_t getClassTypeID() const { return autoRegisterEventBase; }
00244 
00245   virtual unsigned int getBinSize() const; //!< should return the minimum size needed if using binary format (i.e. not XML)
00246   virtual unsigned int loadBinaryBuffer(const char buf[], unsigned int len); //!< load from binary format
00247   virtual unsigned int saveBinaryBuffer(char buf[], unsigned int len) const; //!< save to binary format
00248   virtual void loadXML(xmlNode* node); //!< load from XML format
00249   virtual void saveXML(xmlNode * node) const; //!< save to XML format
00250   
00251   //! no longer need to override this -- will automatically call either loadXML() or loadBinaryBuffer() based on #saveFormat
00252   /*! tries to be smart so if the load based on the current #saveFormat fails, retries with the alternative format */
00253   virtual unsigned int loadBuffer(const char buf[], unsigned int len, const char* filename=NULL)  {
00254     unsigned int test = saveFormat!=BINARY ? XMLLoadSave::loadBuffer(buf,len,filename) : loadBinaryBuffer(buf,len);
00255     if(test!=0) //if the default didn't work, try the other format too...
00256       return test;
00257     return saveFormat!=BINARY ? loadBinaryBuffer(buf,len) : XMLLoadSave::loadBuffer(buf,len,filename);
00258   }
00259   //! no longer need to override this -- will automatically call either saveXML() or saveBinaryBuffer() based on #saveFormat
00260   virtual unsigned int saveBuffer(char buf[], unsigned int len) const { return saveFormat!=BINARY ? XMLLoadSave::saveBuffer(buf,len) : saveBinaryBuffer(buf,len); }
00261 
00262   //! automatically calls either XMLLoadSave::loadFile or LoadSave::loadFile based on #saveFormat
00263   /*! tries to be smart so if the load based on the current #saveFormat fails, retries with the alternative format */
00264   virtual unsigned int loadFile(const char* filename) {
00265     unsigned int test = saveFormat!=BINARY ? XMLLoadSave::loadFile(filename) : LoadSave::loadFile(filename);
00266     if(test!=0) //if the default didn't work, try the other format too...
00267       return test;
00268     return saveFormat!=BINARY ? LoadSave::loadFile(filename) : XMLLoadSave::loadFile(filename);
00269   }
00270   //! automatically calls either XMLLoadSave::saveFile or LoadSave::saveFile based on #saveFormat
00271   virtual unsigned int saveFile(const char* filename) const { return saveFormat!=BINARY ? XMLLoadSave::saveFile(filename) : LoadSave::saveFile(filename); }
00272   
00273   //! automatically calls either XMLLoadSave::loadFileStream or LoadSave::loadFileStream based on #saveFormat
00274   virtual unsigned int loadFileStream(FILE* f, const char* filename=NULL) { return saveFormat!=BINARY ? XMLLoadSave::loadFileStream(f,filename) : LoadSave::loadFileStream(f,filename); }
00275   //! automatically calls either XMLLoadSave::loadFileStream or LoadSave::loadFileStream based on #saveFormat
00276   virtual unsigned int saveFileStream(FILE* f) const { return saveFormat!=BINARY ? XMLLoadSave::saveFileStream(f) : LoadSave::saveFileStream(f); }
00277   
00278   //! values to pass to setSaveFormat()
00279   enum SaveFormat {
00280     BINARY, //!< saves will be in packed binary, loads will try binary first
00281     XML //!< saves will be in xml, loads will try xml first
00282   };
00283   virtual void setSaveFormat(SaveFormat sf) const { saveFormat=sf; } //!< set #saveFormat
00284   virtual SaveFormat getSaveFormat() const { return saveFormat; } //!< return #saveFormat
00285   //@}
00286   
00287  protected:
00288   //! converts the first 4 characters of @a str to an unsigned int, should ensure consistent byte ordering across platforms
00289   static unsigned int makeClassTypeID(const char* str) {
00290 #if LOADSAVE_SWAPBYTES
00291     unsigned int x;
00292     byteswap(x,*reinterpret_cast<const unsigned int*>(str));
00293     return x;
00294 #else
00295     return *reinterpret_cast<const unsigned int*>(str);
00296 #endif
00297   }
00298 
00299   std::string stim_id; //!< the name of the event, use the same name consistently or else will be seen as different stimuli
00300   float magnitude; //!< the current "strength" of the event/stimuli... MAKE SURE this gets set to ZERO IF event is DEACTIVATE
00301   unsigned int timestamp; //!< the time the event was created - set automatically by constructor
00302 
00303   mutable SaveFormat saveFormat; //!< controls the format used during the next call to saveBuffer() (packed binary or XML)
00304 
00305   bool nameisgen; //!< tracks whether the current name (stim_id) was generated by genName() (true) or setName() (false)
00306   virtual void genName(); //!< calls setName() with a string version of sourceID, decimal notation
00307 
00308   EventGeneratorID_t genID; //!< generator ID, see EventGeneratorID_t
00309   EventTypeID_t typeID; //!< type ID, see EventTypeID_t
00310   size_t sourceID;       /*!< @brief the source ID for this event
00311                           * Source IDs are defined by the generator that made it.  This should
00312                           * give authors flexibility to design their modules without having to
00313                           * worry about ID space collision */
00314   int hostID;
00315   unsigned int duration; /*!< @brief the time since this sequence started (like, how long the
00316                           *   button has been pressed); not all generators will set this;
00317                           *   Typically, this would be 0 for activate,
00318                           *   (activate.timestamp-::get_time()) for status and deactivate */
00319 
00320   //! causes class type id to automatically be regsitered with EventBase's FamilyFactory (getTypeRegistry())
00321   static const EventBase::classTypeID_t autoRegisterEventBase;
00322 };
00323 
00324 /*! @file
00325  * @brief Describes EventBase, the basic class for sending events around the system
00326  * @author ejt (Creator)
00327  */
00328 
00329 #endif

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