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