00001 /*!@file Beobot/beobot-BeobotControl.C 00002 controls the Beobot motion input can be from both remote and Board A */ 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: Christian Siagian <siagian@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Beobot/beobot-BeobotControl.C $ 00035 // $Id: beobot-BeobotControl.C 7063 2006-08-29 18:26:55Z rjpeters $ 00036 // 00037 00038 #include "Component/ModelManager.H" 00039 #include "Devices/BeoChip.H" 00040 #include "Devices/DeviceOpts.H" 00041 #include "Beobot/BeobotConfig.H" 00042 #include "Beobot/BeobotControl.H" 00043 #include "Util/MathFunctions.H" 00044 00045 #include <cstdlib> 00046 00047 #include "Beowulf/Beowulf.H" 00048 #include "Util/Types.H" 00049 #include "Util/log.H" 00050 00051 #include <cstring> 00052 #include <signal.h> 00053 #include <time.h> 00054 #include <unistd.h> 00055 00056 static bool goforever = true; 00057 // ###################################################################### 00058 void terminate(int s) { LERROR("*** INTERRUPT ***"); goforever = false; exit(1);} 00059 00060 // ###################################################################### 00061 //! Our own little BeoChipListener 00062 class MyBeoChipListener : public BeoChipListener 00063 { 00064 public: 00065 MyBeoChipListener(nub::soft_ref<BeoChip> bc) : 00066 itsBeoChip(bc), minp0(9999), maxp0(0), minp1(9999), maxp1(0), 00067 counter0(0), counter1(0), kbd(0x1f) 00068 { 00069 performCommand = false; 00070 } 00071 00072 virtual ~MyBeoChipListener() { } 00073 00074 virtual void event(const BeoChipEventType t, const int valint, 00075 const float valfloat) 00076 { 00077 LDEBUG("Event: %d val = %d, fval = %f", int(t), valint, valfloat); 00078 switch(t) 00079 { 00080 case PWM0: 00081 if (valint < minp0) minp0 = valint; 00082 else if (valint > maxp0) maxp0 = valint; 00083 itsBeoChip->setServo(0, valfloat); 00084 00085 if(performCommand) 00086 { 00087 if (++counter0 >= 10) 00088 { 00089 itsBeoChip->lcdPrintf(5, 2, "%04d %04d-%04d", 00090 valint, minp0, maxp0); 00091 itsBeoChip->lcdPrintf(6, 1, "%03d", 00092 itsBeoChip->getServoRaw(0)); 00093 counter0 = 0; 00094 } 00095 } 00096 break; 00097 case PWM1: 00098 if (valint < minp1) minp1 = valint; 00099 else if (valint > maxp1) maxp1 = valint; 00100 00101 if(performCommand) 00102 { 00103 itsBeoChip->setServo(1, valfloat); 00104 if (++counter1 >= 10) 00105 { 00106 itsBeoChip->lcdPrintf(5, 3, "%04d %04d-%04d", 00107 valint, minp1, maxp1); 00108 itsBeoChip->lcdPrintf(17, 1, "%03d", 00109 itsBeoChip->getServoRaw(1)); 00110 counter1 = 0; 00111 } 00112 } 00113 break; 00114 case KBD: kbd = valint; break; 00115 case RESET: LERROR("BeoChip RESET occurred!"); break; 00116 case ECHOREP: LINFO("BeoChip Echo reply received."); break; 00117 case INOVERFLOW: LERROR("BeoChip input overflow!"); break; 00118 case SERIALERROR: LERROR("BeoChip serial error!"); break; 00119 case OUTOVERFLOW: LERROR("BeoChip output overflow!"); break; 00120 default: LERROR("Unknown event %d received!", int(t)); break; 00121 } 00122 } 00123 00124 nub::soft_ref<BeoChip> itsBeoChip; 00125 int minp0, maxp0, minp1, maxp1; 00126 int counter0, counter1; 00127 int kbd; 00128 bool performCommand; 00129 }; 00130 00131 // ###################################################################### 00132 //! Drive the Beobot under remote control and Board A 00133 /*! This simple test program demonstrate how to capture PWM signals 00134 from the Beochip, which on the Beobot correspond to steering and 00135 speed inputs from the remote control. The captured signals are then 00136 directly fed into the Beobot's steering and speed servos controlled 00137 by BeobotControl class (which has the BeoChip). */ 00138 int main(const int argc, const char* argv[]) 00139 { 00140 MYLOGVERB = LOG_INFO; 00141 00142 // instantiate a model manager: 00143 ModelManager manager("beobot-BeobotControl"); 00144 00145 // Instantiate our various ModelComponents: 00146 BeobotConfig bbc; 00147 nub::soft_ref<BeoChip> b(new BeoChip(manager)); 00148 manager.addSubComponent(b); 00149 00150 nub::soft_ref<BeobotControl> bc(new BeobotControl(b, manager)); 00151 manager.addSubComponent(bc); 00152 00153 nub::soft_ref<Beowulf> 00154 beo(new Beowulf(manager, "Beowulf Slave", "BeowulfSlave", false)); 00155 manager.addSubComponent(beo); 00156 00157 // Parse command-line: 00158 if (manager.parseCommandLine(argc, argv, "<serdev>", 1, 1) == false) 00159 return(1); 00160 00161 // let's configure our serial device: 00162 b->setModelParamVal("BeoChipDeviceName", manager.getExtraArg(0)); 00163 00164 // let's register our listener: 00165 rutz::shared_ptr<MyBeoChipListener> lis(new MyBeoChipListener(b)); 00166 rutz::shared_ptr<BeoChipListener> lis2; lis2.dynCastFrom(lis); // cast down 00167 b->setListener(lis2); 00168 00169 // setup signal handling: 00170 signal(SIGHUP, terminate); signal(SIGINT, terminate); 00171 signal(SIGQUIT, terminate); signal(SIGTERM, terminate); 00172 00173 TCPmessage rmsg; // message being received and to process 00174 TCPmessage smsg; // message being sent 00175 00176 // let's get all our ModelComponent instances started: 00177 manager.start(); 00178 00179 // reset the beochip: 00180 LINFO("Resetting BeoChip..."); 00181 b->resetChip(); sleep(1); 00182 00183 // keep the gear at the lowest speed/highest torque 00184 b->setServoRaw(bbc.gearServoNum, bbc.gearMinVal); 00185 00186 // turn on the keyboard 00187 b->debounceKeyboard(true); 00188 b->captureKeyboard(true); 00189 00190 // calibrate the PWMs: 00191 b->calibratePulse(0, 00192 bbc.pwm0NeutralVal, 00193 bbc.pwm0MinVal, 00194 bbc.pwm0MaxVal); 00195 b->calibratePulse(1, 00196 bbc.pwm1NeutralVal, 00197 bbc.pwm1MinVal, 00198 bbc.pwm1MaxVal); 00199 b->capturePulse(0, true); 00200 b->capturePulse(1, true); 00201 00202 // let's play with the LCD: 00203 b->lcdClear(); // 01234567890123456789 00204 b->lcdPrintf(0, 0, "BEOBOT-CONTROL: 0000"); 00205 b->lcdPrintf(0, 1, "STEER=XXX SPEED=XXX"); 00206 b->lcdPrintf(0, 2, "PWM0=0000 0000-0000"); 00207 b->lcdPrintf(0, 3, "PWM1=0000 0000-0000"); 00208 00209 // wait for keyboard and board A process it: 00210 int32 rframe, raction, rnode = -1; // receive from any node 00211 int ct = 0; 00212 while(goforever) { 00213 00214 // print keyboard values: 00215 char kb[6]; kb[5] = '\0'; 00216 for (int i = 0; i < 5; i ++) kb[i] = (lis->kbd>>(4-i))&1 ? '1':'0'; 00217 00218 // quit if both extreme keys pressed simultaneously: 00219 if (kb[0] == '0' && kb[4] == '0') { 00220 b->lcdPrintf(15, 0, "QUIT "); 00221 goforever = false; break; 00222 } 00223 00224 // wait up to 5ms to see if we receive a command from Board A 00225 if( beo->receive( rnode, rmsg, rframe, raction, 5 ) ) 00226 { 00227 // check what the command is through raction 00228 00229 // if UPDATE_IMAGE_COLOR: get the PixRGB<byte> image 00230 00231 // if UPDATE_IMAGE_BW: get the <float> image 00232 00233 // if SET_CONTROL: 0 remote, 1 Board A 00234 00235 // if SET_ACTION: steer, speed, gear 00236 00237 // set the motor to the passed in values 00238 float steerVal = rmsg.getElementFloat(); 00239 float speedVal = rmsg.getElementFloat(); 00240 float gearVal = rmsg.getElementFloat(); 00241 LINFO( "Received steer: %f speed: %f gear: %f", 00242 steerVal, speedVal, gearVal); 00243 bc->setSteer(steerVal); 00244 bc->setSpeed(speedVal); 00245 rmsg.reset(rframe, raction); 00246 00247 if(++ct >= 10) 00248 { 00249 b->lcdPrintf(6, 1, "%03d", b->getServoRaw(0)); 00250 b->lcdPrintf(17, 1, "%03d", b->getServoRaw(1)); 00251 ct = 0; 00252 } 00253 // if SET_STEER_PID 00254 00255 // if SET_SPEED_PID 00256 } 00257 usleep(5000); 00258 } 00259 00260 manager.stop(); 00261 return 0; 00262 } 00263 00264 // ###################################################################### 00265 /* So things look consistent in everyone's emacs... */ 00266 /* Local Variables: */ 00267 /* indent-tabs-mode: nil */ 00268 /* End: */