00001 /** 00002 \file Robots/LoBot/control/LoSpeedArbiter.C 00003 \brief This file defines the non-inline member functions of the 00004 lobot::SpeedArbiter 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/LoSpeedArbiter.C $ 00039 // $Id: LoSpeedArbiter.C 13521 2010-06-06 14:23:03Z mviswana $ 00040 // 00041 00042 //------------------------------ HEADERS -------------------------------- 00043 00044 // lobot headers 00045 #include "Robots/LoBot/control/LoSpeedArbiter.H" 00046 00047 #include "Robots/LoBot/config/LoConfigHelpers.H" 00048 #include "Robots/LoBot/thread/LoUpdateLock.H" 00049 00050 #include "Robots/LoBot/misc/LoExcept.H" 00051 #include "Robots/LoBot/util/LoMath.H" 00052 00053 // INVT utilities 00054 #include "Util/log.H" 00055 00056 // Standard C++ headers 00057 #include <algorithm> 00058 00059 //------------------------------ MACROS --------------------------------- 00060 00061 // As a debugging aid, it can be useful to see how long an arbiter holds 00062 // on to a vote before forwarding it to the motor system. This symbol can 00063 // be turned on/off to enable/disable printing the above-mentioned 00064 // vote-to-motor delay. 00065 //#define LOBOT_PRINT_VOTE_TO_MOTOR_DELAY 1 00066 00067 //----------------------------- NAMESPACE ------------------------------- 00068 00069 namespace lobot { 00070 00071 //--------------------------- LOCAL HELPERS ----------------------------- 00072 00073 // Retrieve settings from speed_arbiter section of config file 00074 template<typename T> 00075 static inline T conf(const std::string& key, const T& default_value) 00076 { 00077 return get_conf<T>("speed_arbiter", key, default_value) ; 00078 } 00079 00080 //-------------------------- INITIALIZATION ----------------------------- 00081 00082 SpeedArbiter::SpeedArbiter() 00083 : Arbiter(clamp(conf("update_delay", 500), 1, 1000)) 00084 { 00085 start("speed_arbiter") ; 00086 } 00087 00088 float SpeedArbiter::get_configured_priority(const std::string& behaviour) const 00089 { 00090 return abs(get_conf(behaviour, "speed_priority", 0.0f)) ; 00091 } 00092 00093 SpeedArbiter::Vote::Vote(float speed, int pwm) 00094 : m_speed(speed), m_pwm(pwm) 00095 {} 00096 00097 //-------------------------- MOTOR COMMANDS ----------------------------- 00098 00099 // According to Rosenblatt, to issue an appropriate motor command, the 00100 // DAMN speed arbiter simply picks the minimum speed that will satisfy 00101 // all the behaviours. 00102 // 00103 // However, for Robolocust, we prefer to take the behaviour priorities 00104 // into account. Otherwise, for example, the extricate behaviour may 00105 // never get to do its thing if the emergency_stop behaviour is always 00106 // voting for a full stop. By issuing the drive commands of the highest 00107 // priority behaviour, we ensure that low priority behaviours issuing 00108 // lower speed commands don't override the directives of higher priority 00109 // behaviours voting for higher speeds. 00110 void SpeedArbiter::motor_cmd(const Arbiter::Votes& votes, Robot* robot) 00111 { 00112 Arbiter::Votes::const_iterator max_priority = 00113 std::max_element(votes.begin(), votes.end(), compare_priorities(this)) ; 00114 00115 const vote_data* D = *max_priority ; 00116 const Vote* V = dynamic_cast<Vote*>(D->vote) ; 00117 //LERROR("vote: %-15s %10.3f [%5.2f %4d]", 00118 //D->behavior_name.c_str(), D->vote_time, V->speed(), V->pwm()) ; 00119 00120 UpdateLock::begin_write() ; 00121 #ifdef LOBOT_PRINT_VOTE_TO_MOTOR_DELAY 00122 LERROR("%-15s vote-to-motor delay = %5lld ms", 00123 D->behavior_name.c_str(), current_time() - D->vote_time) ; 00124 #endif 00125 robot->drive(V->speed(), V->pwm()) ; 00126 UpdateLock::end_write() ; 00127 } 00128 00129 // Helper function object to compare votes based on the priorities of the 00130 // behaviours that cast them. 00131 SpeedArbiter::compare_priorities::compare_priorities(const SpeedArbiter* A) 00132 : arbiter(A) 00133 {} 00134 00135 bool 00136 SpeedArbiter::compare_priorities:: 00137 operator()(const vote_data* a, const vote_data* b) const 00138 { 00139 return arbiter->priority(a->behavior_name) 00140 < arbiter->priority(b->behavior_name) ; 00141 } 00142 00143 //----------------------- TURN ARBITER CLEAN-UP ------------------------- 00144 00145 SpeedArbiter::~SpeedArbiter(){} 00146 00147 //----------------------------------------------------------------------- 00148 00149 } // end of namespace encapsulating this file's definitions 00150 00151 /* So things look consistent in everyone's emacs... */ 00152 /* Local Variables: */ 00153 /* indent-tabs-mode: nil */ 00154 /* End: */