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-TunePID.C $ 00035 // $Id: test-TunePID.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 00103 //! Our own little BeeSTEMListener 00104 class BeeSTEM_PID_Listener : public BeeSTEMListener 00105 { 00106 public: 00107 BeeSTEM_PID_Listener(nub::soft_ref<BeeSTEM> &b) : 00108 itsBeeStem(b) 00109 { 00110 pidHeading.reset(new PID<float>(0.1, 0, 0, -100.0, 100.0)); 00111 pidPitch.reset(new PID<float>(0.1, 0, 0, -100.0, 100.0)); 00112 pidRoll.reset(new PID<float>(0.1, 0, 0, -100.0, 100.0)); 00113 00114 thrust_h_left = 0; 00115 thrust_h_right = 0; 00116 thrust_v_left = 0; 00117 thrust_v_right = 0; 00118 thrust_v_back = 0; 00119 00120 target_heading = 0; 00121 } 00122 00123 virtual ~BeeSTEM_PID_Listener() 00124 { } 00125 00126 //These set and turn off the PID values. 00127 void setTargetHeading(int _h) { 00128 target_heading = _h; 00129 heading_enable = true; 00130 00131 //Now turn off all the motors so we can restart the PID 00132 thrust_h_left = 0; 00133 thrust_h_right = 0; 00134 thrust_v_left = 0; 00135 thrust_v_right = 0; 00136 thrust_v_back = 0; 00137 } 00138 00139 void setTargetPitch(int _h) { 00140 target_pitch = _h; 00141 pitch_enable = true; 00142 00143 //Now turn off all the motors so we can restart the PID 00144 thrust_h_left = 0; 00145 thrust_h_right = 0; 00146 thrust_v_left = 0; 00147 thrust_v_right = 0; 00148 thrust_v_back = 0; 00149 } 00150 00151 void disableHeadingTarget() { 00152 heading_enable = false; 00153 } 00154 00155 void disablePitchTarget() { 00156 pitch_enable = false; 00157 } 00158 00159 void setPrintOnly(bool b) { 00160 print_only = b; 00161 } 00162 00163 int getPos() 00164 { 00165 return itsCurrentPos; 00166 00167 } 00168 00169 00170 00171 virtual void event(const BeeSTEMEventType t, const unsigned char dat1, 00172 const unsigned char dat2) 00173 { 00174 LDEBUG("Event: %d dat1 = %d, dat2 = %d", int(t), dat1, dat2); 00175 00176 switch(t) { 00177 00178 case COMPASS_HEADING_EVENT: 00179 { 00180 int heading = (unsigned int)dat1*2; 00181 itsCurrentPos = heading; 00182 if (pidHeading.is_valid()) 00183 { 00184 float rot = 100*pidHeading->update(target_heading, (float)heading); 00185 thrust_h_left+=(int)rot; 00186 thrust_h_right-=(int)rot; 00187 //LINFO("%f %i %i %i", rot, heading, thrust_h_left, thrust_h_right); 00188 if(!print_only) { 00189 //itsBeeStem->setThrust(THRUSTER_FWD_RIGHT, thrust_h_right); 00190 //itsBeeStem->setThrust(THRUSTER_FWD_LEFT, thrust_h_left); 00191 } 00192 } 00193 00194 } 00195 break; //Careful here! The heading is sent /2 because of byte limits 00196 case COMPASS_PITCH_EVENT: 00197 { 00198 if(pitch_enable) 00199 { 00200 int pitch = (signed char)dat1; 00201 if (pidPitch.is_valid()) 00202 { 00203 float pitchCorr = 100*pidPitch->update(target_pitch, (float)pitch); 00204 thrust_v_left += (int)pitchCorr; 00205 thrust_v_right -= (int)pitchCorr; 00206 itsBeeStem->setMotor(THRUSTER_UP_RIGHT, (int)thrust_v_right); 00207 itsBeeStem->setMotor(THRUSTER_UP_LEFT, (int)thrust_v_left); 00208 } 00209 } 00210 } 00211 break; 00212 case COMPASS_ROLL_EVENT: 00213 { 00214 int roll = (signed char)dat1; 00215 roll++; 00216 } 00217 break; 00218 case ACCEL_X_EVENT: break; 00219 case ACCEL_Y_EVENT: break; 00220 case INT_PRESS_EVENT: /* LINFO("INTERNAL PRESSURE: %d", (int)dat1); */break; 00221 case EXT_PRESS_EVENT: 00222 // LINFO("%i", (unsigned char)dat1); 00223 break; 00224 case TEMP1_EVENT: break; 00225 case TEMP2_EVENT: break; 00226 case DIG_IN_EVENT: break; 00227 case ADC_IN_EVENT: break; 00228 case MOTOR_A_CURR_EVENT: break; 00229 case MOTOR_B_CURR_EVENT: break; 00230 case MOTOR_C_CURR_EVENT: break; 00231 case MOTOR_D_CURR_EVENT: break; 00232 case MOTOR_E_CURR_EVENT: break; 00233 case ECHO_REPLY_EVENT: LINFO("BeeSTEM Echo Reply Recieved."); break; 00234 case RESET_EVENT: LERROR("BeeSTEM RESET occurred!"); break; 00235 case SW_OVERFLOW_EVENT: LERROR("BeeSTEM Software Overflow!"); break; 00236 case FRAMING_ERR_EVENT: LERROR("BeeSTEM Framing Error!"); break; 00237 case OVR_ERR_EVENT: LERROR("BeeSTEM Hardware Overflow!"); break; 00238 case HMR3300_LOST_EVENT: break; 00239 case ACCEL_LOST_EVENT: break; 00240 case TEMP1_LOST_EVENT: break; 00241 case TEMP2_LOST_EVENT: break; 00242 //case TEMP3_LOST_EVENT: break; 00243 case ESTOP_EVENT: break; 00244 case UNRECOGNIZED_EVENT: break; 00245 case BAD_OUT_CMD_SEQ_EVENT: LERROR("BeeSTEM Reports a Bad Command Sequence!"); break; 00246 case BAD_IN_CMD_SEQ_EVENT: break; 00247 case RESET_ACK_EVENT: LINFO("BeeSTEM Acknowledges Reset Request"); break; 00248 case NO_EVENT: break; 00249 default: LERROR("Unknown event %d received!", int(t)); break; 00250 00251 } 00252 00253 00254 00255 } 00256 private: 00257 nub::soft_ref<BeeSTEM> itsBeeStem; 00258 int heading; 00259 bool heading_enable, print_only; 00260 bool pitch_enable; 00261 int target_pitch; 00262 00263 rutz::shared_ptr< PID<float> > pidHeading; 00264 rutz::shared_ptr< PID<float> > pidPitch; 00265 rutz::shared_ptr< PID<float> > pidRoll; 00266 rutz::shared_ptr< PID<float> > pidDepth; 00267 00268 signed int thrust_h_left, thrust_h_right, thrust_v_left, thrust_v_right, thrust_v_back; 00269 00270 int target_heading; 00271 int itsCurrentPos; 00272 }; 00273 00274 00275 void display(Image<PixRGB<byte> > &img, Image<PixRGB<byte> > &posValImg, 00276 int pressure, int heading, int tilt, int pan); 00277 00278 int main(int argc, const char **argv) 00279 { 00280 // Instantiate a ModelManager: 00281 ModelManager *mgr = new ModelManager("SeaBee Interface"); 00282 00283 nub::ref<InputFrameSeries> ifs(new InputFrameSeries(*mgr)); 00284 mgr->addSubComponent(ifs); 00285 00286 nub::ref<OutputFrameSeries> ofs(new OutputFrameSeries(*mgr)); 00287 mgr->addSubComponent(ofs); 00288 00289 nub::soft_ref<BeeSTEM> b(new BeeSTEM(*mgr,"BeeSTEM", "BeeSTEM", "/dev/ttyS1")); 00290 mgr->addSubComponent(b); 00291 00292 //Make the PID Listener 00293 rutz::shared_ptr<BeeSTEM_PID_Listener> PID_Listener(new BeeSTEM_PID_Listener(b)); 00294 rutz::shared_ptr<BeeSTEMListener> lis2; lis2.dynCastFrom(PID_Listener); // cast down 00295 b->setListener(lis2); 00296 00297 mgr->exportOptions(MC_RECURSE); 00298 00299 mgr->setOptionValString(&OPT_InputFrameSource, "V4L2"); 00300 mgr->setOptionValString(&OPT_FrameGrabberMode, "YUYV"); 00301 mgr->setOptionValString(&OPT_FrameGrabberDims, "1024x576"); 00302 mgr->setOptionValString(&OPT_FrameGrabberByteSwap, "no"); 00303 mgr->setOptionValString(&OPT_FrameGrabberFPS, "30"); 00304 00305 // Parse command-line: 00306 if (mgr->parseCommandLine(argc, argv, "", 0, 0) == false) return(1); 00307 00308 // do post-command-line configs: 00309 Dims imageDims(320,240); 00310 00311 xwin = new XWinManaged(Dims(imageDims.w()*2,imageDims.h()*2+20), 00312 -1, -1, "SeaBee interface"); 00313 disp = Image<PixRGB<byte> >(imageDims.w(),imageDims.h()+20, ZEROS); 00314 00315 // let's get all our ModelComponent instances started: 00316 mgr->start(); 00317 00318 //start streaming 00319 ifs->startStream(); 00320 00321 timer.reset(); 00322 00323 int target_heading = 100; 00324 00325 b->setReporting(HMR3300, true); 00326 b->setReporting(INT_PRESS, true); 00327 00328 int x = 0; 00329 Image<PixRGB<byte> > posValImg(256, 256, ZEROS); 00330 00331 while(1) { 00332 00333 const FrameState is = ifs->updateNext(); 00334 if (is == FRAME_COMPLETE) 00335 break; 00336 00337 //grab the images 00338 GenericFrame input = ifs->readFrame(); 00339 if (!input.initialized()) 00340 break; 00341 Image<PixRGB<byte> > frontImg = rescale(input.asRgb(), 320, 240); 00342 00343 ofs->writeRGB(frontImg, "input", FrameInfo("Copy of input", SRC_POS)); 00344 00345 00346 int key = xwin->getLastKeyPress(); 00347 00348 int val = PID_Listener->getPos(); 00349 int y = (256/2) + ((target_heading - val)); 00350 00351 if (!x) 00352 { 00353 posValImg.clear(); 00354 drawLine(posValImg, Point2D<int>(0, 256/2), Point2D<int>(256, 256/2), PixRGB<byte>(255,0,0)); 00355 } 00356 LINFO("%i %i %i", val, (val - target_heading), y); 00357 posValImg.setVal(x,y,PixRGB<byte>(0,256,0)); 00358 x = (x+1)%256; 00359 00360 00361 int speed = 100; 00362 switch(key) 00363 { 00364 case 38: //a 00365 b->setMotor(2,-1 * speed); 00366 b->setMotor(1,-1 * speed); 00367 b->setMotor(3,-1 * speed); 00368 break; 00369 case 52: //z 00370 b->setMotor(2,speed ); 00371 b->setMotor(1,speed ); 00372 b->setMotor(3,speed ); 00373 break; 00374 case LEFT: 00375 b->setMotor(0, 1 * speed); 00376 b->setMotor(4, -1 * speed); 00377 break; 00378 case RIGHT: 00379 //target_heading++; 00380 //PID_Listener->setTargetHeading(target_heading); 00381 b->setMotor(0, -1 * speed); 00382 b->setMotor(4, 1 * speed); 00383 break; 00384 case UP: 00385 b->setMotor(0, -1 * speed); 00386 b->setMotor(4, -1 * speed); 00387 break; 00388 case DOWN: 00389 b->setMotor(0, speed); 00390 b->setMotor(4, speed); 00391 break; 00392 case 65: //space 00393 b->setMotor(0,0); 00394 usleep(1000); 00395 b->setMotor(1,0); 00396 usleep(1000); 00397 b->setMotor(2,0); 00398 usleep(1000); 00399 b->setMotor(3,0); 00400 usleep(1000); 00401 b->setMotor(4,0); 00402 usleep(1000); 00403 break; 00404 case 33: //p 00405 PID_Listener->setTargetHeading((signed char)b->getCompassPitch()); 00406 break; 00407 default: 00408 if (key != -1) 00409 LINFO("Key = %i", key); 00410 break; 00411 } 00412 display(frontImg, posValImg, (int)b->getIntPress(), (int)b->getCompassHeading()*2, (signed char)b->getCompassPitch(), (signed char)b->getCompassRoll()); 00413 00414 } 00415 00416 00417 // stop all our ModelComponents 00418 mgr->stop(); 00419 00420 // all done! 00421 return 0; 00422 } 00423 00424 void display(Image<PixRGB<byte> > &img, Image<PixRGB<byte> > &posValImg, 00425 int pressure, int heading, int tilt, int pan) 00426 { 00427 static int avgn = 0; 00428 static uint64 avgtime = 0; 00429 char msg[255]; 00430 00431 //Left Image 00432 xwin->drawImage(img, 0, 0); 00433 xwin->drawImage(posValImg, img.getWidth()+1, 0); 00434 00435 //calculate fps 00436 avgn++; 00437 avgtime += timer.getReset(); 00438 if (avgn == 20) 00439 { 00440 avgtime = 0; 00441 avgn = 0; 00442 } 00443 00444 sprintf(msg, "pre=%i\t head=%i\t tilt=%i\t pan=%i\t ", 00445 pressure, heading, tilt, pan); 00446 00447 00448 00449 Image<PixRGB<byte> > infoImg(img.getWidth()*2, 20, NO_INIT); 00450 writeText(infoImg, Point2D<int>(0,0), msg, 00451 PixRGB<byte>(255), PixRGB<byte>(127)); 00452 xwin->drawImage(infoImg, 0,img.getHeight()*2); 00453 00454 } 00455