00001 /*!@file BeoSub/BeoSub.C An autonomous submarine */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2003 // 00005 // by the 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/BeoSub/BeoSub.C $ 00035 // $Id: BeoSub.C 14376 2011-01-11 02:44:34Z pez $ 00036 // 00037 00038 #include "BeoSub/BeoSub.H" 00039 00040 #include "BeoSub/BeoSub-defs.H" 00041 #include "BeoSub/BeoSubOpts.H" 00042 #include "BeoSub/CannyModel.H" 00043 #include "Devices/FrameGrabberFactory.H" 00044 #include "Channels/RawVisualCortex.H" 00045 #include "SIFT/VisualObjectDB.H" 00046 #include "SIFT/VisualObjectMatch.H" 00047 00048 #define DEBUG 00049 00050 // ###################################################################### 00051 BeoSub::BeoSub(OptionManager& mgr, const std::string& descrName, 00052 const std::string& tagName) : 00053 ModelComponent(mgr, descrName, tagName), 00054 00055 itsFrontVODBfname(&OPT_FrontVODBfname, this), 00056 itsFrontVODB(new VisualObjectDB()), 00057 itsDownVODBfname(&OPT_DownVODBfname, this), 00058 itsDownVODB(new VisualObjectDB()), 00059 itsUpVODBfname(&OPT_UpVODBfname, this), 00060 itsUpVODB(new VisualObjectDB()), 00061 itsMasterClock(1000000), itsCkPt(0), itsCurrentAttitude(), 00062 itsGlobalHeading(0), 00063 itsTargetAttitude(), 00064 itsVisualCortex(new RawVisualCortex(mgr)), 00065 itsFrontDBfname("/home/tmp/u/beosub/front.db"), 00066 itsFrontDB(new BeoSubDB()), 00067 itsDownDBfname("/home/tmp/u/beosub/down.db"), 00068 itsDownDB(new BeoSubDB()), 00069 itsUpDBfname("/home/tmp/u/beosub/up.db"), 00070 itsUpDB(new BeoSubDB()), 00071 itsShapeDetector(new BeoSubCanny(mgr)), 00072 itsTaskDecoder(new BeoSubTaskDecoder(mgr)), 00073 itsColorTracker(new ColorTracker(mgr)), 00074 itsColorTracker2(new ColorTracker(mgr)), 00075 decoderIsRed(true), 00076 taskAdone(false), 00077 taskBdone(false), 00078 taskCdone(false) 00079 //itscurrentblabla 00080 { 00081 pthread_mutex_init(&itsLock, NULL); 00082 addSubComponent(itsVisualCortex); 00083 addSubComponent(itsShapeDetector); 00084 00085 //set up default tasks order. Change if decoding is successful! 00086 itsTasks.push_back('A'); 00087 itsTasks.push_back('B'); 00088 itsTasks.push_back('C'); 00089 itsTasksIter = itsTasks.begin(); 00090 00091 taskAposition.x = 15; taskAposition.y = 20; 00092 taskBposition.x = 5; taskBposition.y = 50; 00093 taskCposition.x = 10; taskCposition.y = 100; 00094 itsGlobalPosition.x = -19; itsGlobalPosition.y = -8; 00095 itsGlobalHeading = 60; 00096 // mgr.loadConfig("camconfig.pmap"); 00097 } 00098 00099 // ###################################################################### 00100 BeoSub::~BeoSub() 00101 { 00102 pthread_mutex_destroy(&itsLock); 00103 } 00104 00105 // ###################################################################### 00106 void BeoSub::start1() 00107 { 00108 00109 // load our visual object databases: 00110 itsFrontVODB->loadFrom(itsFrontVODBfname.getVal()); 00111 itsDownVODB->loadFrom(itsDownVODBfname.getVal()); 00112 itsUpVODB->loadFrom(itsUpVODBfname.getVal()); 00113 00114 // Pre-build the KDTrees on our visual object databases so that we 00115 // don't waste time on that later: 00116 if (itsFrontVODB->numObjects()) itsFrontVODB->buildKDTree(); 00117 if (itsDownVODB->numObjects()) itsDownVODB->buildKDTree(); 00118 if (itsUpVODB->numObjects()) itsUpVODB->buildKDTree(); 00119 00120 // load our position and sensor databases (assumes already initialized) 00121 itsFrontDB->loadDatabase(itsFrontDBfname); 00122 itsDownDB->loadDatabase(itsDownDBfname); 00123 itsUpDB->loadDatabase(itsUpDBfname); 00124 00125 // get a hold of our special objects: 00126 itsVOtaskAdown = itsDownVODB->getObject("taskAdown"); 00127 itsVOtaskAfront = itsFrontVODB->getObject("taskAfront"); 00128 itsVOtaskBdown = itsDownVODB->getObject("taskBdown"); 00129 itsVOtaskBfront = itsFrontVODB->getObject("taskBfront"); 00130 itsVOtaskCdown = itsDownVODB->getObject("taskCdown"); 00131 itsVOtaskCfront = itsFrontVODB->getObject("taskCfront"); 00132 itsVOtaskCup = itsUpVODB->getObject("taskCtop"); 00133 itsVOtaskGdown = itsDownVODB->getObject("taskGdown"); 00134 itsVOtaskGfront = itsFrontVODB->getObject("taskGfront"); 00135 itsVOtaskGup = itsUpVODB->getObject("taskGtop"); 00136 itsVOtaskDfront = itsFrontVODB->getObject("taskDfront"); 00137 00138 } 00139 00140 // ###################################################################### 00141 bool BeoSub::targetReached(const float tol) const 00142 { 00143 // NOTE: we ignore pitch and roll 00144 bool ret = true; 00145 pthread_mutex_lock(const_cast<pthread_mutex_t *>(&itsLock)); 00146 00147 if (fabsf(itsCurrentAttitude.depth - itsTargetAttitude.depth) > tol * 0.2F) 00148 ret = false; 00149 00150 Angle diff = itsCurrentAttitude.heading - itsTargetAttitude.heading; 00151 if (diff.getVal() < - tol * 10.0F || diff.getVal() > tol * 10.0F) 00152 ret = false; 00153 00154 pthread_mutex_unlock(const_cast<pthread_mutex_t *>(&itsLock)); 00155 00156 return ret; 00157 } 00158 00159 // ###################################################################### 00160 void BeoSub::turnAbs(const Angle finalHeading, const bool blocking) 00161 { 00162 pthread_mutex_lock(&itsLock); 00163 itsTargetAttitude.heading = finalHeading; 00164 const Angle diff = finalHeading - itsCurrentAttitude.heading; 00165 pthread_mutex_unlock(&itsLock); 00166 if (blocking) waitMove(fabs(diff.getVal() * 0.5) + 30.0); 00167 } 00168 00169 // ###################################################################### 00170 void BeoSub::pitchAbs(const Angle finalPitch, const bool blocking) 00171 { 00172 pthread_mutex_lock(&itsLock); 00173 itsTargetAttitude.pitch = finalPitch; 00174 const Angle diff = finalPitch - itsCurrentAttitude.pitch; 00175 pthread_mutex_unlock(&itsLock); 00176 if (blocking) waitMove(fabs(diff.getVal() * 0.5) + 30.0); 00177 } 00178 00179 // ###################################################################### 00180 void BeoSub::turnRel(const Angle relHeading, const bool blocking) 00181 { 00182 /* 00183 pthread_mutex_lock(&itsLock); 00184 itsTargetAttitude.heading += relHeading; 00185 pthread_mutex_unlock(&itsLock); 00186 if (blocking) waitMove(fabs(relHeading.getVal() * 0.5) + 30.0); 00187 */ 00188 //ANDRE -- NOTE: GlobalHeading value 00189 itsGlobalHeading = itsGlobalHeading + relHeading; 00190 turnOpen(relHeading, blocking); 00191 } 00192 00193 // ###################################################################### 00194 void BeoSub::diveAbs(const float finalDepth, const bool blocking) 00195 { 00196 pthread_mutex_lock(&itsLock); 00197 itsTargetAttitude.depth = finalDepth; 00198 pthread_mutex_unlock(&itsLock); 00199 if (blocking) 00200 waitMove(fabs(finalDepth - itsCurrentAttitude.depth) * 5.0 + 30.0); 00201 } 00202 00203 // ###################################################################### 00204 void BeoSub::diveRel(const float relDepth, const bool blocking) 00205 { 00206 pthread_mutex_lock(&itsLock); 00207 itsTargetAttitude.depth += relDepth; 00208 pthread_mutex_unlock(&itsLock); 00209 if (blocking) waitMove(fabs(relDepth) * 5.0 + 30.0); 00210 } 00211 00212 // ###################################################################### 00213 //NOTE: This will work with open turn as an open strafe. FIX? 00214 void BeoSub::strafeRel(const float relDist) 00215 { 00216 // assume we are immobile. First, turn by some angle, then go 00217 // backwards, then turn back, then forward. The first turn (only) 00218 // should have rst true. All calls should have blocking to true. 00219 double alpha = relDist * 30.0; // turn by 30deg if 1m strafe 00220 if (alpha > 80.0) alpha = 80.0; else if (alpha < -80.0) alpha = -80.0; 00221 if (fabs(alpha) < 1.0) 00222 { LERROR("Strafe too small -- IGNORED"); return; } 00223 00224 // more precisely, if we are going to turn by alpha and want to 00225 // strafe by reldist, we should turn by alpha then go backwards by 00226 // relDist/sin(alpha), then turn back by -alpha, finally advance by 00227 // relDist/tan(alpha). Let's do it: 00228 turnRel(Angle(alpha), true); 00229 advanceRel(-fabs(relDist / sin(alpha * M_PI / 180.0))); 00230 turnRel(Angle(alpha), true); 00231 advanceRel(fabs(relDist / tan(alpha * M_PI / 180.0))); 00232 } 00233 00234 // ###################################################################### 00235 void BeoSub::waitMove(const double timeout) 00236 { 00237 // Wait until the desired attitude has been reached. Note: in the 00238 // base class, this will never happen since we have no actuation. In 00239 // derived classes there should be some function running in a thread 00240 // that will activate the various actuators so as to try to reduce 00241 // the difference between itsTargetAttitude and itsCurrentAttitude: 00242 00243 double startt = itsMasterClock.getSecs(); 00244 while(targetReached() == false && 00245 itsMasterClock.getSecs() - startt < timeout) usleep(200000); 00246 00247 if (targetReached() == false) 00248 LERROR("Timeout occurred on move -- IGNORED"); 00249 } 00250 00251 // ###################################################################### 00252 double BeoSub::getTime() const 00253 { return itsMasterClock.getSecs(); } 00254 00255 // ###################################################################### 00256 Attitude BeoSub::getCurrentAttitude() const 00257 { 00258 pthread_mutex_lock(const_cast<pthread_mutex_t *>(&itsLock)); 00259 Attitude att = itsCurrentAttitude; 00260 pthread_mutex_unlock(const_cast<pthread_mutex_t *>(&itsLock)); 00261 return att; 00262 } 00263 00264 // ###################################################################### 00265 Attitude BeoSub::getTargetAttitude() const 00266 { 00267 pthread_mutex_lock(const_cast<pthread_mutex_t *>(&itsLock)); 00268 Attitude att = itsTargetAttitude; 00269 pthread_mutex_unlock(const_cast<pthread_mutex_t *>(&itsLock)); 00270 return att; 00271 } 00272 00273 // ###################################################################### 00274 Angle BeoSub::getHeading() const 00275 { return getCurrentAttitude().heading; } 00276 00277 // ###################################################################### 00278 Angle BeoSub::getPitch() const 00279 { return getCurrentAttitude().pitch; } 00280 00281 // ###################################################################### 00282 Angle BeoSub::getRoll() const 00283 { return getCurrentAttitude().roll; } 00284 00285 // ###################################################################### 00286 void BeoSub::getCompass(Angle& heading, Angle& pitch, Angle& roll) const 00287 { 00288 Attitude att = getCurrentAttitude(); 00289 heading = att.heading; pitch = att.pitch; roll = att.roll; 00290 } 00291 00292 // ###################################################################### 00293 float BeoSub::getDepth() const 00294 { return getCurrentAttitude().depth; } 00295 00296 // ###################################################################### 00297 const char* beoSubCameraName(const BeoSubCamera cam) 00298 { 00299 if (cam == BEOSUBCAMFRONT) return "Front"; 00300 if (cam == BEOSUBCAMDOWN) return "Down"; 00301 if (cam == BEOSUBCAMUP) return "Up"; 00302 LERROR("Unknown BeoSubCamera value %d", int(cam)); 00303 return "Unknown"; 00304 } 00305 00306 // ###################################################################### 00307 Image<float> BeoSub::getSaliencyMap(const enum BeoSubCamera cam) const 00308 { 00309 Image< PixRGB<byte> > img = grabImage(cam); 00310 itsVisualCortex->input(InputFrame::fromRgb 00311 (&img, itsMasterClock.getSimTime())); 00312 return itsVisualCortex->getOutput(); 00313 } 00314 00315 // ###################################################################### 00316 bool BeoSub::recognizeSIFT(const enum BeoSubCamera cam, 00317 MappingData& data, Angle& myHeading) const 00318 { 00319 // grab an image from the specified camera: 00320 Image< PixRGB<byte> > im = grabImage(cam); 00321 00322 // create visual object and extract keypoints: 00323 rutz::shared_ptr<VisualObject> vo(new VisualObject("Captured Image", "", im)); 00324 00325 // get the matches: 00326 std::vector< rutz::shared_ptr<VisualObjectMatch> > matches; 00327 switch(cam) 00328 { 00329 case BEOSUBCAMFRONT: 00330 itsFrontVODB->getObjectMatches(vo, matches, VOMA_KDTREEBBF); 00331 break; 00332 case BEOSUBCAMDOWN: 00333 itsDownVODB->getObjectMatches(vo, matches, VOMA_KDTREEBBF); 00334 break; 00335 case BEOSUBCAMUP: 00336 itsUpVODB->getObjectMatches(vo, matches, VOMA_KDTREEBBF); 00337 break; 00338 default: 00339 LERROR("Wrong camera -- IGNORED"); 00340 } 00341 00342 // if we got nothing, stop here: 00343 if (matches.size() == 0U) return false; 00344 00345 // check that we have a good affine: 00346 if (matches[0]->checkSIFTaffine() == false) return false; 00347 00348 // compute our current heading based on the heading associated with 00349 // the matching picture and the rotation derived from the affine: 00350 SIFTaffine aff = matches[0]->getSIFTaffine(); 00351 float theta, sx, sy, str; 00352 aff.decompose(theta, sx, sy, str); 00353 00354 // our best match is the first in the list of matches. Get its 00355 // associated image name so that we can look it up in the 00356 // appropriate BeoSubDB: 00357 std::string name = matches[0]->getVoTest()->getImageFname(); 00358 00359 // now this has a .png extension while the BeoSubDB uses .txt; let's 00360 // change that: 00361 name.replace(name.length()-3, 3, "txt"); 00362 00363 // query the appropriate metadata database: 00364 switch(cam) 00365 { 00366 case BEOSUBCAMFRONT: 00367 data = itsFrontDB->getMappingData(name); 00368 break; 00369 case BEOSUBCAMDOWN: 00370 data = itsDownDB->getMappingData(name); 00371 break; 00372 case BEOSUBCAMUP: 00373 data = itsUpDB->getMappingData(name); 00374 break; 00375 default: 00376 LERROR("Wrong camera -- IGNORED"); 00377 } 00378 00379 // get our heading from the mapping data and the sift affine: 00380 myHeading = data.itsHeading; 00381 myHeading += theta; 00382 00383 return true; 00384 } 00385 00386 // ###################################################################### 00387 bool BeoSub::matchSIFT(const enum BeoSubCamera cam, 00388 const rutz::shared_ptr<VisualObject>& obj) const 00389 { 00390 // grab an image from the specified camera: 00391 Image< PixRGB<byte> > im = grabImage(cam); 00392 00393 // create visual object and extract keypoints: 00394 rutz::shared_ptr<VisualObject> vo(new VisualObject("Captured Image", "", im)); 00395 00396 // get the matches: 00397 VisualObjectMatch vom(obj, vo, VOMA_SIMPLE); 00398 vom.prune(); 00399 if (vom.checkSIFTaffine() == false) return false; 00400 00401 if (vom.getScore() >= 0.5F) return true; 00402 return false; 00403 } 00404 00405 // ###################################################################### 00406 bool BeoSub::affineSIFT(const enum BeoSubCamera cam, rutz::shared_ptr<VisualObject> goal) 00407 { 00408 float x = 160.0F, y = 120.0F; // center of ref image 00409 const float cu = 160.0F, cv = 120.0F; // center of test image 00410 const float factor = (5.0F - getDepth()) * 0.05F; //NOTE: rough estimate 00411 int counter = 0; 00412 while(++counter < 10) 00413 { 00414 rutz::shared_ptr<VisualObject> 00415 current(new VisualObject("current", "", grabImage(cam))); 00416 VisualObjectMatch match(goal, current, VOMA_KDTREEBBF); 00417 match.prune(); 00418 if (match.size() == 0U) 00419 { 00420 LINFO("No matches found... giving up"); 00421 return false; 00422 } 00423 LINFO("Found %u matches", match.size()); 00424 SIFTaffine aff = match.getSIFTaffine(); 00425 float u, v; aff.transform(x, y, u, v); 00426 if (fabsf(u - cu) < 10.0F) 00427 { 00428 LINFO("Good enough! -- DONE"); 00429 return true; 00430 } 00431 00432 if (cam == BEOSUBCAMDOWN) 00433 { 00434 // this camera is mounted rotated 90deg 00435 if (v < cv) { LINFO("turning left"); turnRel(-10.0F, true); } 00436 else { LINFO("turning right"); turnRel(10.0F, true); } 00437 advanceRel((u - cu) * factor); 00438 } 00439 else 00440 { 00441 if (u < cu) { LINFO("turning left"); turnRel(-10.0F, true); } 00442 else { LINFO("turning right"); turnRel(10.0F, true); } 00443 } 00444 } 00445 // counter timeout: 00446 return false; 00447 } 00448 00449 // ###################################################################### 00450 00451 bool BeoSub::findShape(rutz::shared_ptr<ShapeModel>& shapeArg, const char* colorArg, const enum BeoSubCamera camArg) const 00452 { 00453 00454 Image< PixRGB<byte> > im = grabImage(camArg); 00455 int numDims = shapeArg->getNumDims(); 00456 double* dims = (double*)calloc(numDims+1, sizeof(double)); 00457 dims = shapeArg->getDimensions(); 00458 00459 itsShapeDetector->setupCanny(colorArg, im, false);//declare detector 00460 00461 bool shapeFound = false; 00462 00463 //give shape detector 5 chances to work, using different starting dimensions each time 00464 00465 //Middle 00466 dims[1] = 150.0; 00467 dims[2] = 120.0; 00468 shapeArg->setDimensions(dims); 00469 shapeFound = itsShapeDetector->runCanny(shapeArg); 00470 if(!shapeFound){ //Upper left 00471 dims[1] = 60.0; //Xcenter 00472 dims[2] = 180.0; //Ycenter 00473 shapeArg->setDimensions(dims); 00474 shapeFound = itsShapeDetector->runCanny(shapeArg); 00475 } 00476 if(!shapeFound){ //Upper right 00477 dims[1] = 260.0; //Xcenter 00478 dims[2] = 180.0; //Ycenter 00479 shapeArg->setDimensions(dims); 00480 shapeFound = itsShapeDetector->runCanny(shapeArg); 00481 } 00482 if(!shapeFound){ //Lower left 00483 dims[1] = 60.0; //Xcenter 00484 dims[2] = 60.0; //Ycenter 00485 shapeArg->setDimensions(dims); 00486 shapeFound = itsShapeDetector->runCanny(shapeArg); 00487 } 00488 if(!shapeFound){ //Lower right 00489 dims[1] = 260.0; //Xcenter 00490 dims[2] = 60.0; //Ycenter 00491 shapeArg->setDimensions(dims); 00492 shapeFound = itsShapeDetector->runCanny(shapeArg); 00493 } 00494 00495 if(!shapeFound){ 00496 return false; 00497 } 00498 return true; 00499 } 00500 00501 // ###################################################################### 00502 bool BeoSub::centerColor(const char* colorArg, const enum BeoSubCamera camArg, float& thresholdMass){ 00503 Image< PixRGB<byte> > im; 00504 float x = 0.0, y = 0.0, mass = 0.0; 00505 float threshold = thresholdMass; 00506 float delta = 0; 00507 int lossCount = 0; 00508 bool checking = false; 00509 float xL = (160.0 - (threshold)); 00510 float xR = (160.0 + (threshold)); 00511 float yU = (120.0 - (threshold)); 00512 float yD = (120.0 + (threshold)); 00513 bool xOff = true, yOff = true; 00514 00515 if(camArg == BEOSUBCAMFRONT){ 00516 while(xOff){ 00517 im = grabImage(camArg); 00518 itsColorTracker->setupTracker(colorArg, im, false); 00519 checking = itsColorTracker->runTracker(threshold, x, y, mass); 00520 if( checking && (x >= xL && x <= xR)){ 00521 //Light centered in x plane. Now center in y 00522 xOff = false; 00523 lossCount = 0; 00524 } 00525 else if(checking){ 00526 printf("Fcam turn\n"); 00527 delta = x - 160.0; //delta = x_found - x_center 00528 //TURN left or right, in greater or lesser amounts depending on position 00529 turnRel(delta/2, true); //delta/2 based off of 160degree POV and 320pxl x axis 00530 lossCount = 0; 00531 } 00532 else{ 00533 //Color lost. Use counter to allow for a few noisy losses, then fail 00534 lossCount++; 00535 if(lossCount >4){ 00536 return false; 00537 } 00538 } 00539 } 00540 /* while(yOff){ 00541 im = grabImage(camArg); 00542 itsColorTracker->setupTracker(colorArg, im, false); 00543 checking = itsColorTracker->runTracker(threshold, x, y, mass); 00544 if( checking && (y >= yU && y <= yD)){ 00545 //Light centered in y plane. Stop. 00546 yOff = false; 00547 lossCount = 0; 00548 } 00549 else if(checking){ 00550 delta = y - 120.0; //delta = x_found - x_center 00551 //DIVE or surface, in greater or lesser amounts depending on th position of the light 00552 printf("Dcam turn\n"); 00553 //NOTE: a constant like 2.07 would need testing, since with TASK A, 00554 //there is no cloear way to distinguish between pixel distance and 00555 //difference of depth between the SUB and the Object. FIX???? 00556 float dZ = (30/(mass/10)) * tan(delta/2.07); //amt based off of 116degree POV and 240pxl y axis, as well as dist = (30/(mass/10)) 00557 diveRel(dZ, true); 00558 lossCount = 0; 00559 } 00560 else{ 00561 //Color lost. Use counter to allow for a few noisy losses, then fail 00562 lossCount++; 00563 if(lossCount >3){ 00564 return false; 00565 } 00566 } 00567 }*/ 00568 thresholdMass = mass; 00569 //STOP 00570 return true; 00571 } 00572 00573 //NOTE!: Down camera may need a change in axes if we do not reorient it! FIX!! 00574 else if(camArg == BEOSUBCAMDOWN || camArg == BEOSUBCAMUP){ 00575 while(xOff){ 00576 im = grabImage(camArg); 00577 itsColorTracker->setupTracker(colorArg, im, false); 00578 checking = itsColorTracker->runTracker(threshold, x, y, mass); 00579 if( checking && ( ((x >= xL && x <= xR) && camArg == BEOSUBCAMUP) || ((y >= yU && y <= yD) && camArg == BEOSUBCAMDOWN) ) ){ 00580 //Light centered in x plane. Now center in y 00581 xOff = false; 00582 lossCount = 0; 00583 } 00584 else if(checking){ 00585 //TURN left or right, in greater or lesser amounts depending on position 00586 if(camArg == BEOSUBCAMDOWN){ 00587 turnRel(((y-120)/2.07), true); //delta/2 based off of 160degree POV and 320pxl x axis 00588 00589 } 00590 else{ 00591 turnRel(((x-160)/2), true); 00592 } 00593 lossCount = 0; 00594 } 00595 else{ 00596 //Color lost. Use counter to allow for a few noisy losses, then fail 00597 lossCount++; 00598 if(lossCount >3){ 00599 return false; 00600 } 00601 } 00602 } 00603 while(yOff){ 00604 im = grabImage(camArg); 00605 itsColorTracker->setupTracker(colorArg, im, false); 00606 checking = itsColorTracker->runTracker(threshold, x, y, mass); 00607 if( checking && (((y >= yU && y <= yD) && camArg == BEOSUBCAMUP) || ((x >= xR && x <= xL) && camArg == BEOSUBCAMDOWN))){ 00608 //Light centered in y plane. Stop. 00609 yOff = false; 00610 lossCount = 0; 00611 } 00612 else if(checking){ 00613 //ADVANCE, in greater or lesser amounts depending on the position 00614 if(camArg == BEOSUBCAMUP){ 00615 float dY = (30/(mass/10)) * tan((y-120)/2.07); 00616 advanceRel(dY); 00617 } 00618 else{ 00619 float dY = (30/(mass/10)) * tan((x-160)/2); 00620 advanceRel(dY); 00621 } 00622 lossCount = 0; 00623 } 00624 else{ 00625 //Color lost. Use counter to allow for a few noisy losses, then fail 00626 lossCount++; 00627 if(lossCount >3){ 00628 return false; 00629 } 00630 } 00631 } 00632 00633 return true; 00634 } 00635 return false; //to make compiler happy 00636 } 00637 00638 // ###################################################################### 00639 bool BeoSub::approachArea(std::string name, const enum BeoSubCamera cam, float stepDist){ 00640 switch(cam){ 00641 case(BEOSUBCAMUP):{ 00642 MappingData goal = itsUpDB->getMappingData(name); 00643 } 00644 case(BEOSUBCAMFRONT):{ 00645 MappingData goal = itsFrontDB->getMappingData(name); 00646 } 00647 case(BEOSUBCAMDOWN):{ 00648 MappingData goal = itsDownDB->getMappingData(name); 00649 } 00650 00651 } 00652 //return approachArea(itsCurrentArea, goal, stepDist); 00653 00654 return true; 00655 00656 } 00657 00658 // ###################################################################### 00659 bool BeoSub::approachArea(MappingData goalArea, MappingData currentArea, float stepDist){ 00660 Attitude targetAtt; 00661 float targetDist = 0.0, expectedDist = 0.0; 00662 MappingData contData; 00663 itsDownDB->getDirections(currentArea, goalArea, targetAtt, targetDist); 00664 expectedDist = targetDist; 00665 while(targetDist >= stepDist){ 00666 turnRel(targetAtt.heading, true); 00667 diveAbs(targetAtt.depth, true);//NOTE: should these both be true? 00668 //approach in steps the size of stepDist 00669 advanceRel(stepDist); 00670 expectedDist -= stepDist; 00671 if(expectedDist <= -15.0){//NOTE: needs calibrating! FIX! 00672 //fail 00673 return false; 00674 } 00675 Angle mh; 00676 //get new currentArea 00677 if(recognizeSIFT(BEOSUBCAMDOWN, contData, mh)){ 00678 itsDownDB->getDirections(contData, goalArea, targetAtt, targetDist); 00679 } 00680 else if(recognizeSIFT(BEOSUBCAMFRONT, contData, mh)){ 00681 itsFrontDB->getDirections(contData, goalArea, targetAtt, targetDist); 00682 } 00683 else{//continue in expected path 00684 targetDist -= stepDist;//NOTE: may be bad! FIX? 00685 } 00686 } 00687 //finish off approach 00688 turnRel(targetAtt.heading, true); 00689 diveAbs(targetAtt.depth, true); 00690 advanceRel(targetDist); 00691 //double-check where we are using mapping, and if OK, return true 00692 00693 00694 Image< PixRGB<byte> > im = grabImage(BEOSUBCAMDOWN); 00695 /* rotate the image grabbed from down cameraby 90 counterclockwise*/ 00696 00697 00698 rutz::shared_ptr<VisualObject> vo(new VisualObject("Captured Image", "", im)); 00699 std::vector< rutz::shared_ptr<VisualObjectMatch> > matches; 00700 itsDownVODB->getObjectMatches(vo, matches, VOMA_KDTREEBBF); 00701 if (matches.size() == 0U){ 00702 itsFrontVODB->getObjectMatches(vo, matches, VOMA_KDTREEBBF); 00703 if(matches.size() == 0U) return false; 00704 }//If we cannot recognize where we are, return that we are not sure. NOTE: this false should likely be different than the false above, sinc eit is a better result. FIX? NOTE: perhaps we should keep track of the # of times we estimated a step? 00705 for(uint i = 0; i <= matches.size(); i++){ 00706 if(!strcmp((matches[0]->getVoTest()->getImageFname()).c_str(), goalArea.itsImgFilename.c_str())){//if we have found a match... 00707 return true; //success! 00708 } 00709 } 00710 return false; //again, we may want to distinguish different "failures" 00711 } 00712 00713 // ###################################################################### 00714 bool BeoSub::Decode(){ 00715 //Decode from the order of tasks to the order of the bins!!! 00716 ImageSet< PixRGB<byte> > inStream; 00717 Image< PixRGB<byte> > img; 00718 int NAVG = 20; Timer tim; uint64 t[NAVG]; int frame = 0; //NOTE: what is this NAVG? 00719 float avg2 = 0.0; 00720 //Grab a series of images 00721 for(int i = 0; i < 100; i++){ 00722 tim.reset(); 00723 00724 img = grabImage(BEOSUBCAMFRONT); 00725 inStream.push_back(img); 00726 00727 uint64 t0 = tim.get(); // to measure display time 00728 t[frame % NAVG] = tim.get(); 00729 t0 = t[frame % NAVG] - t0; 00730 // compute framerate over the last NAVG frames: 00731 if (frame % NAVG == 0 && frame > 0) 00732 { 00733 uint64 avg = 0ULL; for (int i = 0; i < NAVG; i ++) avg += t[i]; 00734 avg2 = 1000.0F / float(avg) * float(NAVG); 00735 } 00736 frame ++; 00737 } 00738 bool foundRed = true; 00739 itsTaskDecoder->setupDecoder("Red", false); 00740 itsTaskDecoder->runDecoder(inStream, avg2); 00741 float hertz = itsTaskDecoder->calculateHz(); 00742 if(hertz <= .5){ 00743 //red not detected. Try green 00744 foundRed = false; 00745 itsTaskDecoder->setupDecoder("Green", false); 00746 itsTaskDecoder->runDecoder(inStream, avg2); 00747 hertz = itsTaskDecoder->calculateHz(); 00748 if(hertz <= .5){//fail 00749 return false; 00750 } 00751 } 00752 itsTasks.clear(); 00753 if(foundRed){//RED 00754 decoderIsRed = true; 00755 if(hertz <= 2.8){//AT 2Hz 00756 itsTasks.push_back('B'); 00757 itsTasks.push_back('A'); 00758 itsTasks.push_back('C'); 00759 } 00760 else{//AT 5Hz 00761 itsTasks.push_back('A'); 00762 itsTasks.push_back('C'); 00763 itsTasks.push_back('B'); 00764 } 00765 } 00766 else{//GREEN 00767 decoderIsRed = false; 00768 if(hertz <= 2.8){//AT 2Hz 00769 itsTasks.push_back('C'); 00770 itsTasks.push_back('A'); 00771 itsTasks.push_back('B'); 00772 } 00773 else{//AT 5Hz 00774 itsTasks.push_back('B'); 00775 itsTasks.push_back('C'); 00776 itsTasks.push_back('A'); 00777 } 00778 } 00779 itsTasksIter = itsTasks.begin(); 00780 return true; 00781 } 00782 00783 // ###################################################################### 00784 bool BeoSub::TaskGate(){ 00785 // int counter = 0; 00786 //turn towards gate (assumes starting on launch platform) 00787 //NOTE: LAUNCHTOGATE will have to be found onsite! FIX! 00788 //turnAbs(LAUNCHTOGATE); 00789 //NOTE: perhaps try to recognize gate here to confirm? may also want to recognize light (which may be easier) 00790 //NOTE: may need to approach here 00791 /* 00792 while(!Decode() && (counter < 10)){ 00793 //while the decode light is not found, strafe left until seen. NOTE that this may or may not work 00794 strafeRel(-0.5); 00795 counter++; 00796 } 00797 if(counter >= 10){ 00798 return false; 00799 } 00800 float thresh = 20.0; 00801 //center decoder in camera 00802 if(decoderIsRed){ 00803 centerColor("Red", BEOSUBCAMFRONT, thresh);//perhaps should use thresh? 00804 } 00805 else{ 00806 centerColor("Green", BEOSUBCAMFRONT, thresh); 00807 } 00808 advanceRel(20.0);//NOTE: this value should be far enough to completely clear the gate 00809 return true;//somewhat bunk 00810 */ 00811 int counter = 0; 00812 while(!matchSIFT(BEOSUBCAMFRONT, itsVOtaskDfront) && counter <= 10){ 00813 turnOpen(10.0); 00814 counter++; 00815 } 00816 if(counter > 10){ 00817 return false; 00818 } 00819 diveAbs(2.0); 00820 return true; 00821 } 00822 00823 // ###################################################################### 00824 00825 00826 bool BeoSub::TaskScheduler(int TaskOrder) //Schedule the order of the three tasks 00827 { 00828 00829 //pre-task A 00830 //Assmue we get thru the gate, and recognize the light box 00831 //looking for red light 00832 00833 //approaching red light 00834 00835 //task A 00836 if(TaskA()) //if Task A is done, then go to task B normally 00837 { 00838 //looking for yellow pipeline 00839 00840 //approaching yellow pipeline 00841 00842 }// end of if 00843 else //if task A fails, then use emergancy to find task B 00844 { 00845 00846 }//end of else 00847 00848 00849 //task B 00850 if(TaskB()) //emergancy for task B 00851 { 00852 //well done, go to task C 00853 00854 }//end of if 00855 else 00856 { 00857 //not done, do task B again? or go to task C 00858 00859 }//end of else 00860 00861 00862 //task C 00863 if(TaskC()) 00864 { 00865 00866 } 00867 else 00868 { 00869 00870 } 00871 00872 //post-task C 00873 00874 00875 //done 00876 return true; 00877 00878 }//end of TaskScheduler 00879 00880 //=======================Begins TaskA============================== 00881 bool BeoSub::TaskA(){//NOTE: assumes that sub has already approached task A and dove to the correct depth, as well as turned to a predicted heading 00882 //LOOK FOR THE LIGHT 00883 /* float x = 0.0; 00884 float y = 0.0; 00885 float mass = 0; 00886 float close = 30.0; 00887 bool notDone = true; 00888 int state = 0; 00889 */ 00890 /* 00891 while sift not found, spiral search slowly 00892 once found, center using sift affine 00893 dive 00894 00895 */ 00896 if(!affineSIFT(BEOSUBCAMDOWN, itsVOtaskAdown)){//approach 00897 if(!affineSIFT(BEOSUBCAMFRONT, itsVOtaskAfront)){ 00898 float dist = sqrt(((taskAposition.x - itsGlobalPosition.x)*(taskAposition.x - itsGlobalPosition.x)) + ((taskAposition.y - itsGlobalPosition.y)*(taskAposition.y - itsGlobalPosition.y))); 00899 Angle turn = acos(taskAposition.y/dist); 00900 Angle down = 180; 00901 turn = down - turn; 00902 turn = turn - itsGlobalHeading; 00903 turnOpen(turn); 00904 advanceRel(dist); 00905 } 00906 } 00907 /* 00908 while(notDone){ 00909 switch(state){ 00910 case 0: //LOOK FOR LIGHT 00911 { 00912 //while we don't see the light... 00913 turnRel(10.0, true);//NOTE: 10 perhaps too big. FIX! 00914 itsColorTracker->setupTracker("Red", grabImage(BEOSUBCAMFRONT), false); //reset using most recent image 00915 if(itsColorTracker->runTracker(5.0, x, y, mass)){ 00916 if(mass >= close){ 00917 state = 3; 00918 } 00919 else{ 00920 state = 1; 00921 } 00922 break; 00923 } 00924 } 00925 case 1: //CENTER LIGHT IN CAMERA 00926 { 00927 if(centerColor("Red", BEOSUBCAMFRONT, mass)){ 00928 if(mass >= close){ 00929 //NOTE: check for correct depth vs. decoder depth? 00930 state = 3; 00931 } 00932 else{ 00933 state = 2; 00934 } 00935 } 00936 else{ 00937 state = 0; 00938 } 00939 } 00940 case 2: //APPROACH THE LIGHT (really ghetto right now) 00941 { 00942 advanceRel(1.0);//NOTE: should be some number based off of the mass! FIX! 00943 } 00944 case 3: //RAM THE LIGHT! 00945 //go forward at full speed, but allow color tracker to continue running 00946 itsColorTracker->setupTracker("Red", grabImage(BEOSUBCAMFRONT), false); 00947 if(itsColorTracker->runTracker(40.0, x, y, mass)){ 00948 advanceRel(12.0, false); 00949 advanceRel(-1.0, false); //to stop 00950 } 00951 else{ 00952 //light is assumd to have ben hit. stop ramming and continue to next stage 00953 notDone = false; 00954 break; 00955 } 00956 } 00957 } 00958 */ 00959 taskAdone = true; 00960 return true; 00961 } 00962 00963 //Look around for the red light 00964 bool BeoSub::LookForRedLight() 00965 { 00966 //front camera 00967 //dive close to the pipe 00968 00969 ModelManager camManager("ColorTracker Tester"); 00970 00971 nub::soft_ref<FrameIstream> 00972 gb(makeIEEE1394grabber(camManager, "colorcam", "cocam")); 00973 00974 camManager.addSubComponent(gb); 00975 00976 camManager.start(); 00977 00978 // instantiate a model manager for the color tracker module: 00979 ModelManager manager("ColorTracker Tester"); 00980 00981 // Instantiate our various ModelComponents: 00982 nub::soft_ref<ColorTracker> test(new ColorTracker(manager)); 00983 manager.addSubComponent(test); 00984 00985 manager.start(); 00986 00987 Image< PixRGB<byte> > Img; 00988 float x = 320/2, y=240/2; 00989 float mass; 00990 bool found; 00991 00992 // float width; 00993 00994 rutz::shared_ptr<XWindow> wini; 00995 00996 //turn around until I find orange 00997 //#################control################# 00998 00999 #ifndef DEBUG 01000 turnRel(Angle(15.0)); //turn 01001 #else 01002 printf("DEBUG!!!!!!!!!!!!!!!!!!!!!!!\n"); 01003 printf("i'm doing the first turing!\n"); 01004 #endif 01005 01006 //Note: should check if it turned 360 degrees without finding anything 01007 //now just use a counter for test 01008 01009 int turnCounter=0; 01010 01011 #ifndef DEBUG 01012 Angle initHeading = getHeading(); 01013 Angle currHeading; 01014 Angle epsHeading = Angle(5.0); 01015 #else 01016 #endif 01017 01018 while(1) 01019 { 01020 #ifndef DEBUG 01021 turnRel(5); 01022 #else 01023 printf("turning right to find the red light!\n"); 01024 #endif 01025 01026 Img = gb->readRGB(); 01027 01028 #ifndef DEBUG 01029 test->setupTracker("Red", grabImage(BEOSUBCAMFRONT), true); 01030 #else 01031 test->setupTracker("Red", Img /*grabImage(BEOSUBCAMFRONT)*/, true); 01032 #endif 01033 01034 found = test->runTracker(25.0, x, y, mass); 01035 if (found) 01036 { 01037 #ifdef DEBUG 01038 turnRel(0.01); //stop turning 01039 #else 01040 printf("i see the red light!"); 01041 #endif 01042 break; 01043 } 01044 01045 //test if we have turned for 360 degrees 01046 //if so, go randomly or go according to the mapping info 01047 //now we're just using a counter 01048 #ifndef DEBUG 01049 currHeading = getHeading(); 01050 if(fabs(currHeading.getVal() - initHeading.getVal()) <= - (epsHeading.getVal())) 01051 { 01052 //if we are trying too many times, just give up 01053 if(turnCounter++ > 10) 01054 { 01055 return false; 01056 } 01057 //make a random turn and go (-180, 180) 01058 else 01059 { 01060 int rndTurn = rand()*180; 01061 Angle rndHeading = Angle(360-rndTurn); 01062 turnRel(rndHeading); 01063 advanceRel(10.0); 01064 } 01065 } 01066 #else 01067 if(turnCounter++ > 1000) 01068 { 01069 printf("never see the red light, i give up!"); 01070 return false; 01071 } 01072 #endif 01073 01074 }//end of while 01075 01076 return true; 01077 } 01078 01079 //Center the red light and ready to go 01080 bool BeoSub::CenterRedLight() 01081 { 01082 return false; 01083 } 01084 01085 //Approach the red light until close enough 01086 bool BeoSub::ApproachRedLight() 01087 { 01088 ModelManager camManager("ColorTracker Tester"); 01089 01090 nub::soft_ref<FrameIstream> 01091 gb(makeIEEE1394grabber(camManager, "colorcam", "cocam")); 01092 01093 camManager.addSubComponent(gb); 01094 01095 camManager.start(); 01096 01097 // instantiate a model manager for the color tracker module: 01098 ModelManager manager("ColorTracker Tester"); 01099 01100 // Instantiate our various ModelComponents: 01101 nub::soft_ref<ColorTracker> test(new ColorTracker(manager)); 01102 manager.addSubComponent(test); 01103 01104 manager.start(); 01105 01106 Image< PixRGB<byte> > Img; 01107 float x = 320/2, y=240/2; 01108 01109 //arbitary area of mass, need to calibrate!!!! 01110 float mass=10.0; 01111 bool found; 01112 01113 float width; 01114 01115 rutz::shared_ptr<XWindow> wini; 01116 //approach the orange 01117 bool redInFront = false; //can I see the pipe in front of me 01118 01119 //we're trying to see the red light 01120 //in both the bottom and front cameras (this is kinda idealistic) 01121 while(1) 01122 { 01123 Img = gb->readRGB(); 01124 //chase after red in the front cam 01125 #ifndef DEBUG 01126 test->setupTracker("Red", grabImage(BEOSUBCAMFRONT), true); 01127 #else 01128 test->setupTracker("Red", Img, true); 01129 #endif 01130 redInFront = test->runTracker(25.0, x, y, mass); 01131 #ifndef DEBUG 01132 test->setupTracker("Red", grabImage(BEOSUBCAMDOWN), true); 01133 #else 01134 test->setupTracker("Red", Img, true); 01135 #endif 01136 test->runTracker(25.0, x, y, mass); 01137 01138 #ifndef DEBUG 01139 advanceRel(1.5); 01140 #else 01141 printf("i'm going forward!\n"); 01142 #endif 01143 01144 width = Img.getWidth(); 01145 //make sure that positive is up-right 01146 x = x - width/2; 01147 01148 if (redInFront) 01149 { //if seen in the front camera 01150 printf("i see the red light in the front!\n"); 01151 if (fabs(x) < 10) 01152 { //turn left or right 01153 #ifndef DEBUG 01154 advanceRel(1.5); 01155 #else 01156 printf("now going forward to the pipe!\n"); 01157 #endif 01158 } 01159 else 01160 { 01161 if(x>0) 01162 { 01163 01164 #ifndef DEBUG 01165 turnRel(Angle(5)); 01166 #else 01167 printf("turning right to the red light!\n"); 01168 #endif 01169 } 01170 else 01171 { 01172 #ifndef DEBUG 01173 turnRel(Angle(-5)); 01174 #else 01175 printf("turning left to the red light!\n"); 01176 #endif 01177 } 01178 }//end of if abs of x 01179 }//end of if red in front 01180 else 01181 { //dive until you see red in front again 01182 01183 printf("now i lost the red light, diving to get it!\n"); 01184 while(1) 01185 { 01186 Img = gb->readRGB(); 01187 #ifndef DEBUG 01188 test->setupTracker("Red", grabImage(BEOSUBCAMFRONT), true); 01189 #else 01190 test->setupTracker("Red", Img /*grabImage(BEOSUBCAMFRONT)*/, true); 01191 #endif 01192 redInFront = test->runTracker(25.0, x, y, mass); 01193 01194 //need a timer/counter, if the red never shows in the front, 01195 //we probably are lost, or hit the bottom of the pool! 01196 if (redInFront) 01197 { 01198 printf("got it after dive, now going!\n"); 01199 break; 01200 } 01201 #ifndef DEBUG 01202 diveRel(.3); 01203 #else 01204 printf("i'm diving for the red light!!!\n"); 01205 #endif 01206 01207 }//end of while 01208 01209 }//end of else red light in front 01210 01211 //when a significant amount of red is in the bottom camera 01212 //we are now above the red light, and ready to push! 01213 #ifndef DEBUG 01214 test->setupTracker("Red", grabImage(BEOSUBCAMDOWN), true); 01215 #else 01216 test->setupTracker("Red", Img /*grabImage(BEOSUBCAMDOWN)*/, true); 01217 #endif 01218 found = test->runTracker(25.0, x, y, mass); 01219 01220 printf("testing if the red light shows in my bottom camera\n"); 01221 if (found == true) 01222 { 01223 //see orange in the bottom camera 01224 printf("ok, finally i'm above the red light!\n"); 01225 return true; 01226 } 01227 printf("never see the red light under me, keep going!\n"); 01228 01229 }//end of the while(1) loop 01230 01231 return false; 01232 } 01233 01234 //Push the red light to finish task A 01235 bool BeoSub::PushRedLight() 01236 { 01237 //l: length of the light bar 01238 //alpha: the min angle to push 01239 //pushDist = l * sin(alpha) 01240 //diveDist = pushDist * tan(alpha) 01241 float minAngle = 30; //degrees 01242 float barLength = 10.0; 01243 float pushDist = barLength * sin(minAngle); 01244 //float diveDist = pushDist * tan(minAngle); 01245 01246 //total advanced distant counter 01247 float advDist = 0.0; 01248 //total dived distant counter 01249 float divDist = 0.0; 01250 ModelManager camManager("ColorTracker Tester"); 01251 01252 nub::soft_ref<FrameIstream> 01253 gb(makeIEEE1394grabber(camManager, "colorcam", "cocam")); 01254 01255 camManager.addSubComponent(gb); 01256 01257 camManager.start(); 01258 01259 // instantiate a model manager for the color tracker module: 01260 ModelManager manager("ColorTracker Tester"); 01261 01262 // Instantiate our various ModelComponents: 01263 nub::soft_ref<ColorTracker> test(new ColorTracker(manager)); 01264 manager.addSubComponent(test); 01265 01266 manager.start(); 01267 01268 Image< PixRGB<byte> > Img; 01269 float x = 320/2, y=240/2; 01270 01271 //arbitary area of mass, need to calibrate!!!! 01272 float mass = 10.0; 01273 float width; 01274 01275 rutz::shared_ptr<XWindow> wini; 01276 //approach the red light 01277 bool redInFront = false; //can I see the pipe in front of me 01278 bool redInBottom = false; 01279 01280 //we're trying to see orange in both the bottom and front cameras (this is kinda idealistic) 01281 while(1) 01282 { 01283 Img = gb->readRGB(); 01284 //chase after orange in the front cam 01285 #ifndef DEBUG 01286 test->setupTracker("Red", grabImage(BEOSUBCAMFRONT), true); 01287 #else 01288 test->setupTracker("Red", Img, true); 01289 #endif 01290 redInFront = test->runTracker(25.0, x, y, mass); 01291 #ifndef DEBUG 01292 test->setupTracker("Red", grabImage(BEOSUBCAMDOWN), true); 01293 #else 01294 test->setupTracker("Red", Img, true); 01295 #endif 01296 redInBottom = test->runTracker(25.0, x, y, mass); 01297 01298 width = Img.getWidth(); 01299 //make sure that positive is up-right 01300 x = x - width/2; 01301 01302 if (redInBottom) 01303 { 01304 //if seen in the bottom camera 01305 //dive until never see in the bottom camera 01306 //but still sees it in the front camera 01307 #ifndef DEBUG 01308 diveRel(.3); 01309 #else 01310 printf("now diving to push the red light!\n"); 01311 #endif 01312 } 01313 else if(redInFront) 01314 { 01315 //now we are at the right pos to push 01316 //GO! 01317 printf("i see the red light in the front!\n"); 01318 if (fabs(x) < 10) 01319 { //turn left or right 01320 #ifndef DEBUG 01321 advanceRel(1.5); 01322 advDist += 1.5; 01323 diveRel(1.5 * tan(minAngle)); 01324 divDist += 1.5 * tan(minAngle); 01325 #else 01326 printf("now going forward to the pipe!\n"); 01327 #endif 01328 } 01329 else 01330 { 01331 if(x>0) 01332 { 01333 #ifndef DEBUG 01334 turnRel(Angle(5)); 01335 #else 01336 printf("turning right to the red light!\n"); 01337 #endif 01338 } 01339 else 01340 { 01341 #ifndef DEBUG 01342 turnRel(Angle(-5)); 01343 #else 01344 printf("turning left to the red light!\n"); 01345 #endif 01346 } 01347 }//end of if abs of x 01348 01349 if(advDist > pushDist) 01350 { 01351 //we are done! 01352 //now go up and leave the red light 01353 #ifndef DEBUG 01354 //go up and release the red 01355 //we are both free! 01356 diveRel(- divDist - 5.0); 01357 #else 01358 printf("Job done! Going up to leave the red light!\n"); 01359 printf("up dist: %f", divDist); 01360 #endif 01361 return true; 01362 } 01363 01364 }//end of if red in front 01365 else 01366 { 01367 //we lost the red light 01368 //should we do it again??? 01369 printf("No, lost the red light\n"); 01370 01371 return false; 01372 } 01373 }//end of while(1) 01374 01375 return false; 01376 } 01377 01378 //====================End TaskA========================= 01379 01380 //====================Begins TaskB========================== 01381 bool BeoSub::TaskB(){ 01382 //NOTE: The bottom camera axes are not correct! Will NEED to FIX the indiscrepancy in code below! 01383 //ADD: Orange line flollwing state. AffineXfrm correction, marker dropping 01384 01385 //int stage = 0; 01386 //int counter = 0; 01387 bool TaskBDone = false; //has it dropped the marker into the target bin yet? 01388 //bool foundDown = false; bool foundFront = false; 01389 //float x, y, mass, x2, y2, mass2; 01390 //float usedX, usedY, usedMass; 01391 Image< PixRGB<byte> > image; 01392 01393 /***********************new code ********************************/ 01394 //Assume the order is A to B to C 01395 //So we get from A to B 01396 01397 // const int HatchNull = 0; 01398 // const int HatchNo = 1; 01399 // const int HatchShort = 2; 01400 // const int Hatch45 = 3; 01401 //const int HatchLong = 4; 01402 01403 unsigned int BinCounter = 0; 01404 unsigned int ApproachCounter = 0; 01405 01406 //get random order of the bins 01407 // int TaskBBin = HatchNo; 01408 01409 // int CurrentPos = 0; 01410 /* 01411 ApproachPipeLine(); 01412 while(BinCounter<1) { 01413 bool recbin = FollowPipeLine(); 01414 if (recbin) { 01415 CenterBin(); 01416 DropMarker(); 01417 BinCounter++; 01418 } 01419 01420 FollowPipeLine(); 01421 TaskBDone = true; 01422 } 01423 */ 01424 // bool recognize = false; 01425 01426 const unsigned int binNum = 1; 01427 01428 bool testBin=false; 01429 01430 while((BinCounter < binNum) && (!TaskBDone)) 01431 { 01432 //!!!maybe need to change: looking for pipe and approaching pipe 01433 if(ApproachPipeLine()) 01434 { 01435 ApproachCounter = 0; 01436 01437 //TRUE if found bin at the end of follow pipeline 01438 if( (testBin = FollowPipeLine()) ) 01439 { 01440 //recognize the 4 bins 01441 //need to change to really recognize 01442 printf("TaskB: found a bin at the end of the pipeline! Now checking if the bin is the one we want\n"); 01443 01444 //if(RecognizeBin()==tastBin) 01445 if(testBin == true) //if the bin is the recognized one, drop the marke, else just pass it 01446 { 01447 printf("TaskB: found the bin we want! Now going to center the bin\n"); 01448 01449 if(CenterBin()) 01450 { 01451 printf("TaskB: we have centered the bin! Now we're going to drop the marker!\n"); 01452 01453 if(DropMarker()) 01454 { 01455 printf("TaskB: good, we dropped the marker!\n"); 01456 TaskBDone = true; 01457 BinCounter++; 01458 }//end ofif drop marker 01459 else 01460 { 01461 //failed to drop the marker 01462 //drop again? 01463 printf("TaskB: failed to drop the marker!!!\n"); 01464 return false; 01465 }//end of drop marker 01466 01467 }//end of if center bin 01468 else 01469 { 01470 printf("TaskB: well, we failed to center the bin!\n"); 01471 //fail to center the bin 01472 //center again? 01473 return false; 01474 }//end of center bin 01475 01476 }//end of if test bin 01477 else 01478 { 01479 printf("TaskB: it's not the bin we want! Just go thru it!\n"); 01480 01481 if(PassBin()) 01482 { 01483 printf("TaskB: Ok, we passed the bin! Now follow the pipe to the next bin!\n"); 01484 }//end of if pass bin 01485 else 01486 { 01487 printf("TaskB: well, we failed the pass the bin!"); 01488 //failed to pass the bin 01489 //find the pipeline directly? 01490 return false; 01491 01492 }//end of pass bin 01493 01494 BinCounter++; 01495 01496 }//end of test bin 01497 01498 }//end of if follow 01499 else if(TaskBDone) 01500 { 01501 printf("TaskB: Well, we lost track of the pipe, but the task is done!\n"); 01502 01503 //if(BinCounter<4) 01504 if(BinCounter < 1) //we miss some bins, but we are done 01505 { 01506 return true; 01507 } 01508 else //We are done, go out of the task B zone 01509 { 01510 return true; 01511 } 01512 01513 }//end of else if 01514 01515 else //there is something wrong that we are out of the task B zone 01516 { 01517 printf("TaskB: We lost track of the pipe!\n"); 01518 //go back and check again 01519 return false; 01520 }//end of else follow 01521 01522 }//end of if approach 01523 01524 else //failed to approach, try again? 01525 { 01526 printf("TaskB: Failed to approach to the pipe at try %i\n", ApproachCounter); 01527 if(++ApproachCounter>5) //we give up trying 01528 { 01529 printf("TaskB: Never find the pipe! Give up!\n"); 01530 return false; 01531 } 01532 01533 }//end else approach 01534 01535 }//end of while 01536 01537 printf("TaskB: i'm not suppose to come here, but task is done!\n"); 01538 return true; 01539 01540 /**************************************old code****************************************/ 01541 //while(notDone){ 01542 // switch(stage){ 01543 // case 0: //FINE-TUNE MAPPING MATCH. Accepts image filename and fine-tunes current result to param image 01544 // { 01545 // rutz::shared_ptr<VisualObject> goal = itsDownVODB->getObject("TaskB"); 01546 // if(affineSIFT(BEOSUBCAMDOWN, goal)){//approach 01547 // stage = 3; 01548 // break; 01549 // } 01550 // else{//look for pipes 01551 // stage = 5; 01552 // break; 01553 // } 01554 // } 01555 // case 3: //MARKER DROPPER 1ST AND ONLY STAGE 01556 // { 01557 // for(int i = 0; i < 6; i++) { 01558 // dropMarker(); 01559 // } 01560 // return true; 01561 // // call dropMarker() 01562 // } 01563 // case 5: //APPROACH ORANGE PIPES 01564 // { 01565 01566 // if(taskCdone){//If we came from taskC direction... 01567 // MappingData BtoC = itsDownDB->getMappingData("TaskBtoC.txt"); 01568 // MappingData current; Angle myHeading; 01569 // if(!recognizeSIFT(BEOSUBCAMDOWN, current, myHeading)){//Try to recognize where we are (max 8 tries right now) 01570 // counter++; 01571 // //Ghetto circle search. FIX! 01572 // advanceRel(-1.5); 01573 // turnRel(20.0); 01574 // } 01575 // if(counter >= 8){//If we are lost, fail 01576 // return false; 01577 // } 01578 // else{//approach task A to B pipes 01579 // /* 01580 // if(approachArea(BEOSUBCAMDOWN, BtoC, 3.0)){ 01581 // stage = 7; 01582 // counter = 0; 01583 // break; 01584 // } 01585 // */ 01586 // counter++; 01587 // } 01588 // } 01589 // else if(taskAdone){//If we came from TaskA direction... 01590 // MappingData BtoA = itsDownDB->getMappingData("TaskBtoA.txt"); 01591 // MappingData current; Angle myHeading; 01592 // if(!recognizeSIFT(BEOSUBCAMDOWN, current, myHeading)){//Try to recognize where we are (max 8 tries right now) 01593 // counter++; 01594 // //Ghetto circle search. FIX! 01595 // advanceRel(-3.5); 01596 // turnRel(20.0); 01597 // } 01598 // if(counter >= 8){//If we are lost, fail 01599 // return false; 01600 // } 01601 // else{//approach task A to B pipes 01602 // /* 01603 // if(approachArea(BEOSUBCAMDOWN, BtoA, 3.0)){ 01604 // stage = 7; 01605 // counter = 0; 01606 // break; 01607 // } 01608 // */ 01609 // counter++; 01610 // } 01611 // } 01612 // } 01613 // case 7://PIPE FOLLOWING 01614 // { 01615 // float x = 0.0, y = 0.0, mass = 0.0; 01616 // int counter = 0; 01617 // itsColorTracker2->setupTracker("Orange", grabImage(BEOSUBCAMDOWN), false); 01618 01619 // while(itsColorTracker2->runTracker(10.0, x, y, mass) && counter < 12){ 01620 // ++counter; 01621 // //NOTE: Down cam weirdness! FIX!! 01622 // if(y < 120){//on left... 01623 // turnRel(-10.0); 01624 // } 01625 // else{//on right... 01626 // turnRel(10.0); 01627 // } 01628 01629 // /****/ //FIX 01630 01631 // advanceRel(1.5);//follow 01632 01633 // itsColorTracker->setupTracker("White", grabImage(BEOSUBCAMDOWN), false); 01634 // if(itsColorTracker->runTracker(500.0, x, y, mass)) { 01635 // stage = 3; 01636 // break; 01637 // } 01638 01639 // } 01640 // //itsColorTracker2->setupTracker("Orange", grabImage(BEOSUBCAMDOWN), false); 01641 // stage = 3; 01642 // //done following, try to find box 01643 // // stage = 0; ///????? 01644 // break; 01645 // } 01646 // } 01647 //}//end of while 01648 01649 //return false; 01650 } 01651 01652 bool BeoSub::ApproachPipeLine() 01653 { 01654 //front camera 01655 //dive close to the pipe 01656 01657 ModelManager camManager("ColorTracker Tester"); 01658 01659 nub::soft_ref<FrameIstream> 01660 gb(makeIEEE1394grabber(camManager, "colorcam", "cocam")); 01661 01662 camManager.addSubComponent(gb); 01663 01664 camManager.start(); 01665 01666 // instantiate a model manager for the color tracker module: 01667 ModelManager manager("ColorTracker Tester"); 01668 01669 // Instantiate our various ModelComponents: 01670 nub::soft_ref<ColorTracker> test(new ColorTracker(manager)); 01671 manager.addSubComponent(test); 01672 01673 manager.start(); 01674 01675 Image< PixRGB<byte> > Img; 01676 float x = 320/2, y=240/2; 01677 //arbitary area of mass, need to calibrate!!!! 01678 float mass = 10.0; 01679 bool found; 01680 01681 float width; 01682 01683 rutz::shared_ptr<XWindow> wini; 01684 01685 //turn around until I find orange 01686 //#################control################# 01687 01688 #ifndef DEBUG 01689 turnRel(Angle(15.0)); //turn 01690 #else 01691 printf("DEBUG!!!!!!!!!!!!!!!!!!!!!!!\n"); 01692 printf("i'm doing the first turing!\n"); 01693 #endif 01694 01695 //Note: should check if it turned 360 degrees without finding anything 01696 //now just use a counter for test 01697 01698 int turnCounter=0; 01699 01700 #ifndef DEBUG 01701 Angle initHeading = getHeading(); 01702 Angle currHeading; 01703 Angle epsHeading = Angle(5.0); 01704 #else 01705 #endif 01706 01707 while(1) 01708 { 01709 #ifndef DEBUG 01710 turnRel(5); 01711 #else 01712 printf("turning right to find the pipe!\n"); 01713 #endif 01714 01715 Img = gb->readRGB(); 01716 01717 #ifndef DEBUG 01718 test->setupTracker("Orange", grabImage(BEOSUBCAMFRONT), true); 01719 #else 01720 test->setupTracker("Orange", Img /*grabImage(BEOSUBCAMFRONT)*/, true); 01721 #endif 01722 01723 found = test->runTracker(25.0, x, y, mass); 01724 if (found) 01725 { 01726 #ifdef DEBUG 01727 turnRel(0.01); //stop turning 01728 #else 01729 printf("i see the pipe!"); 01730 #endif 01731 break; 01732 } 01733 01734 //test if we have turned for 360 degrees 01735 //if so, go randomly or go according to the mapping info 01736 //now we're just using a counter 01737 #ifndef DEBUG 01738 currHeading = getHeading(); 01739 if(fabs(currHeading.getVal() - initHeading.getVal()) <= - (epsHeading.getVal())) 01740 { 01741 //if we are trying too many times, just give up 01742 if(turnCounter++ > 10) 01743 { 01744 return false; 01745 } 01746 //make a random turn and go (-180, 180) 01747 else 01748 { 01749 int rndTurn = rand()*180; 01750 Angle rndHeading = Angle(360-rndTurn); 01751 turnRel(rndHeading); 01752 advanceRel(10.0); 01753 } 01754 } 01755 #else 01756 if(turnCounter++ > 1000) 01757 { 01758 printf("never see a pipe, i give up!"); 01759 return false; 01760 } 01761 #endif 01762 01763 }//end of while 01764 01765 //approach the orange 01766 bool pipeInFront = false; //can I see the pipe in front of me 01767 01768 //we're trying to see orange in both the bottom and front cameras (this is kinda idealistic) 01769 while(1) 01770 { 01771 Img = gb->readRGB(); 01772 //chase after orange in the front cam 01773 #ifndef DEBUG 01774 test->setupTracker("Orange", grabImage(BEOSUBCAMFRONT), true); 01775 #else 01776 test->setupTracker("Orange", Img, true); 01777 #endif 01778 pipeInFront = test->runTracker(25.0, x, y, mass); 01779 #ifndef DEBUG 01780 test->setupTracker("Orange", grabImage(BEOSUBCAMDOWN), true); 01781 #else 01782 test->setupTracker("Orange", Img, true); 01783 #endif 01784 test->runTracker(25.0, x, y, mass); 01785 01786 #ifndef DEBUG 01787 advanceRel(1.5); 01788 #else 01789 printf("i'm going forward!\n"); 01790 #endif 01791 01792 width = Img.getWidth(); 01793 //make sure that positive is up-right 01794 x = x - width/2; 01795 01796 if (pipeInFront) 01797 { //if seen in the front camera 01798 printf("i see the pipe in the front!\n"); 01799 if (fabs(x) < 10) 01800 { //turn left or right 01801 #ifndef DEBUG 01802 advanceRel(1.5); 01803 #else 01804 printf("now going forward to the pipe!\n"); 01805 #endif 01806 } 01807 else 01808 { 01809 if(x>0) 01810 { 01811 01812 #ifndef DEBUG 01813 turnRel(Angle(5)); 01814 #else 01815 printf("turning right to the pipe!\n"); 01816 #endif 01817 } 01818 else 01819 { 01820 #ifndef DEBUG 01821 turnRel(Angle(-5)); 01822 #else 01823 printf("turning left to the pipe!\n"); 01824 #endif 01825 } 01826 }//end of if abs of x 01827 }//end of if pipe in front 01828 else 01829 { //dive until you see orange in front again 01830 01831 printf("now i lost the pipe, diving to get it!\n"); 01832 while(1) 01833 { 01834 Img = gb->readRGB(); 01835 #ifndef DEBUG 01836 test->setupTracker("Orange", grabImage(BEOSUBCAMFRONT), true); 01837 #else 01838 test->setupTracker("Orange", Img /*grabImage(BEOSUBCAMFRONT)*/, true); 01839 #endif 01840 pipeInFront = test->runTracker(25.0, x, y, mass); 01841 01842 //need a timer/counter, if the pipe never shows in the front, 01843 //we probably are lost, or hit the bottom of the pool! 01844 if (pipeInFront) 01845 { 01846 printf("got it after dive, now going!\n"); 01847 break; 01848 } 01849 #ifndef DEBUG 01850 diveRel(.3); 01851 #else 01852 printf("i'm diving for the orange!!!\n"); 01853 #endif 01854 01855 }//end of while 01856 01857 }//end of else pipe in front 01858 01859 //stop when a significant amount of orange is in the bottom camera 01860 #ifndef DEBUG 01861 test->setupTracker("Orange", grabImage(BEOSUBCAMDOWN), true); 01862 #else 01863 test->setupTracker("Orange", Img /*grabImage(BEOSUBCAMDOWN)*/, true); 01864 #endif 01865 found = test->runTracker(25.0, x, y, mass); 01866 01867 printf("testing if the pipe shows in my bottom camera\n"); 01868 if (found == true) 01869 { 01870 //see orange in the bottom camera 01871 printf("ok, finally i'm above the pipe!\n"); 01872 return true; 01873 } 01874 printf("never see the pipe under me, keep going!\n"); 01875 01876 }//end of while 01877 01878 //never should come here!!! 01879 return false; 01880 01881 /********** Assume we start from A to B then to C 01882 if(taskCdone){//If we came from taskC direction... 01883 MappingData BtoC = itsDownDB->getMappingData("TaskBtoC.txt"); 01884 MappingData current; Angle myHeading; 01885 if(!recognizeSIFT(BEOSUBCAMDOWN, current, myHeading)){//Try to recognize where we are (max 8 tries right now) 01886 counter++; 01887 //Ghetto circle search. FIX! 01888 advanceRel(-1.5); 01889 turnRel(20.0); 01890 } 01891 if(counter >= 8){//If we are lost, fail 01892 return false; 01893 } 01894 else{//approach task A to B pipes 01895 01896 // if(approachArea(BEOSUBCAMDOWN, BtoC, 3.0)){ 01897 // stage = 7; 01898 // counter = 0; 01899 // break; 01900 // } 01901 01902 //counter++; 01903 //} 01904 //}*/ 01905 01906 //printf("x:%f, y:%f, mass:%f\n",x,y, mass); 01907 01908 01909 01910 // Should be data AtoB??? 01911 // MappingData BtoA = itsDownDB->getMappingData("TaskBtoA.txt"); 01912 01913 // MappingData current;//=??? 01914 // Angle myHeading;//=??? 01915 01916 //Recognize my current position in the mapping, and then go toward the pipeline position 01917 01918 // if(!recognizeSIFT(BEOSUBCAMDOWN, current, myHeading)){//Try to recognize where we are (max 8 tries right now) 01919 //counter++; 01920 //Ghetto circle search. FIX! 01921 01922 //need to calculate the 'distance' between current and goal (BtoA) 01923 //then drive the sub there 01924 //when to stop??? 01925 01926 //advanceRel(-3.5); 01927 //turnRel(20.0); 01928 // } 01929 01930 //if(counter >= 8){//If we are lost, fail 01931 // return false; 01932 //} 01933 //else{//approach task A to B pipes 01934 // /* 01935 // if(approachArea(BEOSUBCAMDOWN, BtoA, 3.0)){ 01936 // stage = 7; 01937 // counter = 0; 01938 // break; 01939 // } 01940 // */ 01941 // tesl counter++; 01942 //} 01943 01944 01945 return true; 01946 }//end of ApproachPipeLine 01947 01948 01949 bool BeoSub::FollowPipeLine() //if the end is the bin, then return true, else, return false 01950 { 01951 ModelManager camManager("ColorTracker Tester"); 01952 01953 nub::soft_ref<FrameIstream> 01954 gb(makeIEEE1394grabber(camManager, "colorcam", "cocam")); 01955 01956 camManager.addSubComponent(gb); 01957 01958 camManager.start(); 01959 01960 // instantiate a model manager for the color tracker module: 01961 ModelManager manager("ColorTracker Tester"); 01962 01963 // Instantiate our various ModelComponents: 01964 nub::soft_ref<ColorTracker> test(new ColorTracker(manager)); 01965 manager.addSubComponent(test); 01966 manager.start(); 01967 01968 Image< PixRGB<byte> > Img; 01969 float x = 320/2, y=240/2; 01970 //arbitary area of mass, need to calibrate!!!! 01971 float mass = 10.0; 01972 01973 float width; 01974 float height; 01975 rutz::shared_ptr<XWindow> wini; 01976 01977 while(1){ 01978 //Get image to be matched 01979 //TO TEST FROM CAMERA 01980 Img = gb->readRGB(); 01981 01982 test->setupTracker("Orange", Img /*grabImage(BEOSUBCAMDOWN)*/, true); 01983 test->runTracker(25.0, x, y, mass); 01984 01985 // wini->drawImage(Img); 01986 width = Img.getWidth(); 01987 01988 //make sure that positive is up-right 01989 x = x - width/2; 01990 01991 height = Img.getHeight(); 01992 y = height/2 - y; 01993 01994 #ifndef DEBUG 01995 #else 01996 printf("X: %f, WIDTH: %f\n", x, width); 01997 printf("Y: %f, HEIGHT: %f\n", y, height); 01998 #endif 01999 //test the area of the yellow pipe, 02000 //if it's small enough, it's the end; 02001 //otherwise, go straight 02002 02003 if( mass > 1000 ) 02004 { //go straight 02005 #ifndef DEBUG 02006 advanceRel(1.5); 02007 #else 02008 printf("i'm going forward!\n"); 02009 #endif 02010 } 02011 else //it's either the end of the pipeline or there's a break for a box 02012 { 02013 printf("Break in pipeline\n"); 02014 02015 //test if the end is a bin or not 02016 //1 for black bin, other for white bin 02017 //bool rec = TestBin(1); 02018 bool rec=TestBin(gb,1); 02019 if (rec) 02020 { 02021 printf("FOUND BIN\n"); 02022 } 02023 // return TestBin(); 02024 return rec; 02025 } 02026 02027 //PID control of the tracking,!!! now just x-tracking 02028 02029 if(fabs(x)<=20) 02030 {//go straight 02031 #ifndef DEBUG 02032 advanceRel(1.5); 02033 #else 02034 printf("Go Straight %f\n", fabs(x)); 02035 #endif 02036 } 02037 else 02038 { 02039 if (y == 0.0) 02040 { 02041 y+=0.01; 02042 } //prevent divide by zero error 02043 02044 printf("turn: %f %f\n",atan(x/y)*180/M_PI, M_PI); 02045 02046 if (atan(x/y)*180/M_PI > 0) 02047 { 02048 printf("Turn Right %f\n", fabs(x)); 02049 } 02050 else 02051 { 02052 printf("Turn Left %f\n", fabs(x)); 02053 } 02054 #ifndef DEBUG 02055 turnRel(Angle(atan(x/y) * 180/M_PI)); 02056 #else 02057 printf("i'm turing to the center of the orange!\n"); 02058 #endif 02059 } 02060 02061 //!!!need to check if overturned 180 degrees 02062 }//end of while 02063 02064 //should never come here 02065 return false; 02066 02067 /*//should x,y,mass be pointer? 02068 float x = 0.0, y = 0.0, mass = 0.0; 02069 //do we need a counter? 02070 int counter = 0; 02071 itsColorTracker2->setupTracker("Orange", grabImage(BEOSUBCAMDOWN), false); 02072 02073 //referance??? 02074 while(itsColorTracker2->runTracker(10.0, x, y, mass) && counter < 12){ 02075 02076 //if current pos is (0,0) 02077 //color tracker returned pos is (x,y) 02078 //should the sub turn to (x,y) 02079 02080 //float eps=0.01; 02081 //if (x == 0.0){ 02082 // x += eps; 02083 //} 02084 // 02085 //if (y == 0.0){ 02086 // y += eps; 02087 //} 02088 //float Angle = tan(y/x); 02089 //float Dist = sqrt(x*x + y*y); 02090 02091 //turn Angle and goto Dist??? 02092 02093 //++counter; 02094 //NOTE: Down cam weirdness! FIX!! 02095 //if(y < 120){//on left... 02096 // turnRel(-10.0); 02097 //} 02098 //else{//on right... 02099 // turnRel(10.0); 02100 //} 02101 02102 //FIX 02103 02104 //advanceRel(1.5);//follow 02105 02106 //test if goes to the bins 02107 itsColorTracker->setupTracker("White", grabImage(BEOSUBCAMDOWN), false); 02108 if(itsColorTracker->runTracker(500.0, x, y, mass)) { 02109 //stage = 3; 02110 break; 02111 }//end of if itsColorTracker 02112 02113 }//end of if itsColor Tracker2 02114 //itsColorTracker2->setupTracker("Orange", grabImage(BEOSUBCAMDOWN), false); 02115 //stage = 3; 02116 //done following, try to find box 02117 // stage = 0; ///????? 02118 */ 02119 //break; 02120 }//end of FollowPipeLine 02121 02122 int BeoSub::RecognizeBin() 02123 { 02124 //recognize the pattern the bins 02125 //return the id of the bin 02126 02127 return 0; 02128 } 02129 02130 02131 bool BeoSub::TestBin(nub::soft_ref<FrameIstream> gb, int testColor) 02132 { //test if the end is a bin or not 02133 02134 const char* colorArg=NULL; 02135 02136 if(testColor==0) 02137 { 02138 colorArg="White"; 02139 } 02140 else 02141 { 02142 colorArg="Black"; 02143 } 02144 02145 int shapeCounter=0;//counter for the shape recognize loop 02146 02147 // instantiate a model manager (for camera input): 02148 ModelManager manager("Canny Tester"); 02149 // Instantiate our various ModelComponents: 02150 02151 //###################################################### 02152 //comment out in order to avoid camera setup problems 02153 // nub::soft_ref<FrameIstream> 02154 // gb(makeIEEE1394grabber(manager, "cannycam", "cc")); 02155 02156 //GRAB image from camera to be tested 02157 //manager.addSubComponent(gb); 02158 //####################################################### 02159 02160 // Instantiate our various ModelComponents: 02161 nub::soft_ref<BeoSubCanny> test(new BeoSubCanny(manager)); 02162 manager.addSubComponent(test); 02163 02164 02165 //Load in config file for camera FIX: put in a check whether config file exists! 02166 manager.loadConfig("camconfig.pmap"); 02167 02168 manager.start(); 02169 02170 //Test with a circle 02171 rutz::shared_ptr<ShapeModel> shape; 02172 02173 Image< PixRGB<byte> > Img; 02174 02175 double* p; 02176 02177 //Set up shape to be matched 02178 //Recongnize the rectangle bin (or square???) 02179 02180 //rectangle 02181 // p = (double*)calloc(6, sizeof(double)); 02182 //p[1] = 150.0; //Xcenter 02183 // p[2] = 120.0; //Ycenter 02184 // p[4] = 80.0f; // Width 02185 // p[5] = 80.0f; // Height 02186 // p[3] = (3.14159/4.0); //alpha 02187 // shape.reset(new RectangleShape(120.0, p, true)); 02188 02189 02190 //square 02191 p = (double*)calloc(5, sizeof(double)); 02192 p[1] = 150.0; //Xcenter 02193 p[2] = 120.0; //Ycenter 02194 p[3] = 100.0; // Height 02195 p[4] = (3.14159/4.0); // alpha 02196 shape.reset(new SquareShape(100.0, p, true)); 02197 02198 while(1){ 02199 02200 //if not found anything in 5 loops, there is no bin 02201 02202 if(shapeCounter++>5) 02203 { 02204 printf("Cannot find the bin, I give up!\n"); 02205 return false; 02206 } 02207 02208 //Get image to be matched 02209 //TO TEST FROM CAMERA 02210 Img = gb->readRGB(); 02211 02212 shape->setDimensions(p); 02213 02214 //run the matching code, black bin 02215 test->setupCanny(colorArg, Img, true); 02216 02217 //Middle 02218 //p[1] = 150.0; 02219 //p[2] = 120.0; 02220 //shape->setDimensions(p); 02221 bool shapeFound = test->runCanny(shape); 02222 02223 if(!shapeFound){ 02224 //stupid compiler, breaking on stupid warnings 02225 } 02226 02227 //NOTE: Uncomment the following code to test using multiple starting points 02228 02229 if(!shapeFound){ //Upper left 02230 p[1] = 60.0; //Xcenter 02231 p[2] = 180.0; //Ycenter 02232 shape->setDimensions(p); 02233 shapeFound = test->runCanny(shape); 02234 } 02235 if(!shapeFound){ //Upper right 02236 p[1] = 260.0; //Xcenter 02237 p[2] = 180.0; //Ycenter 02238 shape->setDimensions(p); 02239 shapeFound = test->runCanny(shape); 02240 } 02241 if(!shapeFound){ //Lower left 02242 p[1] = 60.0; //Xcenter 02243 p[2] = 60.0; //Ycenter 02244 shape->setDimensions(p); 02245 shapeFound = test->runCanny(shape); 02246 } 02247 if(!shapeFound){ //Lower right 02248 p[1] = 260.0; //Xcenter 02249 p[2] = 60.0; //Ycenter 02250 shape->setDimensions(p); 02251 shapeFound = test->runCanny(shape); 02252 } 02253 02254 if(shapeFound) 02255 {//got the bin, go back!!! 02256 return true; 02257 } 02258 02259 printf("shape not found in loop %i\n",shapeCounter-1); 02260 02261 02262 }//end of while loop 02263 02264 //should never got here!!! 02265 return false; 02266 }//end of TestBin 02267 02268 bool BeoSub::CenterBin() 02269 { 02270 //center the bin for marker dropping 02271 02272 //get the mapping of the connection of bin and the pipeline 02273 //compare the mapping, and approach the bin 02274 02275 ModelManager camManager("ColorTracker Tester"); 02276 02277 nub::soft_ref<FrameIstream> 02278 gb(makeIEEE1394grabber(camManager, "colorcam", "cocam")); 02279 02280 camManager.addSubComponent(gb); 02281 02282 camManager.start(); 02283 02284 // instantiate a model manager for the color tracker module: 02285 ModelManager manager("ColorTracker Tester"); 02286 02287 // Instantiate our various ModelComponents: 02288 nub::soft_ref<ColorTracker> test(new ColorTracker(manager)); 02289 manager.addSubComponent(test); 02290 manager.start(); 02291 02292 Image< PixRGB<byte> > Img; 02293 float x = 320/2, y=240/2; 02294 02295 //arbitary area of mass, need to calibrate!!!! 02296 float mass = 10.0; 02297 02298 float width; 02299 float height; 02300 rutz::shared_ptr<XWindow> wini; 02301 02302 bool xdone=false; 02303 bool ydone=false; 02304 02305 while(!(xdone && ydone)){ 02306 //Get image to be matched 02307 //TO TEST FROM CAMERA 02308 Img = gb->readRGB(); 02309 02310 //track the center of the black bin 02311 #ifndef DEBUG 02312 test->setupTracker("Black", grabImage(BEOSUBCAMDOWN), true); 02313 #else 02314 test->setupTracker("Black", Img /*grabImage(BEOSUBCAMDOWN)*/, true); 02315 #endif 02316 02317 test->runTracker(25.0, x, y, mass); 02318 02319 // wini->drawImage(Img); 02320 width = Img.getWidth(); 02321 02322 //make sure that positive is up-right 02323 x = x - width/2; 02324 02325 height = Img.getHeight(); 02326 y = height/2 - y; 02327 02328 //centering part 02329 //need to change to PID control!!! 02330 //now just x,y tracking! 02331 02332 //center x first 02333 printf("centering x...\n"); 02334 if(fabs(x) > 20) 02335 { 02336 if (y == 0.0) 02337 { 02338 y+=0.01; 02339 } //prevent divide by zero error 02340 02341 printf("turn: %f %f\n",atan(x/y)*180/M_PI, M_PI); 02342 02343 #ifndef DEBUG 02344 turnRel(Angle(atan(x/y) * 180/M_PI)); 02345 #else 02346 if (atan(x/y)*180/M_PI > 0) 02347 { 02348 printf("Turn Right %f\n", fabs(x)); 02349 } 02350 else 02351 { 02352 printf("Turn Left %f\n", fabs(x)); 02353 } 02354 #endif 02355 02356 }//end of if x 02357 xdone=true; 02358 02359 //then center y 02360 02361 printf("x done!\ncentering y.\n"); 02362 if(fabs(y) > 20) 02363 { 02364 if(y>0) 02365 { 02366 02367 #ifndef DEBUG 02368 advanceRel(1.5); 02369 #else 02370 printf("going forward!\n"); 02371 #endif 02372 } 02373 else 02374 { 02375 #ifndef DEBUG 02376 advanceRel(-1.5); 02377 #else 02378 printf("going backward!\n"); 02379 #endif 02380 } 02381 }//end of if y 02382 printf("y done!\n"); 02383 ydone=true; 02384 02385 //!!!need to check if overturned 180 degrees 02386 }//end of while 02387 02388 if(xdone && ydone) 02389 { 02390 printf("alright, center finished!\n"); 02391 return true; 02392 } 02393 else 02394 { 02395 printf("woops, center failed!\n"); 02396 return false; 02397 } 02398 02399 // return true; 02400 }//end of CenterBin 02401 02402 bool BeoSub::DropMarker() 02403 { 02404 //can we see the marker??? 02405 for(int i = 0; i < 6; i++) 02406 { 02407 //############sub control part##################### 02408 //dropMarker(); 02409 } 02410 printf("OK, marker dropped!\n"); 02411 return true; 02412 02413 }//end of DropMarker 02414 02415 02416 bool BeoSub::PassBin() //Go Pass the bin 02417 { 02418 //get the mapping the connection of the bin and the pipeline 02419 //compare the mapping, go through the bin to the next connection 02420 02421 return true; 02422 }//end of PassBin 02423 02424 02425 bool BeoSub::TaskC(){ 02426 02427 int step = 0; 02428 bool notDone = true; 02429 int counter = 0, maxcounter = 15; 02430 //NOTE: should we try shape recognition or saliency here? FIX? 02431 while(notDone){ 02432 switch(step){ 02433 02434 case 0: //LOOK FOR PINGER & OCTAGON AT SAME TIME USING MAPPING 02435 { 02436 if (counter > maxcounter) return false; 02437 02438 //BOTTOM 02439 rutz::shared_ptr<VisualObject> down(new VisualObject("current", "", grabImage(BEOSUBCAMDOWN))); 02440 rutz::shared_ptr<VisualObject> pingerDown = itsDownVODB->getObject("TaskC"); 02441 VisualObjectMatch matchDown(pingerDown, down, VOMA_KDTREEBBF); 02442 02443 //FRONT 02444 advanceRel(-8.0); 02445 diveRel(.3); 02446 rutz::shared_ptr<VisualObject> front(new VisualObject("current", "", grabImage(BEOSUBCAMFRONT))); 02447 rutz::shared_ptr<VisualObject> pingerFront = itsFrontVODB->getObject("TaskC"); 02448 VisualObjectMatch matchFront(pingerFront, front, VOMA_KDTREEBBF); 02449 diveRel(-.3); 02450 advanceRel(8.0); 02451 02452 if(matchDown.checkSIFTaffine() || matchFront.checkSIFTaffine()){ 02453 step = 1; 02454 break; 02455 } 02456 else if(counter < 10){ 02457 //ghetto circle strafe 02458 advanceRel(-1.5); 02459 turnRel(20.0); 02460 counter++; 02461 } 02462 else{ 02463 return false; 02464 } 02465 } 02466 case 1://FINE TUNE POSITION USING MAPPING 02467 { 02468 if (counter > maxcounter) return false; 02469 02470 if(affineSIFT(BEOSUBCAMDOWN, itsVOtaskCdown)){//approach 02471 step = 2; 02472 break; 02473 } 02474 else{ 02475 ++counter; step = 0; 02476 } 02477 } 02478 case 2: //SURFACE! 02479 { 02480 if (counter > maxcounter) return false; 02481 02482 //set ballast to 0 and wait until depth says 0? 02483 //or diveAbs? 02484 //use if statement to say whether dive again or not 02485 diveAbs(-1.0, true); //surface 02486 //if(!last){ 02487 // diveAbs(4.0, true); 02488 // } 02489 notDone = false; 02490 } 02491 } 02492 } 02493 taskCdone = true; 02494 return true; 02495 } 02496 // ###################################################################### 02497 /* So things look consistent in everyone's emacs... */ 02498 /* Local Variables: */ 02499 /* indent-tabs-mode: nil */ 02500 /* End: */