SaccadeController.H

Go to the documentation of this file.
00001 /*!@file Neuro/SaccadeController.H Base class for saccade generation */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2003   //
00005 // by the University of Southern California (USC) and the iLab at USC.  //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Laurent Itti <itti@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Neuro/SaccadeController.H $
00035 // $Id: SaccadeController.H 9412 2008-03-10 23:10:15Z farhan $
00036 //
00037 
00038 #ifndef SACCADECONTROLLER_H_DEFINED
00039 #define SACCADECONTROLLER_H_DEFINED
00040 
00041 #include "Component/ModelComponent.H"
00042 #include "Component/ModelParam.H"
00043 #include "Image/Point2DT.H"
00044 #include "Neuro/WTAwinner.H"
00045 #include "Neuro/SaccadeBodyPart.H"
00046 #include "Psycho/SaccadeState.H"
00047 #include "Simulation/SimModule.H"
00048 #include "Util/TransientStatus.H"
00049 #include <deque>
00050 
00051 //! A base class to implement saccade controllers
00052 /*! This base class handles the basic queuing of percepts and
00053 fixations. Typically, new percepts (e.g., winner-take-all winners over
00054 the saliency map) should be passed to the saccade controller using
00055 setPercept(). During normal evolution of a simulation, evolve() should
00056 be called at every time step, in a manner similar to that of Brain,
00057 WTA and SM. In order to obtain coordinates of saccade targets computed
00058 by this class, getDecision() should be called. It will return (-1, -1)
00059 if no new saccade target is decided (either because it cannot be
00060 decided, or because it is the same as the last valid returned
00061 one). So, saccading to and fixating a new target will yield one
00062 initial valid set of returned coordinates, followed by subsequent
00063 returns of (-1, -1) as long as fixation is to be held
00064 stationary. Derived classes should overload computeWhenNewPercept(),
00065 called each time a new percept has arrived, and
00066 computeWhenNewDecision(), called each time a new decision is
00067 requested. In addition, derived classes should usually overload
00068 doEvolve(), typically called at each time step during a simulation.
00069 See SaccadeControllers.H for examples of derived classes which
00070 actually implement saccadic control strategies. */
00071 
00072 class SaccadeController : public SimModule
00073 {
00074 public:
00075   //! Constructor
00076   /*! @param bodypart should be SaccadeBodyPartEye or SaccadeBodyPartHead
00077     @param percept_qlen length of the queue of accumulated percepts
00078     @param decision_qlen length of the queue of generated decisions */
00079   SaccadeController(OptionManager& mgr,
00080                     const std::string& descrName,
00081                     const std::string& tagName,
00082                     const SaccadeBodyPart bodypart,
00083                     const int percept_qlen,
00084                     const int decision_qlen);
00085 
00086   //! Destructor (virtual to ensure that derived classes correctly destroyed)
00087   virtual ~SaccadeController();
00088 
00089   //! evolve one time step (called, e.g., by Brain::evolve())
00090   /*! evolve() should be invoked by external callers to allow the
00091       internals of the controller to evolve as time passes by but no
00092       new percept is available. Derived classes should not override
00093       this function, but should instead override doEvolve(), which is
00094       called from inside evolve(). */
00095   void evolve(SimEventQueue& q);
00096 
00097   //! Receive a new percept (e.g., winner from saliency map)
00098   /*! This method should be invoked by external callers each time a
00099     new percept is available. Do not overload this method, overload
00100     computeWhenNewPercept() instead if you need to perform some
00101     computation for each new percept. */
00102   virtual void setPercept(const WTAwinner& fix, SimEventQueue& q);
00103 
00104   //! Reset to an externally-given position
00105   /*! This will force the current position to the position given as
00106     argument, disregarding any internal physical model. So this may be
00107     used to externally drive the SaccadeController to given
00108     locations. A percept will be queued up, which will be built from
00109     the passed position/time plus default values for the WTAwinner
00110     fields. Do not overload this method, overload computeWhenReset()
00111     instead. NOTE: this will abort any current blink and will reset
00112     our internal state to fixation (if p is valid) or unknown (if p is
00113     invalid). */
00114   virtual void resetPos(const Point2D<int>& p, SimEventQueue& q);
00115 
00116   //! Get the fixation decided by the controller
00117   /*! @param t should be the current time (in seconds) and should be
00118     greater than or equal to the time of the last percept passed to
00119     setPercept(). The coordinates of the decided fixation are returned
00120     (or (-1, -1) of no decision has been made). If a decision is made
00121     but is the same as the previous one, the behavior here is to
00122     return (-1, -1), and the caller has the responsibility of holding
00123     fixation until a new, valid decision can be reached. Do not
00124     overload this method, overload computeWhenNewDecision() instead if
00125     you need to do some computation before returning a fixation. If
00126     dopoststatus is true, we will post a SimEventStatus[Eye|Head] with
00127     our current status to the SimEventQueue. */
00128   virtual Point2D<int> getDecision(SimEventQueue& q,
00129                               const bool dopoststatus = false);
00130 
00131   //! Get a previous percept
00132   /*! This method allows one to access a previous percept passed
00133     through setPercept(), or (-1, -1) if no valid previous percept
00134     exists.
00135     @param index indicates which previous percept; a value of zero
00136     will return the last percept that was passed to setPercept(), and
00137     increasing values will return increasingly older percepts. If
00138     index is more than the queue length, (-1, -1) will be returned. */
00139   WTAwinner getPreviousPercept(const unsigned int index = 0) const;
00140 
00141   //! Do we already have any percepts queued up?
00142   bool havePercepts() const;
00143 
00144   //! Returns length of percept queue
00145   /*! Note that the queue may not be full to that length yet */
00146   int getPqlen() const;
00147 
00148   //! Reset length of percept queue (contents will be lost)
00149   void resetPqlen(const int len);
00150 
00151   //! Kill all previous percepts (empty the percept queue)
00152   void killPercepts();
00153 
00154   //! Get a previous decision
00155   /*! This method allows one to access a previous valid decision. It
00156     will not attempt to determine whether a new decision can be made
00157     now, like getDecision() does. It will simply return the result of
00158     what was previously decided (or (-1, -1) if no valid previous
00159     decision exists).
00160     @param index indicates which previous decision; a value of zero
00161     will return the last decision that was made and returned by
00162     getDecision(), and increasing values will return increasingly
00163     older decisions. if index is more than the queue length, (-1, -1)
00164     will be returned. */
00165   Point2DT getPreviousDecision(const unsigned int index = 0) const;
00166 
00167   //! Do we already have any decisions queued up?
00168   bool haveDecisions() const;
00169 
00170   //! Returns length of decision queue
00171   /*! Note that the queue may not be full to that length yet */
00172   int getDqlen() const;
00173 
00174   //! Reset length of decision queue (contents will be lost)
00175   void resetDqlen(const int len);
00176 
00177   //! Kill all previous decisions (empty the decision queue)
00178   void killDecisions();
00179 
00180   //! get our body part
00181   SaccadeBodyPart bodyPart() const;
00182 
00183    //! Show contents of the queues, for debugging
00184    void dumpQueues() const;
00185 
00186 protected:
00187   OModelParam<Point2D<int> > itsInitialPosition; //!< start position
00188 
00189   //! Reset SaccadeController
00190   virtual void reset1();
00191 
00192   //! Called from within evolve()
00193   /*! Classes deriving from SaccadeController should implement this. */
00194   virtual void doEvolve(SimEventQueue& q) = 0;
00195 
00196   //! This method is called each time a new percept has arrived
00197   /*! The latest percept is at the front of the percept queue. Derived
00198     classes must provide some implementation for this method, as it is
00199     called from within setPercept(). */
00200   virtual void computeWhenNewPercept(SimEventQueue& q) = 0;
00201 
00202   //! This method is called each time a reset() occurs
00203   /*! The reset location/time is at the front of the percept
00204     queue. Derived classes must provide some implementation for this
00205     method, as it is called from within resetPos().  NOTE: a
00206     resetPos(), even if it is to a location far away from the current
00207     one, should not create a saccade, because it is a way to break a
00208     simulation and reset it, not a way to drive saccades
00209     externally. Saccades should arise internally in
00210     computeWhenNewDecision(). You should not change the state here as
00211     resetPos() itself will change if to fixation or unknown anyway. */
00212   virtual void computeWhenResetPos(SimEventQueue& q) = 0;
00213 
00214   //! This method is called each time a new decision is requested
00215   /*! The latest percept is at the front of the percept queue, and the
00216     latest previous decision at the front of the decision queue. The
00217     method should return the decision to be taken given the time
00218     passed as argument. This method should return the current decision
00219     for fixation, as well as current saccade and blink states. The
00220     wrapping getDecision() call will take care of eliminating
00221     decisions that are the same as the previous ones.  Derived classes
00222     must provide some implementation for this method, as it is called
00223     from within getDecision(). */
00224   virtual Point2D<int> computeWhenNewDecision(SaccadeState& sacstate,
00225                                          bool& blinkstate,
00226                                          SimEventQueue& q) = 0;
00227 
00228   //! Helper for derived classes to get our internal saccade/fix/smooth state
00229   SaccadeState getState() const;
00230 
00231   //! Helper for derived classes to get our internal blink state
00232   bool getBlinkState() const;
00233 
00234 private:
00235   std::deque<WTAwinner> percept; // queue of accumulated percepts; front=latest
00236   std::deque<Point2DT> decision; // queue of accumulated decisions;front=latest
00237   unsigned int pqlen, dqlen;     // size of percept & decisioon queues
00238   SaccadeState itsState;         // our saccade/fix/smooth/etc state
00239   SaccadeState itsPrevState;     // state before last evolve()
00240   bool itsBlinkState;            // blink state
00241   bool itsPrevBlinkState;        // previous blink state
00242   SaccadeBodyPart itsBodyPart;   // are we eye or head?
00243 };
00244 
00245 // ######################################################################
00246 /* So things look consistent in everyone's emacs... */
00247 /* Local Variables: */
00248 /* indent-tabs-mode: nil */
00249 /* End: */
00250 #endif
Generated on Sun May 8 08:41:03 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3