00001 /*!@file Demo/test-tracking.C Test tracking */ 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: Lior Elazary <elazary@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/SeaBee/test-SeaBeeInterface.C $ 00035 // $Id: test-SeaBeeInterface.C 14376 2011-01-11 02:44:34Z pez $ 00036 // 00037 00038 #include "Image/OpenCVUtil.H" // must be first to avoid conflicting defs of int64, uint64 00039 00040 #include "Component/ModelManager.H" 00041 #include "Devices/DeviceOpts.H" 00042 #include "GUI/XWinManaged.H" 00043 #include "Raster/GenericFrame.H" 00044 #include "Raster/Raster.H" 00045 #include "Component/ModelManager.H" 00046 #include "Devices/DeviceOpts.H" 00047 #include "GUI/XWindow.H" 00048 #include "Image/DrawOps.H" 00049 #include "Image/CutPaste.H" 00050 #include "Image/Image.H" 00051 #include "Image/Pixels.H" 00052 #include "Image/MathOps.H" 00053 #include "Neuro/EnvVisualCortex.H" 00054 #include "Media/FrameSeries.H" 00055 #include "Media/MediaOpts.H" 00056 #include "Transport/FrameInfo.H" 00057 #include "Raster/GenericFrame.H" 00058 #include "Raster/Raster.H" 00059 #include "Util/Timer.H" 00060 #include "Util/log.H" 00061 #include "Util/MathFunctions.H" 00062 #include "Learn/Bayes.H" 00063 #include "Learn/BackpropNetwork.H" 00064 #include "Envision/env_image_ops.h" 00065 #include "Neuro/BeoHeadBrain.H" 00066 #include "Image/ShapeOps.H" 00067 #include "Devices/BeeSTEM.H" 00068 #include "rutz/shared_ptr.h" 00069 00070 00071 #include <ctype.h> 00072 #include <deque> 00073 #include <iterator> 00074 #include <stdlib.h> // for atoi(), malloc(), free() 00075 #include <string> 00076 #include <vector> 00077 #include <map> 00078 00079 #define UP 98 00080 #define DOWN 104 00081 #define RIGHT 102 00082 #define LEFT 100 00083 00084 00085 #define THRUSTER_UP_LEFT 1 00086 #define THRUSTER_UP_RIGHT 3 00087 #define THRUSTER_UP_BACK 2 00088 #define THRUSTER_FWD_RIGHT 4 00089 #define THRUSTER_FWD_LEFT 0 00090 00091 //ModelManager *mgr; 00092 XWinManaged *xwin; 00093 Timer timer; 00094 Image<PixRGB<byte> > disp; 00095 byte SmaxVal = 0; 00096 int smap_level = -1; 00097 00098 bool debug = 0; 00099 bool init_points = true; 00100 00101 00102 //! Our own little BeeSTEMListener 00103 class BeeSTEM_PID_Listener : public BeeSTEMListener 00104 { 00105 public: 00106 BeeSTEM_PID_Listener(nub::soft_ref<BeeSTEM> &b) : 00107 itsBeeStem(b) 00108 { 00109 pidHeading.reset(new PID<float>(0.1, 0, 0, -100.0, 100.0)); 00110 pidPitch.reset(new PID<float>(0.1, 0, 0, -100.0, 100.0)); 00111 pidRoll.reset(new PID<float>(0.1, 0, 0, -100.0, 100.0)); 00112 00113 thrust_h_left = 0; 00114 thrust_h_right = 0; 00115 thrust_v_left = 0; 00116 thrust_v_right = 0; 00117 thrust_v_back = 0; 00118 00119 target_heading = 0; 00120 } 00121 00122 virtual ~BeeSTEM_PID_Listener() 00123 { } 00124 00125 //These set and turn off the PID values. 00126 void setTargetHeading(int _h) { 00127 target_heading = _h; 00128 heading_enable = true; 00129 00130 //Now turn off all the motors so we can restart the PID 00131 thrust_h_left = 0; 00132 thrust_h_right = 0; 00133 thrust_v_left = 0; 00134 thrust_v_right = 0; 00135 thrust_v_back = 0; 00136 } 00137 00138 void setTargetPitch(int _h) { 00139 target_pitch = _h; 00140 pitch_enable = true; 00141 00142 //Now turn off all the motors so we can restart the PID 00143 thrust_h_left = 0; 00144 thrust_h_right = 0; 00145 thrust_v_left = 0; 00146 thrust_v_right = 0; 00147 thrust_v_back = 0; 00148 } 00149 00150 void disableHeadingTarget() { 00151 heading_enable = false; 00152 } 00153 00154 void disablePitchTarget() { 00155 pitch_enable = false; 00156 } 00157 00158 void setPrintOnly(bool b) { 00159 print_only = b; 00160 } 00161 00162 int getPos() 00163 { 00164 return itsCurrentPos; 00165 00166 } 00167 00168 00169 00170 virtual void event(const BeeSTEMEventType t, const unsigned char dat1, 00171 const unsigned char dat2) 00172 { 00173 LDEBUG("Event: %d dat1 = %d, dat2 = %d", int(t), dat1, dat2); 00174 00175 switch(t) { 00176 00177 case COMPASS_HEADING_EVENT: 00178 { 00179 int heading = (unsigned int)dat1*2; 00180 itsCurrentPos = heading; 00181 if (pidHeading.is_valid()) 00182 { 00183 float rot = 100*pidHeading->update(target_heading, (float)heading); 00184 thrust_h_left+=(int)rot; 00185 thrust_h_right-=(int)rot; 00186 //LINFO("%f %i %i %i", rot, heading, thrust_h_left, thrust_h_right); 00187 if(!print_only) { 00188 //itsBeeStem->setThrust(THRUSTER_FWD_RIGHT, thrust_h_right); 00189 //itsBeeStem->setThrust(THRUSTER_FWD_LEFT, thrust_h_left); 00190 } 00191 } 00192 00193 } 00194 break; //Careful here! The heading is sent /2 because of byte limits 00195 case COMPASS_PITCH_EVENT: 00196 { 00197 if(pitch_enable) 00198 { 00199 int pitch = (signed char)dat1; 00200 if (pidPitch.is_valid()) 00201 { 00202 float pitchCorr = 100*pidPitch->update(target_pitch, (float)pitch); 00203 thrust_v_left += (int)pitchCorr; 00204 thrust_v_right -= (int)pitchCorr; 00205 itsBeeStem->setMotor(THRUSTER_UP_RIGHT, (int)thrust_v_right); 00206 itsBeeStem->setMotor(THRUSTER_UP_LEFT, (int)thrust_v_left); 00207 } 00208 } 00209 } 00210 break; 00211 case COMPASS_ROLL_EVENT: 00212 { 00213 int roll = (signed char)dat1; 00214 roll++; 00215 } 00216 break; 00217 case ACCEL_X_EVENT: break; 00218 case ACCEL_Y_EVENT: break; 00219 case INT_PRESS_EVENT: /* LINFO("INTERNAL PRESSURE: %d", (int)dat1); */break; 00220 case EXT_PRESS_EVENT: 00221 // LINFO("%i", (unsigned char)dat1); 00222 break; 00223 case TEMP1_EVENT: break; 00224 case TEMP2_EVENT: break; 00225 case DIG_IN_EVENT: break; 00226 case ADC_IN_EVENT: break; 00227 case MOTOR_A_CURR_EVENT: break; 00228 case MOTOR_B_CURR_EVENT: break; 00229 case MOTOR_C_CURR_EVENT: break; 00230 case MOTOR_D_CURR_EVENT: break; 00231 case MOTOR_E_CURR_EVENT: break; 00232 case ECHO_REPLY_EVENT: LINFO("BeeSTEM Echo Reply Recieved."); break; 00233 case RESET_EVENT: LERROR("BeeSTEM RESET occurred!"); break; 00234 case SW_OVERFLOW_EVENT: LERROR("BeeSTEM Software Overflow!"); break; 00235 case FRAMING_ERR_EVENT: LERROR("BeeSTEM Framing Error!"); break; 00236 case OVR_ERR_EVENT: LERROR("BeeSTEM Hardware Overflow!"); break; 00237 case HMR3300_LOST_EVENT: break; 00238 case ACCEL_LOST_EVENT: break; 00239 case TEMP1_LOST_EVENT: break; 00240 case TEMP2_LOST_EVENT: break; 00241 //case TEMP3_LOST_EVENT: break; 00242 case ESTOP_EVENT: break; 00243 case UNRECOGNIZED_EVENT: break; 00244 case BAD_OUT_CMD_SEQ_EVENT: LERROR("BeeSTEM Reports a Bad Command Sequence!"); break; 00245 case BAD_IN_CMD_SEQ_EVENT: break; 00246 case RESET_ACK_EVENT: LINFO("BeeSTEM Acknowledges Reset Request"); break; 00247 case NO_EVENT: break; 00248 default: LERROR("Unknown event %d received!", int(t)); break; 00249 00250 } 00251 00252 00253 00254 } 00255 private: 00256 nub::soft_ref<BeeSTEM> itsBeeStem; 00257 int heading; 00258 bool heading_enable, print_only; 00259 bool pitch_enable; 00260 int target_pitch; 00261 00262 rutz::shared_ptr< PID<float> > pidHeading; 00263 rutz::shared_ptr< PID<float> > pidPitch; 00264 rutz::shared_ptr< PID<float> > pidRoll; 00265 rutz::shared_ptr< PID<float> > pidDepth; 00266 00267 signed int thrust_h_left, thrust_h_right, thrust_v_left, thrust_v_right, thrust_v_back; 00268 00269 int target_heading; 00270 int itsCurrentPos; 00271 }; 00272 00273 00274 void display(Image<PixRGB<byte> > &img); 00275 00276 int main(int argc, const char **argv) 00277 { 00278 // Instantiate a ModelManager: 00279 ModelManager *mgr = new ModelManager("SeaBee Interface"); 00280 00281 nub::ref<InputFrameSeries> ifs(new InputFrameSeries(*mgr)); 00282 mgr->addSubComponent(ifs); 00283 00284 nub::ref<OutputFrameSeries> ofs(new OutputFrameSeries(*mgr)); 00285 mgr->addSubComponent(ofs); 00286 00287 nub::soft_ref<BeeSTEM> b(new BeeSTEM(*mgr,"BeeSTEM", "BeeSTEM", "/dev/ttyS1")); 00288 mgr->addSubComponent(b); 00289 00290 //Make the PID Listener 00291 //TODO: fixme: obsolete with the new BeeSTEM 00292 // rutz::shared_ptr<BeeSTEM_PID_Listener> lis(new BeeSTEM_PID_Listener(b)); 00293 // rutz::shared_ptr<BeeSTEMListener> lis2; lis2.dynCastFrom(lis); // cast down 00294 // b->setListener(lis2); 00295 00296 mgr->exportOptions(MC_RECURSE); 00297 00298 mgr->setOptionValString(&OPT_InputFrameSource, "V4L2"); 00299 mgr->setOptionValString(&OPT_FrameGrabberMode, "YUYV"); 00300 mgr->setOptionValString(&OPT_FrameGrabberDims, "1024x576"); 00301 // mgr->setOptionValString(&OPT_FrameGrabberBswap, "no"); 00302 mgr->setOptionValString(&OPT_FrameGrabberFPS, "30"); 00303 00304 // Parse command-line: 00305 if (mgr->parseCommandLine(argc, argv, "", 0, 0) == false) return(1); 00306 00307 // do post-command-line configs: 00308 Dims imageDims(320,240); 00309 00310 xwin = new XWinManaged(Dims(imageDims.w()*2,imageDims.h()*2+20), 00311 -1, -1, "SeaBee interface"); 00312 disp = Image<PixRGB<byte> >(imageDims.w(),imageDims.h()+20, ZEROS); 00313 00314 // let's get all our ModelComponent instances started: 00315 mgr->start(); 00316 00317 //start streaming 00318 ifs->startStream(); 00319 00320 timer.reset(); 00321 00322 00323 while(1) { 00324 00325 const FrameState is = ifs->updateNext(); 00326 if (is == FRAME_COMPLETE) 00327 break; 00328 00329 //grab the images 00330 GenericFrame input = ifs->readFrame(); 00331 if (!input.initialized()) 00332 break; 00333 Image<PixRGB<byte> > frontImg = rescale(input.asRgb(), 320, 240); 00334 00335 ofs->writeRGB(frontImg, "input", FrameInfo("Copy of input", SRC_POS)); 00336 00337 00338 int key = xwin->getLastKeyPress(); 00339 00340 int speed = 100; 00341 switch(key) 00342 { 00343 case 38: //a 00344 b->setMotor(2,-1 * speed); 00345 b->setMotor(1,-1 * speed); 00346 b->setMotor(3,-1 * speed); 00347 break; 00348 case 52: //z 00349 b->setMotor(2,speed ); 00350 b->setMotor(1,speed ); 00351 b->setMotor(3,speed ); 00352 break; 00353 case LEFT: 00354 b->setMotor(0, speed); 00355 b->setMotor(4, -1 * speed); 00356 break; 00357 case RIGHT: 00358 b->setMotor(0, -1 * speed); 00359 b->setMotor(4, speed); 00360 break; 00361 case UP: 00362 b->setMotor(0, -1 * speed); 00363 b->setMotor(4, -1 * speed); 00364 break; 00365 case DOWN: 00366 b->setMotor(0, speed); 00367 b->setMotor(4, speed); 00368 break; 00369 case 65: //space 00370 b->setMotor(0,0); 00371 usleep(1000); 00372 b->setMotor(1,0); 00373 usleep(1000); 00374 b->setMotor(2,0); 00375 usleep(1000); 00376 b->setMotor(3,0); 00377 usleep(1000); 00378 b->setMotor(4,0); 00379 usleep(1000); 00380 break; 00381 00382 default: 00383 break; 00384 } 00385 display(frontImg); 00386 00387 } 00388 00389 00390 // stop all our ModelComponents 00391 mgr->stop(); 00392 00393 // all done! 00394 return 0; 00395 } 00396 00397 void display(Image<PixRGB<byte> > &img) 00398 { 00399 static int avgn = 0; 00400 static uint64 avgtime = 0; 00401 //char msg[255]; 00402 00403 //Left Image 00404 xwin->drawImage(img, 0, 0); 00405 00406 //calculate fps 00407 avgn++; 00408 avgtime += timer.getReset(); 00409 if (avgn == 20) 00410 { 00411 avgtime = 0; 00412 avgn = 0; 00413 } 00414 00415 00416 // Image<PixRGB<byte> > infoImg(leftImg.getWidth()*2, 20, NO_INIT); 00417 // writeText(infoImg, Point2D<int>(0,0), msg, 00418 // PixRGB<byte>(255), PixRGB<byte>(127)); 00419 // //xwin->drawImage(infoImg, 0, leftImg.getHeight()*2); 00420 00421 } 00422