00001 /*!@file Beobot/beobot-master.C main control program for beobots */ 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: Laurent Itti <itti@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Beobot/beobot-master.C $ 00035 // $Id: beobot-master.C 9412 2008-03-10 23:10:15Z farhan $ 00036 // 00037 00038 /*! 00039 This parallel vision processing master is for use with beobot-slave.C. 00040 See the beobotgo script in bin/ for how to launch the slaves. 00041 */ 00042 00043 //#define DEBUG_MODE 00044 00045 #include "Beobot/Beobot.H" 00046 #include "Beobot/beobot-defs.H" 00047 #include "Component/ModelManager.H" 00048 #include "Devices/DeviceOpts.H" 00049 #include "Devices/FrameGrabberConfigurator.H" 00050 #include "Devices/RadioDecoder.H" 00051 #include "GUI/XWindow.H" 00052 #include "Image/Image.H" 00053 #include "Image/Pixels.H" 00054 #include "Image/fancynorm.H" 00055 #include "Transport/FrameIstream.H" 00056 #include "Util/Types.H" 00057 00058 #include <cmath> 00059 #include <netdb.h> 00060 #include <signal.h> 00061 #include <unistd.h> 00062 00063 //! Names of the beowulf slaves (default port is 9789) 00064 #define SLAVES "bb1ag:9790 bb1bg:9789 bb1bg:9790" 00065 00066 //! Number of frames over which to compute average stats: 00067 #define NBAVG 10 00068 //! Number of stats to collect: 00069 #define NBSTATS 6 00070 00071 //! define this to use only one cpu 00072 #define USE_SINGLE_CPU 0 00073 00074 static bool goforever = true; //!< Will turn false on interrupt signal 00075 00076 //! Signal handler (e.g., for control-C) 00077 void terminate(int s) 00078 { LERROR("*** INTERRUPT ***"); goforever = false; } 00079 00080 // ###################################################################### 00081 int main(const int argc, const char **argv) 00082 { 00083 MYLOGVERB = LOG_INFO; 00084 00085 // instantiate a model manager: 00086 ModelManager manager("Beobot Main"); 00087 00088 // Instantiate our various ModelComponents: 00089 nub::soft_ref<FrameGrabberConfigurator> 00090 gbc(new FrameGrabberConfigurator(manager)); 00091 manager.addSubComponent(gbc); 00092 00093 nub::soft_ref<RadioDecoder> radio(new RadioDecoder(manager)); 00094 manager.addSubComponent(radio); 00095 00096 // choose an IEEE1394grabber by default, and a few custom grabbing 00097 // defaults, for backward compatibility with an older version of 00098 // this program: 00099 manager.setOptionValString(&OPT_FrameGrabberType, "1394"); 00100 manager.setOptionValString(&OPT_FrameGrabberDims, "160x120"); 00101 00102 // Parse command-line: 00103 if (manager.parseCommandLine(argc, argv, "<hostname> <port>", 00104 2, 2) == false) return(1); 00105 00106 // do post-command-line configs: 00107 nub::soft_ref<FrameIstream> gb = gbc->getFrameGrabber(); 00108 if (gb.isInvalid()) 00109 LFATAL("You need to select a frame grabber type via the " 00110 "--fg-type=XX command-line option for this program " 00111 "to be useful"); 00112 int imgwidth = gb->getWidth(), imgheight = gb->getHeight(); 00113 00114 struct hostent *he = gethostbyname(manager.getExtraArg(0).c_str()); 00115 in_addr_t myIP = 0; 00116 if (he == NULL) 00117 LFATAL("Cannot determine IP address of %s",manager.getExtraArg(0).c_str()); 00118 else myIP = ntohl( ((in_addr *)(he->h_addr_list[0]))->s_addr ); 00119 short int port = manager.getExtraArgAs<int>(1); 00120 LINFO("Start on %s[%lx]:%d", 00121 manager.getExtraArg(0).c_str(), (unsigned long) myIP, port); 00122 00123 // catch signals and redirect them to terminate for clean exit: 00124 signal(SIGHUP, terminate); signal(SIGINT, terminate); 00125 signal(SIGQUIT, terminate); signal(SIGTERM, terminate); 00126 signal(SIGALRM, terminate); 00127 00128 // calibrate radio: 00129 ///radio.zeroCalibrate(); 00130 ///radio.rangeCalibrate(); 00131 00132 // get prepared to grab: 00133 Image< PixRGB<byte> > *ima; // image to grab 00134 int frame = 0; // grabbed frame number 00135 00136 // initialize beobot: 00137 #if USE_SINGLE_CPU != 0 00138 Beobot beobot(NULL, imgwidth, imgheight, LEVEL_MIN, LEVEL_MAX, 00139 DELTA_MIN, DELTA_MAX, SMLEVEL, NBORIENTS, VCXNORM_MAXNORM, 00140 JETLEVEL, JETDEPTH, NBNEIGH, myIP, port); 00141 #else 00142 Beobot beobot(SLAVES, imgwidth, imgheight, LEVEL_MIN, LEVEL_MAX, 00143 DELTA_MIN, DELTA_MAX, SMLEVEL, NBORIENTS, VCXNORM_MAXNORM, 00144 JETLEVEL, JETDEPTH, NBNEIGH, myIP, port); 00145 #endif 00146 00147 // get access to beobot's input image so that we can grab it: 00148 ima = beobot.getRetinaPtr(); 00149 00150 // accumulate processing statistics: 00151 int stats[NBSTATS]; Timer tim; int navg = 0; 00152 for (int i = 0; i < NBSTATS; i ++) stats[i] = 0; 00153 00154 #ifdef DEBUG_MODE 00155 // get some debug displays going: 00156 XWindow xw(gb->peekDims()), xw2(gb->peekDims()); 00157 #endif 00158 00159 LINFO("All initializations complete. READY."); 00160 00161 // let's get all our ModelComponent instances started: 00162 manager.start(); 00163 00164 // ########## MAIN LOOP: grab, process, display: 00165 while(goforever) 00166 { 00167 tim.reset(); 00168 00169 // grab an image: 00170 *ima = gb->readRGB(); 00171 stats[0] += tim.getReset(); 00172 00173 // start low-level processing on slave nodes: 00174 if (frame == 0 || USE_SINGLE_CPU) beobot.lowLevel(frame); 00175 else beobot.lowLevelStart(frame); 00176 stats[1] += tim.getReset(); 00177 // CAUTION: we do intermediate processing on the low-level results that 00178 // were collected at the previous frame... 00179 00180 // intermediate level processing: 00181 //// beobot.intermediateLevel(true); 00182 // always true until we figure a way to reset when messed up 00183 00184 stats[2] += tim.getReset(); 00185 00186 // high level processing 00187 ////beobot.highLevel(); 00188 stats[3] += tim.getReset(); 00189 00190 #ifdef DEBUG_MODE 00191 // show the clustered image for debug (before we do decision) 00192 Image< PixRGB<byte> >tmp; 00193 ////beobot.DEBUGgetClustered(tmp); xw2.drawImage(tmp); 00194 #endif 00195 00196 // determine current action 00197 ////beobot.decision(); 00198 stats[4] += tim.getReset(); 00199 00200 // and finally... 00201 // we don't move the robot at this point beobot.act(); 00202 BeobotAction a; Point2D<int> win; 00203 ////beobot.DEBUGgetCurrentAction(a); beobot.getWinner(win); 00204 float speed = a.getSpeed(), turn = a.getTurn(); 00205 00206 // radio takeover: 00207 // float rspeed = radio.getVal(0), rturn = radio.getVal(1); 00208 //if (fabs(rspeed) > 0.1F) speed = rspeed; 00209 //if (fabs(rturn) > 0.1F) turn = rturn; 00210 00211 if (fabs(speed) > 0.2) speed = 0.2; // be slooooow 00212 00213 LINFO("frame %d: speed = %.1f, turn = %.1f, winner = [%d, %d]", 00214 frame, speed, turn, win.i, win.j); 00215 00216 // override beobot's action, taking into consideration the radio: 00217 a.setSpeed(speed); a.setTurn(turn); a.setGear(1); 00218 ////beobot.DEBUGsetCurrentAction(a); 00219 00220 // actuate: 00221 ////beobot.action(); 00222 00223 // collect results from low-level processing on slave nodes: 00224 if (frame > 0 && USE_SINGLE_CPU == 0) beobot.lowLevelEnd(frame); 00225 stats[5] += tim.getReset(); 00226 00227 // display stats 00228 navg ++; 00229 if (navg == NBAVG) { 00230 LINFO("GB:%.1f LL:%.1f IL:%.1f HL:%.1f DC:%.1f LL:%.1f", 00231 ((float)(stats[0])) / (float)NBAVG, 00232 ((float)(stats[1])) / (float)NBAVG, 00233 ((float)(stats[2])) / (float)NBAVG, 00234 ((float)(stats[3])) / (float)NBAVG, 00235 ((float)(stats[4])) / (float)NBAVG, 00236 ((float)(stats[5])) / (float)NBAVG); 00237 navg = 0; for (int i = 0; i < NBSTATS; i ++) stats[i] = 0; 00238 } 00239 00240 #ifdef DEBUG_MODE 00241 // draw focus of attention on original frame: 00242 PixRGB<byte> yellow(255, 255, 0); 00243 ima->drawCircle(win, imgwidth/12, yellow, 2); 00244 00245 // show the original frame: 00246 xw.drawImage(*ima); 00247 #endif 00248 00249 // ready for next frame... 00250 frame ++; 00251 } 00252 00253 // got interrupted; let's cleanup and exit: 00254 manager.stop(); 00255 exit(0); 00256 } 00257 00258 // ###################################################################### 00259 /* So things look consistent in everyone's emacs... */ 00260 /* Local Variables: */ 00261 /* indent-tabs-mode: nil */ 00262 /* End: */