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: */