LoArbiter.H

Go to the documentation of this file.
00001 /**
00002    \file  Robots/LoBot/control/LoArbiter.H
00003    \brief An ABC for Robolocust motor control arbiters.
00004 
00005    This file defines an abstract base class that provides a common
00006    interface for the different kinds of arbiters that are used to control
00007    lobot's motors.
00008 */
00009 
00010 // //////////////////////////////////////////////////////////////////// //
00011 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00012 // by the University of Southern California (USC) and the iLab at USC.  //
00013 // See http://iLab.usc.edu for information about this project.          //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00016 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00017 // in Visual Environments, and Applications'' by Christof Koch and      //
00018 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00019 // pending; application number 09/912,225 filed July 23, 2001; see      //
00020 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00021 // //////////////////////////////////////////////////////////////////// //
00022 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00023 //                                                                      //
00024 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00025 // redistribute it and/or modify it under the terms of the GNU General  //
00026 // Public License as published by the Free Software Foundation; either  //
00027 // version 2 of the License, or (at your option) any later version.     //
00028 //                                                                      //
00029 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00030 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00031 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00032 // PURPOSE.  See the GNU General Public License for more details.       //
00033 //                                                                      //
00034 // You should have received a copy of the GNU General Public License    //
00035 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00036 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00037 // Boston, MA 02111-1307 USA.                                           //
00038 // //////////////////////////////////////////////////////////////////// //
00039 //
00040 // Primary maintainer for this file: mviswana usc edu
00041 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Robots/LoBot/control/LoArbiter.H $
00042 // $Id: LoArbiter.H 13521 2010-06-06 14:23:03Z mviswana $
00043 //
00044 
00045 #ifndef LOBOT_ARBITER_DOT_H
00046 #define LOBOT_ARBITER_DOT_H
00047 
00048 //------------------------------ HEADERS --------------------------------
00049 
00050 // lobot headers
00051 #include "Robots/LoBot/ui/LoDrawable.H"
00052 #include "Robots/LoBot/io/LoRobot.H"
00053 #include "Robots/LoBot/thread/LoThread.H"
00054 
00055 // POSIX threads
00056 #ifdef INVT_HAVE_LIBPTHREAD
00057 
00058 #include <pthread.h>
00059 
00060 #else // fake pthreads API to allow builds to succeed
00061 
00062 typedef int pthread_mutex_t ;
00063 
00064 #endif
00065 
00066 // Standard C++ headers
00067 #include <string>
00068 #include <map>
00069 #include <list>
00070 
00071 //----------------------------- NAMESPACE -------------------------------
00072 
00073 namespace lobot {
00074 
00075 //------------------------- CLASS DEFINITION ----------------------------
00076 
00077 /**
00078    \class lobot::Arbiter
00079    \brief An ABC defining the common interface for lobot's motor control
00080    arbiters.
00081 
00082    This class implements an abstract base class that provides a common
00083    interface for a behaviour arbitration mechanism. The Robolocust
00084    arbiter follows Rosenblatt's ideas as described in his Ph.D. thesis on
00085    the Distributed Architecture for Mobile Navigation (DAMN).
00086 
00087    Thus, Robolocust behaviours do not directly control the motors or
00088    engage in such nefarious activities as suppressing or inhibiting each
00089    other (a la subsumption). Instead, they vote for each of the different
00090    possible motor control commands. A central arbiter tallies votes using
00091    a weighted sum and smoothing procedure that results in command fusion
00092    (as opposed to sensor fusion) and then issues the command with the
00093    highest vote.
00094 */
00095 class Arbiter : public Drawable, private Thread {
00096    // Prevent copy and assignment
00097    Arbiter(const Arbiter&) ;
00098    Arbiter& operator=(const Arbiter&) ;
00099 
00100    /// After each iteration of the main loop implemented in the run()
00101    /// method, the arbiter will pause a while. This update delay is a
00102    /// user setting specified in the config file. The delay is expected
00103    /// to be in milliseconds.
00104    ///
00105    /// CAUTION: Since the update delay for each arbiter is customizable,
00106    /// it is possible for users to completely ruin the lobot controller
00107    /// by providing bizarre values. Therefore, each arbiter is expected
00108    /// to guard itself against such weirdness.
00109    int m_update_delay ;
00110 
00111 protected:
00112    /// A protected constructor because only subclasses should be able to
00113    /// invoke it. Clients cannot directly create arbiters.
00114    ///
00115    /// Derived classes must specify an appropriate update delay to use
00116    /// when they invoke this constructor. It is up to each individual
00117    /// arbiter to guard against possibly catastrophic update delay
00118    /// settings in the config file and provide reasonable defaults and
00119    /// boundaries.
00120    ///
00121    /// Optionally, arbiters interested in visualization may provide the
00122    /// names and geometries for their respective drawables.
00123    Arbiter(int update_delay,
00124            const std::string& drawable_name = "",
00125            const Drawable::Geometry& = Drawable::Geometry()) ;
00126 
00127    /// This method implements the arbiter's main loop, taking care of
00128    /// checking with the lobot::Shutdown object whether or not it's time
00129    /// to quit.
00130    ///
00131    /// NOTE: Derived classes may but generally should not provide their
00132    /// own implementations of the Thread::run() method. If, for some
00133    /// reason, a subclass of lobot::Arbiter needs to define its own
00134    /// version of run(), it should be sure to check the status of the
00135    /// lobot::Shutdown object.
00136    void run() ;
00137 
00138    /// Since an arbiter runs in its own thread, all subclasses *must*
00139    /// call Thread::start() in their constructors. However, because of
00140    /// private inheritance, Thread::start() won't be visible to
00141    /// subclasses without this explicit say-so.
00142    using Thread::start ;
00143 
00144    /// These methods provide derived classes hooks for implementing any
00145    /// pre- and post-run operations. pre_run() is called right before the
00146    /// main loop is entered and post_run() right after it is exited.
00147    ///
00148    /// Derived classes are not required to define these functions. The
00149    /// default versions implemented in the Arbiter base class do nothing.
00150    //@{
00151    virtual void pre_run() ;
00152    virtual void post_run() ;
00153    //@}
00154 
00155 private:
00156    /// In order to perform command fusion properly, the arbiter needs to
00157    /// know each behaviour's priority. Behaviour priorities are assigned
00158    /// by users. User-specified values are usually not normalized, which
00159    /// is why we need to maintain this map.
00160    //@{
00161    typedef std::map<std::string, float> PriorityMap ;
00162    PriorityMap m_priorities ;
00163    //@}
00164 
00165    /// This method populates the behaviours priority map when the arbiter
00166    /// thread starts up.
00167    void init_priorities() ;
00168 
00169    /// Retrieve the priority associated with the given behaviour. Each
00170    /// Arbiter subclass must implement this method. Usually, it would
00171    /// involve a lookup in the Robolocust configuration database.
00172    virtual float get_configured_priority(const std::string& beh) const = 0 ;
00173 
00174 protected:
00175    /// Returns the normalized priority value stored in the behaviours
00176    /// priority map.
00177    float priority(const std::string& behaviour_name) const ;
00178 
00179 public:
00180    /// Sometimes, a behaviour might want/need exclusive control over the
00181    /// robot's actuators. To facilitate this, the freeze() method freezes
00182    /// the arbiter's priority to that of the behaviour identified by the
00183    /// given name. Once frozen, the arbiter will ignore votes cast by
00184    /// behaviours whose priorities are lower than the priority at which
00185    /// the arbiter is frozen.
00186    ///
00187    /// After its need is fulfilled, the behaviour that has frozen the
00188    /// arbiter must unfreeze it to resume normal operation.
00189    ///
00190    /// NOTE: Freezing the arbiter goes against the grain of the DAMN
00191    /// paradigm. This feature is meant for occasional use by high
00192    /// priority behaviours that might have a need for implementing a
00193    /// sequence of actions without "interference" from other behaviours.
00194    /// Use this feature only if absolutely necessary.
00195    //@{
00196    void freeze  (const std::string& name) ;
00197    void unfreeze(const std::string& name) ;
00198    //@}
00199 
00200    /// Check if the named behaviour has frozen the arbiter.
00201    bool is_frozen(const std::string& name) const ;
00202 
00203 private:
00204    /// These data members keep track of the arbiter's freeze state.
00205    //@{
00206    std::string m_freezer ;         ///< behaviour that has frozen arbiter
00207    float       m_freeze_priority ; ///< priority at which arbiter is frozen
00208    //@}
00209 
00210    /// Because the freeze state can be accessed by multiple threads, we
00211    /// need to synchronize accesses, which we do with this mutex.
00212    mutable pthread_mutex_t m_freeze_mutex ;
00213 
00214 protected:
00215    /// In the DAMN paradigm to robot control, the behaviours do not
00216    /// directly issue motor commands. Rather they vote for or against the
00217    /// available motor commands. Then, the DAMN arbiter issues the motor
00218    /// command by tallying votes and performing appropriate command
00219    /// fusions.
00220    ///
00221    /// Different types of arbiters will have different voting semantics
00222    /// and provide their own vote structures. However, all these vote
00223    /// structures should be derived from this one, i.e.,
00224    /// Arbiter::VoteBase.
00225    ///
00226    /// NOTE: This inner class, which serves as a common base for all
00227    /// arbiter vote types, exists only to provide a virtual destructor so
00228    /// that the Arbiter base class can properly clean up its vote list.
00229    struct VoteBase {
00230       virtual ~VoteBase() ;
00231    } ;
00232 
00233    /// This inner class is used to hold some vote metadata plus the vote
00234    /// itself (in terms of a VoteBase pointer).
00235    ///
00236    /// NOTE: This class's data members are all public. However, Arbiter
00237    /// subclasses should treat it as a read-only structure.
00238    struct vote_data {
00239       std::string behavior_name ;
00240       long long   vote_time ;
00241       VoteBase*   vote ;
00242 
00243       vote_data(const std::string&, long long, VoteBase*) ;
00244       ~vote_data() ;
00245    } ;
00246 
00247    /// The arbiter maintains all the votes in a list of this type. The
00248    /// list is held privately by the base (i.e., this) class and passed
00249    /// to subclasses as part of the motor_cmd() method.
00250    typedef std::list<vote_data*> Votes ;
00251 
00252 private:
00253    /// All the votes are stored in this list and tallied in the arbiter's
00254    /// main loop.
00255    Votes m_votes ;
00256 
00257    /// When a behaviour casts its vote for some set of motor commands,
00258    /// the vote gets added to the arbiter's list of votes. After the
00259    /// arbiter is done tallying votes, the list is purged prior to
00260    /// starting the next cycle. Since behaviours and arbiters run in
00261    /// separate threads, it is imperative to protect against simultaneous
00262    /// accesses to the votes list.
00263    pthread_mutex_t m_votes_mutex ;
00264 
00265 public:
00266    /// Behaviours use this method to cast their votes.
00267    void vote(const std::string& name, VoteBase* vote) ;
00268 
00269 protected:
00270    /// The DAMN arbiter's main loop (implemented in Arbiter::run()) is
00271    /// responsible for tallying the available votes and issuing the
00272    /// appropriae motor command. However, since each type of arbiter can
00273    /// have different voting semantics, the base class cannot tally votes
00274    /// and issue the motor commands. That must be done by subclasses.
00275    /// This method performs the vote tallying and issuance of motor
00276    /// commands. It must be implemented by each subclass.
00277    ///
00278    /// NOTE: Subclasses must treat the votes list as read-only. Although
00279    /// this list is passed to the subclass as const object, its nodes are
00280    /// actually up for grabs and can be modified. However, subclasses
00281    /// must refrain from editing the individual vote_data* nodes held by
00282    /// the votes list. Otherwise, Bad Things will happen.
00283    virtual void motor_cmd(const Votes&, Robot*) = 0 ;
00284 
00285 public:
00286    /// Clean-up.
00287    virtual ~Arbiter() ;
00288 } ;
00289 
00290 //-----------------------------------------------------------------------
00291 
00292 } // end of namespace encapsulating this file's definitions
00293 
00294 #endif
00295 
00296 /* So things look consistent in everyone's emacs... */
00297 /* Local Variables: */
00298 /* indent-tabs-mode: nil */
00299 /* End: */
Generated on Sun May 8 08:41:22 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3