LoLocustViz.C

Go to the documentation of this file.
00001 /**
00002    \file Robots/LoBot/ui/LoLocustViz.C
00003 
00004    This file defines the non-inline member functions of the
00005    lobot::LocustViz class used for visualizing the LGMD spike rates of
00006    all the (virtual) locusts.
00007 */
00008 
00009 // //////////////////////////////////////////////////////////////////// //
00010 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00011 // by the University of Southern California (USC) and the iLab at USC.  //
00012 // See http://iLab.usc.edu for information about this project.          //
00013 // //////////////////////////////////////////////////////////////////// //
00014 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00015 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00016 // in Visual Environments, and Applications'' by Christof Koch and      //
00017 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00018 // pending; application number 09/912,225 filed July 23, 2001; see      //
00019 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00020 // //////////////////////////////////////////////////////////////////// //
00021 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00022 //                                                                      //
00023 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00024 // redistribute it and/or modify it under the terms of the GNU General  //
00025 // Public License as published by the Free Software Foundation; either  //
00026 // version 2 of the License, or (at your option) any later version.     //
00027 //                                                                      //
00028 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00029 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00030 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00031 // PURPOSE.  See the GNU General Public License for more details.       //
00032 //                                                                      //
00033 // You should have received a copy of the GNU General Public License    //
00034 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00035 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00036 // Boston, MA 02111-1307 USA.                                           //
00037 // //////////////////////////////////////////////////////////////////// //
00038 //
00039 // Primary maintainer for this file: mviswana usc edu
00040 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Robots/LoBot/ui/LoLocustViz.C $
00041 // $Id: LoLocustViz.C 13811 2010-08-21 02:00:08Z mviswana $
00042 //
00043 
00044 //------------------------------ HEADERS --------------------------------
00045 
00046 // lobot headers
00047 #include "Robots/LoBot/ui/LoLocustViz.H"
00048 
00049 #include "Robots/LoBot/lgmd/LocustModel.H"
00050 #include "Robots/LoBot/thread/LoUpdateLock.H"
00051 #include "Robots/LoBot/config/LoConfigHelpers.H"
00052 
00053 #include "Robots/LoBot/misc/LoTypes.H"
00054 #include "Robots/LoBot/misc/LoExcept.H"
00055 #include "Robots/LoBot/misc/singleton.hh"
00056 
00057 #include "Robots/LoBot/util/LoGL.H"
00058 #include "Robots/LoBot/util/LoMath.H"
00059 #include "Robots/LoBot/util/triple.hh"
00060 
00061 // OpenGL headers
00062 #ifdef INVT_HAVE_LIBGL
00063 #include <GL/gl.h>
00064 #endif
00065 
00066 // Boost headers
00067 #include <boost/bind.hpp>
00068 
00069 // Standard C++ headers
00070 #include <algorithm>
00071 #include <iterator>
00072 
00073 //----------------------------- NAMESPACE -------------------------------
00074 
00075 namespace lobot {
00076 
00077 //-------------------------- KNOB TWIDDLING -----------------------------
00078 
00079 namespace {
00080 
00081 // Retrieve settings from locust_viz section of config file
00082 template<typename T>
00083 inline T conf(const std::string& key, const T& default_value)
00084 {
00085    return get_conf<T>("locust_viz", key, default_value) ;
00086 }
00087 
00088 // Overload for retrieving triples
00089 template<typename T>
00090 inline triple<T, T, T>
00091 conf(const std::string& key, const triple<T, T, T>& default_value)
00092 {
00093    return get_conf<T>("locust_viz", key, default_value) ;
00094 }
00095 
00096 // This local helper class encapsulates settings that can be used to
00097 // tweak various aspects of the locust spike rate visualizer.
00098 class Params : public singleton<Params> {
00099    /// The spike rate visualizer shows each LGMD's current value as a bar
00100    /// starting at the center of the visualizer window and going out
00101    /// along the direction vector of that LGMD. The length of this bar
00102    /// denotes magnitude of the spiking activity for the locust looking
00103    /// in the bar's direction.
00104    ///
00105    /// Thus, for the entire array of locusts, the visualizer will
00106    /// resemble the depiction of a range sensor such as the laser range
00107    /// finder with the individual "rays" denoting the "range" measurement
00108    /// (in this case spike rate) along each of the directions "scanned"
00109    /// by this sensor.
00110    ///
00111    /// This setting specifies the width (in pixels) of the spike rate
00112    /// rays/bars.
00113    float m_ray_width ;
00114 
00115    /// This setting specifies the color of the LGMD "range sensor" rays.
00116    /// It should be a triple of integers, each in the range [0,255].
00117    GLColor m_ray_color ;
00118 
00119    /// To help gauge each ray's associated numeric value, we draw a
00120    /// series of concentric rings. This setting specifies the increments
00121    /// in the radii between two consecutive rings. Its unit is Hertz. Its
00122    /// value should be a reasonable number between the min and max spike
00123    /// rate range specified for the locust model in effect.
00124    ///
00125    /// For example, if the spike range is 0 to 800 and this increment is
00126    /// given as 100, the visualizer will setup its internal coordinate
00127    /// system to go from 0 to 800 in each direction and draw 8 circles,
00128    /// starting with a radius of 100 units and incrementing thereafter by
00129    /// 100 units all the way up to 800. By seeing where each ray's end
00130    /// point falls, the user can get a rough idea of the spike rate
00131    /// associated with that ray.
00132    float m_ring_incr ;
00133 
00134    /// This setting specifies the color of concentric rings described
00135    /// above. It should be a triple of integers, each in the range
00136    /// [0,255].
00137    GLColor m_ring_color ;
00138 
00139    /// The location and size (inside the Robolocust main window) of the
00140    /// locust spike rate visualizer's drawing area.
00141    Drawable::Geometry m_geometry ;
00142 
00143    /// Private constructor because this is a singleton.
00144    Params() ;
00145 
00146    // Boilerplate code to make generic singleton design pattern work
00147    friend class singleton<Params> ;
00148 
00149 public:
00150    /// Accessing the various parameters.
00151    //@{
00152    static float ray_width() {return instance().m_ray_width ;}
00153    static float ring_incr() {return instance().m_ring_incr ;}
00154    static const float* ray_color()  {return instance().m_ray_color.rgb()  ;}
00155    static const float* ring_color() {return instance().m_ring_color.rgb() ;}
00156    static Drawable::Geometry geometry() {return instance().m_geometry ;}
00157    //@}
00158 } ;
00159 
00160 // Parameters initialization
00161 Params::Params()
00162    : m_ray_width(clamp(conf("ray_width", 3.0f), 1.0f, 10.0f)),
00163      m_ray_color(conf<int>("ray_color", make_triple(96, 96, 96))),
00164      m_ring_incr(clamp(conf("ring_incr", 100.0f), 1.0f, 1000.0f)),
00165      m_ring_color(conf<int>("ring_color", make_triple(255, 0, 0))),
00166      m_geometry(conf<std::string>("geometry", "0 0 10 10"))
00167 {}
00168 
00169 } // end of local anonymous namespace encapsulating above helper class
00170 
00171 //-------------------------- INITIALIZATION -----------------------------
00172 
00173 LocustViz::LocustViz(const std::vector<LocustModel*>& locusts)
00174    : Drawable("locust_viz", Params::geometry()),
00175      m_locusts(locusts), m_spike_max(1), m_display_list(0)
00176 {
00177    if (m_locusts.empty()) // what the hell are we visualizing?
00178       throw misc_error(NOT_ENOUGH_LOCUSTS) ;
00179 
00180    // Compute the unit vectors associated with the radial directions in
00181    // which each locust is looking.
00182    m_directions.reserve(m_locusts.size()) ;
00183    std::transform(m_locusts.begin(), m_locusts.end(),
00184                   std::back_inserter(m_directions),
00185                   boost::bind(unit_vector,
00186                               boost::bind(&LocustModel::direction, _1))) ;
00187 
00188    // Record the max spike rate so we can setup the visualizer's
00189    // coordinate properly.
00190    m_spike_max = m_locusts[0]->get_range().max() ;
00191 }
00192 
00193 // Once we know the max spike rate, we know all that we need to know to
00194 // be able to draw the concentric rings used to help the user gauge the
00195 // numeric value associated with each spike rate ray. Therefore, we can
00196 // stuff that bit of rendering code in a display list...
00197 void LocustViz::gl_init()
00198 {
00199    // We use two display lists for the concentric rings: one for drawing
00200    // a unit circle and another for scaling this circle and drawing the
00201    // required number of rings.
00202    m_display_list = glGenLists(2) ;
00203 
00204    // First, setup the display list for a unit circle
00205    glNewList(m_display_list + 1, GL_COMPILE) ;
00206    glBegin(GL_LINE_LOOP) ;
00207       for (int angle = 0; angle < 360; ++angle)
00208          glVertex2f(cos(angle), sin(angle)) ;
00209    glEnd() ;
00210    glEndList() ;
00211 
00212    // Then, scale the unit circle display list to draw the required
00213    // number of concentric rings.
00214    const float R = Params::ring_incr() ;
00215    glNewList(m_display_list, GL_COMPILE) ;
00216    for (float radius = R; radius <= m_spike_max; radius += R) {
00217       glLoadIdentity() ;
00218       glScalef(radius, radius, 1) ;
00219       glCallList(m_display_list + 1) ;
00220    }
00221    glEndList() ;
00222 }
00223 
00224 //----------------------------- RENDERING -------------------------------
00225 
00226 #ifdef INVT_HAVE_LIBGL
00227 
00228 // Scale a locust's direction vector by its current spike rate
00229 static Vector compute_spike_vector(const LocustModel* L, const Vector& v)
00230 {
00231    return v * L->get_lgmd() ;
00232 }
00233 
00234 // Draw the "ray" associated with a spike rate vector
00235 static void render_spike(const Vector& spike)
00236 {
00237    glVertex2i(0, 0) ;
00238    glVertex2f(spike.i, spike.j) ;
00239 }
00240 
00241 // Draw the latest set of spike rates so as to make the LGMD array look
00242 // like a range sensor (in fact, this imitates the LRF visualizer's "ray"
00243 // style; see ui/LoLaserViz.C).
00244 void LocustViz::render_me()
00245 {
00246    // We use a vector to represent each locust's spike rate "ray"
00247    std::vector<Vector> spikes ;
00248    spikes.reserve(m_locusts.size()) ;
00249 
00250    // Scale each locust's direction vector by its current spike rate to
00251    // obtain its spike rate "ray."
00252    UpdateLock::begin_read() ;
00253       std::transform(m_locusts.begin(), m_locusts.end(), m_directions.begin(),
00254                      std::back_inserter(spikes), compute_spike_vector) ;
00255    UpdateLock::end_read() ;
00256 
00257    setup_view_volume(-m_spike_max, m_spike_max, -m_spike_max, m_spike_max) ;
00258    glPushAttrib(GL_LINE_BIT | GL_CURRENT_BIT) ;
00259       // Draw the concentric rings to help user gauge the numeric value
00260       // associated with each spike rate ray.
00261       glColor3fv(Params::ring_color()) ;
00262       glCallList(m_display_list) ;
00263 
00264       // The above display list messes with the modelview matrix. So we
00265       // reset it and apply a rotation so that the visualizer's notion of
00266       // "up" (positive x-direction) corresponds with our notion of "up"
00267       // (positive y-direction).
00268       glLoadIdentity() ;
00269       glRotatef(90, 0, 0, 1) ;
00270 
00271       // Draw the spike rate rays
00272       glLineWidth(Params::ray_width()) ;
00273       glColor3fv(Params::ray_color()) ;
00274       glBegin(GL_LINES) ;
00275          std::for_each(spikes.begin(), spikes.end(), render_spike) ;
00276       glEnd() ;
00277    glPopAttrib() ;
00278 
00279    // Label to let user know what this drawable is visualizing
00280    restore_view_volume() ;
00281    text_view_volume() ;
00282       glColor3f(0, 1, 1) ;
00283       draw_label(3, 12, "LGMD Spikes") ;
00284    restore_view_volume() ;
00285 }
00286 
00287 #endif // INVT_HAVE_LIBGL
00288 
00289 //----------------------------- CLEAN-UP --------------------------------
00290 
00291 void LocustViz::gl_cleanup()
00292 {
00293    glDeleteLists(m_display_list, 2) ;
00294 }
00295 
00296 LocustViz::~LocustViz(){}
00297 
00298 //-----------------------------------------------------------------------
00299 
00300 } // end of namespace encapsulating this file's definitions
00301 
00302 /* So things look consistent in everyone's emacs... */
00303 /* Local Variables: */
00304 /* indent-tabs-mode: nil */
00305 /* End: */
Generated on Sun May 8 08:41:31 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3