LoSensorModel.H

Go to the documentation of this file.
00001 /**
00002    \file  Robots/LoBot/tti/LoSensorModel.H
00003    \brief A data structure encapsulating the sensor model for Bayesian
00004    TTI estimation.
00005 
00006    This file defines a class that encapsulates the sensor model required
00007    to make Bayesian time-to-impact estimation work. This sensor model is
00008    basically a table of probabilities that describe the causal data,
00009    i.e., P(lgmd|tti), or, the likelihoods of seeing different LGMD values
00010    given different TTI values.
00011 
00012    The columns of the table discretize the LGMD "space" and its rows
00013    discretize the TTI "space." The Bayes filter works by using the column
00014    vector of the sensor model corresponding to the latest LGMD value as
00015    the P(lgmd|tti) term in the update equation.
00016 
00017    The sensor model's probabilities are generated by applying the
00018    Gabbiani LGMD model on each discretized TTI value to get the
00019    corresponding LGMD spike rate. These [TTI, LGMD] pairs are then used
00020    to find the correct bin in the table and increment it. To ensure that
00021    we don't have zeros in any bin, the remaining bins in the column
00022    corresponding to the generated LGMD value are also incremented
00023    according to a Gaussian weighting formula.
00024 */
00025 
00026 // //////////////////////////////////////////////////////////////////// //
00027 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00028 // by the University of Southern California (USC) and the iLab at USC.  //
00029 // See http://iLab.usc.edu for information about this project.          //
00030 // //////////////////////////////////////////////////////////////////// //
00031 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00032 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00033 // in Visual Environments, and Applications'' by Christof Koch and      //
00034 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00035 // pending; application number 09/912,225 filed July 23, 2001; see      //
00036 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00037 // //////////////////////////////////////////////////////////////////// //
00038 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00039 //                                                                      //
00040 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00041 // redistribute it and/or modify it under the terms of the GNU General  //
00042 // Public License as published by the Free Software Foundation; either  //
00043 // version 2 of the License, or (at your option) any later version.     //
00044 //                                                                      //
00045 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00046 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00047 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00048 // PURPOSE.  See the GNU General Public License for more details.       //
00049 //                                                                      //
00050 // You should have received a copy of the GNU General Public License    //
00051 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00052 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00053 // Boston, MA 02111-1307 USA.                                           //
00054 // //////////////////////////////////////////////////////////////////// //
00055 //
00056 // Primary maintainer for this file: mviswana usc edu
00057 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Robots/LoBot/tti/LoSensorModel.H $
00058 // $Id: LoSensorModel.H 13521 2010-06-06 14:23:03Z mviswana $
00059 //
00060 
00061 #ifndef LOBOT_SENSOR_MODEL_DOT_H
00062 #define LOBOT_SENSOR_MODEL_DOT_H
00063 
00064 //------------------------------ HEADERS --------------------------------
00065 
00066 // lobot headers
00067 #include "Robots/LoBot/thread/LoMutex.H"
00068 #include "Robots/LoBot/misc/singleton.hh"
00069 #include "Robots/LoBot/util/range.hh"
00070 #include "Robots/LoBot/util/triple.hh"
00071 
00072 // Standard C++ headers
00073 #include <string>
00074 #include <deque>
00075 #include <vector>
00076 
00077 //----------------------------- NAMESPACE -------------------------------
00078 
00079 namespace lobot {
00080 
00081 //------------------------- CLASS DEFINITION ----------------------------
00082 
00083 /**
00084    \class lobot::SensorModel
00085 
00086    \brief Data structure encapsulating sensor model required for Bayesian
00087    time-to-impact state estimation.
00088 
00089    This class implements a two-dimensional array (i.e., a table)
00090    containing P(lgmd|tti) probability values. The columns of this table
00091    correspond to different LGMD ranges; its rows to different TTI states.
00092    The array is stored in a single-dimensional array in column-major
00093    order.
00094 */
00095 class SensorModel {
00096    // Prevent copy and assignment
00097    SensorModel(const SensorModel&) ;
00098    SensorModel& operator=(const SensorModel&) ;
00099 
00100    /// The basic idea behind any sort of Bayesian state estimation is to
00101    /// determine P(x|z), i.e., the likelihood of being in state x given a
00102    /// measurement z. For this to work, we will need a sensor model,
00103    /// viz., a table containing P(z|x), i.e., the likelihood of seeing a
00104    /// measurement z given that the system is in state x.
00105    ///
00106    /// The columns of the sensor model's probability table denote the
00107    /// different ranges of values for sensor measurements. For
00108    /// Robolocust, the sensor measurements are LGMD spike rates. Thus,
00109    /// the columns of the sensor model table will be LGMD spike rate
00110    /// ranges. These ranges are read from the config file and mapped to
00111    /// column indices using a simple linear search through the range
00112    /// boundaries.
00113    ///
00114    /// For example, let's say the user configures Robolocust to use LGMD
00115    /// ranges 0, 250, 400, 600. The m_lgmd_ranges member variable will be
00116    /// a list of these numbers. There will be three LGMD ranges, viz.,
00117    /// [0, 250), [250, 400) and [400, 600]. LGMD values in the range [0,
00118    /// 250) will correspond to the first column in the sensor model
00119    /// probability table; LGMD values in [250, 400) will pick the second
00120    /// column; and LGMD values in [400, 600] will pick the probability
00121    /// table's third column.
00122    std::deque<float> m_lgmd_ranges ;
00123 
00124    /// As mentioned above, for the Bayesian time-to-impact estimation to
00125    /// work, we need a table containing P(lgmd|tti) values. This table is
00126    /// considered to be a collection of column vectors. Each column
00127    /// contains the so-called causal probabilities for some range of
00128    /// sensor (LGMD) values.
00129    ///
00130    /// The size of each column vector will be the same as the size of the
00131    /// posterior probability distribution, which depends on how the TTI
00132    /// space has been discretized. For instance, if the TTI range is [0,
00133    /// 3] and the discretization step size is 0.1 seconds, then the TTI
00134    /// belief consists of a distribution containing 30 probabilities.
00135    /// Therefore, the size of each column vector in the sensor model must
00136    /// also be 30 elements.
00137    ///
00138    /// This data structure is used to represent the sensor model, viz., a
00139    /// table of probabilities stored in a single-dimensional array in
00140    /// column-major order.
00141    //@{
00142    typedef std::vector<float> Table ;
00143    Table m_prob ;
00144    //@}
00145 
00146    /// The sensor model's probability table's column vectors have to be
00147    /// combined with the current TTI belief in each iteration of the
00148    /// Bayes filter. To ensure that the filter works reasonably well
00149    /// without entering pathological conditions, the sensor model's
00150    /// column vectors should avoid having zero probabilities (extremely
00151    /// low likelihoods can also cause trouble due to numerical
00152    /// instabilities).
00153    ///
00154    /// Thus, during initialization, when we apply the Gabbiani model to
00155    /// obtain [TTI, LGMD] pairs that point to bins in the probability
00156    /// table that should be incremented, we should also update the other
00157    /// bins in the columns pointed to by each of the generated LGMD
00158    /// values by some amount. The nearby bins' increment factors are
00159    /// obtained using a Gaussian weighting formula.
00160    ///
00161    /// This data member stores the standard deviation of the
00162    /// above-mentioned Gaussian weighting formula.
00163    float m_sigma ;
00164 
00165    /// The LGMD spikes with increasing frequency as objects approach and
00166    /// then, right before collision, it reaches a peak and experiences a
00167    /// rapid die-off. Therefore, we can divide the LGMD's spike rate
00168    /// curve into two distinct phases, viz., LOOMING and BLANKING.
00169    ///
00170    /// It is best to have different sensor model corresponding to each of
00171    /// the above-mentioned phases of the LGMD input signal. Since each
00172    /// phase's sensor model can be parametrized differently, clients must
00173    /// specify the name of the LGMD signal's phase when instantiating a
00174    /// sensor model object. This name is used to lookup the different
00175    /// parameters in the config file.
00176    std::string m_name ;
00177 
00178    /// This class is designed to allow multiple threads to access its
00179    /// instances simultaneously. Specifically, behaviours such as
00180    /// lgmd_extricate_tti, which use this class indirectly via
00181    /// lobot::TTIEstimator, will read probabilities from the sensor
00182    /// model, while others such as calibrate_let will update the sensor
00183    /// model. This allows customizations to the Bayes filter while the
00184    /// robot is online.
00185    ///
00186    /// We use a mutex to ensure that one behaviour doesn't read
00187    /// intermediate results while another is busy writing to the sensor
00188    /// model.
00189    Mutex m_mutex ;
00190 
00191 public:
00192    /// As mentioned earlier, the LGMD input signal is partitioned into
00193    /// two phases, viz., LOOMING and BLANKING. Robolocust uses different
00194    /// causal likelihood profiles for these phases. Thus, when creating a
00195    /// sensor model object, the client must specify the phase
00196    /// corresponding to this instance so that it can retrieve the correct
00197    /// set of parameters from the config file.
00198    SensorModel(const std::string& lgmd_phase) ;
00199 
00200    /// This method can be used to recompute the sensor model using some
00201    /// new value for the standard deviation of the Gaussian weighting
00202    /// formula used for the increment factors of each bin in the sensor
00203    /// model's probability table.
00204    ///
00205    /// NOTE: The standard deviation provided to this function is actually
00206    /// an increment factor for the current sigma value maintained
00207    /// internally by the sensor model object. Thus, the dsigma parameter
00208    /// to this function will be added to the m_sigma member variable.
00209    /// This design caters to a client behaviour that is specifically
00210    /// designed to update and visualize the available sensor models.
00211    void update(float dsigma) ;
00212 
00213 private:
00214 
00215    /// This method increments the bin "pointed" to by the given [TTI,
00216    /// LGMD] pair. It also increments the other bins in the row "pointed"
00217    /// to by the TTI using a Gaussian weighting formula (which is what
00218    /// the third parameter is for) to ensure that no bin in that row has
00219    /// weird likelihood values that can screw up the Bayesian TTI
00220    /// estimation. Finally, it normalizes the row to ensure that each row
00221    /// vector is a valid probability distribution.
00222    void update_row(float tti, float lgmd, float sigma) ;
00223 
00224    /// This method uses the LGMD discretization to look up the column
00225    /// index in the probability table given an LGMD spike rate.
00226    int col_index(float lgmd) const ;
00227 
00228    /// Given a time-to-impact, this method returns the row index in the
00229    /// probability table using the TTI discretization parameters.
00230    int row_index(float tti) const {
00231       return static_cast<int>((tti - row_min())/row_step()) ;
00232    }
00233 
00234 public:
00235    /// As mentioned earlier, the sensor model is a table containing
00236    /// causal probabilities. These methods return the sizes of this
00237    /// table's rows and columns and the its total size.
00238    //@{
00239    int column_size() const {return Params::belief_size()    ;}
00240    int row_size()    const {return m_lgmd_ranges.size() - 1 ;}
00241    //@}
00242 
00243    /// These methods return the minimum, maximum and step values
00244    /// associated with the discretization used on the rows (i.e., TTI
00245    /// values).
00246    //@{
00247    float row_min () const {return Params::tti_range().min() ;}
00248    float row_max () const {return Params::tti_range().max() ;}
00249    float row_step() const {return Params::tti_step()        ;}
00250    //@}
00251 
00252    /// Return the current value of the standard deviation used for the
00253    /// Gaussian weighting for neighbouring bins.
00254    float sigma() const {return m_sigma ;}
00255 
00256    /// Return the name of LGMD phase this sensor model corresponds to.
00257    std::string name() const {return m_name ;}
00258 
00259    /// This method returns an STL vector containing the column vector
00260    /// "pointed to" by the given LGMD value.
00261    std::vector<float> column_vector(float lgmd) const  ;
00262 
00263    /// This method returns an STL vector containing the entire table of
00264    /// probabilities.
00265    std::vector<float> table() const ;
00266 
00267    /// Clean-up.
00268    ~SensorModel() ;
00269 
00270 private:
00271    /// This inner class encapsulates various parameters that can be used
00272    /// to tweak different aspects of the Bayesian time-to-impact
00273    /// estimation's sensor model.
00274    class Params : public singleton<Params> {
00275       /// To get the Bayesian time-to-impact state estimation to work, we
00276       /// need to discretize both TTI and LGMD values. This setting
00277       /// specifies the TTI discretization using three parameters, viz.,
00278       /// a TTI [min, max] range and a step value. For example, a triple
00279       /// containing [0 10 0.1] means that the time-to-impact estimates
00280       /// will be made in the range of zero to ten seconds in increments
00281       /// of a tenth of a second.
00282       triple<float, float, float> m_tti_discretization ;
00283 
00284       /// It can be cumbersome to constantly "convert" the above triple
00285       /// into a [min, max] range and step value. Therefore, these two
00286       /// member variables are used to "split" the TTI discretization
00287       /// into its range and step components.
00288       //@{
00289       range<float> m_tti_range ;
00290       float m_tti_step ;
00291       //@}
00292 
00293       /// This member variable is used to compute (once during
00294       /// initialization) and store the number of elements in the TTI
00295       /// probability distribution. It is simply the TTI range divided by
00296       /// the TTI step size.
00297       int m_belief_size ;
00298 
00299       /// Private constructor because this is a singleton.
00300       Params() ;
00301 
00302       // Boilerplate code to make generic singleton design pattern work
00303       friend class singleton<Params> ;
00304 
00305    public:
00306       /// Accessing the various parameters.
00307       //@{
00308       static range<float> tti_range() {return instance().m_tti_range   ;}
00309       static float tti_step()         {return instance().m_tti_step    ;}
00310       static int   belief_size()      {return instance().m_belief_size ;}
00311       //@}
00312 
00313       /// Clean-up.
00314       ~Params() ;
00315    } ;
00316 } ;
00317 
00318 //-----------------------------------------------------------------------
00319 
00320 } // end of namespace encapsulating this file's definitions
00321 
00322 #endif
00323 
00324 /* So things look consistent in everyone's emacs... */
00325 /* Local Variables: */
00326 /* indent-tabs-mode: nil */
00327 /* End: */
Generated on Sun May 8 08:05:55 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3