LoSensorModel.C

Go to the documentation of this file.
00001 /**
00002    \file  Robots/LoBot/tti/LoSensorModel.C
00003    \brief This file defines the non-inline member functions of the
00004    lobot::SensorModel class.
00005 */
00006 
00007 // //////////////////////////////////////////////////////////////////// //
00008 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00009 // by the University of Southern California (USC) and the iLab at USC.  //
00010 // See http://iLab.usc.edu for information about this project.          //
00011 // //////////////////////////////////////////////////////////////////// //
00012 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00013 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00014 // in Visual Environments, and Applications'' by Christof Koch and      //
00015 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00016 // pending; application number 09/912,225 filed July 23, 2001; see      //
00017 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00018 // //////////////////////////////////////////////////////////////////// //
00019 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00020 //                                                                      //
00021 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00022 // redistribute it and/or modify it under the terms of the GNU General  //
00023 // Public License as published by the Free Software Foundation; either  //
00024 // version 2 of the License, or (at your option) any later version.     //
00025 //                                                                      //
00026 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00027 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00028 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00029 // PURPOSE.  See the GNU General Public License for more details.       //
00030 //                                                                      //
00031 // You should have received a copy of the GNU General Public License    //
00032 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00033 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00034 // Boston, MA 02111-1307 USA.                                           //
00035 // //////////////////////////////////////////////////////////////////// //
00036 //
00037 // Primary maintainer for this file: mviswana usc edu
00038 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Robots/LoBot/tti/LoSensorModel.C $
00039 // $Id: LoSensorModel.C 13120 2010-04-01 08:29:56Z mviswana $
00040 //
00041 
00042 //------------------------------ HEADERS --------------------------------
00043 
00044 // lobot headers
00045 #include "Robots/LoBot/tti/LoSensorModel.H"
00046 #include "Robots/LoBot/lgmd/gabbiani/LoGabbiani.H"
00047 #include "Robots/LoBot/config/LoConfigHelpers.H"
00048 #include "Robots/LoBot/util/LoMath.H"
00049 #include "Robots/LoBot/util/LoDebug.H"
00050 
00051 // Standard C++ headers
00052 #include <numeric>
00053 #include <algorithm>
00054 #include <functional>
00055 #include <iterator>
00056 
00057 //----------------------------- NAMESPACE -------------------------------
00058 
00059 namespace lobot {
00060 
00061 //--------------------------- LOCAL HELPERS -----------------------------
00062 
00063 // Retrieve settings from extricate section of config file
00064 template<typename T>
00065 static inline T conf(const std::string& key, const T& default_value)
00066 {
00067    return get_conf<T>("tti_estimator", key, default_value) ;
00068 }
00069 
00070 // Overload of above function for retrieving ranges
00071 template<typename T>
00072 static inline range<T>
00073 conf(const std::string& key, const range<T>& default_value)
00074 {
00075    return get_conf<T>("tti_estimator", key, default_value) ;
00076 }
00077 
00078 // Overload of above function for retrieving triples
00079 template<typename T>
00080 static inline triple<T, T, T>
00081 conf(const std::string& key, const triple<T, T, T>& default_value)
00082 {
00083    return get_conf<T>("tti_estimator", key, default_value) ;
00084 }
00085 
00086 //-------------------------- INITIALIZATION -----------------------------
00087 
00088 // The constructor uses the appropriate settings in the config file to
00089 // properly set up the sensor model for the specified "phase" of the LGMD
00090 // input signal.
00091 SensorModel::SensorModel(const std::string& lgmd_phase)
00092    : m_sigma(0.0f), m_name(lgmd_phase)
00093 {
00094    const range<float> lgmd_range =
00095       get_conf(locust_model(), "spike_range", make_range(0.0f, 800.0f)) ;
00096 
00097    // Get the LGMD ranges for the columns of the sensor model
00098    m_lgmd_ranges = string_to_deque<float>(
00099       conf<std::string>(lgmd_phase + "_lgmd_ranges", "0 800")) ;
00100    if (m_lgmd_ranges.size() < 2) { // crappy configuration!
00101       m_lgmd_ranges.clear() ;
00102       m_lgmd_ranges.push_back(lgmd_range.min()) ;
00103       m_lgmd_ranges.push_back(lgmd_range.max()) ;
00104    }
00105    sort(m_lgmd_ranges.begin(), m_lgmd_ranges.end()) ;
00106    if (m_lgmd_ranges.front() > lgmd_range.min())
00107       m_lgmd_ranges.push_front(lgmd_range.min()) ;
00108    if (m_lgmd_ranges.back() < lgmd_range.max())
00109       m_lgmd_ranges.push_back(lgmd_range.max()) ;
00110 
00111    // Figure out how many rows and columns the sensor model's probability
00112    // table has and allocate space for the required number of elements.
00113    // Initialize the probability table using a uniform distribution.
00114    const int C = m_lgmd_ranges.size() - 1 ;
00115    const int R = column_size() ;
00116    const int N = R * C ;
00117    m_prob.reserve(N) ;
00118    std::fill_n(std::back_inserter(m_prob), N, 1.0f/N) ;
00119 
00120    // Apply Gabbiani model to obtain causal probabilities and Gaussian
00121    // blur neighbouring bins in each row.
00122    update(clamp(conf(lgmd_phase + "_sigma", 1.0f),
00123                 0.1f, static_cast<float>(row_size()))) ;
00124 }
00125 
00126 // This method regenerates the sensor model's probabilities using the
00127 // Gabbiani LGMD model and the given standard deviation for the Gaussian
00128 // blurring operation for bins near the ones actually "pointed to" by the
00129 // [TTI, LGMD] pairs returned by the Gabbiani model.
00130 //
00131 // DEVNOTE: The sigma provided to this function is actually added to the
00132 // m_sigma member variable. This allows client behaviours to increment or
00133 // decrement the current sigma value rather than provide an actual sigma.
00134 // The very first sigma will be read from the config file (see
00135 // constructor).
00136 void SensorModel::update(float dsigma)
00137 {
00138    AutoMutex M(m_mutex) ;
00139 
00140    // Record new standard deviation
00141    const float R = row_size() ;
00142    m_sigma = clamp(m_sigma + dsigma, 0.1f, R) ;
00143 
00144    // Begin with a uniform distribution for each state
00145    const int N = m_prob.size() ;
00146    std::fill_n(m_prob.begin(), N, 1/R) ;
00147 
00148    // Apply Gabbiani LGMD model to generate causal likelihoods
00149    const float step = row_step()/4.0f ;
00150    const range<float> tti = conf(m_name + "_tti_range", Params::tti_range()) ;
00151    for (float t = tti.min(); t <= tti.max(); t += step)
00152       update_row(t, GabbianiModel::spike_rate(t), m_sigma) ;
00153 }
00154 
00155 // This function increments the bin "pointed" to by the given [TTI, LGMD]
00156 // pair. It also increments the other bins in the row "pointed" to by the
00157 // TTI using a Gaussian weighting formula to ensure that no bin in that
00158 // row has weird likelihood values that can screw up the Bayesian TTI
00159 // estimation. Finally, it normalizes the row to ensure that each row
00160 // vector is a valid probability distribution.
00161 void SensorModel::update_row(float tti, float lgmd, float sigma)
00162 {
00163    const int   N = row_size() ;
00164    const int   C = column_size() ;
00165    const int   I = col_index(lgmd) ;
00166    const float S = 1/(2 * sqr(sigma)) ;
00167 
00168    Table::iterator begin = m_prob.begin() + row_index(tti) ;
00169 
00170    float normalizer = 0 ;
00171    Table::iterator it = begin ;
00172    for (int i = 0; i < N; ++i, it += C) {
00173       *it += exp(-sqr(i - I) * S) ;
00174       //*it = exp(-sqr(i - I) * S) ;
00175       normalizer += *it ;
00176    }
00177 
00178    it = begin ;
00179    for (int i = 0; i < N; ++i, it += C)
00180       *it /= normalizer ;
00181 }
00182 
00183 //--------------------------- TABLE ACCESS ------------------------------
00184 
00185 // This function returns the index of the column in the sensor model's
00186 // probability table that corresponds to a given LGMD spike rate.
00187 int SensorModel::col_index(float lgmd) const
00188 {
00189    const int N = m_lgmd_ranges.size() - 1 ;
00190    for  (int i = 0; i < N; ++i)
00191       if (m_lgmd_ranges[i] <= lgmd && lgmd < m_lgmd_ranges[i + 1])
00192          return i ;
00193    return N - 1 ;
00194 }
00195 
00196 // Copy column vector specified by given LGMD value
00197 std::vector<float> SensorModel::column_vector(float lgmd) const
00198 {
00199    AutoMutex M(m_mutex) ;
00200    const int N = column_size() ;
00201    Table::const_iterator begin = m_prob.begin() + col_index(lgmd) * N ;
00202    return std::vector<float>(begin, begin + N) ;
00203 }
00204 
00205 // Copy entire probability table
00206 std::vector<float> SensorModel::table() const
00207 {
00208    AutoMutex M(m_mutex) ;
00209    return m_prob ;
00210 }
00211 
00212 //----------------------------- CLEAN-UP --------------------------------
00213 
00214 SensorModel::~SensorModel(){}
00215 
00216 //-------------------------- KNOB TWIDDLING -----------------------------
00217 
00218 // Parameters initialization
00219 SensorModel::Params::Params()
00220    : m_tti_discretization(conf("tti_discretization",
00221                                make_triple(0.0f, 10.0f, 0.1f))),
00222      m_tti_range(clamp(make_range(m_tti_discretization.first,
00223                                   m_tti_discretization.second),
00224                        make_range(0.0f, 1000.0f))),
00225      m_tti_step(clamp(m_tti_discretization.third, 0.001f, m_tti_range.max())),
00226      m_belief_size(round(m_tti_range.size()/m_tti_step))
00227 {}
00228 
00229 // Parameters clean-up
00230 SensorModel::Params::~Params(){}
00231 
00232 //-----------------------------------------------------------------------
00233 
00234 } // end of namespace encapsulating this file's definitions
00235 
00236 /* So things look consistent in everyone's emacs... */
00237 /* Local Variables: */
00238 /* indent-tabs-mode: nil */
00239 /* End: */
Generated on Sun May 8 08:41:31 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3