LoArbiter.C

Go to the documentation of this file.
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: */
Generated on Sun May 8 08:41:22 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3