00001 /*!@file Roomba.C Simple roomba class to interact with irobot create */ 00002 00003 //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00005 // University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Farhan Baluch <fbaluch@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Robots/IRobot/Roomba.C $ 00035 // $Id: Roomba.C 12962 2010-03-06 02:13:53Z irock $ 00036 // 00037 00038 00039 #include "Robots/IRobot/Roomba.H" 00040 #include "Devices/Serial.H" 00041 #include "Component/OptionManager.H" 00042 #include "Util/Timer.H" 00043 #include <vector> 00044 00045 00046 #define SERIAL_TIMEOUT 1.0 //The maximum number of seconds to wait for a serial response 00047 00048 // ###################################################################### 00049 Roomba::Roomba(OptionManager& mgr, const std::string& descrName, 00050 const std::string& tagName, const char *defdev) : 00051 ModelComponent(mgr, descrName, tagName),itsPort(new Serial(mgr,"roomba-serial","roomba-serial")) 00052 { 00053 00054 // set a default config for our serial port: 00055 itsPort->configure(defdev, 57600, "8N1", false, false, 1); 00056 // attach our port as a subcomponent: 00057 addSubComponent(itsPort); 00058 itsSpeed = 0; 00059 itsRadius =0; 00060 itsAngle=0; 00061 itsDist = 0; 00062 } 00063 00064 00065 // ###################################################################### 00066 Roomba::~Roomba() 00067 {} 00068 00069 00070 // ###################################################################### 00071 int Roomba::getSpeed() 00072 { 00073 return itsSpeed; 00074 } 00075 00076 // ###################################################################### 00077 int Roomba::getRadius() 00078 { 00079 return itsRadius; 00080 } 00081 00082 00083 // ###################################################################### 00084 int Roomba::getAngle() 00085 { 00086 return itsAngle; 00087 } 00088 00089 // ###################################################################### 00090 int Roomba::getDist() 00091 { 00092 return itsDist; 00093 } 00094 00095 // ###################################################################### 00096 void Roomba::setSpeed(const int speed) 00097 { 00098 if(!robotStarted) 00099 LFATAL("You must send start command first"); 00100 00101 itsSpeed = speed; 00102 sendDriveCommand(); 00103 } 00104 00105 // ###################################################################### 00106 void Roomba::setRadius(const int radius) 00107 { 00108 if(!robotStarted) 00109 LFATAL("You must send start command first"); 00110 00111 itsRadius = radius; 00112 sendDriveCommand(); 00113 } 00114 00115 // ###################################################################### 00116 void Roomba::sendDriveCommand() 00117 { 00118 if(!robotStarted) 00119 LFATAL("You must send start command first"); 00120 00121 unsigned char cmd[5]; 00122 cmd[0] = 137; //drive command 00123 cmd[1] = ((short int)itsSpeed&0x00FF00)>>8; //velocity high byte 00124 cmd[2] = ((short int)itsSpeed&0x0000FF); //velocity low byte 00125 00126 if (itsRadius == 0) //drive striaght 00127 { 00128 cmd[3] = 0x7F; //Radius high byte 00129 cmd[4] = 0xFF; //Radius low byte 00130 } 00131 else { 00132 cmd[3] = ((short int)itsRadius&0x00FF00)>>8; //Radius high byte 00133 cmd[4] = ((short int)itsRadius&0x0000FF); //Radius low byte 00134 } 00135 00136 00137 itsPort->write(cmd, 5); 00138 usleep(15*1000); 00139 00140 } 00141 00142 // ###################################################################### 00143 void Roomba::sendStart() 00144 { 00145 unsigned char cmd[1]; 00146 cmd[0] = 128; 00147 itsPort->write(cmd,1); 00148 usleep(15*1000); 00149 robotStarted = 1; 00150 } 00151 // ###################################################################### 00152 void Roomba::setMode(const int mode) 00153 { 00154 unsigned char cmd[1]; 00155 cmd[0] = 0; 00156 00157 switch(mode) 00158 { 00159 case 1: cmd[0] = 131; break; //safemode 00160 case 2: cmd[0] = 132; break; //fullmode 00161 default: LFATAL("bad mode bye"); 00162 }; 00163 00164 itsPort->write(cmd, 1); 00165 usleep(15*1000); 00166 } 00167 00168 // ###################################################################### 00169 void Roomba::setDemo(const short demo) 00170 { 00171 unsigned char cmd[2]; 00172 cmd[0] = 136; 00173 cmd[1] = demo; 00174 00175 itsPort->write(cmd,1); 00176 00177 } 00178 00179 // ###################################################################### 00180 void Roomba::setLED(const short led, const short color, const short intensity) 00181 { 00182 unsigned char cmd[4]; 00183 cmd[0] = 139; 00184 00185 switch(led) 00186 { 00187 case 1: cmd[1] = 8; break; //Advance LED 00188 case 2: cmd[1] = 2; break; //Play Led 00189 case 3: cmd[1] = 10; break; //Both Led 00190 default: cmd[1] = 0; //default to turn off 00191 }; 00192 00193 cmd[2] = color; 00194 cmd[3] = intensity; 00195 00196 itsPort->write(cmd,4); 00197 00198 } 00199 00200 // ###################################################################### 00201 void Roomba::playSong(int song) 00202 { 00203 // The imperial March Song 00204 // G G G E Bb G E Bb G 2D 2D 2D 2Eb Bb F# E Bb G 00205 // 55 55 55 52 58 55 52 58 55 62 62 62 63 58 54 51 58 55 00206 unsigned char s1[21] = {140, 0, 9, 55, 30, 55, 30, 55, 30, 51, 30, 58, 12, 55, 30, 51, 30, 58, 12, 55, 30}; 00207 //unsigned char s2[21] = {140, 0, 9, 55, 30, 55, 30, 55, 30, 51, 30, 58, 12, 55, 30, 51, 30, 58, 12, 55, 30}; 00208 unsigned char s2[21] = {140, 1, 9, 62, 30, 62, 30, 62, 30, 63, 30, 58, 12, 54, 30, 51, 30, 58, 12, 55, 30}; 00209 00210 unsigned char cmd[2] ; 00211 00212 itsPort->write(s1,21); 00213 itsPort->write(s2,21); 00214 00215 cmd[0] = 141; 00216 cmd[1] = (short)song; 00217 00218 itsPort->write(cmd,2); 00219 } 00220 00221 00222 // ###################################################################### 00223 void Roomba::getDistanceAngle(int& dist,int& ang) 00224 { 00225 00226 unsigned char buff[255]; 00227 int len = itsPort->read(buff,255); 00228 printf("%d bytes cleared\n",len); 00229 00230 //Query the distance and angle sensors 00231 unsigned char cmd[4]; 00232 unsigned char data[255]; 00233 cmd[0] = 149; //Query list opcode 00234 cmd[1] = 2; //we need two sensors 00235 cmd[2] = 19; //distance 00236 cmd[3] = 20; //angle 00237 00238 itsPort->write(cmd,4); 00239 00240 usleep(10*1000); 00241 00242 //get the data 00243 len = itsPort->read(data, 4); 00244 std::vector<byte> data_rcvd; 00245 for(int i=0; i<len; i++) data_rcvd.push_back(data[i]); 00246 00247 Timer serialTimeout; 00248 serialTimeout.reset(); 00249 while(data_rcvd.size() < 4 && serialTimeout.getSecs() < SERIAL_TIMEOUT) 00250 { 00251 len = itsPort->read(data, 4); 00252 for(int i=0; i<len; i++) data_rcvd.push_back(data[i]); 00253 } 00254 double timeToRcv = serialTimeout.getSecs(); 00255 00256 00257 00258 printf("Read dist angle bytes %i\n", data_rcvd.size()); 00259 short int rDist = 0, rAng = 0; 00260 if (data_rcvd.size() == 4) 00261 { 00262 //printf("%i %i %i %i\n\n", 00263 //data[0], data[1], data[2], data[3]); 00264 00265 rDist = (int16_t)((data_rcvd[0]<<8) | data_rcvd[1]); 00266 rAng = (int16_t)((data_rcvd[2]<<8) | data_rcvd[3]); 00267 00268 } 00269 else 00270 LERROR("Read return = %d bytes -- took %fs", data_rcvd.size(), timeToRcv); 00271 00272 LINFO("Read Took %fs", timeToRcv); 00273 dist= rDist; 00274 ang = rAng; 00275 itsDist = dist; 00276 itsAngle = ang; 00277 } 00278 00279 // ###################################################################### 00280 void Roomba::sendRawCmd(const std::string& data) 00281 { 00282 } 00283 00284 // ###################################################################### 00285 void Roomba::sendDirectDriveCommand(float itsCurrentSteering) 00286 { 00287 00288 int rightWheel = (int)((itsSpeed*500) + (itsCurrentSteering*500)); 00289 int leftWheel = (int)((itsSpeed*500) - (itsCurrentSteering*500)); 00290 00291 if (rightWheel > 500) rightWheel = 500; 00292 if (rightWheel < -500) rightWheel = -500; 00293 00294 if (leftWheel > 500) leftWheel = 500; 00295 if (leftWheel < -500) leftWheel = -500; 00296 00297 unsigned char cmd[5]; 00298 cmd[0] = 145; //Direct drive command 00299 cmd[1] = ((short int)rightWheel&0xFFFF)>>8; //Right Wheel high byte 00300 cmd[2] = ((short int)rightWheel&0xFF); //Right Wheel low byte 00301 00302 cmd[3] = ((short int)leftWheel&0xFFFF)>>8; //Left Wheel high byte 00303 cmd[4] = ((short int)leftWheel&0xFF); //Left Wheel low byte 00304 00305 itsPort->write(cmd,5); 00306 } 00307 00308 // ###################################################################### 00309 /* So things look consistent in everyone's emacs... */ 00310 /* Local Variables: */ 00311 /* indent-tabs-mode: nil */ 00312 /* End: */ 00313 00314 00315 00316 00317 00318 00319 00320 00321 00322 00323 00324 00325 00326