LoRemote.c

Go to the documentation of this file.
00001 /**
00002    \file  Robots/LoBot/irccm/LoRemote.c
00003    \brief Implementation of the low-level remote control module.
00004 */
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 
00038 /*
00039    Primary maintainer for this file: mviswana usc edu
00040    $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Robots/LoBot/irccm/LoRemote.c $
00041    $Id: LoRemote.c 13768 2010-08-07 23:41:41Z mviswana $
00042 */
00043 
00044 /*------------------------------ HEADERS ------------------------------*/
00045 
00046 // lobot headers
00047 #include "LoDrive.h"
00048 #include "LoSensors.h"
00049 #include "LoIO.h"
00050 #include "LoTimer.h"
00051 #include "LoCMInterface.h"
00052 #include "LoOpenInterface.h"
00053 
00054 /*----------------------------- CONSTANTS -----------------------------*/
00055 
00056 // The remote control module works by checking the robot's sensors to see
00057 // if a remote control command has been sent. If so, it transitions to
00058 // the REMOTE_CONTROL state and executes the specified command. While in
00059 // the REMOTE_CONTROL state, if no more remote control commands come in
00060 // within the predefined timeout, the module releases the motors and
00061 // returns to the AUTONOMOUS state.
00062 //
00063 // This enumeration defines symbolic constants for the above-mentioned
00064 // two states.
00065 enum {
00066    AUTONOMOUS,
00067    REMOTE_CONTROL,
00068 } ;
00069 
00070 // Some parameters for this module
00071 enum {
00072    LOBOT_REMOTE_DRIVE_SPEED = 250,
00073    LOBOT_REMOTE_TURN_SPEED  = 100,
00074 
00075    LOBOT_REMOTE_TIMEOUT = 1500,
00076 
00077    LOBOT_POWER_DEBOUNCE = 5,
00078 } ;
00079 
00080 /*------------------------------ GLOBALS ------------------------------*/
00081 
00082 // This variable is used to keep track of the current state of the remote
00083 // control module.
00084 static char g_state ;
00085 
00086 // As mentioned earlier, the remote control module works by keeping track
00087 // of how long it has been since the most recent remote control command
00088 // was received and reverting to normal autonomous operation on timeout.
00089 // This variable is used to time-stamp the remote control commands.
00090 static unsigned long g_time ;
00091 
00092 // A data buffer for keeping track of pending ACK_REMOTE messages. The
00093 // first byte of this buffer is used to store the ACK_REMOTE message
00094 // itself; the remaining bytes are for the actual data that is sent with
00095 // the acknowledgement.
00096 static char g_remote[LOBOT_REMOTE_SIZE + 1] ;
00097 
00098 // To help debounce the 'P' button press and ensure that user really does
00099 // want to quit the lobot controller and dock the robot, we use a counter
00100 // and return true for the "quit event" only if the counter has reached
00101 // its minimum threshold (viz., LOBOT_POWER_DEBOUNCE).
00102 static char g_power_count ;
00103 
00104 /*------------------------- LOW-LEVEL ACTIONS -------------------------*/
00105 
00106 // This helper function returns true if the specified IR byte corresponds
00107 // to a supported remote control command; false otherwise.
00108 static char supported_cmd(char c)
00109 {
00110    switch (c)
00111    {
00112       case LOBOT_OI_REMOTE_LEFT:
00113       case LOBOT_OI_REMOTE_RIGHT:
00114       case LOBOT_OI_REMOTE_PAUSE:
00115       case LOBOT_OI_REMOTE_CLEAN:
00116       case LOBOT_OI_REMOTE_FORWARD:
00117       case LOBOT_OI_REMOTE_POWER:
00118       case LOBOT_OI_REMOTE_SPOT:
00119       case LOBOT_OI_REMOTE_MAX:
00120          return 1 ;
00121       default:
00122          return 0 ;
00123    }
00124 }
00125 
00126 // Helper function to respond to each of the remote control commands
00127 static void execute(char ir_cmd)
00128 {
00129    switch (ir_cmd)
00130    {
00131       case LOBOT_OI_REMOTE_FORWARD:
00132          lo_drive(LOBOT_REMOTE_DRIVE_SPEED, LOBOT_OI_DRIVE_STRAIGHT, 1) ;
00133          break ;
00134       case LOBOT_OI_REMOTE_CLEAN: // use clean button for driving backwards
00135          lo_drive(-LOBOT_REMOTE_DRIVE_SPEED, LOBOT_OI_DRIVE_STRAIGHT, 1) ;
00136          break ;
00137       case LOBOT_OI_REMOTE_PAUSE:
00138          lo_stop_immediate() ;
00139          break ;
00140       case LOBOT_OI_REMOTE_LEFT:
00141          lo_drive(LOBOT_REMOTE_TURN_SPEED, LOBOT_OI_TURN_INPLACE_CCW, 0) ;
00142          break ;
00143       case LOBOT_OI_REMOTE_RIGHT:
00144          lo_drive(LOBOT_REMOTE_TURN_SPEED, LOBOT_OI_TURN_INPLACE_CW, 0) ;
00145          break ;
00146       case LOBOT_OI_REMOTE_SPOT:
00147          lo_toggle_rear_bumps() ;
00148          break ;
00149       case LOBOT_OI_REMOTE_MAX:
00150          lo_toggle_rear_bumps_spin() ;
00151          break ;
00152       case LOBOT_OI_REMOTE_POWER:
00153          ++g_power_count ;
00154          return ; // important: no ACK_REMOTE when 'P' button is pressed
00155    }
00156 
00157    // Every time we execute a remote control command, we mark an
00158    // acknowledgement as pending.
00159    g_remote[0] = LOBOT_ACK_REMOTE ;
00160    g_remote[1] = ir_cmd ;
00161 }
00162 
00163 // The remote control module works by maintaining an internal state. When
00164 // the user presses a supported remote control button, it transitions to
00165 // the REMOTE_CONTROL state and takes over the robot's motors. When it
00166 // times out waiting for a remote control command, it reverts to the
00167 // AUTONOMOUS state and relinquishes the robot's motors so that normal
00168 // operation may continue.
00169 //
00170 // DEVNOTE: This function does not check to see if sensor data is
00171 // available before retrieving the infrared byte from the LoSensors
00172 // module. The main program should take care of that, i.e., check that
00173 // sensor data is actually available before calling this function. We do
00174 // it like this because there are other low-level sensor reaction modules
00175 // and all of them would have to keep checking the same flag over and
00176 // over again. Much nicer if the main program checks the sensor data
00177 // availability flag once and then calls all the sensor reaction
00178 // functions one-by-one.
00179 void lo_remote(void)
00180 {
00181    char ir = lo_get_sensor(LOBOT_SENSORS_INFRARED_BYTE) ;
00182    switch (g_state)
00183    {
00184       case AUTONOMOUS:
00185          if (supported_cmd(ir))
00186          {
00187             execute(ir) ;
00188             g_state = REMOTE_CONTROL ;
00189             g_time  = lo_ticks() ;
00190          }
00191          break ;
00192       case REMOTE_CONTROL:
00193          if (lo_ticks() - g_time <= LOBOT_REMOTE_TIMEOUT)
00194          {
00195             if (supported_cmd(ir))
00196             {
00197                execute(ir) ;
00198                g_time = lo_ticks() ;
00199             }
00200          }
00201          else
00202          {
00203             g_state = AUTONOMOUS ;
00204             g_time  = 0 ;
00205             g_power_count = 0 ;
00206          }
00207          break ;
00208    }
00209 }
00210 
00211 /*------------------ REMOTE CONTROL ACKNOWLEDGEMENTS ------------------*/
00212 
00213 // When the low level responds to remote control commands, it lets the
00214 // high level know. This function checks if a ACK_REMOTE message is
00215 // pending or not.
00216 char lo_remote_pending(void)
00217 {
00218    return g_remote[0] == LOBOT_ACK_REMOTE ;
00219 }
00220 
00221 // Send pending remote control acknowledgement to the high level
00222 void lo_send_remote(void)
00223 {
00224    for (unsigned char i = 0; i < LOBOT_REMOTE_SIZE + 1; ++i)
00225       lo_tx(g_remote[i]) ;
00226 
00227    // Sensor data no longer pending after being sent to high level
00228    g_remote[0] = 0 ;
00229 }
00230 
00231 /*------------------- REMOTE CONTROL STATE QUERIES --------------------*/
00232 
00233 // Check if the user is remote controlling the robot or whether it is
00234 // operating autonomously.
00235 char lo_is_remote_control(void)
00236 {
00237    return g_state == REMOTE_CONTROL ;
00238 }
00239 
00240 // Returns true if the Roomba Remote's 'P' button has been pressed;
00241 // false otherwise.
00242 char lo_remote_quit(void)
00243 {
00244    return g_power_count >= LOBOT_POWER_DEBOUNCE ;
00245 }
Generated on Sun May 8 08:05:55 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3