00001 /*! 00002 \file Robots/LoBot/lgmd/gabbiani/LoGabbiani.C 00003 \brief Gabbiani's LGMD model. 00004 */ 00005 00006 // //////////////////////////////////////////////////////////////////// // 00007 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00008 // by the University of Southern California (USC) and the iLab at USC. // 00009 // See http://iLab.usc.edu for information about this project. // 00010 // //////////////////////////////////////////////////////////////////// // 00011 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00012 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00013 // in Visual Environments, and Applications'' by Christof Koch and // 00014 // Laurent Itti, California Institute of Technology, 2001 (patent // 00015 // pending; application number 09/912,225 filed July 23, 2001; see // 00016 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00017 // //////////////////////////////////////////////////////////////////// // 00018 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00019 // // 00020 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00021 // redistribute it and/or modify it under the terms of the GNU General // 00022 // Public License as published by the Free Software Foundation; either // 00023 // version 2 of the License, or (at your option) any later version. // 00024 // // 00025 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00026 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00027 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00028 // PURPOSE. See the GNU General Public License for more details. // 00029 // // 00030 // You should have received a copy of the GNU General Public License // 00031 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00032 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00033 // Boston, MA 02111-1307 USA. // 00034 // //////////////////////////////////////////////////////////////////// // 00035 // 00036 // Primary maintainer for this file: mviswana usc edu 00037 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Robots/LoBot/lgmd/gabbiani/LoGabbiani.C $ 00038 // $Id: LoGabbiani.C 13730 2010-07-29 12:26:38Z mviswana $ 00039 // 00040 00041 //------------------------------ HEADERS -------------------------------- 00042 00043 // lobot headers 00044 #include "Robots/LoBot/lgmd/gabbiani/LoGabbiani.H" 00045 00046 #include "Robots/LoBot/LoApp.H" 00047 #include "Robots/LoBot/io/LoRobot.H" 00048 00049 #include "Robots/LoBot/config/LoConfigHelpers.H" 00050 #include "Robots/LoBot/config/LoDefaults.H" 00051 00052 #include "Robots/LoBot/misc/LoVector.H" 00053 #include "Robots/LoBot/misc/LoExcept.H" 00054 #include "Robots/LoBot/misc/LoRegistry.H" 00055 #include "Robots/LoBot/misc/factory.hh" 00056 #include "Robots/LoBot/util/LoMath.H" 00057 00058 // Standard C++ headers 00059 #include <utility> 00060 00061 // Standard C headers 00062 #include <math.h> 00063 00064 //----------------------------- NAMESPACE ------------------------------- 00065 00066 namespace lobot { 00067 00068 //-------------------------- INITIALIZATION ----------------------------- 00069 00070 GabbianiModel::GabbianiModel(const LocustModel::InitParams& p) 00071 : base(p) 00072 { 00073 if (! App::lrf()) 00074 throw io_error(LASER_RANGE_FINDER_MISSING) ; 00075 if (! App::robot()) 00076 throw io_error(MOTOR_SYSTEM_MISSING) ; 00077 } 00078 00079 //------------------------- LGMD COMPUTATIONS --------------------------- 00080 00081 // This helper function projects the robot's current velocity vector 00082 // along the specified direction and then returns the magnitude of the 00083 // resulting vector, i.e., the speed along the input direction. 00084 static float project_velocity(float direction) 00085 { 00086 float S = App::robot()->current_speed() ; 00087 float H = App::robot()->current_heading() ; 00088 00089 Vector v(S * cos(H), S * sin(H)) ; 00090 Vector d(cos(direction), sin(direction)) ; 00091 00092 float D = dot(d, v) ; 00093 return sign(D) * magnitude(D * d) ; 00094 } 00095 00096 // This method applies the Gabbiani LGMD model to determine the current 00097 // spike rate for this virtual locust. 00098 void GabbianiModel::update() 00099 { 00100 float speed = project_velocity(m_direction) ; 00101 if (is_zero(speed)) 00102 { 00103 update_lgmd(0) ; 00104 m_distance = m_tti = -1 ; 00105 } 00106 else 00107 { 00108 m_distance = m_source->average_distance(m_lrf_range) ; 00109 float dist = m_distance/1000.0f ; 00110 float time = dist/speed ; 00111 update_lgmd(spike_rate(time)) ; 00112 m_tti = abs(time) ; 00113 //LERROR("%6.3f m/s, %6.3f m, %6.3f s, %8.3f spikes/s", 00114 //speed, dist, m_tti, get_lgmd()) ; 00115 } 00116 //LERROR("locust[%4.0f] = %8.3f spikes/second", m_direction, get_lgmd()) ; 00117 } 00118 00119 /* 00120 Once we have an estimate of the time-to-impact t, we can determine the 00121 LGMD spike rate by applying the equations that Gabbiani, et al. 00122 developed to fit the electrophysiological data they gathered: 00123 00124 00125 f(t) = C * abs(D(t-d)) * exp(-a * T(t-d)) 00126 00127 where f(t) = the desired spike rate 00128 00129 -(l/v) 00130 D(t) = ------------- [aka theta_dot] 00131 t^2 + (l/v)^2 00132 00133 (l/v) 00134 T(t) = 2 * arctan----- [aka theta] 00135 t 00136 00137 C = a proportionality constant 00138 a = a parameter (alpha) 00139 d = a parameter (delta) 00140 l/v = a parameter (the famous ell-over-vee) 00141 00142 00143 This function applies the above multiplicative model of the LGMD to 00144 the supplied time-to-impact and returns the resulting spike rate. 00145 */ 00146 float GabbianiModel::spike_rate(float t) 00147 { 00148 const float C = Params::C() ; 00149 const float alpha = Params::alpha() ; 00150 const float delta = Params::delta() ; 00151 const float l_over_v = Params::l_over_v() ; 00152 00153 t -= delta ; 00154 float theta = -l_over_v/(sqr(t) + sqr(l_over_v)) ; 00155 float theta_dot = 2 * atanf(l_over_v/t) ; 00156 float lgmd_ideal = C * abs(theta_dot) * exp(-alpha * theta) ; 00157 00158 const float sigma = Params::sigma() ; 00159 return is_zero(sigma) ? lgmd_ideal //no noise 00160 : lgmd_ideal + sample_tri(sigma) ; 00161 } 00162 00163 //----------------------------- CLEAN-UP -------------------------------- 00164 00165 GabbianiModel::~GabbianiModel(){} 00166 00167 //-------------------------- KNOB TWIDDLING ----------------------------- 00168 00169 // Quick helper to retrieve configuration settings from the gabbiani 00170 // section of the config file. 00171 template<typename T> 00172 static T conf(const std::string& key, const T& default_value) 00173 { 00174 return get_conf<T>(LOLM_GABBIANI, key, default_value) ; 00175 } 00176 00177 // Parameters initialization 00178 GabbianiModel::Params::Params() 00179 : m_C(conf("C", 150)), 00180 m_alpha(conf("alpha", 0.75f)), 00181 m_delta(conf("delta", 2.5f)), 00182 m_l_over_v(conf("l_over_v", 1.5f)), 00183 m_sigma(clamp(conf("sigma", 0.0f), 0.0f, 200.0f)) 00184 {} 00185 00186 // Parameters clean-up 00187 GabbianiModel::Params::~Params(){} 00188 00189 //----------------------------------------------------------------------- 00190 00191 } // end of namespace encapsulating this file's definitions 00192 00193 /* So things look consistent in everyone's emacs... */ 00194 /* Local Variables: */ 00195 /* indent-tabs-mode: nil */ 00196 /* End: */