00001 /*!@file Beobot/beobot-GSnav-master.C Robot navigation using a 00002 combination saliency and gist. 00003 Run beobot-GSnav-master at CPU_A to run Gist-Saliency model 00004 Run beobot-GSnav at CPU_B to run SIFT object recognition */ 00005 // //////////////////////////////////////////////////////////////////// // 00006 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00007 // University of Southern California (USC) and the iLab at USC. // 00008 // See http://iLab.usc.edu for information about this project. // 00009 // //////////////////////////////////////////////////////////////////// // 00010 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00011 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00012 // in Visual Environments, and Applications'' by Christof Koch and // 00013 // Laurent Itti, California Institute of Technology, 2001 (patent // 00014 // pending; application number 09/912,225 filed July 23, 2001; see // 00015 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00016 // //////////////////////////////////////////////////////////////////// // 00017 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00018 // // 00019 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00020 // redistribute it and/or modify it under the terms of the GNU General // 00021 // Public License as published by the Free Software Foundation; either // 00022 // version 2 of the License, or (at your option) any later version. // 00023 // // 00024 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00025 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00026 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00027 // PURPOSE. See the GNU General Public License for more details. // 00028 // // 00029 // You should have received a copy of the GNU General Public License // 00030 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00031 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00032 // Boston, MA 02111-1307 USA. // 00033 // //////////////////////////////////////////////////////////////////// // 00034 // 00035 // Primary maintainer for this file: Christian Siagian <siagian@usc.edu> 00036 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Beobot/beobot-GSnav-master.C $ 00037 // $Id: beobot-GSnav-master.C 12962 2010-03-06 02:13:53Z irock $ 00038 // 00039 ////////////////////////////////////////////////////////////////////////// 00040 // beobot-GSnav-Master.C <operation mode> <environment file> 00041 // [number of segments] [current Segment Number] 00042 // 00043 // 00044 // This is an on-going project for biologically-plausible 00045 // mobile-robotics navigation. 00046 // It accepts any inputs: video clip <input.mpg>, camera feed, frames. 00047 // 00048 // The system uses Gist to recognize places and saliency 00049 // to get better localization within the place. 00050 // The program also is made to be streamline for fast processing using 00051 // parallel computation of the different the V1 feature channels 00052 // 00053 // It is able to recognize places through the use of gist features. 00054 // The place classifier uses a neural networks, 00055 // passed in a form of <input_train.txt> - 00056 // the same file is used in the training phase by train-FFN.C. 00057 // 00058 // In parallel we use saliency to obtain salient objects for better 00059 // spatial location accuracy. 00060 // We use ShapeEstimator algorithm to segment out 00061 // the sub-region to get a landmark and SIFT toidentify the object, 00062 // create a database, etc. 00063 // 00064 // for localization, we use particle filter/Monte Carlo Localization 00065 // for path planning we perform landmark-hopping to get to the destination 00066 00067 #include "Beowulf/Beowulf.H" 00068 #include "Component/ModelManager.H" 00069 #include "Media/FrameSeries.H" 00070 #include "Transport/FrameIstream.H" 00071 #include "Neuro/SaccadeController.H" 00072 #include "Neuro/SaccadeControllers.H" 00073 #include "Neuro/SaccadeControllerConfigurator.H" 00074 #include "Neuro/NeuroOpts.H" 00075 #include "Image/Image.H" 00076 #include "Image/Pixels.H" 00077 #include "Raster/Raster.H" 00078 #include "GUI/XWinManaged.H" 00079 #include "Media/MediaOpts.H" 00080 #include "Util/Timer.H" 00081 #include "Simulation/SimEventQueue.H" 00082 #include "Simulation/SimEventQueueConfigurator.H" 00083 #include "Devices/DeviceOpts.H" 00084 00085 #include "Beobot/BeobotBrainMT.H" 00086 #include "Beobot/BeobotConfig.H" 00087 #include "Beobot/BeobotControl.H" 00088 #include "Beobot/BeobotBeoChipListener.H" 00089 00090 #include "RCBot/Motion/MotionEnergy.H" 00091 #include "Controllers/PID.H" 00092 00093 #include "Image/MathOps.H" // for findMax 00094 #include "Image/CutPaste.H" // for inplacePaste() 00095 #include "Image/DrawOps.H" 00096 #include "Image/FilterOps.H" 00097 #include "Image/PyramidOps.H" 00098 #include "Image/ShapeOps.H" 00099 #include "Image/Transforms.H" 00100 00101 #include "Beobot/beobot-GSnav-def.H" 00102 #include "Beobot/GSnavResult.H" 00103 00104 #include <signal.h> 00105 00106 #include <errno.h> 00107 00108 #define ERR_INTERVAL 5000 00109 00110 static bool goforever = true; 00111 00112 // ###################################################################### 00113 // ###################################################################### 00114 //! get the input prefix to save the intermdeiate results 00115 std::string getInputPrefix(nub::soft_ref<InputFrameSeries> ifs, 00116 int &inputType); 00117 00118 //! get the operation mode of the current run 00119 int getOpMode(std::string opmodestr); 00120 00121 //! setup the BeoChip 00122 void setupBeoChip(nub::soft_ref<BeoChip> b, BeobotConfig bbc); 00123 00124 //! process beoChip input 00125 int beoChipProc 00126 (rutz::shared_ptr<BeobotBeoChipListener> lis, nub::soft_ref<BeoChip> b); 00127 00128 //! get all the necessary information from the visual cortex 00129 void getBbmtResults 00130 ( nub::ref<BeobotBrainMT> bbmt, 00131 Image<PixRGB<byte> > &currIma, Image<double> &cgist, 00132 Image<float> &currSalMap, ImageSet<float> &cmap, 00133 std::vector<Point2D<int> > &salpt, std::vector<std::vector<double> > &feat, 00134 std::vector<Rectangle> &objRect); 00135 00136 //! display results 00137 void dispResults 00138 ( Image< PixRGB<byte> > disp, rutz::shared_ptr<XWinManaged> win, 00139 Image< PixRGB<byte> > ima, Image< PixRGB<byte> > prevIma, 00140 std::vector<Point2D<int> > clmpt, std::vector<Point2D<int> > nlmpt, 00141 Image<float> currSalMap, 00142 std::vector<Point2D<int> > salpt, std::vector<Rectangle> objRect); 00143 00144 //! check to see if the node have returned results 00145 bool checkNode 00146 ( int opMode, nub::soft_ref<Beowulf> beo, 00147 int32 &rnode, TCPmessage &rmsg, int32 &raction, int32 &rframe); 00148 00149 //! check to see if the new input should be processed 00150 bool checkInput(int opMode, bool resetNextLandmark, 00151 uint64 inputFrameRate, uint64 inputTime); 00152 00153 //! setup the packat containing the salient region information 00154 //! to be recognized by the ventral module 00155 void setupVentralPacket 00156 ( TCPmessage &smsg, int rframe, 00157 bool resetVentralSearch, Image< PixRGB<byte> > currIma, 00158 Image<double> cgist, std::vector<Point2D<int> > salpt, 00159 std::vector<std::vector<double> > feat, std::vector<Rectangle> objRect, 00160 float dx, float dy, uint snumGT, float ltravGT); 00161 00162 //! setup the packet containing cmaps for tracking 00163 void setupDorsalPacket 00164 ( TCPmessage &smsg, int rframe, ImageSet<float> cmap, 00165 bool resetCurrLandmark, std::vector<Point2D<int> > clmpt, 00166 bool resetNextLandmark, std::vector<Point2D<int> > nlmpt); 00167 00168 //! get the proper motor command to run the robot 00169 void processDorsalResult 00170 ( TCPmessage &rmsg, int32 raction, int32 rframe, 00171 std::vector<Point2D<int> > &clmpt, std::vector<Point2D<int> > &nlmpt, 00172 bool &resetNextLandmark, float &sp, float &st); 00173 00174 //! setup for the next search 00175 void processVentralResult 00176 ( TCPmessage &rmsg, int32 raction, int32 rframe, 00177 std::vector<Point2D<int> > &clmpt, std::vector<Point2D<int> > &nlmpt, 00178 bool &resetCurrLandmark, bool &resetNextLandmark); 00179 00180 //! get the odometry information 00181 void getOdometry(float &dx, float &dy); 00182 00183 //! execute the motor command from Dorsal 00184 void executeMotorCommand(int opMode, float st, float sp); 00185 00186 //! feed in the current ground truth 00187 Image<double> 00188 getGroundTruth(uint fNum, uint &snumGT, float <ravGT, float &dx, float &dy); 00189 00190 //! report the results of the current run 00191 void reportResults(std::string resultPrefix, uint nsegment); 00192 00193 // ###################################################################### 00194 //! Signal handler (e.g., for control-C) 00195 void terminate(int s) 00196 { LERROR("*** INTERRUPT ***"); goforever = false; exit(1); } 00197 00198 // ###################################################################### 00199 int main(const int argc, const char **argv) 00200 { 00201 MYLOGVERB = LOG_INFO; 00202 00203 // instantiate a model manager: 00204 ModelManager manager("beobot Navigation using Gist and Saliency - Master"); 00205 00206 // Instantiate our various ModelComponents: 00207 //BeobotConfig bbc; 00208 //nub::soft_ref<BeoChip> b(new BeoChip(manager)); 00209 //manager.addSubComponent(b); 00210 00211 nub::soft_ref<InputFrameSeries> ifs(new InputFrameSeries(manager)); 00212 manager.addSubComponent(ifs); 00213 00214 nub::ref<BeobotBrainMT> bbmt(new BeobotBrainMT(manager)); 00215 manager.addSubComponent(bbmt); 00216 00217 nub::soft_ref<Beowulf> 00218 beo(new Beowulf(manager, "Beowulf Master", "BeowulfMaster", true)); 00219 manager.addSubComponent(beo); 00220 00221 manager.exportOptions(MC_RECURSE); 00222 00223 // Parse command-line: 00224 // if (manager.parseCommandLine 00225 // (argc, argv, 00226 // "<operation mode: train/trainX/test> <environment file> " 00227 // "[TR: number of segments |TX: NodeNumber |TS: delay] " 00228 // "[TR: current Segment Number |TX: startEdge,endEdge |TS: fstart] " 00229 // "[test run file prefix] ", 00230 // 2, 5) 00231 if (manager.parseCommandLine(argc, argv, 00232 "<operation mode> <environment file> " 00233 "[TR: number of segments | TS: delay] " 00234 "[current Segment Number | TS: fstart] " 00235 "[test run file prefix] ", 00236 2, 5) 00237 == false) return(1); 00238 00239 // do post-command-line configs: 00240 00241 // let's configure our serial device: 00242 //b->setModelParamVal("BeoChipDeviceName", std::string("/dev/ttyS0")); 00243 00244 // let's register our listener: 00245 //rutz::shared_ptr<BeobotBeoChipListener> lis(new BeobotBeoChipListener(b)); 00246 //rutz::shared_ptr<BeoChipListener> lis2; lis2.dynCastFrom(lis); // cast down 00247 //b->setListener(lis2); 00248 00249 // inputs: number of segments and current segment number 00250 // is needed for initial training, otherwise it is reset later on 00251 int nSegment = 0, currSegNum = -1; 00252 //int currNodeNum = -1, startEdge = -1, endEdge = -1; 00253 00254 // get the environment file and folder to save 00255 std::string envFName = manager.getExtraArg(1); 00256 std::string saveFilePath = ""; 00257 std::string::size_type lspos = envFName.find_last_of('/'); 00258 int ldpos = envFName.find_last_of('.'); 00259 std::string envPrefix; 00260 if(lspos != std::string::npos) 00261 { 00262 saveFilePath = envFName.substr(0, lspos+1); 00263 envPrefix = envFName.substr(lspos+1, ldpos - lspos - 1); 00264 } 00265 else 00266 envPrefix = envFName.substr(0, ldpos - 1); 00267 00268 // get the the input type and prefix to name the salient objects, gistfile 00269 int inputType; 00270 std::string testRunFPrefix = 00271 std::string("results_") + getInputPrefix(ifs, inputType); 00272 if(manager.numExtraArgs() > 4) 00273 testRunFPrefix = manager.getExtraArgAs<std::string>(4); 00274 00275 std::string testRunFolder = 00276 saveFilePath + testRunFPrefix + std::string("/"); 00277 std::string resultPrefix = testRunFolder + envPrefix; 00278 00279 // get the operation mode 00280 int opMode = getOpMode(manager.getExtraArg(0)); 00281 00282 // means next frame will be processed once Ventral is done 00283 uint64 inputFrameRate = 0; 00284 uint fstart = 0; 00285 00286 // handle the command line inputs 00287 LINFO("opmode: %d", opMode); 00288 if(opMode == TRAIN_MODE) 00289 { 00290 if(manager.numExtraArgs() < 4) 00291 LFATAL("Training needs at least 4 params"); 00292 nSegment = manager.getExtraArgAs<int>(2); 00293 currSegNum = manager.getExtraArgAs<int>(3); 00294 LINFO("number of segments: %d", nSegment); 00295 LINFO("current segment: %d", currSegNum); 00296 } 00297 // else if(opMode == TRAIN_X_MODE) 00298 // { 00299 // if(manager.numExtraArgs() < 4) 00300 // LFATAL("Junction training needs at least 4 params"); 00301 00302 // currNodeNum = manager.getExtraArgAs<int>(2); 00303 // std::string tempRange = manager.getExtraArg(3); 00304 // std::string::size_type lspos = tempRange.size()-1; 00305 // std::string::size_type lcpos = tempRange.find_last_of(','); 00306 // startEdge = atoi(tempRange.substr(1, lcpos-1).c_str()); 00307 // endEdge = atoi(tempRange.substr(lcpos+1, lspos).c_str()); 00308 00309 // LINFO("Junction Node: %d", currNodeNum); 00310 // LINFO("Start Edge: %d", startEdge); 00311 // LINFO("End Edge: %d", endEdge); 00312 // } 00313 else if(opMode == TEST_MODE) 00314 { 00315 if(manager.numExtraArgs() > 2) 00316 inputFrameRate = manager.getExtraArgAs<uint>(2); 00317 00318 if(manager.numExtraArgs() > 3) 00319 fstart = manager.getExtraArgAs<uint>(3); 00320 } 00321 else LFATAL("invalid opmode"); 00322 00323 LINFO("Environment file: %s", envFName.c_str()); 00324 LINFO("Save file to this folder: %s", saveFilePath.c_str()); 00325 LINFO("envPrefix: %s", envPrefix.c_str()); 00326 LINFO("test run prefix: %s", testRunFPrefix.c_str()); 00327 LINFO("test run folder: %s", testRunFolder.c_str()); 00328 LINFO("result prefix: %s", resultPrefix.c_str()); 00329 LINFO("frame frequency: %f ms/frame", inputFrameRate/1000.0F); 00330 00331 // create the session result folder 00332 if (mkdir(testRunFolder.c_str(), 0777) == -1 && errno != EEXIST) 00333 { 00334 LFATAL("Cannot create log folder: %s", testRunFolder.c_str()); 00335 } 00336 00337 // HACK: results for paper 00338 //reportResults(resultPrefix, 9); Raster::waitForKey(); 00339 00340 int w = ifs->getWidth(), h = ifs->getHeight(); 00341 std::string dims = convertToString(Dims(w, h)); 00342 LINFO("image size: [%dx%d]", w, h); 00343 manager.setOptionValString(&OPT_InputFrameDims, dims); 00344 00345 manager.setModelParamVal("InputFrameDims", Dims(w, h), 00346 MC_RECURSE | MC_IGNORE_MISSING); 00347 00348 TCPmessage rmsg; // buffer to receive messages 00349 TCPmessage smsg; // buffer to send messages 00350 int32 rframe = 0, raction = 0, rnode = 0; 00351 00352 // catch signals and redirect them to terminate for clean exit: 00353 signal(SIGHUP, terminate); signal(SIGINT, terminate); 00354 signal(SIGQUIT, terminate); signal(SIGTERM, terminate); 00355 signal(SIGALRM, terminate); 00356 00357 // let's do it! 00358 manager.start(); 00359 00360 // send params to dorsal and ventral node to initialize contact: 00361 smsg.reset(0, INIT_COMM); 00362 smsg.addInt32(int32(fstart)); 00363 smsg.addInt32(int32(w)); 00364 smsg.addInt32(int32(h)); 00365 smsg.addInt32(int32(opMode)); 00366 smsg.addInt32(int32(nSegment)); 00367 smsg.addInt32(int32(currSegNum)); 00368 smsg.addString(envFName.c_str()); 00369 smsg.addString(testRunFPrefix.c_str()); 00370 smsg.addString(saveFilePath.c_str()); 00371 smsg.addString(resultPrefix.c_str()); 00372 00373 // send the same initial values message to both nodes 00374 beo->send(DORSAL_NODE, smsg); 00375 beo->send(VENTRAL_NODE, smsg); 00376 00377 // saliency map 00378 Image<float> currSalMap(w >> sml, h >> sml, ZEROS); 00379 00380 // image buffer and window for display: 00381 Image<PixRGB<byte> > disp(w * 5, h, ZEROS); 00382 //rutz::shared_ptr<XWinManaged> mwin 00383 // (new XWinManaged(disp.getDims(), w*2 + 10, 0, "Master window")); 00384 00385 // setup the configuration of BeoChip 00386 //setupBeoChip(b,bbc); 00387 00388 // if we are on training mode 00389 // the remote control can be used to steer 00390 //if(opMode == TRAIN_MODE) lis->moveServo = true; 00391 00392 ImageSet<float> cmap(NUM_CHANNELS); 00393 Point2D<int> lastwin(-1,-1); Point2D<int> lastwinsc(-1,-1); 00394 00395 // SYNCHRONIZATION: wait until the other board is ready 00396 LINFO("waiting until Ventral and Dorsal is ready to go"); 00397 rnode = VENTRAL_NODE; 00398 while(!beo->receive(rnode, rmsg, rframe, raction, 5)); 00399 LINFO("%d is ready", rnode); 00400 rnode = DORSAL_NODE; 00401 while(!beo->receive(rnode, rmsg, rframe, raction, 5)); 00402 LINFO("%d is ready", rnode); 00403 rmsg.reset(rframe, raction); 00404 LINFO("Ventral and Dorsal are ready to go"); 00405 Raster::waitForKey(); 00406 00407 // time result file 00408 std::string resFName = resultPrefix + sformat("_M_results.txt"); 00409 00410 // MAIN LOOP 00411 bool resetCurrLandmark = false; 00412 std::vector<Point2D<int> > clmpt; // landmarks that are currently followed 00413 bool resetNextLandmark = true; 00414 std::vector<Point2D<int> > nlmpt; // landmarks that are currently searched 00415 00416 float sp = 0.0f; float st = 0.0f; 00417 00418 Timer inputTimer(1000000); uint64 t[NAVG]; float frate = 0.0f; 00419 Timer ventralTimer(1000000); Timer dorsalTimer(1000000); 00420 float vTime = -1.0F; float dTime = -1.0F; 00421 00422 // feed an initial image to get the ball rolling 00423 bool dorsalReplied = false; std::vector<float> procTime; 00424 bool resetVentralSearch = false; 00425 bool stopSent = false; 00426 Image<PixRGB<byte> > ima; int32 fNum = fstart; 00427 Image<PixRGB<byte> > prevIma; inputTimer.reset(); 00428 ifs->updateNext(); ima = ifs->readRGB(); 00429 if(!ima.initialized()) { goforever = false; } 00430 else { bbmt->input(ima);} //mwin->drawImage(ima,0,0); } 00431 while(goforever || !dorsalReplied) 00432 { 00433 // ADD GUI HANDLER HERE 00434 00435 // beoChip procedures 00436 //int bcCom = beoChipProc(lis, b); 00437 //if(bcCom == BC_QUIT_SIGNAL) { goforever = false; break; } 00438 00439 // // keyboard input 00440 // // FIX: figure out the mapping from just printing it 00441 // // get the 1 - 0 - enter sequence 00442 // int tPress = mwin->getLastKeyPress(); 00443 // if(tPress != -1 && tPress >= 10 && tPress <= 18) 00444 // currSegNum = tPress - 10; 00445 00446 // if Dorsal computation is ready 00447 rnode = DORSAL_NODE; int32 rDframe; 00448 if(checkNode(opMode, beo, rnode, rmsg, raction, rDframe)) 00449 { 00450 LINFO("IN DORSAL: %d", rDframe); 00451 processDorsalResult(rmsg, raction, rframe, clmpt, nlmpt, 00452 resetNextLandmark, sp, st); 00453 dTime = dorsalTimer.get()/1000.0F; 00454 LDEBUG("Dorsal time[%d]: %f", rDframe, dTime); 00455 dorsalReplied = true; 00456 } 00457 00458 // if ventral computation is ready 00459 // & dorsal replied at least once 00460 rnode = VENTRAL_NODE; int32 rVframe; 00461 if(dorsalReplied && 00462 checkNode(opMode, beo, rnode, rmsg, raction, rVframe)) 00463 { 00464 processVentralResult(rmsg, raction, rframe, clmpt, nlmpt, 00465 resetCurrLandmark, resetNextLandmark); 00466 LINFO("IN VENTRAL: %d ::: %d", rVframe, resetNextLandmark); 00467 00468 vTime = ventralTimer.get()/1000.0F; 00469 LDEBUG("Ventral time[%d]: %f", rVframe, vTime); 00470 stopSent = false; 00471 } 00472 00473 // get odometry information 00474 float dx, dy; getOdometry(dx, dy); 00475 00476 // execute the motor command 00477 executeMotorCommand(opMode, sp, st); 00478 00479 // when the saliency and gist computation is ready 00480 // AND input timing is right 00481 uint64 inputTime = inputTimer.get(); 00482 if(checkInput(opMode, resetNextLandmark, inputFrameRate, inputTime) 00483 && bbmt->outputReady()) 00484 { 00485 t[fNum % NAVG] = inputTime; inputTimer.reset(); 00486 Timer t1(1000000); t1.reset(); 00487 float bbmtTime = bbmt->getProcessTime(); 00488 rframe = fNum; 00489 00490 // get all the necesary information from V1: 00491 Image<PixRGB<byte> > currIma; Image<float> currSalMap; 00492 Image<double> cgist; 00493 std::vector<Point2D<int> > salpt; 00494 std::vector<std::vector<double> >feat; 00495 std::vector<Rectangle> objRect; 00496 getBbmtResults(bbmt, currIma, cgist, currSalMap, 00497 cmap, salpt, feat, objRect); 00498 00499 // get the next frame and start processing 00500 FrameState fState = ifs->updateNext(); ima = ifs->readRGB(); 00501 if(!ima.initialized() || fState == FRAME_COMPLETE) 00502 { goforever = false; } 00503 else bbmt->input(ima); 00504 uint snumGT = 0; float ltravGT = -1.0F; 00505 00506 // get ground truth 00507 if(opMode == TEST_MODE) 00508 { 00509 getGroundTruth(fNum, snumGT, ltravGT, dx, dy); 00510 //cgist = getGroundTruth(fNum, snumGT, ltravGT, dx, dy); 00511 LINFO("GT: (%d, %f) d (%f, %f)", snumGT, ltravGT, dx, dy); 00512 } 00513 00514 // if timer goes past the time limit and robot is moving 00515 // FIX: maybe we still discard search even if robot is stationary 00516 if(resetNextLandmark) ventralTimer.reset(); 00517 if(inputFrameRate != 0 && 00518 ventralTimer.get() > (inputFrameRate * SEARCH_TIME_LIMIT) && 00519 !stopSent && sp != 0.0) 00520 { 00521 resetVentralSearch = true; 00522 LINFO("ventral time: %f ms. STOP", ventralTimer.get()/1000.0f); 00523 stopSent = true; 00524 } 00525 00526 // set up the salient region packet and send to ventral 00527 setupVentralPacket 00528 (smsg, rframe, resetVentralSearch, currIma, 00529 cgist, salpt, feat, objRect, dx, dy, snumGT, ltravGT); 00530 beo->send(VENTRAL_NODE, smsg); 00531 resetVentralSearch = false; 00532 LINFO("send ventral done"); 00533 00534 // setup the tracking packet and send to dorsal 00535 setupDorsalPacket(smsg, rframe, cmap, 00536 resetCurrLandmark, clmpt, 00537 resetNextLandmark, salpt); 00538 beo->send(DORSAL_NODE, smsg); 00539 dorsalTimer.reset(); 00540 dorsalReplied = false; 00541 00542 // once landmarks are reset, we don't do it over again 00543 bool rCL = resetCurrLandmark; 00544 bool rNL = resetNextLandmark; 00545 if(resetCurrLandmark) resetCurrLandmark = false; 00546 if(resetNextLandmark) resetNextLandmark = false; 00547 00548 // display the results 00549 //mwin->setTitle(sformat("fNum: %d",fNum).c_str()); 00550 //dispResults(disp, mwin, currIma, prevIma, clmpt, nlmpt, 00551 // currSalMap, salpt, objRect); 00552 prevIma = currIma; 00553 //Raster::waitForKey(); 00554 00555 // compute and show framerate over the last NAVG frames: 00556 float iTime = t[fNum % NAVG]/1000.0F; 00557 FILE *rFile = fopen(resFName.c_str(), "at"); 00558 if (rFile != NULL) 00559 { 00560 // if ventral search has not returned 00561 float dispVTime = vTime; 00562 if(!rNL) dispVTime = ventralTimer.get()/1000.0F; 00563 00564 std::string line = 00565 sformat("%5d %11.5f %d %d %11.5f %11.5f %11.5f", 00566 fNum, bbmtTime, rCL, rNL, dTime, dispVTime, iTime); 00567 LINFO("%s", line.c_str()); 00568 line += std::string("\n"); 00569 fputs(line.c_str(), rFile); 00570 fclose (rFile); 00571 } 00572 else LFATAL("can't create result file: %s", resFName.c_str()); 00573 00574 fNum++; 00575 if (fNum % NAVG == 0 && fNum > 0) 00576 { 00577 uint64 sum = 0ULL; for(int i = 0; i < NAVG; i ++) sum += t[i]; 00578 frate = 1000000.0F / float(sum) * float(NAVG); 00579 LINFO("Fr: %6.3f fps -> %8.3f ms/f\n", frate, 1000.0/frate); 00580 } 00581 uint64 ptime = t1.get(); float ptime2 = ptime/1000.0; 00582 procTime.push_back(ptime2); 00583 LDEBUG("total proc time: %f", ptime2); 00584 t1.reset(); 00585 } 00586 //else{ usleep(10); } 00587 } 00588 00589 // wait for the ventral response for one more time step 00590 uint64 inputTime = inputTimer.get(); 00591 while(!checkInput(opMode, resetNextLandmark, inputFrameRate, inputTime)) 00592 { 00593 rnode = VENTRAL_NODE; int32 rVframe; 00594 if(checkNode(opMode, beo, rnode, rmsg, raction, rVframe)) 00595 { 00596 processVentralResult(rmsg, raction, rframe, clmpt, nlmpt, 00597 resetCurrLandmark, resetNextLandmark); 00598 vTime = ventralTimer.get()/1000.0F; 00599 LINFO("Ventral time[%d]: %f", rVframe, vTime); 00600 } 00601 00602 usleep(1000); 00603 inputTime = inputTimer.get(); 00604 } 00605 00606 // save last time step performance 00607 FILE *rFile = fopen(resFName.c_str(), "at"); 00608 if (rFile != NULL) 00609 { 00610 float dispVTime = vTime; 00611 if(!resetNextLandmark) dispVTime = ventralTimer.get()/1000.0F; 00612 00613 std::string line = 00614 sformat("%5d %11.5f %d %d %11.5f %11.5f %11.5f", 00615 fNum, -1.0F, resetCurrLandmark, resetNextLandmark, 00616 dTime, dispVTime, inputTime/1000.0); 00617 LINFO("%s", line.c_str()); 00618 line += std::string("\n"); 00619 fputs(line.c_str(), rFile); 00620 fclose (rFile); 00621 } 00622 else LFATAL("can't create result file: %s", resFName.c_str()); 00623 00624 // signal the other processors to stop working 00625 LINFO("sending ABORT to Dorsal"); 00626 rframe = fNum; 00627 smsg.reset(rframe, ABORT); 00628 beo->send(DORSAL_NODE, smsg); 00629 //rnode = DORSAL_NODE; 00630 //while(!beo->receive(rnode, rmsg, rframe, raction, 5)); 00631 //LINFO("rec Dorsal"); 00632 //rmsg.reset(rframe,raction); 00633 00634 LINFO("sending ABORT to ventral"); 00635 beo->send(VENTRAL_NODE, smsg); 00636 rnode = VENTRAL_NODE; 00637 while(!beo->receive(rnode, rmsg, rframe, raction, 5)); 00638 LINFO("rec Ventral"); 00639 rmsg.reset(rframe,raction); 00640 00641 // ending operations 00642 // this needs both XXX_M_results.txt and XXX_results.txt 00643 switch(opMode) 00644 { 00645 case TRAIN_MODE: break; 00646 00647 case TEST_MODE: 00648 { 00649 // report some statistical data 00650 reportResults(resultPrefix, 9); 00651 00652 float min = 0.0f, max = 0.0f; 00653 if(procTime.size() > 0){ min = procTime[0]; max = procTime[0]; } 00654 for(uint i = 1; i < procTime.size(); i++) 00655 { 00656 if (min > procTime[i]) min = procTime[i]; 00657 if (max < procTime[i]) max = procTime[i]; 00658 } 00659 LINFO("proc Time: %f - %f", min, max); 00660 } 00661 break; 00662 00663 default: LERROR("Unknown operation mode"); 00664 } 00665 00666 LINFO("we can now exit"); 00667 Raster::waitForKey(); 00668 00669 // get ready to terminate: 00670 manager.stop(); 00671 return 0; 00672 } 00673 00674 // ###################################################################### 00675 std::string getInputPrefix(nub::soft_ref<InputFrameSeries> ifs, 00676 int &inputType) 00677 { 00678 std::string input = 00679 ifs->getModelParamVal<std::string>("InputFrameSource"); 00680 std::string prefix; 00681 00682 // if it camera input 00683 std::string camInput("ieee1394"); 00684 if(!input.compare(camInput)) 00685 { 00686 inputType = CAMERA_INPUT; 00687 // use the time of day 00688 time_t rawtime; struct tm * timeinfo; 00689 time ( &rawtime ); 00690 timeinfo = localtime ( &rawtime ); 00691 std::string cTime(asctime (timeinfo)); 00692 cTime = cTime.substr(4); // take out the day 00693 00694 for(uint i = 0; i < cTime.length(); i++) 00695 if(cTime[i] == ' ' || cTime[i] == ':') cTime[i] = '_'; 00696 prefix = std::string("cam_") + cTime; 00697 LINFO("Camera input, prefix: %s", prefix.c_str()); 00698 } 00699 // if it is a frame series input 00700 else if(input.find_last_of('#') == (input.length() - 5)) 00701 { 00702 inputType = FILE_INPUT; 00703 00704 prefix = input.substr(0, input.length() - 5); 00705 std::string::size_type spos = prefix.find_last_of('/'); 00706 if(spos != std::string::npos) 00707 prefix = prefix.substr(spos+1); 00708 00709 // if the last part of the prefix is an '_' 00710 if(prefix.find_last_of('_') == prefix.length() - 1) 00711 { 00712 // take it out 00713 prefix = prefix.substr(0, prefix.length() - 1); 00714 } 00715 00716 LINFO("Frame series input, prefix: %s", prefix.c_str()); 00717 } 00718 // it is an mpeg 00719 else 00720 { 00721 inputType = FILE_INPUT; 00722 00723 prefix = input.substr(0, input.length() - 4); 00724 std::string::size_type spos = prefix.find_last_of('/'); 00725 if(spos != std::string::npos) 00726 prefix = prefix.substr(spos+1); 00727 00728 LINFO("mpeg Input, prefix: %s", prefix.c_str()); 00729 } 00730 00731 return prefix; 00732 } 00733 00734 // ###################################################################### 00735 int getOpMode(std::string opmodestr) 00736 { 00737 // compare returns zero if they are equal 00738 std::string trainMode("train"); int op; 00739 //std::string trainXMode("trainX"); 00740 if(!opmodestr.compare(trainMode)) op = TRAIN_MODE; 00741 //else if(!opmodestr.compare(trainXMode)) op = TRAIN_X_MODE; 00742 else op = TEST_MODE; 00743 return op; 00744 } 00745 00746 // ###################################################################### 00747 void setupBeoChip(nub::soft_ref<BeoChip> b, BeobotConfig bbc) 00748 { 00749 // reset the beochip: 00750 LINFO("Resetting BeoChip..."); 00751 b->resetChip(); sleep(1); 00752 00753 // calibrate the servos 00754 b->calibrateServo(bbc.steerServoNum, bbc.steerNeutralVal, 00755 bbc.steerMinVal, bbc.steerMaxVal); 00756 b->calibrateServo(bbc.speedServoNum, bbc.speedNeutralVal, 00757 bbc.speedMinVal, bbc.speedMaxVal); 00758 b->calibrateServo(bbc.gearServoNum, bbc.gearNeutralVal, 00759 bbc.gearMinVal, bbc.gearMaxVal); 00760 00761 // keep the gear at the lowest speed/highest Ntorque 00762 b->setServoRaw(bbc.gearServoNum, bbc.gearMinVal); 00763 00764 // zero out the speed 00765 //b->setServoRaw(bbc.speedServoNum, bbc.speedNeutralVal); 00766 00767 // turn on the keyboard 00768 b->debounceKeyboard(true); 00769 b->captureKeyboard(true); 00770 00771 // calibrate the PWMs: 00772 b->calibratePulse(0, 00773 bbc.pwm0NeutralVal, 00774 bbc.pwm0MinVal, 00775 bbc.pwm0MaxVal); 00776 b->calibratePulse(1, 00777 bbc.pwm1NeutralVal, 00778 bbc.pwm1MinVal, 00779 bbc.pwm1MaxVal); 00780 b->capturePulse(0, true); 00781 b->capturePulse(1, true); 00782 00783 // let's play with the LCD: 00784 b->lcdClear(); // 01234567890123456789 00785 b->lcdPrintf(0, 0, "collectFrames: 00000"); 00786 b->lcdPrintf(0, 1, "STEER=XXX SPEED=XXX"); 00787 b->lcdPrintf(0, 2, "PWM0=0000 0000-0000"); 00788 b->lcdPrintf(0, 3, "PWM1=0000 0000-0000"); 00789 } 00790 00791 // ###################################################################### 00792 void getOdometry(float &dx, float &dy) 00793 { 00794 dx = 0.0F; 00795 dy = 0.0F; 00796 } 00797 00798 // ###################################################################### 00799 void executeMotorCommand(int opMode, float st, float sp) 00800 { 00801 switch(opMode) 00802 { 00803 case TRAIN_MODE: 00804 case TEST_MODE: 00805 // a remote controller to train the robot 00806 00807 // have a point to pursue 00808 00809 // or to close to it 00810 00811 // execute action command 00812 //b->setServo(bbc.steerServoNum, st); 00813 //b->setServo(bbc.speedServoNum, sp); 00814 break; 00815 default: 00816 LERROR("Unknown operation mode"); 00817 } 00818 } 00819 00820 // ###################################################################### 00821 void dispResults 00822 ( Image< PixRGB<byte> > disp, rutz::shared_ptr<XWinManaged> win, 00823 Image< PixRGB<byte> > ima, Image< PixRGB<byte> > prevIma, 00824 std::vector<Point2D<int> > clmpt, std::vector<Point2D<int> > nlmpt, 00825 Image<float> currSalMap, 00826 std::vector<Point2D<int> > salpt, std::vector<Rectangle> objRect) 00827 { 00828 int w = ima.getWidth(); 00829 int h = ima.getHeight(); 00830 const int foa_size = std::min(w, h) / 12; 00831 00832 // display input image: 00833 inplacePaste(disp, ima, Point2D<int>(0, 0)); 00834 00835 // display the saliency map 00836 Image<float> dispsm = quickInterpolate(currSalMap * SMFAC, 1 << sml); 00837 inplaceNormalize(dispsm, 0.0f, 255.0f); 00838 Image<PixRGB<byte> > sacImg = Image<PixRGB<byte> >(toRGB(dispsm)); 00839 for(uint i = 0; i < objRect.size(); i++) 00840 drawRect(sacImg,objRect[i],PixRGB<byte>(255,0,0)); 00841 inplacePaste(disp, sacImg, Point2D<int>(w, 0)); 00842 00843 // draw coordinates of fixation for both input and sal image 00844 for(uint i = 0; i < salpt.size(); i++) 00845 { 00846 Point2D<int> salpt2(salpt[i].i + w, salpt[i].j); 00847 drawDisk(disp, salpt[i], foa_size/6+2, PixRGB<byte>(20, 50, 255)); 00848 drawDisk(disp, salpt[i], foa_size/6, PixRGB<byte>(255, 255, 20)); 00849 drawDisk(disp, salpt2, foa_size/6+2, PixRGB<byte>(20, 50, 255)); 00850 drawDisk(disp, salpt2, foa_size/6, PixRGB<byte>(255, 255, 20)); 00851 } 00852 00853 // draw the SE bounding box 00854 Image< PixRGB<byte> > roiImg = ima; 00855 for(uint i = 0; i < objRect.size(); i++) 00856 { 00857 drawRect(roiImg, objRect[i], PixRGB<byte>(255,255,0)); 00858 drawDisk(roiImg, salpt[i], 3, PixRGB<byte>(255,0,0)); 00859 std::string ntext(sformat("%d", i)); 00860 writeText(roiImg, salpt[i], ntext.c_str()); 00861 } 00862 inplacePaste(disp, roiImg, Point2D<int>(w*2, 0)); 00863 00864 // if there is a previous image 00865 if(prevIma.initialized()) 00866 { 00867 // display the current landmark tracked 00868 Image< PixRGB<byte> > clmDisp = prevIma; 00869 for(uint i = 0; i < clmpt.size(); i++) 00870 { 00871 if(clmpt[i].isValid()) 00872 { 00873 drawDisk(clmDisp, clmpt[i], 3, PixRGB<byte>(0,255,0)); 00874 std::string ntext(sformat("%d", i)); 00875 writeText(clmDisp, clmpt[i], ntext.c_str()); 00876 } 00877 } 00878 inplacePaste(disp, clmDisp, Point2D<int>(w*3, 0)); 00879 00880 // display the next landmark tracked 00881 Image< PixRGB<byte> > nlmDisp = prevIma; 00882 for(uint i = 0; i < nlmpt.size(); i++) 00883 { 00884 if(nlmpt[i].isValid()) 00885 { 00886 drawDisk(nlmDisp, nlmpt[i], 3, PixRGB<byte>(0,255,255)); 00887 std::string ntext(sformat("%d", i)); 00888 writeText(nlmDisp, nlmpt[i], ntext.c_str()); 00889 } 00890 } 00891 inplacePaste(disp, nlmDisp, Point2D<int>(w*4, 0)); 00892 } 00893 00894 // display the image 00895 win->drawImage(disp,0,0); 00896 //Raster::waitForKey(); 00897 } 00898 00899 // ###################################################################### 00900 int beoChipProc(rutz::shared_ptr<BeobotBeoChipListener> lis, 00901 nub::soft_ref<BeoChip> b) 00902 { 00903 // print keyboard values: 00904 char kb[6]; kb[5] = '\0'; 00905 for (int i = 0; i < 5; i ++) kb[i] = (lis->kbd>>(4-i))&1 ? '1':'0'; 00906 00907 // quit if both extreme keys pressed simultaneously: 00908 if (kb[0] == '0' && kb[4] == '0') { 00909 b->lcdPrintf(15, 0, "QUIT "); 00910 00911 // return QUIT signal 00912 return BC_QUIT_SIGNAL; 00913 } 00914 00915 return BC_NO_SIGNAL; 00916 } 00917 00918 // ###################################################################### 00919 void getBbmtResults 00920 ( nub::ref<BeobotBrainMT> bbmt, 00921 Image<PixRGB<byte> > &currIma, Image<double> &cgist, 00922 Image<float> &currSalMap, ImageSet<float> &cmap, 00923 std::vector<Point2D<int> > &salpt, std::vector<std::vector<double> > &feat, 00924 std::vector<Rectangle> &objRect) 00925 { 00926 // current image, gist vector, and saliency map 00927 currIma = bbmt->getCurrImage(); 00928 cgist = bbmt->getGist(); 00929 currSalMap = bbmt->getSalMap(); 00930 00931 // current conspicuity maps 00932 for(uint i = 0; i < NUM_CHANNELS; i++) cmap[i] = bbmt->getCurrCMap(i); 00933 00934 salpt.clear(); objRect.clear(); 00935 uint numpt = bbmt->getNumSalPoint(); 00936 for(uint i = 0; i < numpt; i++) 00937 { 00938 salpt.push_back(bbmt->getSalPoint(i)); 00939 objRect.push_back(bbmt->getObjRect(i)); 00940 00941 std::vector<double> features; bbmt->getSalientFeatures(i, features); 00942 feat.push_back(features); 00943 00944 } 00945 } 00946 00947 // ###################################################################### 00948 bool checkNode 00949 ( int opMode, nub::soft_ref<Beowulf> beo, 00950 int32 &rnode, TCPmessage &rmsg, int32 &raction, int32 &rframe) 00951 { 00952 // non-blocking call 00953 if(beo->receive(rnode, rmsg, rframe, raction)) return true; 00954 // && (rmsg.getSize() == 0)); 00955 return false; 00956 } 00957 00958 // ###################################################################### 00959 bool checkInput(int opMode, bool resetNextLandmark, uint64 inputFrameRate, 00960 uint64 inputTime) 00961 { 00962 // if train mode: need to have a ventral reset signal 00963 if(opMode == TRAIN_MODE && resetNextLandmark) return true; 00964 00965 // if test mode and using infinite time: need reset signal 00966 if(opMode == TEST_MODE && inputFrameRate == 0 && 00967 resetNextLandmark) return true; 00968 00969 // else test mode and need to get in after time is up 00970 if(opMode == TEST_MODE && inputFrameRate != 0 && 00971 (inputFrameRate - ERR_INTERVAL) < inputTime) return true; 00972 00973 return false; 00974 } 00975 00976 // ###################################################################### 00977 void setupVentralPacket 00978 ( TCPmessage &smsg, int rframe, 00979 bool resetVentralSearch, Image< PixRGB<byte> > currIma, 00980 Image<double> cgist, std::vector<Point2D<int> > salpt, 00981 std::vector<std::vector<double> > feat, std::vector<Rectangle> objRect, 00982 float dx, float dy, uint snumGT, float ltravGT) 00983 { 00984 // FIX SEND TO VENTRAL 00985 // put a label that we are trying to track 00986 // and recognize the current tracked object 00987 // while we also want to track a new location for next 00988 00989 // signal if we need to reset the landmark search 00990 smsg.reset(rframe, SEARCH_LM); 00991 smsg.addInt32(int32(resetVentralSearch)); 00992 00993 // send the full image (cropping done on the other side) 00994 smsg.addImage(currIma); 00995 00996 // send the gist vector 00997 smsg.addInt32(int32(cgist.getSize())); 00998 Image<double>::iterator aptr = cgist.beginw(); 00999 for(int i = 0; i < cgist.getSize(); i++) smsg.addDouble(*aptr++); 01000 01001 // send the number of salient points included 01002 smsg.addInt32(int32(salpt.size())); 01003 for(uint i = 0; i < salpt.size(); i++) 01004 { 01005 // salient point 01006 smsg.addInt32(int32(salpt[i].i)); 01007 smsg.addInt32(int32(salpt[i].j)); 01008 01009 // top, left, bottom, right 01010 smsg.addInt32(int32(objRect[i].top())); 01011 smsg.addInt32(int32(objRect[i].left())); 01012 smsg.addInt32(int32(objRect[i].bottomO())); 01013 smsg.addInt32(int32(objRect[i].rightO())); 01014 smsg.addInt32(int32(feat[i].size())); 01015 LDEBUG("[%u] salpt:(%s) r:[%s]", i, 01016 convertToString(salpt[i]).c_str(), 01017 convertToString(objRect[i]).c_str()); 01018 for(uint j = 0; j < feat[i].size(); j++) 01019 smsg.addDouble(feat[i][j]); 01020 } 01021 01022 // pass in the odometry information 01023 smsg.addFloat(dx); 01024 smsg.addFloat(dy); 01025 01026 // pass in the ground truth 01027 smsg.addInt32(int32(snumGT)); 01028 smsg.addFloat(ltravGT); 01029 01030 LINFO("setup VENTRAL %d", rframe ); 01031 } 01032 01033 // ###################################################################### 01034 void setupDorsalPacket 01035 ( TCPmessage &smsg, int rframe, ImageSet<float> cmap, 01036 bool resetCurrLandmark, std::vector<Point2D<int> > clmpt, 01037 bool resetNextLandmark, std::vector<Point2D<int> > nlmpt) 01038 { 01039 // tracking packet: always have the cmap 01040 smsg.reset(rframe, TRACK_LM); 01041 smsg.addImageSet(cmap); 01042 smsg.addInt32(int32(resetCurrLandmark)); 01043 smsg.addInt32(int32(resetNextLandmark)); 01044 smsg.addInt32(int32(clmpt.size())); 01045 LDEBUG("[%4d] reset currLM? %d nextLM? %d", 01046 rframe, resetCurrLandmark, resetNextLandmark); 01047 01048 for(uint i = 0; i < clmpt.size(); i++) 01049 { 01050 smsg.addInt32(int32(clmpt[i].i)); 01051 smsg.addInt32(int32(clmpt[i].j)); 01052 LDEBUG("curr[%d]: (%3d, %3d)", i, clmpt[i].i, clmpt[i].j); 01053 } 01054 01055 smsg.addInt32(int32(nlmpt.size())); 01056 for(uint i = 0; i < nlmpt.size(); i++) 01057 { 01058 smsg.addInt32(int32(nlmpt[i].i)); 01059 smsg.addInt32(int32(nlmpt[i].j)); 01060 LDEBUG("next[%d]: (%3d, %3d)", i, nlmpt[i].i, nlmpt[i].j); 01061 } 01062 } 01063 01064 // ###################################################################### 01065 void processVentralResult 01066 ( TCPmessage &rmsg, int32 raction, int32 rframe, 01067 std::vector<Point2D<int> > &clmpt, std::vector<Point2D<int> > &nlmpt, 01068 bool &resetCurrLandmark, bool &resetNextLandmark) 01069 { 01070 if(raction == SEARCH_LM_RES) 01071 { 01072 LDEBUG("Packet size: %d", rmsg.getSize()); 01073 bool isLocalized = true; 01074 int searchFrame = int(rmsg.getElementInt32()); 01075 int sentAt = int(rmsg.getElementInt32()); 01076 rmsg.reset(rframe, raction); 01077 LINFO("Ventral processing[%d]: SEARCH_LM_RES: %d sent at %d\n", 01078 rframe, searchFrame, sentAt); 01079 01080 // check the return type: 01081 // CURR_LM, NEXT_LM, BOTH_LM 01082 // CURR_LM: for feedback for current landmark dorsal tracking 01083 // NEXT_LM: for feedback for next landmark dorsal tracking 01084 // BOTH_LM: for feedback for both landmarks dorsal tracking 01085 01086 // NEW FUNKY IDEA: 01087 // TRACKED_OBJ_W_BIAS, TRACKED_OBJECT_WO_BIAS 01088 // when the object is about to be passed 01089 // use the frame num of the DB 01090 01091 // get the object setup the tracking: 01092 01093 // if current landmark is identified 01094 // we can keep tracking 01095 // -> note that it also returns the proper location in the memory 01096 // that is, at which side of the corridor it was located & how far away 01097 // we can use the getAffineDiff 01098 // horizontal comp: - val: move right, + val: move left 01099 // otherwise tracking is lost 01100 01101 // if next landmark is identified 01102 if(isLocalized) 01103 { 01104 // usually we make the new Landmark be the current one 01105 clmpt.clear(); 01106 for(uint i = 0; i < nlmpt.size(); i++) 01107 clmpt.push_back(nlmpt[i]); 01108 resetCurrLandmark = true; 01109 // also try to bias to the next landmark 01110 } 01111 else 01112 { 01113 // otherwise, nothing to do 01114 //we'll just start a new search 01115 } 01116 resetNextLandmark = true; 01117 } 01118 } 01119 01120 // ###################################################################### 01121 void processDorsalResult 01122 (TCPmessage &rmsg, int32 raction, int32 rframe, 01123 std::vector<Point2D<int> > &clmpt, std::vector<Point2D<int> > &nlmpt, 01124 bool &resetNextLandmark, float &sp, float &st) 01125 { 01126 if(raction == TRACK_LM_RES) 01127 { 01128 LDEBUG("Dorsal TRACK_LM_RES[%4d]", rframe); 01129 uint nClmpt = (rmsg.getElementInt32()); 01130 clmpt.clear(); 01131 for(uint i = 0; i < nClmpt; i++) 01132 { 01133 uint cI = int(rmsg.getElementInt32()); 01134 uint cJ = int(rmsg.getElementInt32()); 01135 clmpt.push_back(Point2D<int>(cI,cJ)); 01136 if(clmpt[i].isValid()) 01137 LDEBUG("track currLM[%d]: (%3d, %3d)", 01138 i, clmpt[i].i, clmpt[i].j); 01139 else 01140 LINFO("track currLM[%d]: (%3d, %3d) LOST", 01141 i, clmpt[i].i, clmpt[i].j); 01142 } 01143 01144 uint nNlmpt = (rmsg.getElementInt32()); 01145 nlmpt.clear(); 01146 for(uint i = 0; i < nNlmpt; i++) 01147 { 01148 uint nI = int(rmsg.getElementInt32()); 01149 uint nJ = int(rmsg.getElementInt32()); 01150 nlmpt.push_back(Point2D<int>(nI,nJ)); 01151 if(nlmpt[i].isValid()) 01152 LDEBUG("track nextLM[%d]: (%3d, %3d)", 01153 i, nlmpt[i].i, nlmpt[i].j); 01154 else 01155 LINFO("track nextLM[%d]: (%3d, %3d) LOST", 01156 i, nlmpt[i].i, nlmpt[i].j); 01157 } 01158 rmsg.reset(rframe, raction); 01159 01160 //FIX: there is a time where tracking would fail 01161 01162 // scenarios: 01163 // track currlm only: when the segment is about to end 01164 // track nextlm only: when starting a segment 01165 // track both: in between 2 landmarks 01166 01167 // if current landmark is lost 01168 //if(false)//!clmptFound) 01169 // { 01170 // stop motor: 01171 // have to wait for SEARCH_LM to return an answer 01172 // tell them to take all the time it needs 01173 // sp = 0.0f; st = 0.0f; 01174 // } 01175 01176 // if next landmark is lost 01177 //if(!nlmptFound) 01178 // { 01179 // stop DB search in Ventral 01180 // there's no use, it's already past 01181 // resetNextLandmark = true; 01182 // LINFO("stop Ventral Search"); 01183 // } 01184 01185 // if both points are found 01186 //if(clmptFound && nlmptFound) 01187 // { 01188 // process for best motor command 01189 // that keeps all points within sight 01190 01191 // FIX: how do we home location in this case ?? 01192 // } 01193 01194 // RESEARCH: if both tracked landmarks are lost: 01195 // add motion energy - run straight slowly 01196 // need special exploration stuff: scan in place 180 degrees 01197 } 01198 } 01199 01200 // ###################################################################### 01201 Image<double> 01202 getGroundTruth(uint fNum, uint &snumGT, float <ravGT, float &dx, float &dy) 01203 { 01204 // // ACB IROS 07 test 01205 // uint sfnum [9] = { 377, 496, 541, 401, 304, 555, 486, 327, 307 }; 01206 // uint ssfnum[9] = { 0, 377, 873, 1414, 1815, 2119, 2674, 3160, 3487 }; 01207 01208 // // AnFpark IROS 07 test 01209 // uint sfnum [9] = { 866, 569, 896, 496, 769, 1250, 588, 844, 919 }; 01210 // uint ssfnum[9] = { 0, 866, 1435, 2331, 2827, 3596, 4846, 5434, 6278 }; 01211 01212 // // FDFpark IROS 07 test 01213 // uint sfnum [9] = { 782, 813, 869, 795, 857, 1434, 839, 1149, 749 }; 01214 // uint ssfnum[9] = { 0, 782, 1595, 2464, 3259, 4116, 5550, 6389, 7538 }; 01215 01216 // ===================================================================== 01217 // // ACB_1 IEEE-TR 07 test T_A 01218 // std::string stem("/lab/tmpib/u/siagian/PAMI07/ACB/gist/ACB"); 01219 // uint sfnum [9] = { 387, 440, 465, 359, 307, 556, 438, 290, 341 }; 01220 // uint ssfnum[9] = { 0, 387, 827, 1292, 1651, 1958, 2514, 2952, 3242 }; 01221 01222 // // ACB_2 IEEE-TR 07 test T_B 01223 // std::string stem("/lab/tmpib/u/siagian/PAMI07/ACB/gist/ACB"); 01224 // uint sfnum [9] = { 410, 436, 485, 321, 337, 495, 445, 247, 373 }; 01225 // uint ssfnum[9] = { 0, 410, 846, 1331, 1652, 1989, 2484, 2929, 3176 }; 01226 01227 // // ACB_3 IEEE-TR 07 test T_E 01228 // std::string stem("/lab/tmpib/u/siagian/PAMI07/ACB/gist/ACB"); 01229 // uint sfnum [9] = { 388, 461, 463, 305, 321, 534, 398, 274, 313 }; 01230 // uint ssfnum[9] = { 0, 388, 849, 1312, 1617, 1938, 2472, 2870, 3144 }; 01231 01232 // // ACB_4 IEEE-TR 07 test T_F 01233 // std::string stem("/lab/tmpib/u/siagian/PAMI07/ACB/gist/ACB"); 01234 // uint sfnum [9] = { 411, 438, 474, 249, 319, 502, 400, 288, 296 }; 01235 // uint ssfnum[9] = { 0, 411, 849, 1323, 1572, 1891, 2393, 2793, 3081 }; 01236 01237 // // AnFpark_1 IEEE-TR 07 test D 01238 // std::string stem("/lab/tmpib/u/siagian/PAMI07/AnFpark/gist/AnFpark"); 01239 // uint sfnum [9] = { 698, 570, 865, 488, 617, 1001, 422, 598, 747 }; 01240 // uint ssfnum[9] = { 0, 698, 1268, 2133, 2621, 3238, 4239, 4661, 5259 }; 01241 01242 // // AnFpark_2 IEEE-TR 07 test J 01243 // std::string stem("/lab/tmpib/u/siagian/PAMI07/AnFpark/gist/AnFpark"); 01244 // uint sfnum [9] = { 802, 328, 977, 597, 770, 1122, 570, 692, 809 }; 01245 // uint ssfnum[9] = { 0, 802, 1130, 2107, 2704, 3474, 4596, 5166, 5858 }; 01246 01247 // // AnFpark_3 IEEE-TR 07 test T_A 01248 // std::string stem("/lab/tmpib/u/siagian/PAMI07/AnFpark/gist/AnFpark"); 01249 // uint sfnum [9] = { 891, 474, 968, 688, 774, 1003, 561, 797, 862 }; 01250 // uint ssfnum[9] = { 0, 891, 1365, 2333, 3021, 3795, 4798, 5359, 6156 }; 01251 01252 // // AnFpark_4 IEEE-TR 07 test T_B 01253 // std::string stem("/lab/tmpib/u/siagian/PAMI07/AnFpark/gist/AnFpark"); 01254 // uint sfnum [9] = { 746, 474, 963, 632, 777, 1098, 399, 768, 849 }; 01255 // uint ssfnum[9] = { 0, 746, 1220, 2183, 2815, 3592, 4690, 5089, 5857 }; 01256 01257 // // FDFpark_1 IEEE-TR 07 test T_C 01258 // std::string stem("/lab/tmpib/u/siagian/PAMI07/FDFpark/gist/FDFpark"); 01259 // uint sfnum [9] = { 881, 788, 858, 837, 831, 1680, 1037, 1172, 739 }; 01260 // uint ssfnum[9] = { 0, 881, 1669, 2527, 3364, 4195, 5875, 6912, 8084 }; 01261 01262 // // FDFpark_2 IEEE-TR 07 test T_D 01263 // std::string stem("/lab/tmpib/u/siagian/PAMI07/FDFpark/gist/FDFpark"); 01264 // uint sfnum [9] = { 670, 740, 696, 740, 748, 1565, 923, 1211, 825 }; 01265 // uint ssfnum[9] = { 0, 670, 1410, 2106, 2846, 3594, 5159, 6082, 7293 }; 01266 01267 // // FDFpark_3 IEEE-TR 07 test T_H 01268 // std::string stem("/lab/tmpib/u/siagian/PAMI07/FDFpark/gist/FDFpark"); 01269 // uint sfnum [9] = { 847, 797, 922, 837, 694, 1712, 857, 1355, 794 }; 01270 // uint ssfnum[9] = { 0, 847, 1644, 2566, 3403, 4097, 5809, 6666, 8021 }; 01271 01272 // // FDFpark_4 IEEE-TR 07 test T_I 01273 // std::string stem("/lab/tmpib/u/siagian/PAMI07/FDFpark/gist/FDFpark"); 01274 // uint sfnum [9] = { 953, 878, 870, 821, 854, 1672, 894, 1270, 743 }; 01275 // uint ssfnum[9] = { 0, 953, 1831, 2701, 3522, 4376, 6048, 6942, 8212 }; 01276 01277 // ===================================================================== 01278 // // ACB_1 ICRA 08 test T_A 01279 // std::string stem("/lab/tmpib/u/siagian/PAMI07/ACB/gist/ACB"); 01280 // uint sfnum [9] = { 387, 440, 465, 359, 307, 556, 438, 290, 341 }; 01281 // uint ssfnum[9] = { 0, 387, 827, 1292, 1651, 1958, 2514, 2952, 3242 }; 01282 01283 // // AnFpark_1 IEEE-TR 07 test D 01284 // std::string stem("/lab/tmpib/u/siagian/PAMI07/AnFpark/gist/AnFpark"); 01285 // uint sfnum [9] = { 698, 570, 865, 488, 617, 1001, 422, 598, 747 }; 01286 // uint ssfnum[9] = { 0, 698, 1268, 2133, 2621, 3238, 4239, 4661, 5259 }; 01287 01288 // // FDFpark_1 IEEE-TR 07 test T_C 01289 // std::string stem("/lab/tmpib/u/siagian/PAMI07/FDFpark/gist/FDFpark"); 01290 // uint sfnum [9] = { 881, 788, 858, 837, 831, 1680, 1037, 1172, 739 }; 01291 // uint ssfnum[9] = { 0, 881, 1669, 2527, 3364, 4195, 5875, 6912, 8084 }; 01292 01293 // HNB testing for Loc & Nav 01294 std::string stem("../data/HNB_T/gist/"); 01295 uint sfnum [4] = { 655, 653, 521, 353 }; 01296 uint ssfnum[4] = { 0, 655, 1308, 1829 }; 01297 //uint ssfnum[4] = { 21696, 22351, 23004, 23525 }; 01298 01299 //FILE *gfp; 01300 int afnum = 0; 01301 //for(uint i = 0; i < 9; i++) 01302 for(uint i = 0; i < 4; i++) 01303 { 01304 if((fNum >= ssfnum[i]) && (fNum < ssfnum[i]+sfnum[i])) 01305 { 01306 stem = stem + sformat("_T_%dE", i+1); 01307 afnum = fNum - ssfnum[i]; 01308 dx = 1.0/float(sfnum[i]); dy = 0.0F; 01309 snumGT = i; ltravGT = float(afnum)/float(sfnum[i]); 01310 break; 01311 } 01312 } 01313 01314 // ltravGT = fNum/866.0; dx = 1/866.0; afnum = fNum; 01315 // stem = sformat("/lab/tmpib/u/siagian/PAMI07/ACB/gist/ACB1B"); 01316 01317 // std::string gfname = stem + sformat("_%03d.gist", afnum); 01318 Image<double> cgist(1, 714, NO_INIT); 01319 // if((gfp = fopen(gfname.c_str(),"rb")) != NULL) 01320 // { 01321 // Image<double>::iterator aptr = cgist.beginw(); 01322 // for(uint i = 0; i < 714; i++) 01323 // { 01324 // double val; fread(&val, sizeof(double), 1, gfp); 01325 // *aptr++ = val; 01326 // } 01327 // LDEBUG("gist file found: %s ground truth: %d %f", 01328 // gfname.c_str(), snumGT, ltravGT); 01329 01330 // fclose(gfp); 01331 // } 01332 // else LFATAL("gist file NOT found: %s", gfname.c_str()); 01333 01334 //Image<double> tempGist(1,544, NO_INIT); uint tcount = 0; 01335 // for(uint i = 0; i < 714; i++) 01336 // { 01337 // //if(i%21 >= 5) 01338 // { 01339 // tempGist.setVal(0, tcount, cgist.getVal(i)); tcount++; 01340 // } 01341 // } 01342 01343 // add random error to the robot movement 01344 dy =+ 0.0F; //FIX 01345 01346 return cgist; 01347 } 01348 01349 // ###################################################################### 01350 void reportResults(std::string resultPrefix, uint nsegment) 01351 { 01352 // NOTE: for crash recovery 01353 // resultPrefix = std::string("/lab/tmpib/u/siagian/PAMI07/FDFpark/envComb/RES/FDFpark_T_C_track/AAAI/FDFpark_500"); 01354 //GSnavResult r1; r1.combine(resultPrefix); 01355 //r1.read(resultPrefix, nsegment); 01356 //r1.createSummaryResult(); 01357 01358 // read and print the timing information 01359 GSnav_M_Result r2; r2.read(resultPrefix); 01360 01361 // std::string resCfName = savePrefix + sformat("_comb_results.txt"); 01362 // FILE *rFile = fopen(resCfName.c_str(), "at"); 01363 // if (rFile == NULL) LFATAL("can't create res file: %s", resCfName.c_str()); 01364 01365 LINFO("bbmtTime: %f (%f - %f) std: %f", 01366 r2.meanBbmtTime, r2.minBbmtTime, r2.maxBbmtTime, 01367 r2.stdevBbmtTime); 01368 01369 LINFO("Dorsal Time: %f (%f - %f) std: %f", 01370 r2.meanDorsalTime, r2.minDorsalTime, r2.maxDorsalTime, 01371 r2.stdevDorsalTime); 01372 01373 LINFO("Ventral Time: %f (%f - %f) std: %f", 01374 r2.meanVentralSearchTime, r2.minVentralSearchTime, 01375 r2.maxVentralSearchTime, r2.stdevVentralSearchTime); 01376 01377 LINFO("Input Time: %f (%f - %f) std: %f", 01378 r2.meanInputTime, r2.minInputTime, r2.maxInputTime, 01379 r2.stdevInputTime); 01380 // fputs(temp.c_str(), rFile); 01381 // fclose (rFile); 01382 } 01383 01384 // ###################################################################### 01385 /* So things look consistent in everyone's emacs... */ 01386 /* Local Variables: */ 01387 /* indent-tabs-mode: nil */ 01388 /* End: */