LoLaserViz.C

Go to the documentation of this file.
00001 /**
00002    \file Robots/LoBot/ui/LoLaserViz.C
00003 
00004    This file defines the non-inline member functions of the
00005    lobot::LaserViz class used for visualizing the laser range finder
00006    measurements.
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/LoLaserViz.C $
00041 // $Id: LoLaserViz.C 13674 2010-07-18 22:13:22Z mviswana $
00042 //
00043 
00044 //------------------------------ HEADERS --------------------------------
00045 
00046 // lobot headers
00047 #include "Robots/LoBot/ui/LoLaserViz.H"
00048 
00049 #include "Robots/LoBot/config/LoConfigHelpers.H"
00050 
00051 #include "Robots/LoBot/misc/LoExcept.H"
00052 #include "Robots/LoBot/misc/LoTypes.H"
00053 #include "Robots/LoBot/misc/factory.hh"
00054 #include "Robots/LoBot/util/LoMath.H"
00055 
00056 // OpenGL headers
00057 #ifdef INVT_HAVE_LIBGL
00058 #include <GL/gl.h>
00059 #endif
00060 
00061 //----------------------------- NAMESPACE -------------------------------
00062 
00063 namespace lobot {
00064 
00065 //-------------------------- INITIALIZATION -----------------------------
00066 
00067 LaserViz::LaserViz(const LaserRangeFinder* lrf)
00068    : Drawable("laser_viz", Params::geometry()),
00069      m_lrf(lrf),
00070      m_canvas(new GLCanvas()),
00071      m_markings(factory<LaserWindowMarkings>::create(Params::markings_type()))
00072 {
00073    if (! lrf)
00074       throw misc_error(LASER_RANGE_FINDER_MISSING) ;
00075 
00076    m_markings->use_canvas(m_canvas.get()) ;
00077    m_markings->set_maximum(m_lrf->get_distance_range().max()) ;
00078 }
00079 
00080 void LaserViz::gl_init()
00081 {
00082    const int M = m_lrf->get_distance_range().max() ;
00083    m_canvas->set_window(-M, M, -M, M) ;
00084 }
00085 
00086 //----------------------------- RENDERING -------------------------------
00087 
00088 #ifdef INVT_HAVE_LIBGL
00089 
00090 // This function draws the measurements made by the laser range finder,
00091 // showing them as rays emanating from the origin of the world coordinate
00092 // system (where the laser range finder is positioned; yes, the laser
00093 // range finder is the center of the world).
00094 //
00095 // Since drawing each and every measurement can make the resulting
00096 // picture crowded, this function only draws the distance measurements
00097 // corresponding to angles within the [min, max] range with the specified
00098 // step size.
00099 static void draw_rays(const LaserRangeFinder* lrf,
00100                       const range<int>& angles, int step, const GLColor& color)
00101 {
00102    glPushAttrib(GL_COLOR_BUFFER_BIT) ;
00103    glBegin(GL_LINES) ;
00104       glColor3fv(color.rgb()) ;
00105 
00106       for (float angle = angles.min(); angle <= angles.max(); angle += step)
00107       {
00108          int D = lrf->get_distance(static_cast<int>(angle)) ;
00109          if (D < 0) // didn't get a valid reading in this direction
00110             continue ;
00111          glVertex2i(0, 0) ;
00112          glVertex2f(D * cos(angle), D * sin(angle)) ;
00113       }
00114 
00115       // In case the above loop missed zero degrees, i.e., straight in
00116       // front of the laser range finder...
00117       int D = lrf->get_distance(0) ;
00118       if (D > 0) {
00119          glVertex2i(0, 0) ;
00120          glVertex2i(0, D) ;
00121       }
00122    glEnd() ;
00123    glPopAttrib() ;
00124 }
00125 
00126 // This function draws the measurements made by the laser range finder,
00127 // showing them as an outline hull.
00128 //
00129 // Since drawing each and every measurement can make the resulting
00130 // picture crowded, this function only draws the distance measurements
00131 // corresponding to angles within the [min, max] range with the specified
00132 // step size.
00133 static void draw_hull(const LaserRangeFinder* lrf,
00134                       const range<int>& angles, int step, const GLColor& color)
00135 {
00136    glPushAttrib(GL_COLOR_BUFFER_BIT) ;
00137    glBegin(GL_LINE_LOOP) ;
00138       glColor3fv(color.rgb()) ;
00139 
00140       glVertex2i(0, 0) ;
00141       for (float angle = angles.min(); angle <= angles.max(); angle += step)
00142       {
00143          int D = lrf->get_distance(static_cast<int>(angle)) ;
00144          if (D < 0) // didn't get a valid reading in this direction
00145             continue ;
00146          glVertex2f(D * cos(angle), D * sin(angle)) ;
00147       }
00148    glEnd() ;
00149    glPopAttrib() ;
00150 }
00151 
00152 // The laser range finder is depicted as a rectangle with a triangle on
00153 // it serving to let users know where the front of the device is. This
00154 // function expects to be passed the half-size R of a square inside of
00155 // which the entire rectangle + triangle combo is to inscribed. The
00156 // rectangle is drawn with sides R and 2R; the triangle is drawn with
00157 // height R and base length 2R.
00158 static void draw_lrf(float R, const GLColor& color)
00159 {
00160    glPushAttrib(GL_COLOR_BUFFER_BIT) ;
00161    glBegin(GL_TRIANGLES) ;
00162       glColor3fv(color.rgb()) ;
00163 
00164       // The triangle
00165       glVertex2f(R,  0) ; // apex
00166       glVertex2f(0,  R) ; // base
00167       glVertex2f(0, -R) ;
00168 
00169       // The rectangle (drawn as two triangles)
00170       glVertex2f( 0,  R) ;
00171       glVertex2f(-R,  R) ;
00172       glVertex2f( 0, -R) ;
00173       glVertex2f(-R,  R) ;
00174       glVertex2f(-R, -R) ;
00175       glVertex2f( 0, -R) ;
00176    glEnd() ;
00177    glPopAttrib() ;
00178 }
00179 
00180 // This method draws the latest set of distance measurements from the
00181 // laser range finder.
00182 void LaserViz::render_me()
00183 {
00184    glPushMatrix() ;
00185       glRotatef(Params::lrf_direction(), 0, 0, 1) ;
00186       m_markings->render() ;
00187       if (Params::draw_rays())
00188          draw_rays(m_lrf, Params::angles_range(), Params::angles_step(),
00189                    Params::measurements_color()) ;
00190       else
00191          draw_hull(m_lrf, Params::angles_range(), Params::angles_step(),
00192                    Params::measurements_color()) ;
00193       draw_lrf(Params::lrf_size(), Params::lrf_color()) ;
00194    glPopMatrix() ;
00195 }
00196 
00197 #endif // INVT_HAVE_LIBGL
00198 
00199 //----------------------------- ZOOM/PAN --------------------------------
00200 
00201 void LaserViz::zoom_by(float dz)
00202 {
00203    m_canvas->zoom_by(dz) ;
00204 }
00205 
00206 void LaserViz::pan(int cx, int cy, int px, int py)
00207 {
00208    double curr_x, curr_y ;
00209    m_canvas->screen_to_world(cx, cy, &curr_x, &curr_y) ;
00210 
00211    double prev_x, prev_y ;
00212    m_canvas->screen_to_world(px, py, &prev_x, &prev_y) ;
00213 
00214    const float dx = static_cast<float>(curr_x - prev_x) ;
00215    const float dy = static_cast<float>(curr_y - prev_y) ;
00216    m_canvas->pan(-dx, -dy) ;
00217 }
00218 
00219 void LaserViz::reset_zoom_pan()
00220 {
00221    m_canvas->reset_zoom_pan() ;
00222 }
00223 
00224 //----------------------------- CLEAN-UP --------------------------------
00225 
00226 void LaserViz::gl_cleanup()
00227 {
00228    // Force auto_ptr to delete the markings object now rather than in
00229    // destructor to ensure that any GL resources held by it are cleaned
00230    // up here. Otherwise, depending on the order in which the thread
00231    // scheduler shuts down different threads, the GL rendering context
00232    // could disappear before we get around to properly cleaning up...
00233    m_markings.reset(0) ;
00234 
00235    // Ditto for the GL canvas
00236    m_canvas.reset(0) ;
00237 }
00238 
00239 LaserViz::~LaserViz(){}
00240 
00241 //-------------------------- KNOB TWIDDLING -----------------------------
00242 
00243 // Retrieve settings from laser_viz section of config file
00244 template<typename T>
00245 static inline T viz_conf(const std::string& key, const T& default_value)
00246 {
00247    return get_conf<T>("laser_viz", key, default_value) ;
00248 }
00249 
00250 // Overload of above function for retrieving ranges
00251 template<typename T>
00252 static inline range<T>
00253 viz_conf(const std::string& key, const range<T>& default_value)
00254 {
00255    return get_conf<T>("laser_viz", key, default_value) ;
00256 }
00257 
00258 // Overload for retrieving triples
00259 template<typename T>
00260 static inline triple<T, T, T>
00261 viz_conf(const std::string& key, const triple<T, T, T>& default_value)
00262 {
00263    return get_conf<T>("laser_viz", key, default_value) ;
00264 }
00265 
00266 // Retrieve settings from markings section of config file
00267 template<typename T>
00268 static inline T markings_conf(const std::string& key, const T& default_value)
00269 {
00270    return get_conf<T>("markings", key, default_value) ;
00271 }
00272 
00273 // Parameters initialization
00274 LaserViz::Params::Params()
00275    : m_geometry(viz_conf<std::string>("geometry", "0 0 480 480")),
00276      m_measurements_style(downstring(
00277         viz_conf<std::string>("measurements_style", "rays"))),
00278      m_markings_type(downstring(markings_conf<std::string>("type", "rings"))),
00279      m_angles_range(viz_conf<int>("angles_range", make_range(-119, 135))),
00280      m_angles_step(clamp(viz_conf("angles_step", 5), 1, 30)),
00281      m_measurements_color(viz_conf<int>("measurements_color",
00282                                         make_triple(0, 128, 128))),
00283      m_lrf_size(clamp(viz_conf("lrf_size", 100.0f), 10.0f, 250.0f)),
00284      m_lrf_direction(clamp_angle(viz_conf("lrf_direction", 90.0f))),
00285      m_lrf_color(viz_conf<int>("lrf_color", make_triple(242, 13, 26)))
00286 {}
00287 
00288 // Parameters clean-up
00289 LaserViz::Params::~Params(){}
00290 
00291 //-----------------------------------------------------------------------
00292 
00293 } // end of namespace encapsulating this file's definitions
00294 
00295 /* So things look consistent in everyone's emacs... */
00296 /* Local Variables: */
00297 /* indent-tabs-mode: nil */
00298 /* End: */
Generated on Sun May 8 08:05:56 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3