Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

DataSource.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_DataSource_h_
00003 #define INCLUDED_DataSource_h_
00004 
00005 #include <string>
00006 #include <iostream>
00007 
00008 /* Usage cases:
00009 
00010 Pulled (on demand):
00011   block with timeout: save bandwidth, accept latency -- load only after last was read and framerate delay
00012   sleep: minimize latency, waste bandwidth -- send requests at framerate
00013 Pushed (sent by source):
00014   block (no timeout): when new data arrives, insert into queue (might overwrite last queue slot)
00015   sleep: can't block, have to poll at framerate
00016 */
00017 
00018 class LoadDataThread;
00019 
00020 //! abstract base class for simulator data sources
00021 /*! Each subclass will implement loading data from some piece of hardware or network protocol.  This class
00022  *  is expected to be tied to a LoadDataThread (or subclass) which holds configuration settings which might
00023  *  be shared by multiple data sources, in particular LoadDataThread::src.
00024  *
00025  *  Ideally, getData() should return the most recent unprocessed data -- meaning that if you are pulling
00026  *  from a realtime source like a network stream, if multiple frames have arrived since the last call to
00027  *  getData(), you should return the most recent frame of the bunch.
00028  *
00029  *  If your data source provides sensor data including current output values, you should call
00030  *  providingOutput() for those outputs when you start being used by a LoadDataThread
00031  *  (e.g. setDataSourceThread() is called), and ignoringOutput() when you are no longer active
00032  *  (e.g. setDataSourceThread() is called with NULL).  This prevents the Motion process from
00033  *  clobbering your readings with its own feedback.
00034  */
00035 class DataSource {
00036 public:
00037   DataSource() : frozen(true), framerate(-1), verbose(0), thread(NULL) {} //!< constructor
00038   DataSource(const DataSource& ds) : frozen(ds.frozen), framerate(ds.framerate), verbose(ds.verbose), thread(NULL) {} //!< copy constructor, just in case your subclass wants it
00039   DataSource& operator=(const DataSource&) { return *this; } //!< assignment operator, just in case your subclass wants it
00040   virtual ~DataSource() {} //!< destructor
00041 
00042   //! returns the simulator time of the next data segment
00043   /*! should be in the future if nothing new since last data segment, otherwise should be the 
00044    *  timestamp of the most recent data segment (older segments are skipped), return -1U if there is no more data
00045    *  @see timestamp argument of getData() */
00046   virtual unsigned int nextTimestamp()=0;
00047   
00048   //! returns a descriptive name of the next data segment for user feedback
00049   /*! @see name argument of getData() */
00050   virtual const std::string& nextName()=0;
00051   
00052   //! called to retrieve the most recent data segment, or blocking until new data is available
00053   /*! @param[out] payload on return, should point to beginning of data segment, or NULL if none available
00054    *  @param[out] payloadSize on return, should indicate size in bytes of data segment as @a payload
00055    *  @param[in] timestamp the suggested return time; if multiple samples may be taken in the interval, they should be skipped until this time
00056    *  @param[out] timestamp on return, should contain the time at which the data arrived (real time stream) or was scheduled to be sent (log on disk)
00057    *  @param[out] name on return, a human-readable name for the frame -- e.g. filename for a data file loaded from disk
00058    *  @return frame serial number, used to tell when frames from the data source have been dropped (indicated by the return value incrementing by more than one)
00059    *
00060    *  If no more data is available, set payload to NULL, and return the current frame (i.e. don't increment serial number).
00061    *
00062    * This call <b>should block</b> until data is available.  Other functions may be called
00063    * asynchronously from other threads while in this function, see ThreadNS::Lock to implement
00064    * mutual exclusion locks if needed.
00065    *
00066    * The input value of @a timestamp is a suggestion from the user's requested framerate -- try
00067    * to return the frame closest to it.  If it is already past (e.g. 0 on 'advance'), return the current data!
00068    * If you return a timestamp in the future, the LoadDataThread will sleep until the appropriate time.
00069    * 
00070    * Note that this can be called when the source is frozen, which means you should unfreeze,
00071    * get the current (unread) data or block until the next data, freeze again, and return the data.  */
00072   virtual unsigned int getData(const char *& payload, unsigned int& payloadSize, unsigned int& timestamp, std::string& name)=0;
00073   
00074   //! called by simulator when the data source's activity changes; calls doFreeze() or doUnfreeze() as appropriate
00075   /*! You probably don't want to override this function -- that's what doFreeze() doUnfreeze are for! */
00076   virtual void setFrozen(bool fr) { if(fr==frozen) return; if((frozen=fr)) doFreeze(); else doUnfreeze(); }
00077   virtual bool getFrozen() const { return frozen; } //!< returns #frozen status
00078   
00079   //! if called, indicates a request to restart/reinitialize the data source
00080   /*! For example, a FileSystemDataSource would go back to the beginning of its list,
00081    *  and a network-based source would close and reopen the connection */
00082   virtual void reset() {}
00083   
00084   //! called by the LoadDataThread subclass, allows you to register for properties which your subclass may care about
00085   /*! a pointer to the LoadDataThread is passed when this is becoming the current data source;
00086    *  NULL will be passed when the data source is no longer being used */
00087   virtual void setDataSourceThread(LoadDataThread* th) { thread=th; }
00088   //! returns the LoadDataThread using this data source
00089   virtual LoadDataThread* getDataSourceThread() const { return thread; }
00090   
00091   virtual void setDataSourceFramerate(float fr) { framerate=fr; } //!< called by LoadDataThread whenever the expected framerate changes (LoadDataThread::framerate)
00092   virtual void setDataSourceVerbose(int v) { verbose=v; } //!< called by LoadDataThread whenever the requested verbosity level changes (LoadDataThread::verbosity)
00093   
00094   //! Called by simulator during initialization to tell DataSources where the array of output reference counts are stored (see #providedOutputs)
00095   /*! This would need to point into a shared memory region if using multi-process model, hence we can't just
00096    *  use process-local static allocation. */
00097   static void setOutputTracker(unsigned int outputs[]) { providedOutputs=outputs; }
00098   
00099   //! will be called by initialization code prior to first getData() if client code is going to block on getting the first sensor reading
00100   static void setNeedsSensor(bool waiting) { requiresFirstSensor=waiting; }
00101   
00102 protected:
00103   //! subclasses should call this if they provide sensor updates which will contain a measurement of the current position of output @a i.
00104   /* A DataSource should consider itself providing an output if it will be sending some kind of measurement of
00105    *  the current value of an output, and has been assigned to a LoadDataThread
00106    *  (i.e. setDataSourceThread() has been called and #thread is non-NULL).\n
00107    *  This prevents the motion process from clobbering your readings with its own feedback.  */
00108   static void providingOutput(unsigned int i) {
00109     if(providedOutputs==NULL) {
00110       std::cerr << "Warning: unable to access DataSource::providedOutputs (NULL) +" << i << std::endl;
00111       return;
00112     }
00113     providedOutputs[i]++;
00114   }
00115   //! subclasses should call this if they used to, but will no longer, provide sensor updates containing the current position of output @a i.
00116   /*! You don't need to call this if you didn't previously call providingOutput(). */
00117   static void ignoringOutput(unsigned int i) {
00118     if(providedOutputs==NULL) {
00119       std::cerr << "Warning: unable to access DataSource::providedOutputs (NULL) -" << i << std::endl;
00120       return;
00121     }
00122     if(providedOutputs[i]==0) {
00123       std::cerr << "ERROR: DataSource output tracking underflow (" << __FILE__ << ":" << __LINE__ << ")" << std::endl;
00124       return;
00125     }
00126     providedOutputs[i]--;
00127   }
00128 
00129   virtual void doFreeze() {} //!< user hook for when #frozen is set to true
00130   virtual void doUnfreeze() {} //!< user hook for when #frozen is set to false
00131   
00132   bool frozen;  //!< indicates that data is going to be requested "sparsely"; logged data sources should not increment with time
00133   float framerate;
00134   int verbose;
00135   LoadDataThread* thread; //!< stores last call to setParent()
00136 
00137   //! if true, indicates that client code is going to wait for sensor readings returned by getData before executing
00138   /*! Allocation defined in LoadDataThread.cc */
00139   static bool requiresFirstSensor;
00140 
00141 private:
00142   //! The counts of which outputs are being provided are used so the motion process can tell if it needs to provide feedback.
00143   /*! Subclasses should call providingOutput() and ignoringOutput() when they start and stop providing an output.
00144    *  A DataSource should consider itself providing an output if it will be sending some kind of measurement of
00145    *  the current value of an output, and has been assigned to a LoadDataThread
00146    *  (i.e. setDataSourceThread() has been called and #thread is non-NULL).
00147    *
00148    *  Allocation is found in LoadDataThread.cc to avoid file clutter (no other need for a DataSource.cc) */
00149   static unsigned int * providedOutputs;
00150 };
00151 
00152 /*! @file
00153  * @brief Defines DataSource, an abstract base class for simulator data sources
00154  * @author Ethan Tira-Thompson (ejt) (Creator)
00155  *
00156  * $Author: ejt $
00157  * $Name: tekkotsu-4_0 $
00158  * $Revision: 1.8 $
00159  * $State: Exp $
00160  * $Date: 2007/07/24 03:46:35 $
00161  */
00162 
00163 #endif

Tekkotsu Hardware Abstraction Layer 4.0
Generated Thu Nov 22 01:00:53 2007 by Doxygen 1.5.4