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/get_time.h"
00006 #include "Shared/XMLLoadSave.h"
00007 #include <string>
00008 
00009 //! The basis of events passed around the high level system
00010 /*! Contains the list of 'known' event generators in #EventGeneratorID_t
00011  *  and #EventGeneratorNames[].  If you want to make a new generator, all
00012  *  you have to do is add a new entry to the ID list (#EventGeneratorID_t)
00013  *  and then put its name in the #EventGeneratorNames[] array.
00014  *
00015  *  The #EventGeneratorID_t list should contain links to the
00016  *  generators' documentation, or will directly give information about
00017  *  what to expect in events from that generator.
00018  *  
00019  *  Alternatively, there is an 'unlicensed spectrum' available under
00020  *  the #unknownEGID.  You can send out events from that generator just
00021  *  like any other, but it should only be used for quick tests and hacking
00022  *  around...
00023  *
00024  *  The #sourceID (just an unsigned int) is generator specific.  A SID
00025  *  of @a i from the button generator (#buttonEGID) will refer to a
00026  *  particular button, whereas a SID from a vision detector (say
00027  *  #visObjEGID) refers to seeing a particular object.  These SIDs are
00028  *  usually defined in the generators themselves.
00029  *
00030  *  If more information needs to be sent along with the event, the
00031  *  cleanest solution is to create a subclass of EventBase to hold the
00032  *  additional information.  For example, you can see the existing
00033  *  subclasses in the inheritance diagram above.  If you want to use a
00034  *  quick hack however, you could assume the pointer size is the same
00035  *  as an unsigned int and just pass a pointer to data as the SID.
00036  *  Your funeral, err, I mean your call. ;)
00037  *
00038  *  The #duration field is also generator specific - some may refer to
00039  *  the time since the last activation event (e.g. button events)
00040  *  where as others refer to time since last status (e.g. sensors
00041  *  updates)
00042  *
00043  *  @note All subclasses must override getClassTypeID() and provide
00044  *  a unique value to allow fast serialization for inter-process
00045  *  communication.
00046  */
00047 class EventBase : public XMLLoadSave {
00048  public:
00049   //! Lists all possible event generator ids
00050   /*! An event generator is a abstract source of events, used for listening to and parsing certain classes of events
00051    *
00052    *  IF YOU ADD AN EVENT GENERATOR, DON'T FORGET TO NAME IT (EventBase::EventGeneratorNames, actual names are in EventBase.cc)*/
00053   enum EventGeneratorID_t {
00054     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
00055     aiEGID,           //!< not being used, yet (might use this when AI makes decisions?)
00056     audioEGID,        //!< Sends an event when a sound starts/ends playback, status events as chained sounds end; SID is SoundManager::Play_ID; duration is playtime
00057     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
00058     erouterEGID,      //!< Sends activate event on first listener, deactivate on last listener, and status on other listener changes.; SID is the generator ID affected
00059     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
00060     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...)
00061     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)
00062     micRawEGID,       //!< reserved for future use
00063     micFFTEGID,       //!< reserved for future use
00064     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
00065     powerEGID,        //!< Sends events for low power warnings, temperature, etc. see PowerSourceID::PowerSourceID_t
00066     sensorEGID,       //!< Sends a status event when new sensor readings are available. see SensorSourceID::SensorSourceID_t
00067     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
00068     stateTransitionEGID, //!< Sends an event each time a transition is triggered; SID is a pointer to the transition; type is always status, duration is always 0; guaranteed to occur immediately *before* the transition actually occurs
00069     textmsgEGID,      //!< Sends status events when a text msg is received on console; generated by the Controller, SID is always -1; durations is always 0 (see Controller for more information)
00070     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
00071     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)
00072     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
00073     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
00074     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
00075     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
00076     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
00077     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
00078     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
00079     wmVarEGID,        //!< Sends an event when a watched memory is changed; source id is pointer to WMEntry
00080     worldModelEGID,   //!< not being used, yet (for when objects are detected/lost?)
00081     numEGIDs          //!< the number of generators available
00082   };
00083 
00084   //! 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)
00085   static const char* const EventGeneratorNames[numEGIDs];
00086   
00087   //! 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)
00088   enum EventTypeID_t {
00089     activateETID,   //!< Start of an event sequence, e.g. button down
00090     statusETID,     //!< Indicates a value has changed, e.g. new sensor readings
00091     deactivateETID, //!< Last of a series of events, e.g. button up
00092     numETIDs        //!< the number of different event types
00093   };
00094   
00095   //! holds string versions of EventTypeID_t
00096   static const char* const EventTypeNames[numETIDs];
00097   
00098   //! holds abbreviated string versions of EventTypeID_t
00099   static const char* const EventTypeAbbr[numETIDs];
00100 
00101   /*! @name Constructors/Destructors */
00102   //! constructor
00103   /*! @see EventRouter::postEvent() */
00104   EventBase(); 
00105   EventBase(EventGeneratorID_t gid, unsigned int sid, EventTypeID_t tid, unsigned int dur=0);
00106   EventBase(EventGeneratorID_t gid, unsigned int sid, EventTypeID_t tid, unsigned int dur, const std::string& n);
00107   EventBase(EventGeneratorID_t gid, unsigned int sid, EventTypeID_t tid, unsigned int dur, const std::string& n, float mag);
00108   virtual ~EventBase() {} //!< destructor
00109 
00110   //! allows a copy to be made of an event, supporting polymorphism
00111   /*! Must be overridden by all subclasses to allow this to happen
00112    * 
00113    *  I would like to switch this over to the cloneable interface once
00114    *  the compiler gets updated out of the 3.3 branch... see
00115    *  Cloneable::clone() for a discussion of the issue and
00116    *  implementation notes. */
00117   virtual EventBase* clone() const { return new EventBase(*this); }
00118   //@}
00119 
00120   /*! @name Methods */
00121   virtual const std::string& getName() const { return stim_id; } //!< gets the name of the event - useful for debugging output, see also getDescription()
00122   virtual EventBase& setName(const std::string& n); //!< sets name to a given string, prevents overwriting by generated names
00123 
00124   virtual float getMagnitude() const { return magnitude; } //!< gets "strength" of event - by default 1 for activate and status events, 0 for deactivate events
00125   virtual EventBase& setMagnitude(float m) { magnitude=m; return *this; }//!< sets "strength" of event - you may want to override the default values (see getMagnitude())
00126 
00127   virtual unsigned int getTimeStamp() const { return timestamp; } //!< time event was created
00128 
00129   virtual EventGeneratorID_t getGeneratorID() const { return genID; } /*!< @brief gets the generator ID for this event @see EventGeneratorID_t */
00130   virtual EventBase& setGeneratorID(EventGeneratorID_t gid) { genID=gid; genName(); return *this; } /*!< @brief sets the generator ID for this event @see EventGeneratorID_t */
00131   
00132   virtual unsigned int getSourceID() const { return sourceID; } /*!< @brief gets the source ID for this event @see sourceID */
00133   virtual EventBase& setSourceID(unsigned int sid) { sourceID=sid; genName(); return *this; } /*!< @brief sets the source ID for this event @see sourceID */
00134   
00135   virtual EventTypeID_t getTypeID() const { return typeID; } /*!< @brief gets the type ID @see EventTypeID_t */
00136   virtual EventBase& setTypeID(EventTypeID_t tid) { typeID=tid; genName(); return *this; } /*!< @brief sets the type ID @see EventTypeID_t */
00137 
00138   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 */
00139   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 */
00140 
00141   virtual const std::string& resetName() { nameisgen=true; genName(); return stim_id; } //!< resets name to generated form, overwriting any previous name
00142   virtual bool isCustomName() const { return !nameisgen; } //!< returns true if not using the generated name
00143 
00144   //! generates a description of the event with variable verbosity 
00145   /*! @param showTypeSpecific should be read by subclasses to add additional information
00146    *  @param verbosity can be one of the following values:
00147    *    - 0 - Basic: <i>event_name</i> \\t <i>generator_id</i> \\t <i>source_id</i> \\t <i>type_id</i>
00148    *    - 1 - Numerics: <i>event_name</i> \\t <i>generator_id</i> \\t <i>source_id</i> \\t <i>type_id</i>
00149    *    - 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>
00150    *    - 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>
00151    *  if showTypeSpecific, additional fields will be added after the common fields listed above. */
00152   virtual std::string getDescription(bool showTypeSpecific=true, unsigned int verbosity=0) const; 
00153 
00154   inline bool operator<(const EventBase& e) const { return timestamp<e.timestamp; }
00155 
00156   //! is true if the genID, typeID, and sourceID's all match
00157   virtual bool operator==(const EventBase& eb) const {
00158     return (sourceID==eb.sourceID && genID==eb.genID && typeID==eb.typeID);
00159   }
00160   //!tests to see if events have the same generator and source IDs
00161   bool sameGenSource(const EventBase& eb) const { return genID==eb.genID && sourceID==eb.sourceID; }
00162   
00163   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
00164   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
00165   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
00166   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
00167   
00168   static bool isValidGeneratorID(unsigned int egid) { return egid<numEGIDs; }
00169   //@}
00170 
00171   //! Useful for serializing events to send between processes
00172   /*! @name LoadSave interface */
00173 
00174   //! All subclasses should override this and return a unique ID for their class.
00175   /*! All IDs corresponding to all-capital letters are reserved for future
00176    *  framework expansion.  (Thus, user subclasses should contain at least one
00177    *  lower-case letter.)  This code can be used when serializing to allow quick
00178    *  identification of the class type by the receiver. */
00179   virtual unsigned int getClassTypeID() const { return makeClassTypeID("BASE"); }
00180 
00181   virtual unsigned int getBinSize() const;
00182   virtual unsigned int LoadBinaryBuffer(const char buf[], unsigned int len);
00183   virtual unsigned int SaveBinaryBuffer(char buf[], unsigned int len) const;
00184   virtual void LoadXML(xmlNode* node);
00185   virtual void SaveXML(xmlNode * node) const;
00186 
00187   virtual unsigned int LoadBuffer(const char buf[], unsigned int len)  {
00188     unsigned int test = saveFormat!=BINARY ? XMLLoadSave::LoadBuffer(buf,len) : LoadBinaryBuffer(buf,len);
00189     if(test!=0) //if the default didn't work, try the other format too...
00190       return test;
00191     return saveFormat!=BINARY ? LoadBinaryBuffer(buf,len) : XMLLoadSave::LoadBuffer(buf,len);
00192   }
00193   virtual unsigned int SaveBuffer(char buf[], unsigned int len) const { return saveFormat!=BINARY ? XMLLoadSave::SaveBuffer(buf,len) : SaveBinaryBuffer(buf,len); }
00194 
00195   virtual unsigned int LoadFile(const char* filename) {
00196     unsigned int test = saveFormat!=BINARY ? XMLLoadSave::LoadFile(filename) : LoadSave::LoadFile(filename);
00197     if(test!=0) //if the default didn't work, try the other format too...
00198       return test;
00199     return saveFormat!=BINARY ? LoadSave::LoadFile(filename) : XMLLoadSave::LoadFile(filename);
00200   }
00201   virtual unsigned int SaveFile(const char* filename) const { return saveFormat!=BINARY ? XMLLoadSave::SaveFile(filename) : LoadSave::SaveFile(filename); }
00202   
00203   virtual unsigned int LoadFileStream(FILE* f) { return saveFormat!=BINARY ? XMLLoadSave::LoadFileStream(f) : LoadSave::LoadFileStream(f); }
00204   virtual unsigned int SaveFileStream(FILE* f) const { return saveFormat!=BINARY ? XMLLoadSave::SaveFileStream(f) : LoadSave::SaveFileStream(f); }
00205   
00206   //! values to pass to setSaveFormat()
00207   enum SaveFormat {
00208     BINARY, //!< saves will be in packed binary, loads will try binary first
00209     XML //!< saves will be in xml, loads will try xml first
00210   };
00211   virtual void setSaveFormat(SaveFormat sf) const { saveFormat=sf; } //!< set #saveFormat
00212   virtual SaveFormat getSaveFormat() const { return saveFormat; } //!< return #saveFormat
00213   //@}
00214   
00215  protected:
00216   //! converts the first 4 characters of @a str to an unsigned int, should ensure consistent byte ordering across platforms
00217   /*! The numeric value may differ between platforms, but it will be consistent
00218    *  with the IDs on that platform, which is the real key since we aren't doing
00219    *  math, just equality */
00220   static unsigned int makeClassTypeID(const char* str) { return *reinterpret_cast<const unsigned int*>(str); }
00221 
00222   std::string stim_id; //!< the name of the event, use the same name consistently or else will be seen as different stimuli
00223   float magnitude; //!< the current "strength" of the event/stimuli... MAKE SURE this gets set to ZERO IF event is DEACTIVATE
00224   unsigned int timestamp; //!< the time the event was created - set automatically by constructor
00225 
00226   mutable SaveFormat saveFormat; //!< controls the format used during the next call to SaveBuffer() (packed binary or XML)
00227 
00228   bool nameisgen; //!< tracks whether the current name (stim_id) was generated by genName() (true) or setName() (false)
00229   virtual void genName(); //!< calls setName() with a string version of sourceID, decimal notation
00230 
00231   EventGeneratorID_t genID; //!< generator ID, see EventGeneratorID_t
00232   EventTypeID_t typeID; //!< type ID, see EventTypeID_t
00233   unsigned int sourceID; /*!< @brief the source ID for this event
00234                           * Source IDs are defined by the generator that made it.  This should
00235                           * give authors flexibility to design their modules without having to
00236                           * worry about ID space collision */
00237   unsigned int duration; /*!< @brief the time since this sequence started (like, how long the
00238                           *   button has been pressed); not all generators will set this;
00239                           *   Typically, this would be 0 for activate,
00240                           *   (activate.timestamp-::get_time()) for status and deactivate */
00241 };
00242 
00243 /*! @file
00244  * @brief Describes EventBase, the basic class for sending events around the system
00245  * @author ejt (Creator)
00246  *
00247  * $Author: ejt $
00248  * $Name: tekkotsu-2_4_1 $
00249  * $Revision: 1.34 $
00250  * $State: Exp $
00251  * $Date: 2005/06/29 22:03:34 $
00252  */
00253 
00254 #endif

Tekkotsu v2.4.1
Generated Tue Aug 16 16:32:46 2005 by Doxygen 1.4.4