LoTurnArbiter.H

Go to the documentation of this file.
00001 /**
00002    \file  Robots/LoBot/control/LoTurnArbiter.H
00003    \brief An arbiter for issuing turn commands to steer the robot.
00004 
00005    This file defines a class that implements a DAMN turn arbiter for
00006    Robolocust.
00007 */
00008 
00009 // //////////////////////////////////////////////////////////////////// //
00010 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00011 // by the University of Southern California (USC) and the iLab at USC.  //
00012 // See http://iLab.usc.edu for information about this project.          //
00013 // //////////////////////////////////////////////////////////////////// //
00014 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00015 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00016 // in Visual Environments, and Applications'' by Christof Koch and      //
00017 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00018 // pending; application number 09/912,225 filed July 23, 2001; see      //
00019 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00020 // //////////////////////////////////////////////////////////////////// //
00021 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00022 //                                                                      //
00023 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00024 // redistribute it and/or modify it under the terms of the GNU General  //
00025 // Public License as published by the Free Software Foundation; either  //
00026 // version 2 of the License, or (at your option) any later version.     //
00027 //                                                                      //
00028 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00029 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00030 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00031 // PURPOSE.  See the GNU General Public License for more details.       //
00032 //                                                                      //
00033 // You should have received a copy of the GNU General Public License    //
00034 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00035 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00036 // Boston, MA 02111-1307 USA.                                           //
00037 // //////////////////////////////////////////////////////////////////// //
00038 //
00039 // Primary maintainer for this file: mviswana usc edu
00040 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Robots/LoBot/control/LoTurnArbiter.H $
00041 // $Id: LoTurnArbiter.H 12858 2010-02-17 20:35:10Z mviswana $
00042 //
00043 
00044 #ifndef LOBOT_TURN_ARBITER_DOT_H
00045 #define LOBOT_TURN_ARBITER_DOT_H
00046 
00047 //------------------------------ HEADERS --------------------------------
00048 
00049 // lobot headers
00050 #include "Robots/LoBot/control/LoArbiter.H"
00051 #include "Robots/LoBot/misc/singleton.hh"
00052 
00053 // Standard C++ headers
00054 #include <string>
00055 #include <map>
00056 #include <vector>
00057 #include <iterator>
00058 
00059 //----------------------------- NAMESPACE -------------------------------
00060 
00061 namespace lobot {
00062 
00063 //------------------------- CLASS DEFINITION ----------------------------
00064 
00065 /**
00066    \class lobot::TurnArbiter
00067    \brief A DAMN turn arbiter for controlling Robolocust's steering.
00068 
00069    This class implements a DAMN turn arbiter that acts as the interface
00070    between the Robolocust behaviours and the robot's steering controls.
00071    The arbiter supports a certain set of turns (hard right, medium right,
00072    soft right, straight ahead, etc.). Each behaviour that wants to
00073    influence the steering direction will have to vote for or against each
00074    of these possible steering commands. The turn arbiter will then tally
00075    all the votes using a weighted sum and smoothing procedure and issue
00076    the motor control command that ends up with the maximum votes.
00077 */
00078 class TurnArbiter : public Arbiter, public singleton<TurnArbiter> {
00079    // Prevent copy and assignment
00080    TurnArbiter(const TurnArbiter&) ;
00081    TurnArbiter& operator=(const TurnArbiter&) ;
00082 
00083    // Boilerplate code to make the generic singleton design pattern work
00084    friend class singleton<TurnArbiter> ;
00085 
00086    /// A private constructor because this class is a singleton.
00087    TurnArbiter() ;
00088 
00089    /// Retrieve the user-assigned priority for the given behaviour.
00090    float get_configured_priority(const std::string& behaviour) const ;
00091 
00092    /// Tally votes and issue appropriate motor command.
00093    void motor_cmd(const Votes&, Robot*) ;
00094 
00095 public:
00096    /// To control the robot's steering, each turn related behaviour must
00097    /// vote for or against each possible turn direction. These votes are
00098    /// represented by this inner class. In order to vote, a behaviour
00099    /// must instantiate this class with the new operator, fill out the
00100    /// voting structure properly and then pass it to the arbiter's vote()
00101    /// method.
00102    ///
00103    /// A vote is a number between -1 and +1. If a behaviour votes -1 for
00104    /// some direction, it means that the behaviour is dead-set against
00105    /// turning in that direction; a vote of +1 indicates a strong
00106    /// preference for going in that direction; and a vote of zero means
00107    /// the behaviour is neutral with regards to that direction.
00108    /// Fractional numbers indicate varying degrees between the three
00109    /// states described above. For example, an obstacle avoidance
00110    /// behaviour might scale vote values based on the distance to
00111    /// obstacles.
00112    class Vote : public VoteBase {
00113       /// We store the votes for each turn direction supported by the
00114       /// controller in a map that maps directions to their corresponding
00115       /// vote values.
00116       //@{
00117       typedef std::map<int, float> VoteMap ;
00118       VoteMap m_votes ;
00119       //@}
00120 
00121       // Allow the turn arbiter to access VoteMap
00122       friend class TurnArbiter ;
00123 
00124    public:
00125       /// When a new turn arbiter vote object is created, we initialize
00126       /// the internal turn-direction-to-vote-value map by using the
00127       /// appropriate config file parameters.
00128       Vote() ;
00129 
00130       /// Retrieve the supported turn directions in a vector.
00131       std::vector<int> get_directions() const ;
00132 
00133       /// Operator to access the vote value corresponding to the supplied
00134       /// direction. If the turn direction is not supported by the
00135       /// arbiter, an exception will be thrown.
00136       VoteMap::mapped_type& operator[](int direction) ;
00137 
00138       /// After creating a new turn arbiter vote object, behaviours can
00139       /// use this method to specify their votes for a given direction.
00140       void vote(int direction, float vote_value) {
00141          operator[](direction) = vote_value ;
00142       }
00143 
00144       // Forward declarations
00145       class iterator ;
00146       friend class iterator ; // because it needs to muck around with vote map
00147 
00148       /// An iterator interface for filling out votes for all the
00149       /// directions.
00150       class iterator {
00151          /// Each Vote iterator has to be associated with a Vote object.
00152          Vote& m_vote ;
00153 
00154          /// A Vote iterator keeps track of itself simply by reusing an
00155          /// iterator from the Vote's vote map.
00156          mutable Vote::VoteMap::iterator m_iterator ;
00157 
00158          /// Private constructors to ensure that only the Vote class can
00159          /// create Vote iterators.
00160          //@{
00161          iterator(const Vote&) ;
00162          iterator(const Vote&, bool) ;
00163          friend class Vote ;
00164          //@}
00165 
00166       public:
00167          /// Copy, assignment and clean-up for turn arbiter vote object
00168          /// iterators.
00169          //@{
00170          iterator(const iterator&) ;
00171          iterator& operator=(const iterator&) ;
00172          ~iterator() ;
00173          //@}
00174 
00175          /// Typedefs for STL compatibility.
00176          //@{
00177          typedef std::bidirectional_iterator_tag iterator_category ;
00178          typedef Vote::VoteMap::mapped_type value_type ;
00179          typedef int difference_type ;
00180          typedef value_type* pointer ;
00181          typedef value_type& reference ;
00182          //@}
00183 
00184          /// Item access
00185          //@{
00186                reference operator*()        {return   m_iterator->second ;}
00187          const reference operator*()  const {return   m_iterator->second ;}
00188                pointer   operator->()       {return & m_iterator->second ;}
00189          const pointer   operator->() const {return & m_iterator->second ;}
00190          //@}
00191 
00192          /// Prefix increment
00193          //@{
00194                iterator& operator++()       {++m_iterator ; return *this ;}
00195          const iterator& operator++() const {++m_iterator ; return *this ;}
00196          //@}
00197 
00198          /// Postfix increment
00199          //@{
00200          iterator operator++(int) {
00201             iterator tmp(*this) ;
00202             ++*this ;
00203             return tmp ;
00204          }
00205          const iterator operator++(int) const {
00206             iterator tmp(*this) ;
00207             ++*this ;
00208             return tmp ;
00209          }
00210          //@}
00211 
00212          /// Prefix decrement
00213          //@{
00214                iterator& operator--()       {--m_iterator ; return *this ;}
00215          const iterator& operator--() const {--m_iterator ; return *this ;}
00216          //@}
00217 
00218          /// Postfix decrement
00219          //@{
00220          iterator operator--(int) {
00221             iterator tmp(*this) ;
00222             --*this ;
00223             return tmp ;
00224          }
00225          const iterator operator--(int) const {
00226             iterator tmp(*this) ;
00227             --*this ;
00228             return tmp ;
00229          }
00230          //@}
00231 
00232          /// Relational operators
00233          //@{
00234          operator bool() const {
00235             return m_iterator != m_vote.m_votes.end() ;
00236          }
00237          bool operator==(const iterator& it) const {
00238             return m_iterator == it.m_iterator ;
00239          }
00240          bool operator!=(const iterator& it) const {
00241             return ! operator==(it) ;
00242          }
00243          //@}
00244 
00245          /// Additional functions for Vote object iterators.
00246          //@{
00247          const Vote::VoteMap::key_type& direction() const {
00248             return m_iterator->first ;
00249          }
00250          const Vote::VoteMap::mapped_type& value()  const {
00251             return operator*() ;
00252          }
00253          //@}
00254       } ;
00255 
00256       /// Obtaining iterators for the vote object.
00257       //@{
00258       iterator begin() {return iterator(*this) ;}
00259       iterator end()   {return iterator(*this, true) ;}
00260       const iterator begin() const {return iterator(*this) ;}
00261       const iterator end()   const {return iterator(*this, true) ;}
00262       //@}
00263 
00264       /// An operator to add one vote to another.
00265       Vote& operator+=(const Vote& v) ;
00266 
00267       /// When many votes are added together, the result can go out of
00268       /// the [-1, +1] range. This method normalizes such votes so that
00269       /// all directions get a vote in the proper range.
00270       void normalize() ;
00271 
00272       /// Normalization requires finding the current min and max votes.
00273       /// However, sometimes, clients might obligingly have already done
00274       /// this. This method can be used when the current min and max vote
00275       /// values are known beforehand.
00276       void normalize(float min, float max) ;
00277 
00278       /// Helpers to return the turn direction parameters.
00279       //@{
00280       int num_directions() const {return m_votes.size() ;}
00281       //@}
00282 
00283       /// Turn arbiter vote clean-up.
00284       ~Vote() ;
00285 
00286       /// Debug support
00287       void dump(const std::string& caller = "Vote::dump") const ;
00288    } ;
00289 
00290 private:
00291    /// To aid with development and debugging, this arbiter supports a
00292    /// visualization callback, which needs the most recent vote so that
00293    /// it can perform the proper visualization.
00294    Vote m_vote ;
00295 
00296    /// Visualization routines to aid with development and debugging.
00297    void render_me() ;
00298 
00299 public:
00300    /// Turn arbiter clean-up.
00301    ~TurnArbiter() ;
00302 
00303 private:
00304    /// This inner class encapsulates various parameters that can be used
00305    /// to tweak different aspects of the turn arbiter.
00306    class Params : public singleton<Params> {
00307       /// The turn arbiter maintains a set of turn directions in which it
00308       /// can command the motors to go. These directions are specified
00309       /// with a max value and a step value. For example, max and step
00310       /// values of 30 and 10 would indicate that the robot can be
00311       /// commanded to turn in the directions corresponding to -30, -20,
00312       /// -10, 0, 10, 20 and 30 degrees.
00313       int m_turn_max, m_turn_step ;
00314 
00315       /// The turn arbiter tallies all the votes by applying a weighted
00316       /// sum procedure (where the weights are the behaviour priorities).
00317       /// It then smooths the resulting weighted sum by applying a
00318       /// Gaussian to adjacent vote values. The following parameter
00319       /// specifies the size of the smoothing window, i.e., it specifies
00320       /// how many neighbouring vote values should be considered while
00321       /// smoothing each one.
00322       int m_smoothing_width ;
00323 
00324       /// This parameter specifies the standard deviation to use for the
00325       /// Gaussian smoothing mentioned above. Since the Gaussian operates
00326       /// in turn command space, this standard deviation is in degrees.
00327       float m_sigma ;
00328 
00329       /// Private constructor because this is a singleton.
00330       Params() ;
00331 
00332       // Boilerplate code to make generic singleton design pattern work
00333       friend class singleton<Params> ;
00334 
00335    public:
00336       /// Accessing the various parameters.
00337       //@{
00338       static int   turn_max()        {return instance().m_turn_max  ;}
00339       static int   turn_step()       {return instance().m_turn_step ;}
00340       static int   smoothing_width() {return instance().m_smoothing_width ;}
00341       static float sigma()           {return instance().m_sigma ;}
00342       //@}
00343 
00344       /// Clean-up.
00345       ~Params() ;
00346    } ;
00347 
00348 public:
00349    /// Helpers to return some turn arbiter parameters used by other
00350    /// modules.
00351    //@{
00352    static int turn_max()  {return Params::turn_max()  ;}
00353    static int turn_step() {return Params::turn_step() ;}
00354    //@}
00355 } ;
00356 
00357 //------------------------- HELPER FUNCTIONS ----------------------------
00358 
00359 /// A convenience function to return a turn vote centered around a given
00360 /// angle, i.e., the returned vote is +1 for the given direction and
00361 /// falls linearly away from +1 as we fan outwards from the input angle.
00362 ///
00363 /// To illustrate how this function works, let us say that the supported
00364 /// steering directions go from -6 degrees (on the right) to +6 degrees
00365 /// (on the left) in steps of 3 degrees. That is, turn_max is 6 and
00366 /// turn_step is 3 and the supported steering directions are 6, 3, 0, -3,
00367 /// -6.
00368 ///
00369 /// If we would like to make a medium left turn, i.e., turn direction is
00370 /// 3, then the votes returned by this function will be +1 for 3 and less
00371 /// than that for the other directions. The amount by which the other
00372 /// directions' votes will be less depends on the turn_max and turn_step
00373 /// parameters. In this example, the vote step is 3/6 (step/max) or 0.5.
00374 /// Thus, the steering direction 3 will get a vote of +1; 6 and 0 will
00375 /// get 1 - 0.5 = 0.5; and -3 will get 1 - 2*0.5 = 0; and -6 will be
00376 /// assigned 1 - 3*.5 = -0.5. That is, the votes will look like so:
00377 ///
00378 ///                         6   3   0   -3   -6
00379 ///                        0.5  1  0.5   0  -0.5
00380 TurnArbiter::Vote turn_vote_centered_at(float direction) ;
00381 
00382 //-----------------------------------------------------------------------
00383 
00384 } // end of namespace encapsulating this file's definitions
00385 
00386 #endif
00387 
00388 /* So things look consistent in everyone's emacs... */
00389 /* Local Variables: */
00390 /* indent-tabs-mode: nil */
00391 /* End: */
Generated on Sun May 8 08:41:30 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3