00001 /** 00002 \file Robots/LoBot/control/LoArbiter.C 00003 \brief This file defines the non-inline member functions of the 00004 lobot::Arbiter 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/LoArbiter.C $ 00039 // $Id: LoArbiter.C 13567 2010-06-13 15:58:59Z mviswana $ 00040 // 00041 00042 //---------------------- ALTERNATIVE DEFINITION ------------------------- 00043 00044 // In case pthreads is missing 00045 #ifndef INVT_HAVE_LIBPTHREAD 00046 00047 #include "Robots/LoBot/control/LoArbiter.H" 00048 #include "Robots/LoBot/misc/LoExcept.H" 00049 00050 namespace lobot { 00051 00052 // Constructor 00053 Arbiter::Arbiter(int) 00054 : m_update_delay(0), 00055 m_freeze_priority(-1), m_freeze_mutex(0), 00056 m_votes_mutex(0), m_viz_mutex(0) 00057 { 00058 throw missing_libs(MISSING_PTHREAD) ; 00059 } 00060 00061 // Empty API 00062 void Arbiter::run(){} 00063 void Arbiter::pre_run(){} 00064 void Arbiter::post_run(){} 00065 00066 void Arbiter::init_priorities(){} 00067 float Arbiter::priority(const std::string&) {return 0 ;} 00068 00069 void Arbiter::render_cb(unsigned long){} 00070 void Arbiter::render(){} 00071 00072 Arbiter::vote_data::vote_data(const std::string&, long long, VoteBase*){} 00073 Arbiter::vote_data::~vote_data(){} 00074 void Arbiter::vote(const std::string&, void*){} 00075 00076 void Arbiter:: freeze (const std::string&){} 00077 void Arbiter::unfreeze (const std::string&){} 00078 bool Arbiter::is_frozen(const std::string&) const {return false ;} 00079 00080 // Destructor 00081 Arbiter::~Arbiter(){} 00082 00083 } // end of namespace encapsulating above empty definition 00084 00085 #else // pthreads available ==> the real McCoy 00086 00087 //------------------------------ HEADERS -------------------------------- 00088 00089 // lobot headers 00090 #include "Robots/LoBot/control/LoArbiter.H" 00091 #include "Robots/LoBot/control/LoBehavior.H" 00092 00093 #include "Robots/LoBot/LoApp.H" 00094 #include "Robots/LoBot/ui/LoLaserViz.H" 00095 #include "Robots/LoBot/config/LoConfigHelpers.H" 00096 00097 #include "Robots/LoBot/thread/LoShutdown.H" 00098 #include "Robots/LoBot/thread/LoPause.H" 00099 00100 #include "Robots/LoBot/misc/LoExcept.H" 00101 #include "Robots/LoBot/util/LoSTL.H" 00102 #include "Robots/LoBot/util/LoTime.H" 00103 00104 // INVT utilities 00105 #include "Util/log.H" 00106 00107 // Unix headers 00108 #include <unistd.h> 00109 00110 //----------------------------- NAMESPACE ------------------------------- 00111 00112 namespace lobot { 00113 00114 //-------------------------- INITIALIZATION ----------------------------- 00115 00116 Arbiter:: 00117 Arbiter(int update_delay, const std::string& name, const Drawable::Geometry& g) 00118 : Drawable(name, g), 00119 m_update_delay(clamp(update_delay, 1, 900000) * 1000), 00120 m_freeze_priority(-1) 00121 { 00122 if (pthread_mutex_init(& m_freeze_mutex, 0) != 0) 00123 throw thread_error(MUTEX_INIT_ERROR) ; 00124 if (pthread_mutex_init(& m_votes_mutex, 0) != 0) { 00125 pthread_mutex_destroy(& m_freeze_mutex) ; 00126 throw thread_error(MUTEX_INIT_ERROR) ; 00127 } 00128 } 00129 00130 //------------------------ THE THREAD FUNCTION -------------------------- 00131 00132 void Arbiter::pre_run(){} 00133 00134 void Arbiter::run() 00135 { 00136 try 00137 { 00138 // Before initializing behaviour priorities and checking for 00139 // existence of motor subsystem, ensure that the application object 00140 // has been fully loaded. 00141 App::wait_for_init() ; 00142 00143 init_priorities() ; 00144 if (! App::robot()) { 00145 LERROR("arbiter error: robot sensorimotor subsystem unavailable") ; 00146 return ; 00147 } 00148 00149 // Main loop 00150 pre_run() ; 00151 while (! Shutdown::signaled()) 00152 { 00153 if (Pause::is_clear()) 00154 { 00155 pthread_mutex_lock(& m_votes_mutex) ; 00156 if (! m_votes.empty()) { 00157 motor_cmd(m_votes, App::robot()) ; 00158 purge_container(m_votes) ; 00159 m_votes.clear() ; 00160 } 00161 pthread_mutex_unlock(& m_votes_mutex) ; 00162 } 00163 usleep(m_update_delay) ; 00164 } 00165 post_run() ; 00166 } 00167 catch (uhoh& e) 00168 { 00169 LERROR("arbiter error: %s", e.what()) ; 00170 purge_container(m_votes) ; 00171 m_votes.clear() ; 00172 pthread_mutex_unlock(& m_votes_mutex) ; 00173 } 00174 } 00175 00176 void Arbiter::post_run(){} 00177 00178 //---------------------- BEHAVIOUR PRIORITY MAP ------------------------- 00179 00180 void Arbiter::init_priorities() 00181 { 00182 float sum = 0 ; 00183 App::Behaviours::const_iterator it = App::behaviours().begin() ; 00184 for (; it != App::behaviours().end(); ++it) 00185 { 00186 const std::string& i = (*it)->name ; 00187 float p = get_configured_priority(i) ; 00188 m_priorities[i] = p ; 00189 sum += p ; 00190 } 00191 00192 // Normalize the user-assigned priorities 00193 if (sum > 0) 00194 for (it = App::behaviours().begin(); it != App::behaviours().end(); ++it) 00195 m_priorities[(*it)->name] /= sum ; 00196 } 00197 00198 float Arbiter::priority(const std::string& behaviour) const 00199 { 00200 PriorityMap::const_iterator it = m_priorities.find(behaviour) ; 00201 if (it == m_priorities.end()) 00202 return 0 ; 00203 return it->second ; 00204 } 00205 00206 //--------------------- ARBITER FREEZING SUPPORT ------------------------ 00207 00208 void Arbiter::freeze(const std::string& name) 00209 { 00210 float p = priority(name) ; 00211 pthread_mutex_lock(& m_freeze_mutex) ; 00212 if (p > m_freeze_priority) { 00213 m_freezer = name ; 00214 m_freeze_priority = p ; 00215 } 00216 pthread_mutex_unlock(& m_freeze_mutex) ; 00217 } 00218 00219 void Arbiter::unfreeze(const std::string& name) 00220 { 00221 pthread_mutex_lock(& m_freeze_mutex) ; 00222 if (m_freezer == name) { 00223 m_freezer.clear() ; 00224 m_freeze_priority = -1 ; 00225 } 00226 pthread_mutex_unlock(& m_freeze_mutex) ; 00227 } 00228 00229 bool Arbiter::is_frozen(const std::string& name) const 00230 { 00231 bool frozen = false ; 00232 pthread_mutex_lock(& m_freeze_mutex) ; 00233 if (name == m_freezer) 00234 frozen = true ; 00235 pthread_mutex_unlock(& m_freeze_mutex) ; 00236 return frozen ; 00237 } 00238 00239 //---------------------- ARBITER VOTING SUPPORT ------------------------- 00240 00241 Arbiter::VoteBase::~VoteBase(){} 00242 00243 Arbiter::vote_data:: 00244 vote_data(const std::string& n, long long t, VoteBase* v) 00245 : behavior_name(n), vote_time(t), vote(v) 00246 {} 00247 00248 Arbiter::vote_data::~vote_data() 00249 { 00250 delete vote ; 00251 } 00252 00253 void Arbiter::vote(const std::string& name, VoteBase* vote) 00254 { 00255 if (! running()) 00256 throw arbiter_error(ARBITER_NOT_RUNNING) ; 00257 00258 pthread_mutex_lock(& m_freeze_mutex) ; 00259 float freeze_priority = m_freeze_priority ; 00260 pthread_mutex_unlock(& m_freeze_mutex) ; 00261 if (priority(name) < freeze_priority) 00262 return ; 00263 00264 pthread_mutex_lock(& m_votes_mutex) ; 00265 m_votes.push_back(new vote_data(name, current_time(), vote)) ; 00266 pthread_mutex_unlock(& m_votes_mutex) ; 00267 } 00268 00269 //----------------------------- CLEAN-UP -------------------------------- 00270 00271 Arbiter::~Arbiter() 00272 { 00273 pthread_mutex_destroy(& m_freeze_mutex) ; 00274 pthread_mutex_destroy(& m_votes_mutex) ; 00275 purge_container(m_votes) ; // should be okay to do without mutex 00276 } 00277 00278 //----------------------------------------------------------------------- 00279 00280 } // end of namespace encapsulating this file's definitions 00281 00282 #endif // INVT_HAVE_PTHREAD 00283 00284 /* So things look consistent in everyone's emacs... */ 00285 /* Local Variables: */ 00286 /* indent-tabs-mode: nil */ 00287 /* End: */