00001 /** 00002 \file Robots/LoBot/control/LoRemoteControl.C 00003 \brief This file defines the non-inline member functions of the 00004 lobot::RemoteControl 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/LoRemoteControl.C $ 00039 // $Id: LoRemoteControl.C 13521 2010-06-06 14:23:03Z mviswana $ 00040 // 00041 00042 //------------------------------ HEADERS -------------------------------- 00043 00044 // lobot headers 00045 #include "Robots/LoBot/control/LoRemoteControl.H" 00046 #include "Robots/LoBot/control/LoTurnArbiter.H" 00047 #include "Robots/LoBot/control/LoSpeedArbiter.H" 00048 00049 #include "Robots/LoBot/LoApp.H" 00050 #include "Robots/LoBot/io/LoRobot.H" 00051 #include "Robots/LoBot/config/LoConfigHelpers.H" 00052 #include "Robots/LoBot/thread/LoUpdateLock.H" 00053 00054 #include "Robots/LoBot/misc/LoExcept.H" 00055 #include "Robots/LoBot/misc/LoRegistry.H" 00056 #include "Robots/LoBot/util/LoMath.H" 00057 #include "Robots/LoBot/util/LoTime.H" 00058 00059 #include "Robots/LoBot/irccm/LoOpenInterface.h" 00060 00061 //----------------------------- NAMESPACE ------------------------------- 00062 00063 namespace lobot { 00064 00065 //--------------------------- LOCAL HELPERS ----------------------------- 00066 00067 // Retrieve settings from extricate section of config file 00068 template<typename T> 00069 static inline T conf(const std::string& key, const T& default_value) 00070 { 00071 return get_conf<T>(LOBE_REMOTE_CONTROL, key, default_value) ; 00072 } 00073 00074 // Freeze the arbiters to the given behaviour's priority so that 00075 // behaviours with lower priority will be ignored. 00076 static inline void freeze_arbiters(const std::string& name) 00077 { 00078 TurnArbiter::instance().freeze(name) ; 00079 SpeedArbiter::instance().freeze(name) ; 00080 } 00081 00082 // Unfreeze the arbiters so that other behaviours can resume having their 00083 // actions processed. 00084 static inline void unfreeze_arbiters(const std::string& name) 00085 { 00086 TurnArbiter::instance().unfreeze(name) ; 00087 SpeedArbiter::instance().unfreeze(name) ; 00088 } 00089 00090 // Returns true if the remote control command code received from the 00091 // robot's sensors corresponds to one of the buttons this behaviour 00092 // recognizes. 00093 static bool supported_command(int c) 00094 { 00095 switch (c) 00096 { 00097 case LOBOT_OI_REMOTE_LEFT: 00098 case LOBOT_OI_REMOTE_RIGHT: 00099 case LOBOT_OI_REMOTE_PAUSE: 00100 case LOBOT_OI_REMOTE_CLEAN: 00101 case LOBOT_OI_REMOTE_FORWARD: 00102 return true ; 00103 default: 00104 return false ; 00105 } 00106 } 00107 00108 //-------------------------- INITIALIZATION ----------------------------- 00109 00110 RemoteControl::RemoteControl() 00111 : base(clamp(conf("update_delay", 500), 1, 2500)), 00112 m_state(AUTONOMOUS), 00113 m_time(0) 00114 { 00115 start(LOBE_REMOTE_CONTROL) ; 00116 } 00117 00118 void RemoteControl::pre_run() 00119 { 00120 if (! App::robot()) 00121 throw behavior_error(MOTOR_SYSTEM_MISSING) ; 00122 } 00123 00124 //---------------------- THE BEHAVIOUR'S ACTION ------------------------- 00125 00126 // The remote control behaviour works by checking the robot's sensors to 00127 // see if a remote control command has been sent. If so, it transitions 00128 // to the REMOTE_CONTROL state and executes the specified command. While 00129 // in the REMOTE_CONTROL state, if no more remote control commands come 00130 // in within the configured timeout, the behaviour releases the arbiters 00131 // and returns to the AUTONOMOUS state. 00132 void RemoteControl::action() 00133 { 00134 UpdateLock::begin_read() ; 00135 int ir = App::robot()->sensors().infrared() ; // remote control IR byte 00136 UpdateLock::end_read() ; 00137 00138 switch (m_state) 00139 { 00140 case AUTONOMOUS: 00141 if (supported_command(ir)) 00142 { 00143 freeze_arbiters(base::name) ; 00144 execute(ir) ; 00145 m_state = REMOTE_CONTROL ; 00146 m_time = current_time() ; 00147 } 00148 break ; 00149 case REMOTE_CONTROL: 00150 if (current_time() - m_time <= Params::timeout()) 00151 { 00152 if (supported_command(ir)) 00153 { 00154 execute(ir) ; 00155 m_time = current_time() ; 00156 } 00157 } 00158 else // timed out without getting (valid) remote control command 00159 { 00160 m_state = AUTONOMOUS ; 00161 m_time = 0 ; 00162 unfreeze_arbiters(base::name) ; 00163 } 00164 break ; 00165 } 00166 } 00167 00168 // Execute the command specified by the remote control 00169 void RemoteControl::execute(int cmd) 00170 { 00171 switch (cmd) 00172 { 00173 case LOBOT_OI_REMOTE_FORWARD: 00174 TurnArbiter::instance().vote(base::name, 00175 new TurnArbiter::Vote(turn_vote_centered_at(0))) ; 00176 SpeedArbiter::instance().vote(base::name, 00177 new SpeedArbiter::Vote(Params::drive_speed(), 0)) ; 00178 break ; 00179 00180 case LOBOT_OI_REMOTE_CLEAN: // use clean button for driving backwards 00181 TurnArbiter::instance().vote(base::name, 00182 new TurnArbiter::Vote(turn_vote_centered_at(0))) ; 00183 SpeedArbiter::instance().vote(base::name, 00184 new SpeedArbiter::Vote(-Params::drive_speed(), 0)) ; 00185 break ; 00186 00187 case LOBOT_OI_REMOTE_PAUSE: 00188 TurnArbiter::instance().vote(base::name, 00189 new TurnArbiter::Vote(turn_vote_centered_at(0))) ; 00190 SpeedArbiter::instance().vote(base::name, 00191 new SpeedArbiter::Vote(0, 0)) ; 00192 break ; 00193 00194 case LOBOT_OI_REMOTE_LEFT: 00195 TurnArbiter::instance().vote(base::name, new TurnArbiter::Vote( 00196 turn_vote_centered_at(TurnArbiter::turn_max()))) ; 00197 SpeedArbiter::instance().vote(base::name, 00198 new SpeedArbiter::Vote(Params::turn_speed(), 0)) ; 00199 break ; 00200 00201 case LOBOT_OI_REMOTE_RIGHT: 00202 TurnArbiter::instance().vote(base::name, new TurnArbiter::Vote( 00203 turn_vote_centered_at(-TurnArbiter::turn_max()))) ; 00204 SpeedArbiter::instance().vote(base::name, 00205 new SpeedArbiter::Vote(Params::turn_speed(), 0)) ; 00206 break ; 00207 } 00208 } 00209 00210 //----------------------------- CLEAN-UP -------------------------------- 00211 00212 RemoteControl::~RemoteControl(){} 00213 00214 //-------------------------- KNOB TWIDDLING ----------------------------- 00215 00216 // Parameters initialization 00217 RemoteControl::Params::Params() 00218 : m_timeout(clamp(conf("timeout", 1000), 100, 5000)), 00219 m_drive_speed(clamp(conf("drive_speed", 0.3f), 0.1f, 0.5f)), 00220 m_turn_speed (clamp(conf("turn_speed", 0.2f), 0.1f, 0.5f)) 00221 {} 00222 00223 // Parameters clean-up 00224 RemoteControl::Params::~Params(){} 00225 00226 //----------------------------------------------------------------------- 00227 00228 } // end of namespace encapsulating this file's definitions 00229 00230 /* So things look consistent in everyone's emacs... */ 00231 /* Local Variables: */ 00232 /* indent-tabs-mode: nil */ 00233 /* End: */