00001 /*! @file Beobot/test-gistNav-master.C -- An autonomous visual navigation 00002 using image intensity amplitude spectrum components FFT (fast and free 00003 from fftw.com) via object FFTWWrapper. Computes outputs with a back-prop 00004 network (FFN.H&.C) and online learning. 00005 -- Christopher Ackerman, 7/30/2003 */ 00006 // //////////////////////////////////////////////////////////////////// // 00007 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00008 // University of Southern California (USC) and the iLab at USC. // 00009 // See http://iLab.usc.edu for information about this project. // 00010 // //////////////////////////////////////////////////////////////////// // 00011 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00012 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00013 // in Visual Environments, and Applications'' by Christof Koch and // 00014 // Laurent Itti, California Institute of Technology, 2001 (patent // 00015 // pending; application number 09/912,225 filed July 23, 2001; see // 00016 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00017 // //////////////////////////////////////////////////////////////////// // 00018 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00019 // // 00020 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00021 // redistribute it and/or modify it under the terms of the GNU General // 00022 // Public License as published by the Free Software Foundation; either // 00023 // version 2 of the License, or (at your option) any later version. // 00024 // // 00025 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00026 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00027 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00028 // PURPOSE. See the GNU General Public License for more details. // 00029 // // 00030 // You should have received a copy of the GNU General Public License // 00031 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00032 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00033 // Boston, MA 02111-1307 USA. // 00034 // //////////////////////////////////////////////////////////////////// // 00035 // 00036 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Beobot/test-gistNav-master.C $ 00037 // $Id: test-gistNav-master.C 13712 2010-07-28 21:00:40Z itti $ 00038 00039 #include "Beowulf/Beowulf.H" 00040 #include "Beowulf/BeowulfOpts.H" 00041 #include "Component/ModelManager.H" 00042 #include "Devices/DeviceOpts.H" 00043 #include "Devices/FrameGrabberConfigurator.H" 00044 #include "Devices/KeyBoard.H" 00045 #include "Devices/RadioDecoder.H" 00046 #include "Devices/lcd.H" 00047 #include "Gist/FFN.H" 00048 #include "Image/FFTWWrapper.H" 00049 #include "Image/Image.H" 00050 #include "Image/Pixels.H" 00051 #include "Transport/FrameIstream.H" 00052 #include "Util/Timer.H" 00053 #include "Util/log.H" 00054 00055 #include <math.h> 00056 #include <pthread.h> 00057 #include <signal.h> 00058 #include <stdio.h> 00059 #include <stdlib.h> 00060 00061 #define OUTPATH "/home/tmp/7/gistNav/" 00062 // Current directory to write to for this grab 00063 00064 char dir[10]; 00065 00066 // tell writer thread when to write a new image: 00067 bool doWrite; 00068 00069 // tell grabber it is okay to grab 00070 bool grabOk; 00071 00072 // tell writer thread to quit: 00073 bool doQuit; 00074 00075 // tell grabbing loop that the user has pushed quit 00076 bool quitGrab; 00077 00078 // current frame number: 00079 int frame=0; 00080 00081 //!< Will turn false on interrupt signal 00082 static bool goforever = true; 00083 00084 // ###################################################################### 00085 //! Signal handler (e.g., for control-C) 00086 void terminate(int s) 00087 { LERROR("*** INTERRUPT ***"); goforever = false; exit(1); } 00088 00089 #define HBLOCKS 4 00090 #define WBLOCKS 4 00091 #define DIMSINALL 640 00092 #define DIMSIN 40 00093 #define DIMSHID 90 00094 #define DIMS1HID 40 00095 #define DIMS2HID 40 00096 #define DIMSOUT 13 00097 #define IMAGEHEIGHT 120 00098 #define IMAGEWIDTH 160 00099 #define IMAGESIZE IMAGEHEIGHT*IMAGEWIDTH 00100 #define WINDOWHEIGHT 30 00101 #define WINDOWWIDTH 40 00102 #define WINDOWSIZE WINDOWHEIGHT*WINDOWWIDTH 00103 #define LEARNRATE 0.5 00104 #define MOMENTUM 0.0 00105 00106 double compsteer, compspeed; 00107 Image< PixRGB<byte> > ima(IMAGEWIDTH,IMAGEHEIGHT, NO_INIT); 00108 00109 // ###################################################################### 00110 void gzWriteFrame(int frameNum, Image< PixRGB<byte> >& imag) 00111 { 00112 char temp[256]; 00113 char head[256]; 00114 00115 head[0] = '\0'; 00116 temp[0] = '\0'; 00117 00118 // gzFile gzOut; 00119 FILE *fp; 00120 00121 //To copy the RC data 00122 float taccel, tsteer; 00123 taccel = compspeed; 00124 tsteer = compsteer; 00125 00126 // sprintf(temp, "./frame%06d.ppm.gz", frameNum); 00127 sprintf(temp, "./frame%06d.ppm", frameNum); 00128 LDEBUG("Filename: %s", temp); 00129 00130 // Open the file using zlib gzopen routine 00131 // gzOut = gzopen (temp, "wb"); 00132 fp = fopen(temp, "wb"); 00133 00134 // if( gzOut == NULL ) //Check status of file open operation 00135 if( fp == NULL ) //Check status of file open operation 00136 LFATAL("There was an error opening the gzip file for writing"); 00137 00138 // Write out the header information 00139 sprintf(temp, "P6\n"); 00140 00141 strcpy(head, temp); 00142 00143 sprintf(temp, "#ACCEL:%-10f STEER:%-10f\n", taccel, tsteer); 00144 strcat(head, temp); 00145 sprintf(temp, "%d %d\n255\n", imag.getWidth(), imag.getHeight() ); 00146 strcat(head, temp); 00147 00148 // if( !gzwrite(gzOut, head, strlen(head)) ) 00149 if( !fwrite(head, 1, strlen(head), fp) ) 00150 LFATAL("There was an error gzwriting %"ZU" bytes", strlen(head)); 00151 00152 if( !fwrite(reinterpret_cast<void*>(imag.getArrayPtr()), 1, 00153 3*imag.getSize(), fp)) 00154 // if( !gzwrite(gzOut, reinterpret_cast<void*>(imag.getArrayPtr()), 00155 // 3*imag.getSize())) 00156 LFATAL("There was an error gzwriting %d bytes", 3*imag.getSize()); 00157 00158 // gzclose(gzOut); 00159 fclose(fp); 00160 } 00161 00162 // ###################################################################### 00163 void* imageWriterThread(void *junk) 00164 { 00165 //// while(doQuit == false){ 00166 if (doWrite) 00167 { 00168 Image< PixRGB<byte> > currFrame = ima; 00169 // for a deep copy of the image data: 00170 Image< PixRGB<byte> >::iterator data = currFrame.beginw(); 00171 data ++; // keep g++ happy 00172 grabOk = true; 00173 00174 gzWriteFrame(frame++, currFrame); 00175 00176 doWrite = false; 00177 } 00178 else 00179 usleep(500); 00180 //// } 00181 00182 // quit the thread: 00183 //// pthread_exit(0); 00184 return NULL; 00185 } 00186 00187 // ###################################################################### 00188 void grabCycleInit( KeyBoard& myKB, nub::soft_ref<lcd> lcdDisp, 00189 nub::soft_ref<FrameIstream>& gb ) 00190 { 00191 char tmp[100]; 00192 int i = 0; 00193 00194 //We want to create a new directory to put frames in 00195 //But make sure that we don't overwrite any directories 00196 //That already exist 00197 00198 if( chdir( OUTPATH ) ) //If there's a problem cding to ouput dir 00199 { 00200 LINFO("There was an error changing to directory: %s", OUTPATH); 00201 lcdDisp->clear(); 00202 lcdDisp->printf(0, 0, " Output directory" ); 00203 lcdDisp->printf(0, 1, " Does not exist!" ); 00204 lcdDisp->printf(0, 2, " Trying to create. "); 00205 sleep(1); 00206 00207 if( mkdir( OUTPATH, S_IRUSR | S_IWUSR ) != 0 ) 00208 { 00209 LINFO("There was an error creating directory: %s", OUTPATH); 00210 lcdDisp->clear(); 00211 lcdDisp->printf(0, 0, " mkdir() failed! "); 00212 lcdDisp->printf(0, 1, " bailing out... "); 00213 sleep(1); 00214 return; 00215 } 00216 if (chdir( OUTPATH )) LFATAL("chdir error"); 00217 } 00218 00219 i = 0; 00220 do 00221 { 00222 sprintf( tmp, "%d", i++ ); 00223 } 00224 while ( mkdir(tmp, S_IRUSR | S_IWUSR | S_IEXEC ) != 0 ); 00225 sprintf( tmp, "%s%d", OUTPATH, i-1 ); 00226 if (chdir( tmp )) LFATAL("chdir error"); 00227 00228 char * ptr = getcwd( NULL, 0 ); 00229 LDEBUG( "Working directory is %s", ptr); 00230 free( ptr ); 00231 00232 frame = 0; doQuit = false; 00233 doWrite = false; grabOk = true; quitGrab = false; // start writer thread: 00234 00235 //// pthread_t runner; 00236 //// pthread_create(&runner, NULL, &imageWriterThread, NULL); 00237 } 00238 00239 // ###################################################################### 00240 void grabCycle( KeyBoard& myKB, nub::soft_ref<lcd> lcdDisp, 00241 nub::soft_ref<FrameIstream>& gb ) 00242 { 00243 // wait for writer thread to be ready and tell it to write frame: 00244 while (doWrite) usleep(500); 00245 grabOk = false; // not okay to grab until writer thread authorizes us 00246 doWrite = true; // trigger write of current frame 00247 imageWriterThread(NULL); 00248 while(grabOk == false) usleep(500); 00249 } 00250 00251 // ###################################################################### 00252 int main(const int argc, const char **argv) 00253 { 00254 int i, j, h, l; 00255 bool updateweights = false; 00256 double steer, speed; 00257 double rcspeed, rcsteer; 00258 00259 // Choose steering probabilisticly, 00260 // with the probabilities coming from the relative strengths 00261 // of the network outputs 00262 srand((unsigned)time(0)); 00263 00264 int flag=0; 00265 long ctr=0; 00266 double total,mean,std; 00267 //double orient,open,expand,obstacle,avgsteer=0.0,laststeer=0.0; 00268 //double safety=0.5; 00269 00270 /**************** 0: Setup *********************/ 00271 Image<double> trueout(1, DIMSOUT, ZEROS); 00272 double masks[DIMSIN][WINDOWSIZE]; 00273 Image<double> meanarr(1, DIMSIN, ZEROS); // normalizer 00274 Image<double> stdarr(1, DIMSIN,ZEROS); // normalizer 00275 //double minarr[DIMSIN];// normalizer 00276 //double maxarr[DIMSIN];// normalizer 00277 //double range[DIMSIN]; // normalizer 00278 double evecs[DIMSIN][DIMSINALL]; 00279 Image<double> allfeatures(1, DIMSINALL, ZEROS); 00280 Image<double> features(1, DIMSIN, ZEROS);// amp-dims input 00281 00282 double **magspec = (double **)malloc((WINDOWHEIGHT)*sizeof(double *)); 00283 if(magspec == NULL) 00284 LINFO("Error allocating memory for magspec"); 00285 for(i = 0; i < WINDOWHEIGHT; i++) 00286 { 00287 magspec[i] = (double *)malloc((WINDOWWIDTH/2+1)*sizeof(double)); 00288 if(magspec[i] == NULL) 00289 LINFO("Error allocating memory for magspec[i]"); 00290 } 00291 00292 double *bwimage = (double *)malloc(IMAGESIZE*sizeof(double)); 00293 if(bwimage == NULL) 00294 LINFO("Error allocating memory for bwimage"); 00295 else 00296 LINFO("okay"); 00297 00298 double *bwimage_sm = (double *)malloc(WINDOWSIZE*sizeof(double)); 00299 00300 FeedForwardNetwork *ffn_dm = new FeedForwardNetwork(); 00301 00302 // I was going to do a command line thing 00303 // where you could tell it to initialize with random weights in a range 00304 // instead of using a weight file 00305 /*(if (argc==2) 00306 if(strcmp(argv[1],"-i")==0) 00307 ffn_dm->init(atof(argv[1]),DIMSIN,DIMSHID,DIMSOUT,LEARNRATE); 00308 else{ 00309 LERROR("Invalid switch"); 00310 exit(1); 00311 } 00312 else*/ 00313 00314 // But when I tried the manager business choked on the new parameters. 00315 // So now it will initialize randomly within a hard-coded range 00316 // if it doesn't find the appropriately named weight files 00317 // if I am using a weight file computed offline in Matlab, 00318 // I pass it in a .mat file. 00319 // I also have to make some changes (uncomment some code) 00320 // in FFN.C to handle to Matlab file format. That kind of sucks. 00321 // If it's too much of a pain, then just convert the Matlab file to the 00322 // appropriate format and name in .dat. 00323 //ffn_dm->init("/lab/bb/data/nnwhdm-T.mat","/lab/bb/data/nnwodm-T.mat", 00324 //DIMSIN,DIMSHID,DIMSOUT,LEARNRATE,MOMENTUM); 00325 //ffn_dm->init("/lab/bb/data/nnwhdm.dat","/lab/bb/data/nnwodm.dat", 00326 //DIMSIN,DIMSHID,DIMSOUT,LEARNRATE,MOMENTUM); 00327 //ffn_dm->init3L("/lab/bb/data/nnwh1dm-T.mat","/lab/bb/data/nnwh2dm-T.mat", 00328 //"/lab/bb/data/nnwodm-T.mat",DIMSIN,DIMS1HID,DIMS2HID,DIMSOUT,LEARNRATE); 00329 ffn_dm->init3L("/lab/bb/data/nnwh1dm.dat","/lab/bb/data/nnwh2dm.dat", 00330 "/lab/bb/data/nnwodm.dat",DIMSIN,DIMS1HID,DIMS2HID,DIMSOUT,LEARNRATE,0.0); 00331 00332 FFTWWrapper *fftw = new FFTWWrapper( WINDOWWIDTH,WINDOWHEIGHT); 00333 fftw->init(bwimage_sm); 00334 00335 FILE *fp=fopen("/lab/bb/data/meanarrall.mat","rb"); 00336 if(fp==NULL) LFATAL("Mean file not found"); 00337 00338 fseek(fp, 0, SEEK_END); 00339 long pos = ftell(fp); 00340 fseek(fp,pos-(DIMSIN*sizeof(double)), SEEK_SET); 00341 // FIX below 00342 //for(i = 0; i < DIMSIN; i++) fread(&meanarr[i],sizeof(double),1,fp); 00343 fclose(fp); 00344 00345 // These four are Matlab-created files. 00346 // Note the way to find the beginning of the data 00347 fp = fopen("/lab/bb/data/stdarrall.mat","rb"); 00348 if(fp == NULL) LFATAL("STD file not found"); 00349 fseek(fp, 0, SEEK_END); 00350 pos=ftell(fp); 00351 fseek(fp,pos-(DIMSIN*sizeof(double)), SEEK_SET); 00352 // FIX below 00353 // for(i = 0; i < DIMSIN; i++) fread(&stdarr[i],sizeof(double),1,fp); 00354 fclose(fp); 00355 00356 //for(i = 0; i < DIMSIN; i++) 00357 // range[i] = maxarr[i]-minarr[i]; 00358 00359 fp = fopen("/lab/bb/data/G2small.mat","rb"); 00360 //G = fftshift(reshape(H:,i)...G2=reshape(G(:,:,i)' 00361 //...must have super low values from matlab trimmed 00362 if(fp == NULL) LFATAL("Mask file not found"); 00363 fseek(fp, 0, SEEK_END); 00364 pos = ftell(fp); 00365 fseek(fp,pos-(DIMSIN*WINDOWSIZE*sizeof(double)), SEEK_SET); 00366 for(i = 0; i < DIMSIN; i++) 00367 if (fread(masks[i],sizeof(double),WINDOWSIZE,fp) != WINDOWSIZE) LFATAL("fread error"); 00368 fclose(fp); 00369 00370 fp=fopen("/lab/bb/data/evec40all.mat","rb"); 00371 if(fp==NULL) LFATAL("Eigenvector file not found"); 00372 fseek(fp, 0, SEEK_END); 00373 pos=ftell(fp); 00374 fseek(fp,pos-(DIMSIN*DIMSINALL*sizeof(double)), SEEK_SET); 00375 for(i=0;i<DIMSIN;i++) 00376 if (fread(evecs[i],sizeof(double),DIMSINALL,fp) != DIMSINALL) LFATAL("fread error"); 00377 fclose(fp); 00378 00379 double *iptr = NULL; 00380 00381 TCPmessage smsg; // buffer to send messages to nodes; 00382 // in my case speed and steering... 00383 // when the ethernet was working, counter and status stuff for lcd display now 00384 00385 KeyBoard myKB; 00386 LINFO("Press A to do initialization"); // this is to get the beobot outside 00387 // before you start camera so it adjust to luminance properly 00388 while (myKB.getKey( true ) != KBD_KEY1) // actually that's no longer true. 00389 // Mostly it's to make sure you're ready. 00390 // As it happens, the camera adjusts itself well with time anyway 00391 LINFO("\a"); // beep 00392 00393 // instantiate a model manager: 00394 ModelManager manager("Gist Navigator - Master"); 00395 00396 // Instantiate our various ModelComponents: 00397 nub::soft_ref<FrameGrabberConfigurator> 00398 gbc(new FrameGrabberConfigurator(manager)); 00399 manager.addSubComponent(gbc); 00400 00401 //uncomment when ethernet is fixed --changed bb1bg to bb1ag 00402 nub::soft_ref<Beowulf> 00403 beo(new Beowulf(manager, "Beowulf Master", "BeowulfMaster", true)); 00404 manager.addSubComponent(beo); 00405 manager.setOptionValString(&OPT_BeowulfSlaveNames, "bb1ag"); 00406 00407 nub::soft_ref<RadioDecoder> rd(new RadioDecoder(manager)); 00408 manager.addSubComponent(rd); 00409 00410 nub::soft_ref<lcd> lcdDisp(new lcd(manager)); 00411 lcdDisp->setModelParamString("SerialPortDevName", 00412 "/dev/ttyS0", MC_RECURSE); 00413 manager.addSubComponent(lcdDisp); 00414 00415 // choose an IEEE1394grabber by default, and a few custom grabbing 00416 // defaults, for backward compatibility with an older version of 00417 // this program: 00418 manager.setOptionValString(&OPT_FrameGrabberType, "1394"); 00419 manager.setOptionValString(&OPT_FrameGrabberDims, "160x120"); 00420 manager.setOptionValString(&OPT_FrameGrabberMode, "YUV444"); 00421 manager.setOptionValString(&OPT_FrameGrabberNbuf, "20"); 00422 00423 // Parse command-line: 00424 if (manager.parseCommandLine(argc, argv, "", 0, 0) == false) return(1); 00425 00426 nub::soft_ref<FrameIstream> gb = gbc->getFrameGrabber(); 00427 if (gb.isInvalid()) 00428 LFATAL("No grabber. Why does god hate me?"); 00429 LINFO("GB width = %d height = %d\n",gb->getWidth(),gb->getHeight()); 00430 00431 // catch signals and redirect them to terminate for clean exit: 00432 signal(SIGHUP, terminate); signal(SIGINT, terminate); 00433 signal(SIGQUIT, terminate); signal(SIGTERM, terminate); 00434 signal(SIGALRM, terminate); 00435 00436 // let's get all our ModelComponent instances started: 00437 manager.start(); 00438 00439 // Calibrate the controls' 0 position 00440 lcdDisp->clear(); 00441 lcdDisp->printf(0, 1, "Calibrate Controls"); 00442 lcdDisp->printf(0, 2, "Rest Controls NOW!"); 00443 rd->zeroCalibrate(); 00444 00445 // Calibrate range of control swing 00446 lcdDisp->clear(); 00447 lcdDisp->printf(0, 1, "Calibrate Controls"); 00448 lcdDisp->printf(0, 2, "Full Swing NOW!"); 00449 rd->rangeCalibrate(); 00450 00451 // Save our configuration data so we don't have to calibrate again (Ha!) 00452 manager.saveConfig(); 00453 00454 lcdDisp->clear(); 00455 lcdDisp->printf(0, 2, "Press 2 (B) to Start"); 00456 smsg.reset(ctr, 0); 00457 smsg.addInt32(0); 00458 beo->send(0, smsg); 00459 while (myKB.getKey( true ) != KBD_KEY2) 00460 printf("\a"); // beep 00461 lcdDisp->clear(); 00462 printf("\a\a\a"); // beep 00463 00464 grabCycleInit( myKB, lcdDisp, gb ); 00465 /*******************************************************/ 00466 00467 Timer tim(1000000); 00468 tim.reset(); 00469 uint64 end, start=tim.get(); 00470 uint64 endpause, startpause=0, totalpause=0; 00471 double elapsed; 00472 double lastspeed = 0.4; // this is the default speed it starts out with. 00473 double totspeed = 0.0; 00474 unsigned long speedctr = 0; 00475 bool setspeed = false; 00476 int keypress = KBD_NONE; 00477 bool paused = false; 00478 while(!flag && goforever) 00479 { 00480 // this is to allow me to stop and change batteries, 00481 // etc w/o shutting down or causing it to learn to stop 00482 if( myKB.getKey( false ) == KBD_KEY3 || keypress == KBD_KEY3) 00483 { 00484 printf("pause\n"); 00485 keypress=KBD_NONE; 00486 usleep(500);//to avoid double hits 00487 if(paused) 00488 { 00489 paused=false; 00490 endpause=tim.get(); 00491 totalpause+=endpause-startpause; 00492 } 00493 else 00494 { 00495 smsg.reset(ctr, 0); //when ethernet is fixed, 00496 //remove these 3 line and update lcd here 00497 smsg.addInt32(-1); 00498 beo->send(0, smsg); 00499 paused=true; 00500 startpause=tim.get(); 00501 } 00502 } 00503 if(paused) continue; 00504 00505 /****************** 1: Grab Frame ******************/ 00506 ima = gb->readRGB(); 00507 Image< PixRGB<byte> >::const_iterator data = ima.begin();//w(); 00508 /***************************************************/ 00509 00510 /************** 2: Do Image Preproc ****************/ 00511 // extract Value (brightness/luminance/intensity/whatever) from HSV 00512 total = 0.0; 00513 iptr = bwimage; 00514 while (data != ima.end()) 00515 { 00516 double max = 0.0; 00517 if (data->red() > max) max = data->red(); 00518 if (data->green() > max) max = data->green(); 00519 if (data->blue() > max) max = data->blue(); 00520 *iptr = max; 00521 data++; 00522 total += *iptr++; 00523 } 00524 00525 //normalize 00526 mean = total / ((double)IMAGESIZE); 00527 std = 0.0; 00528 for(i = 0; i < IMAGESIZE; i++) 00529 std += pow(bwimage[i]-mean,2); 00530 std /= IMAGESIZE-1; 00531 std = sqrt(std); 00532 for(i = 0; i < IMAGESIZE; i++) 00533 { 00534 bwimage[i] -= mean; 00535 bwimage[i] /= std; 00536 } 00537 00538 /****************************************************/ 00539 00540 /***** 3: Do FFT and convolution for each block *****/ 00541 for(h = 0; h < HBLOCKS; h++) 00542 { 00543 for(l = 0; l < WBLOCKS; l++) 00544 { 00545 //FFT 00546 iptr = bwimage_sm; 00547 for(i = 0; i < WINDOWHEIGHT; i++) 00548 for(j = 0; j < WINDOWWIDTH; j++) 00549 *iptr++ = bwimage[h*WINDOWHEIGHT*IMAGEWIDTH+ 00550 l*WINDOWWIDTH + i*IMAGEWIDTH + j]; 00551 fftw->compute(magspec); 00552 00553 // Convolve with masks 00554 // This looks a bit more complicated than you might think 00555 // because I'm saving some time by not multiplying by the 00556 // whole image. The masks only cover a bit over half the image. 00557 for(i=0;i<DIMSIN;i++) 00558 { 00559 const int halfwidth=WINDOWWIDTH/2+1; 00560 const int halfheight=WINDOWHEIGHT/2; 00561 00562 int heighttop=halfheight; 00563 switch (i%8) 00564 { 00565 case 0: 00566 heighttop = halfheight; 00567 break; 00568 case 1: 00569 case 7: 00570 heighttop = (int)((double)halfheight*0.75); 00571 break; 00572 case 2: 00573 case 6: 00574 heighttop = (int)((double)halfheight*0.5); 00575 break; 00576 case 3: 00577 case 5: 00578 heighttop = (int)((double)halfheight*0.25); 00579 break; 00580 case 4: 00581 heighttop = 0; 00582 break; 00583 } 00584 00585 //some portion of top half 00586 for(int j = 0; j < heighttop; j++) 00587 {//left side 00588 for(int k = 0; k < halfwidth; k++) 00589 { 00590 int index = h*WBLOCKS*DIMSIN+l*DIMSIN+i; 00591 allfeatures.setVal 00592 (0, index, allfeatures.getVal(0, index) + 00593 magspec[j][k]*masks[i][j*WINDOWWIDTH+k]); 00594 } 00595 } 00596 if(heighttop>0) 00597 for(int k = halfwidth; k < WINDOWWIDTH; k++)//top row 00598 { 00599 int index = h*WBLOCKS*DIMSIN+l*DIMSIN+i; 00600 allfeatures.setVal 00601 (0, index, allfeatures.getVal(0,index) + 00602 magspec[0][WINDOWWIDTH-k]*masks[i][k]); 00603 } 00604 00605 for(int j = 1; j < heighttop; j++) 00606 {//right side 00607 for(int k = halfwidth; k < WINDOWWIDTH; k++) 00608 { 00609 int index = h*WBLOCKS*DIMSIN+l*DIMSIN+i; 00610 allfeatures.setVal 00611 (0, index, allfeatures.getVal(0,index) + 00612 magspec[WINDOWHEIGHT-j][WINDOWWIDTH-k]* 00613 masks[i][j*WINDOWWIDTH+k] ); 00614 } 00615 } 00616 00617 //bottom half 00618 for(int j = halfheight; j < WINDOWHEIGHT; j++) 00619 {//left side 00620 for(int k = 0; k < halfwidth; k++) 00621 { 00622 int index = h*WBLOCKS*DIMSIN+l*DIMSIN+i; 00623 allfeatures.setVal 00624 (0, index, allfeatures.getVal(0,index) + 00625 magspec[j][k]*masks[i][j*WINDOWWIDTH+k]); 00626 } 00627 } 00628 00629 for(int j = halfheight; j < WINDOWHEIGHT; j++) 00630 {//right side 00631 for(int k = halfwidth; k < WINDOWWIDTH; k++) 00632 { 00633 int index = h*WBLOCKS*DIMSIN+l*DIMSIN+i; 00634 allfeatures.setVal 00635 (0, index, allfeatures.getVal(0, index) + 00636 magspec[halfheight-(j-halfheight)][WINDOWWIDTH-k]* 00637 masks[i][j*WINDOWWIDTH+k]); 00638 } 00639 } 00640 } 00641 } 00642 } 00643 /************************************************/ 00644 00645 /********** 4: Project onto eigenvectors ********/ 00646 for(i = 0; i < DIMSIN; i++) 00647 for(j = 0; j < DIMSINALL; j++) 00648 features.setVal 00649 (0, i, features.getVal(0,i) + evecs[i][j]*allfeatures.getVal(0,j)); 00650 /************************************************/ 00651 00652 /****************** 5: FFN for Dims *************/ 00653 features = (features - meanarr)/stdarr; 00654 ffn_dm->run3L(features); 00655 /************************************************/ 00656 00657 /************ 6: Compute Motor Commands *********/ 00658 //// speed=ffn_dm->out[DIMSOUT-1]*2.0-1.0; 00659 // eh, make when I was computing speed to, rather than hacking it 00660 /* speed hack: if I'm giving it a speed command with the remote, 00661 it goes with that, otherwise it uses it's last speed value 00662 which is either the default (if I haven't given any speed commands yet) 00663 or the average of all the speed commands I gave last time*/ 00664 rcspeed = rd->getVal(0); 00665 if(fabs(rcspeed) > 0.1) 00666 { 00667 setspeed = true; 00668 lastspeed = rcspeed; 00669 totspeed += rcspeed; 00670 speedctr++; 00671 } 00672 else 00673 { 00674 if(setspeed) 00675 { 00676 setspeed = false; 00677 lastspeed = totspeed/(double)speedctr; 00678 totspeed = 0.0; 00679 speedctr = 0; 00680 } 00681 } 00682 speed = lastspeed; 00683 00684 /* // I could just choose the average output, but... 00685 double mysum=0.0;steer=0.0; 00686 for(i=0;i<DIMSOUT-1;i++){ 00687 mysum+=ffn_dm->out[i]; 00688 steer+=((double)(i+1))*ffn_dm->out[i]; 00689 } 00690 steer=steer/mysum; 00691 steer=((steer-1.0)/((double)DIMSOUT-1.0[2.0])*2.0-1.0)*-1.0; 00692 */ 00693 00694 // I choose the output probabilisticly 00695 double target=(double)rand()/(double)RAND_MAX; 00696 double mysum=0.0;double tprob=0.0; 00697 for(i=0;i<DIMSOUT-1;i++) 00698 mysum+=ffn_dm->getOutput().getVal(0,i); 00699 for(i=0;i<DIMSOUT-1;i++) 00700 { 00701 tprob+=ffn_dm->getOutput().getVal(0,i)/mysum; 00702 if (tprob>target) 00703 break; 00704 } 00705 steer=((((double)i+1.0)-1.0)/((double)DIMSOUT-1.0/*2.0*/)*2.0-1.0)*-1.0; 00706 //the commented 2 is left over from when speed was the last output 00707 00708 /***********************************************/ 00709 00710 /************ 7: Execute Motor Control *********/ 00711 compspeed = speed; //this is what gets written to the image file 00712 compsteer = steer; 00713 printf("computed speed=%f, steer=%f ctr=%ld\n",speed,steer,ctr+1); 00714 00715 updateweights=false; 00716 rcsteer=rd->getVal(1); 00717 if(fabs(rcspeed)>0.1 || fabs(rcsteer)>0.1){ 00718 printf("big rc signal\n"); 00719 updateweights=true; 00720 /*if(fabs(rcspeed)>0.1)*///speed=rcspeed; 00721 /*if(fabs(rcsteer)>0.1)*/steer=rcsteer; 00722 } 00723 printf("rc speed=%f, steer=%f ctr=%ld\n",rcspeed,rcsteer,ctr+1); 00724 00725 // call servo controller 00726 smsg.reset(ctr, 0); 00727 //// steer=steer-steer*fabs(steer)/5; 00728 smsg.addDouble(steer); 00729 // smsg.addDouble((speed*safety)); 00730 // speed=speed-speed*fabs(speed)/1.6666666667;//2;//max of 4 00731 smsg.addDouble(speed-speed*fabs(speed)/1.6666666667); 00732 beo->send(0, smsg); // send off to slave 00733 00734 // backprop 00735 if(updateweights==true){ 00736 trueout.clear(0.0); 00737 int on; 00738 on=(int)round(((steer*-1.0+1.0)/2.0)*((double)DIMSOUT-1.0/*2.0*/)+1.0); 00739 trueout.setVal(0, on-1, 1.0); 00740 if (on>1) 00741 trueout.setVal(0, on-2, 0.5);//give some weight to nearby orientations. 00742 // My thinking is this suppies a little bit of ordering to a system 00743 if (on>2) 00744 trueout.setVal(0, on-3, 0.25);//assuming choosing probabilisticly 00745 // rather than averaging) that regards eg hard right as equally distant 00746 if (on<DIMSOUT) 00747 trueout.setVal(0, on, 0.5);//from slightly less hard right as from left 00748 if (on<DIMSOUT-1) 00749 trueout.setVal(0, on+1, 0.25); 00750 ///// trueout[DIMSOUT-1]=(speed+1.0)/2.0; 00751 ffn_dm->backprop3L(trueout); 00752 } 00753 00754 // administrative stuff 00755 if(ctr%90==0 && ctr!=0)grabCycle( myKB, lcdDisp, gb ); 00756 // I save weights occasionally to prevent 00757 // the obligatory battery deaths from becoming catastrophic 00758 if(ctr%5000==0 && ctr!=0) 00759 ffn_dm->write3L("/lab/bb/data/nnwh1dm.dat", 00760 "/lab/bb/data/nnwh2dm.dat", "/lab/bb/data/nnwodm.dat"); 00761 // so I don't lose my work when it crashes 00762 00763 keypress=myKB.getKey( false ); 00764 if( keypress == KBD_KEY4 ){ 00765 flag=1; 00766 doQuit=true; 00767 LDEBUG("quit = true;"); 00768 } 00769 ctr++; 00770 if(ctr==0)flag=1; 00771 lcdDisp->clear(); 00772 lcdDisp->printf(0, 2, "%ld",ctr); 00773 smsg.reset(ctr, 0); 00774 smsg.addInt32(ctr); 00775 beo->send(0, smsg); 00776 /**************************************************/ 00777 } 00778 00779 /**************** 8: Cleanup...sort of ************/ 00780 end=tim.get(); 00781 elapsed=((end-start)-totalpause)/(double)1000000; 00782 printf("time=%f secs; processed %ld pics\n",elapsed,ctr); 00783 00784 //write weights 00785 ffn_dm->write3L("/lab/bb/data/nnwh1dm.dat", "/lab/bb/data/nnwh2dm.dat", 00786 "/lab/bb/data/nnwodm.dat"); 00787 delete ffn_dm; 00788 manager.stop(); 00789 /*************************************************/ 00790 00791 return 0; 00792 } 00793 00794 // ###################################################################### 00795 /* So things look consistent in everyone's emacs... */ 00796 /* Local Variables: */ 00797 /* indent-tabs-mode: nil */ 00798 /* End: */