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