00001 /*!@file Neuro/SaccadeControllers.H Derived classes 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/SaccadeControllers.H $ 00035 // $Id: SaccadeControllers.H 9412 2008-03-10 23:10:15Z farhan $ 00036 // 00037 00038 #ifndef SACCADECONTROLLERS_H_DEFINED 00039 #define SACCADECONTROLLERS_H_DEFINED 00040 00041 #include "Component/ModelParam.H" 00042 #include "Image/ArrayData.H" // for class Dims 00043 #include "Neuro/SaccadeController.H" 00044 #include "Util/SimTime.H" 00045 00046 #include <deque> 00047 #include <string> 00048 00049 class SpatialMetrics; 00050 00051 // ###################################################################### 00052 //! Stub saccade controller 00053 /*! No-op implementation -- never makes a decision (eye movement). */ 00054 00055 class StubSaccadeController : public SaccadeController 00056 { 00057 public: 00058 //! Constructor 00059 StubSaccadeController(OptionManager& mgr, const SaccadeBodyPart bodypart); 00060 00061 //! Destructor 00062 virtual ~StubSaccadeController(); 00063 00064 protected: 00065 //! evolve one time step 00066 virtual void doEvolve(SimEventQueue& q); 00067 00068 //! This method is called each time a new percept has arrived 00069 virtual void computeWhenNewPercept(SimEventQueue& q); 00070 00071 //! This method is called each time a reset is made 00072 virtual void computeWhenResetPos(SimEventQueue& q); 00073 00074 //! This method is called each time a new decision is requested 00075 virtual Point2D<int> computeWhenNewDecision(SaccadeState& sacstate, 00076 bool& blinkstate, SimEventQueue& q); 00077 }; 00078 00079 // ###################################################################### 00080 //! Trivial saccade controller 00081 /*! TrivialSaccadeController is a direct mapping from percept to decision. */ 00082 00083 class TrivialSaccadeController : public SaccadeController 00084 { 00085 public: 00086 //! Constructor 00087 TrivialSaccadeController(OptionManager& mgr, const SaccadeBodyPart bodypart); 00088 00089 //! Destructor 00090 virtual ~TrivialSaccadeController(); 00091 00092 protected: 00093 OModelParam<float> itsMinSacLen; //!< Minimum saccade len 00094 00095 //! evolve one time step 00096 virtual void doEvolve(SimEventQueue& q); 00097 00098 //! This method is called each time a new percept has arrived 00099 virtual void computeWhenNewPercept(SimEventQueue& q); 00100 00101 //! This method is called each time a reset is made 00102 virtual void computeWhenResetPos(SimEventQueue& q); 00103 00104 //! This method is called each time a new decision is requested 00105 virtual Point2D<int> computeWhenNewDecision(SaccadeState& sacstate, 00106 bool& blinkstate, SimEventQueue& q); 00107 }; 00108 00109 // ###################################################################### 00110 //! Fixed saccade controller 00111 /*! FixedSaccadeController holds fixation at a fixed point, ignoring 00112 its percepts. Useful to render the difference between covert and overt 00113 attention evident in the model. Also useful for creating foveated 00114 displays with fixed viewpoint. Like with all saccade controllers, the 00115 fixation point may externally be changed using resetPos(). */ 00116 00117 class FixedSaccadeController : public SaccadeController 00118 { 00119 public: 00120 //! Constructor 00121 FixedSaccadeController(OptionManager& mgr, const SaccadeBodyPart bodypart); 00122 00123 //! Destructor 00124 virtual ~FixedSaccadeController(); 00125 00126 protected: 00127 //! evolve one time step 00128 virtual void doEvolve(SimEventQueue& q); 00129 00130 //! This method is called each time a new percept has arrived 00131 virtual void computeWhenNewPercept(SimEventQueue& q); 00132 00133 //! This method is called each time a reset is made 00134 virtual void computeWhenResetPos(SimEventQueue& q); 00135 00136 //! This method is called each time a new decision is requested 00137 virtual Point2D<int> computeWhenNewDecision(SaccadeState& sacstate, 00138 bool& blinkstate, SimEventQueue& q); 00139 00140 private: 00141 Point2D<int> itsPos; 00142 }; 00143 00144 // ###################################################################### 00145 //! Friction-damped mass-spring saccade controller 00146 /*! FrictionSaccadeController acts like a mass (at saccade center) 00147 connected to the covert focus of attention through a spring of zero 00148 rest length, and sliding on a plane in the presence of friction. */ 00149 00150 class FrictionSaccadeController : public SaccadeController 00151 { 00152 public: 00153 //! Constructor 00154 /*! @param part As this controller may be used either for the eye or 00155 for the head (as part of bigger controllers that include both eye 00156 and head), this should be either SaccadeBodyPartEye or 00157 SaccadeBodyPartHead and will determine which model options we use 00158 for our internal parameters (eye or head) */ 00159 FrictionSaccadeController(OptionManager& mgr, 00160 const SaccadeBodyPart bodypart); 00161 00162 //! Destructor 00163 virtual ~FrictionSaccadeController(); 00164 00165 protected: 00166 friend class ThresholdFrictionSaccadeController; 00167 friend class MonkeySaccadeController; 00168 00169 OModelParam<double> itsSpringK; //!< spring stiffness 00170 OModelParam<double> itsFrictionMu; //!< friction coeff 00171 OModelParam<Dims> itsDims; //!< Image size so that we stay inside it 00172 OModelParam<SimTime> itsTimeStep; //!< Simulation time step 00173 00174 //! evolve one time step 00175 virtual void doEvolve(SimEventQueue& q); 00176 00177 //! This method is called each time a new percept has arrived 00178 virtual void computeWhenNewPercept(SimEventQueue& q); 00179 00180 //! This method is called each time a reset is made 00181 virtual void computeWhenResetPos(SimEventQueue& q); 00182 00183 //! This method is called each time a new decision is requested 00184 virtual Point2D<int> computeWhenNewDecision(SaccadeState& sacstate, 00185 bool& blinkstate, SimEventQueue& q); 00186 00187 private: 00188 double x, y, oldx, oldy; 00189 SimTime oldt; 00190 }; 00191 00192 // ###################################################################### 00193 //! Threshold-limited controller that eliminates small or unreliable shifts 00194 /*! ThresholdSaccadeController will issue an overt control whenever 00195 the received covert shifts are large and go to a same target for 00196 several successive covert shifts. It is hence to be used with IOR 00197 turned off, so that the covert system will keep attending to a same 00198 location for a while. Once a minimum number of covert shifts have 00199 been made that are sufficiently far from the current overt location 00200 and that are sufficiently close to each other, an overt shift will 00201 be issued, to the average location of the accumulated covert 00202 locations. */ 00203 00204 class ThresholdSaccadeController : public SaccadeController 00205 { 00206 public: 00207 //! Constructor 00208 /*! @param minovertdist minimum distance required to warrant an overt 00209 shift (in pixels at the original image's scale). 00210 @param maxcovertdist maximum distance to consider that two covert 00211 shifts point to the "same" location. 00212 @param minfix minimum number of covert shifts within maxcovertdist 00213 of each other and farther than minovertdist from the curent overt 00214 fixation, such as to warrant an overt shift. 00215 @param sweigh if true, average covert location is a weighted average 00216 with saliency values at the covert locations used as weights. Otherwise, 00217 the weight of each covert location is unity. */ 00218 00219 /*! @param part As this controller may be used either for the eye or 00220 for the head (as part of bigger controllers that include both 00221 eye and head), this should be either SaccadeBodyPartEye or 00222 SaccadeBodyPartHead and will determine which model options we 00223 use for our internal parameters (eye or head) */ 00224 ThresholdSaccadeController(OptionManager& mgr, 00225 const SaccadeBodyPart bodypart); 00226 00227 //! Destructor 00228 virtual ~ThresholdSaccadeController(); 00229 00230 //! Reset ThresholdSaccadeController 00231 /*! See the base function in ModelComponent.H for info. */ 00232 virtual void reset1(); 00233 00234 //! Check queued-up percepts and return average 00235 /*! check whether queued-up percepts are close to each other, and 00236 also return average position of percept queue */ 00237 virtual void checkPercepts(bool& areclose, Point2D<int>& avgp); 00238 00239 protected: 00240 friend class ThresholdFrictionSaccadeController; 00241 00242 //! evolve one time step 00243 virtual void doEvolve(SimEventQueue& q); 00244 00245 //! This method is called each time a new percept has arrived 00246 virtual void computeWhenNewPercept(SimEventQueue& q); 00247 00248 //! This method is called each time a reset is made 00249 virtual void computeWhenResetPos(SimEventQueue& q); 00250 00251 //! This method is called each time a new decision is requested 00252 virtual Point2D<int> computeWhenNewDecision(SaccadeState& sacstate, 00253 bool& blinkstate, SimEventQueue& q); 00254 00255 //! Get us started 00256 virtual void start1(); 00257 00258 OModelParam<float> itsOdist; //!< min overt distance 00259 OModelParam<float> itsCdist; //!< max covert distance 00260 OModelParam<int> itsMinNum; //!< min number of close covert shifts 00261 OModelParam<bool> itsSalWeight; //!< weight average covert pos by saliency 00262 00263 nub::ref<SpatialMetrics> itsMetrics; //!< metrics that depend on input size 00264 00265 float odistsq; // square of min overt distance 00266 float cdistsq; // square of max covert distance 00267 bool sweight; // use saliency as weight for average covert location 00268 bool didresetpos; // just did a resetPos 00269 Point2D<int> resetloc; // location of reset 00270 }; 00271 00272 // ###################################################################### 00273 //! Threshold-limited friction-damped controller 00274 /*! ThresholdFrictionSaccadeController combines the features of 00275 ThresholdSaccadeController and FrictionSaccadeController. 00276 00277 The ThresholdSaccadeController determines when a new saccade is 00278 warranted. The FrictionSaccadeController is fed with the average 00279 covert location over the duration of the percept queue of the 00280 Threshold controller. It then is responsible for inducing slow 00281 drifts of overt attention towards that average, in between two 00282 saccades. In addition, this controller will return to the center of 00283 the image if it does not move in some time. */ 00284 class ThresholdFrictionSaccadeController : public SaccadeController 00285 { 00286 public: 00287 //! Constructor 00288 /*! See the two base classes for parameters. 00289 00290 @param maxidle max time (in seconds) before we naturally return 00291 to the center of the image. This will happen if the covert 00292 shifts are so chaotic that we never decide to follow them 00293 overtly. 00294 00295 @param part As this controller may be used either for the eye or 00296 for the head (as part of bigger controllers that include both 00297 eye and head), this should be either SaccadeBodyPartEye or 00298 SaccadeBodyPartHead and will determine which model options we 00299 use for our internal parameters (eye or head) */ 00300 ThresholdFrictionSaccadeController(OptionManager& mgr, 00301 const SaccadeBodyPart bodypart); 00302 00303 //! Destructor 00304 virtual ~ThresholdFrictionSaccadeController(); 00305 00306 protected: 00307 //! evolve one time step 00308 virtual void doEvolve(SimEventQueue& q); 00309 00310 //! This method is called each time a new percept has arrived 00311 virtual void computeWhenNewPercept(SimEventQueue& q); 00312 00313 //! This method is called each time a reset is made 00314 virtual void computeWhenResetPos(SimEventQueue& q); 00315 00316 //! This method is called each time a new decision is requested 00317 virtual Point2D<int> computeWhenNewDecision(SaccadeState& sacstate, 00318 bool& blinkstate, SimEventQueue& q); 00319 00320 OModelParam<SimTime> itsMaxIdle; //!< max time (in s) before we return to IEP 00321 00322 private: 00323 nub::ref<SpatialMetrics> itsMetrics; 00324 nub::ref<ThresholdSaccadeController> tsc; 00325 nub::ref<FrictionSaccadeController> fsc; 00326 }; 00327 00328 00329 // ###################################################################### 00330 //! Realistic Monkey Eye or Head controller 00331 /*! This is part of an attempt at a simplified approach to the 00332 MonkeySaccadeCopntroller, which turned out quite complex because of 00333 the interdependency between head and eye movements. Here, we fake it 00334 by having independent controllers for the eyes and the head, such 00335 that we don't need to even deal with gaze stabilization during head 00336 movements and VOR. This controller will do either the head or the 00337 eye. For a controller that does both, see 00338 Monkey2SaccadeController. */ 00339 class MonkeySaccadeController : public SaccadeController 00340 { 00341 public: 00342 //! Constructor 00343 /*! Parameters are similar to the FrictionSaccadeController, plus 00344 @param part As this controller may be used either for the eye or 00345 for the head (as part of bigger controllers that include both 00346 eye and head), this should be either SaccadeBodyPartEye or 00347 SaccadeBodyPartHead and will determine which model options we 00348 use for our internal parameters (eye or head) */ 00349 MonkeySaccadeController(OptionManager& mgr, 00350 const SaccadeBodyPart bodypart); 00351 00352 //! Destructor 00353 ~MonkeySaccadeController(); 00354 00355 protected: 00356 //! evolve one time step 00357 virtual void doEvolve(SimEventQueue& q); 00358 00359 //! This method is called each time a new percept has arrived 00360 virtual void computeWhenNewPercept(SimEventQueue& q); 00361 00362 //! This method is called each time a reset is made 00363 virtual void computeWhenResetPos(SimEventQueue& q); 00364 00365 //! This method is called each time a new decision is requested 00366 virtual Point2D<int> computeWhenNewDecision(SaccadeState& sacstate, 00367 bool& blinkstate, SimEventQueue& q); 00368 00369 private: 00370 nub::ref<FrictionSaccadeController> fsc; 00371 nub::ref<SpatialMetrics> itsMetrics; // metrics that depend on input size 00372 double duration; // duration of realistic saccade 00373 SimTime oldt; // time of last call to evolve() 00374 SimTime startt; // time of start of realistic saccade 00375 double currx, curry; // current eye position 00376 double vmax; // max velocity 00377 double accel; // acceleration 00378 double theta; // angle of saccade 00379 }; 00380 00381 #endif 00382 00383 // ###################################################################### 00384 /* So things look consistent in everyone's emacs... */ 00385 /* Local Variables: */ 00386 /* indent-tabs-mode: nil */ 00387 /* End: */