LoMonitorDZone.C

Go to the documentation of this file.
00001 /**
00002    \file  Robots/LoBot/control/LoMonitorDZone.C
00003    \brief This file defines the non-inline member functions of the
00004    lobot::MonitorDZone 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/control/LoMonitorDZone.C $
00039 // $Id: LoMonitorDZone.C 14041 2010-09-25 02:10:39Z mviswana $
00040 //
00041 
00042 //------------------------------ HEADERS --------------------------------
00043 
00044 // lobot headers
00045 #include "Robots/LoBot/control/LoMonitorDZone.H"
00046 #include "Robots/LoBot/control/LoMetrics.H"
00047 #include "Robots/LoBot/control/LoSpinArbiter.H"
00048 
00049 #include "Robots/LoBot/LoApp.H"
00050 #include "Robots/LoBot/slam/LoMap.H"
00051 #include "Robots/LoBot/io/LoDangerZone.H"
00052 #include "Robots/LoBot/config/LoConfigHelpers.H"
00053 
00054 #include "Robots/LoBot/thread/LoUpdateLock.H"
00055 #include "Robots/LoBot/thread/LoPause.H"
00056 #include "Robots/LoBot/thread/LoShutdown.H"
00057 
00058 #include "Robots/LoBot/misc/LoRegistry.H"
00059 #include "Robots/LoBot/misc/singleton.hh"
00060 
00061 #include "Robots/LoBot/util/LoString.H"
00062 #include "Robots/LoBot/util/LoMath.H"
00063 #include "Robots/LoBot/util/LoTime.H"
00064 
00065 // Standard C++ headers
00066 #include <iomanip>
00067 #include <algorithm>
00068 #include <iterator>
00069 
00070 //----------------------------- NAMESPACE -------------------------------
00071 
00072 namespace lobot {
00073 
00074 //-------------------------- KNOB TWIDDLING -----------------------------
00075 
00076 namespace {
00077 
00078 // Retrieve settings from monitor_danger_zone section of config file
00079 template<typename T>
00080 inline T conf(const std::string& key, const T& default_value)
00081 {
00082    return get_conf<T>(LOBE_MONITOR_DZONE, key, default_value) ;
00083 }
00084 
00085 // This enumeration names the different possible actions the
00086 // monitor_danger_zone behaviour can take when it finds that the robot's
00087 // danger zone has been penetrated.
00088 enum Action {
00089    SPIN,
00090    PAUSE,
00091    QUIT,
00092 } ;
00093 
00094 /// This local class encapsulates various parameters that can be used to
00095 /// tweak different aspects of the monitor_danger_zone behaviour.
00096 class MonitorDZoneParams : public singleton<MonitorDZoneParams> {
00097    /// Once the robot's danger zone has been penetrated, the
00098    /// monitor_danger_zone behaviour will start an internal stopwatch
00099    /// ticking and wait for it to reach at least the amount specified by
00100    /// this setting before actually taking any action.
00101    ///
00102    /// This setting should be a time delay specified in milliseconds.
00103    int m_duration ;
00104 
00105    /// By default, the monitor_danger_zone behaviour will wait for the
00106    /// robot to come to a full stop before considering any action. Thus,
00107    /// if the danger zone has been penetrated but the robot is still
00108    /// moving (for example, an extricate behaviour is getting the robot
00109    /// unstuck), then monitor_danger_zone will not interfere.
00110    ///
00111    /// However, by turning this flag off, we can have this behaviour
00112    /// ignore the robot's current state of motion so that it takes action
00113    /// whenever the danger zone has been penetrated for at least the
00114    /// duration specified by the previous setting regardless of whether
00115    /// the robot is moving or not.
00116    bool m_wait_for_stop ;
00117 
00118    /// This setting specifies the action to take when the robot's danger
00119    /// zone has been penetrated. The following actions are supported:
00120    ///
00121    ///    - Spin, i.e., turn the robot in-place, by some random amount.
00122    ///      This is the default action.
00123    ///
00124    ///    - Pause the robot and wait for the user to take appropriate
00125    ///      action, e.g., remote control to get the robot out of the
00126    ///      danger zone.
00127    ///
00128    ///      NOTE: The pause action will require the user to explicitly
00129    ///      restart the robot's controller, i.e., unpause it by pressing
00130    ///      the 'p' key. This also requires that the UI not be disabled.
00131    ///
00132    ///    - Quit the Robolocust controller application. This can be
00133    ///      useful, for instance, when we are running experiments that
00134    ///      require us to simply drive the robot up to a wall and then
00135    ///      stop and start over.
00136    Action m_action ;
00137 
00138    /// The number of milliseconds between successive iterations of this
00139    /// behaviour.
00140    ///
00141    /// WARNING: The ability to change a behaviour's update frequency is a
00142    /// very powerful feature whose misuse or abuse can wreak havoc! Be
00143    /// sure to use reasonable values for this setting.
00144    int m_update_delay ;
00145 
00146    /// Private constructor because this is a singleton.
00147    MonitorDZoneParams() ;
00148    friend class singleton<MonitorDZoneParams> ;
00149 
00150 public:
00151    /// Accessing the various parameters
00152    //@{
00153    static int    duration()      {return instance().m_duration      ;}
00154    static bool   wait_for_stop() {return instance().m_wait_for_stop ;}
00155    static Action action()        {return instance().m_action        ;}
00156    static int    update_delay()  {return instance().m_update_delay  ;}
00157    //@}
00158 } ;
00159 
00160 // Parameter initialization
00161 MonitorDZoneParams::MonitorDZoneParams()
00162    : m_duration(clamp(conf("duration", 2500), 100, 60000)),
00163      m_wait_for_stop(conf("wait_for_stop", true)),
00164      m_update_delay(clamp(conf("update_delay", 1000), 100, 5000))
00165 {
00166    const std::string action = downstring(conf<std::string>("action", "spin")) ;
00167    if (action == "spin")
00168       m_action = SPIN ;
00169    else if (action == "pause")
00170       m_action = PAUSE ;
00171    else if (action == "quit")
00172       m_action = QUIT ;
00173 }
00174 
00175 // Shortcut
00176 typedef MonitorDZoneParams Params ;
00177 
00178 } // end of local anonymous namespace encapsulating above helpers
00179 
00180 //-------------------------- INITIALIZATION -----------------------------
00181 
00182 MonitorDZone::MonitorDZone()
00183    : base(Params::update_delay(), LOBE_MONITOR_DZONE),
00184      m_time(-1)
00185 {
00186    start(LOBE_MONITOR_DZONE) ;
00187 }
00188 
00189 //---------------------- THE BEHAVIOUR'S ACTION -------------------------
00190 
00191 static void log(const std::string& msg)
00192 {
00193    using std::setw ; using std::left ;
00194 
00195    Metrics::Log log ;
00196    log << setw(Metrics::opw()) << left << msg ;
00197    Map* M = App::map() ;
00198    if (M)
00199       log << M->current_pose() ;
00200 }
00201 
00202 static void spin(int angle)
00203 {
00204    log(std::string("mon_dzone spin ") + to_string(angle)) ;
00205    SpinArbiter::instance().
00206       vote(LOBE_MONITOR_DZONE, new SpinArbiter::Vote(angle)) ;
00207 }
00208 
00209 void MonitorDZone::action()
00210 {
00211    UpdateLock::begin_read() ;
00212       bool danger_zone_penetrated = DangerZone::penetrated() ;
00213       bool stopped = App::robot()->stopped() ;
00214    UpdateLock::end_read() ;
00215 
00216    if (danger_zone_penetrated)
00217    {
00218       if (m_time < 0)
00219       {
00220          if (Params::wait_for_stop() && !stopped)
00221             return ;
00222          m_time = current_time() ;
00223          log("mon_dzone begin") ;
00224       }
00225       else
00226       {
00227          if (Params::wait_for_stop() && !stopped)
00228             reset() ;
00229          else
00230          {
00231             int duration = current_time() - m_time ;
00232             if (duration >= Params::duration())
00233             {
00234                switch (Params::action())
00235                {
00236                   case SPIN:
00237                      spin(random(-350, 350)) ;
00238                      break ;
00239                   case PAUSE:
00240                      log("mon_dzone pause") ;
00241                      Pause::set() ;
00242                      break ;
00243                   case QUIT:
00244                      log("mon_dzone quit") ;
00245                      Shutdown::signal() ;
00246                      break ;
00247                }
00248                reset() ;
00249             }
00250          }
00251       }
00252    }
00253    else
00254    {
00255       if (m_time >= 0)
00256          reset() ;
00257    }
00258 }
00259 
00260 void MonitorDZone::reset()
00261 {
00262    m_time = -1 ;
00263    log("mon_dzone end") ;
00264 }
00265 
00266 //----------------------------- CLEAN-UP --------------------------------
00267 
00268 MonitorDZone::~MonitorDZone(){}
00269 
00270 //-----------------------------------------------------------------------
00271 
00272 } // end of namespace encapsulating this file's definitions
00273 
00274 /* So things look consistent in everyone's emacs... */
00275 /* Local Variables: */
00276 /* indent-tabs-mode: nil */
00277 /* End: */
Generated on Sun May 8 08:05:44 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3