00001 /*!@file SeaBee/test-FollowPipe.C test submarine pipe following */ 00002 // //////////////////////////////////////////////////////////////////// // 00003 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00004 // University of Southern California (USC) and the iLab at USC. // 00005 // See http://iLab.usc.edu for information about this project. // 00006 // //////////////////////////////////////////////////////////////////// // 00007 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00008 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00009 // in Visual Environments, and Applications'' by Christof Koch and // 00010 // Laurent Itti, California Institute of Technology, 2001 (patent // 00011 // pending; application number 09/912,225 filed July 23, 2001; see // 00012 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00013 // //////////////////////////////////////////////////////////////////// // 00014 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00015 // // 00016 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00017 // redistribute it and/or modify it under the terms of the GNU General // 00018 // Public License as published by the Free Software Foundation; either // 00019 // version 2 of the License, or (at your option) any later version. // 00020 // // 00021 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00022 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00023 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00024 // PURPOSE. See the GNU General Public License for more details. // 00025 // // 00026 // You should have received a copy of the GNU General Public License // 00027 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00028 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00029 // Boston, MA 02111-1307 USA. // 00030 // //////////////////////////////////////////////////////////////////// // 00031 // 00032 // Primary maintainer for this file: Michael Montalbo <montalbo@usc.edu> 00033 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/SeaBee/test-FollowPipe.C $ 00034 // $Id: test-FollowPipe.C 10794 2009-02-08 06:21:09Z itti $ 00035 00036 #include "Component/ModelManager.H" 00037 00038 #include "Media/FrameSeries.H" 00039 #include "Transport/FrameIstream.H" 00040 #include "Media/MediaOpts.H" 00041 00042 #include "Image/Image.H" 00043 #include "Image/Pixels.H" 00044 #include "Raster/Raster.H" 00045 #include "Image/CutPaste.H" 00046 00047 #include "BeoSub/IsolateColor.H" 00048 #include "Image/DrawOps.H" 00049 #include "Image/ColorOps.H" 00050 00051 #include "GUI/XWinManaged.H" 00052 00053 #include "SeaBee/PipeRecognizer.H" 00054 #include "BeoSub/BeoSubBin.H" 00055 #include "SeaBee/BinRecognizer.H" 00056 00057 00058 #include "SeaBee/SubController.H" 00059 00060 #include "SeaBee/SubGUI.H" 00061 00062 //whether or not to run the simulator 00063 #define SIM_MODE true 00064 00065 #define CREATE_MOVIE true 00066 00067 int main(int argc, char* argv[]) 00068 { 00069 00070 MYLOGVERB = LOG_INFO; 00071 00072 ModelManager manager("PipeRecognizer Tester"); 00073 00074 00075 nub::soft_ref<InputFrameSeries> ifs; 00076 #if SIM_MODE == false 00077 ifs.reset(new InputFrameSeries(manager)); 00078 manager.addSubComponent(ifs); 00079 #endif 00080 00081 nub::soft_ref<OutputFrameSeries> ofs(new OutputFrameSeries(manager)); 00082 manager.addSubComponent(ofs); 00083 00084 00085 nub::soft_ref<SubGUI> subGUI(new SubGUI(manager)); 00086 manager.addSubComponent(subGUI); 00087 00088 nub::soft_ref<SubController> subController(new SubController(manager, "SubController", "SubController", SIM_MODE)); 00089 manager.addSubComponent(subController); 00090 00091 manager.exportOptions(MC_RECURSE); 00092 00093 // Parse command-line: 00094 if (manager.parseCommandLine(argc, argv, 00095 "[image {*.ppm}]", 00096 0, 1) 00097 == false) return(1); 00098 00099 int w, h; 00100 00101 #if SIM_MODE == false 00102 w = ifs->getWidth(); 00103 h = ifs->getHeight(); 00104 #else 00105 w = 320; 00106 h = 240; 00107 #endif 00108 00109 std::string dims = convertToString(Dims(w, h)); 00110 LINFO("image size: [%dx%d]", w, h); 00111 manager.setOptionValString(&OPT_InputFrameDims, dims); 00112 00113 manager.setModelParamVal("InputFrameDims", Dims(w, h), 00114 MC_RECURSE | MC_IGNORE_MISSING); 00115 00116 manager.start(); 00117 00118 bool goforever = true; 00119 00120 rutz::shared_ptr<XWinManaged> dispWin; 00121 dispWin.reset(new XWinManaged(Dims(w*2,h*2), 0, 0, "Pipe Recognizer Display")); 00122 00123 rutz::shared_ptr<PipeRecognizer> pipeRecognizer(new PipeRecognizer()); 00124 //rutz::shared_ptr<BeoSubBin> binRecognizer(new BeoSubBin()); 00125 rutz::shared_ptr<Point2D<int> > pipeCenter(new Point2D<int>(0,0)); 00126 00127 rutz::shared_ptr<BinRecognizer> binRecognizer(new BinRecognizer()); 00128 rutz::shared_ptr<Point2D<int> > binCenter(new Point2D<int>(0,0)); 00129 00130 00131 Point2D<int> projPoint(Point2D<int>(0,0)); 00132 // Point2D<int> projPoint2(Point2D<int>(0,0)); 00133 00134 rutz::shared_ptr<double> pipeAngle(new double); 00135 // rutz::shared_ptr<double> pipeAngleSmooth(new double); 00136 00137 00138 subGUI->startThread(ofs); 00139 subGUI->setupGUI(subController.get(), true); 00140 subGUI->addMeter(subController->getIntPressurePtr(), 00141 "Int Pressure", 500, PixRGB<byte>(255, 0, 0)); 00142 subGUI->addMeter(subController->getHeadingPtr(), 00143 "Heading", 360, PixRGB<byte>(192, 255, 0)); 00144 subGUI->addMeter(subController->getPitchPtr(), 00145 "Pitch", 256, PixRGB<byte>(192, 255, 0)); 00146 subGUI->addMeter(subController->getRollPtr(), 00147 "Roll", 256, PixRGB<byte>(192, 255, 0)); 00148 subGUI->addMeter(subController->getDepthPtr(), 00149 "Depth", 300, PixRGB<byte>(192, 255, 0)); 00150 00151 subGUI->addMeter(subController->getThruster_Up_Left_Ptr(), 00152 "Motor_Up_Left", -100, PixRGB<byte>(0, 255, 0)); 00153 subGUI->addMeter(subController->getThruster_Up_Right_Ptr(), 00154 "Motor_Up_Right", -100, PixRGB<byte>(0, 255, 0)); 00155 subGUI->addMeter(subController->getThruster_Up_Back_Ptr(), 00156 "Motor_Up_Back", -100, PixRGB<byte>(0, 255, 0)); 00157 subGUI->addMeter(subController->getThruster_Fwd_Left_Ptr(), 00158 "Motor_Fwd_Left", -100, PixRGB<byte>(0, 255, 0)); 00159 subGUI->addMeter(subController->getThruster_Fwd_Right_Ptr(), 00160 "Motor_Fwd_Right", -100, PixRGB<byte>(0, 255, 0)); 00161 00162 00163 subGUI->addImage(subController->getSubImagePtr()); 00164 subGUI->addImage(subController->getPIDImagePtr()); 00165 00166 // input and output images 00167 00168 rutz::shared_ptr<Image< PixRGB<byte> > > img; 00169 img.reset(new Image< PixRGB<byte> >(w,h, ZEROS)); 00170 00171 // Image< PixRGB<byte> > img(w,h, ZEROS); 00172 rutz::shared_ptr<Image<byte> > orangeIsoImage(new Image<byte>(w,h, ZEROS)); 00173 Image< PixRGB<byte> > dispImg(w*2,h*2, ZEROS); 00174 00175 rutz::shared_ptr<Image< PixRGB<byte> > > pipelineOutputImg(new Image<PixRGB<byte> >(w,h, ZEROS)); 00176 rutz::shared_ptr<Image< PixRGB<byte> > > outputImg(new Image<PixRGB<byte> >(w,h, ZEROS)); 00177 00178 00179 00180 Point2D<int> centerOfMass; 00181 std::vector<Point2D<int> > avgCenter; 00182 00183 00184 #if SIM_MODE == true 00185 uint staleCount = 0; 00186 #endif 00187 00188 while(goforever) 00189 { 00190 // subController->runSimLoop(); 00191 orangeIsoImage.reset(new Image<byte>(w,h, ZEROS)); 00192 outputImg.reset(new Image<PixRGB<byte> >(w,h, ZEROS)); 00193 00194 #if SIM_MODE == false 00195 ifs->updateNext(); *img = ifs->readRGB(); 00196 if(!img->initialized()) {Raster::waitForKey(); break; } 00197 #else 00198 //get sim image from bottom camera 00199 *img = subController->getImage(2); 00200 #endif 00201 00202 inplacePaste(dispImg, *img, Point2D<int>(0,0)); 00203 00204 orangeIsoImage->resize(w,h); 00205 isolateOrange(*img, *orangeIsoImage); 00206 00207 inplacePaste(dispImg, toRGB(*orangeIsoImage), Point2D<int>(w,0)); 00208 00209 //Perform PipeLine Recognition 00210 //get all the orange lines in the image 00211 std::vector<LineSegment2D> pipelines = pipeRecognizer->getPipeLocation(orangeIsoImage, 00212 pipelineOutputImg, 00213 PipeRecognizer::HOUGH); 00214 00215 00216 #if SIM_MODE == true 00217 00218 binRecognizer->getBinLocation(img, 00219 outputImg, 00220 BinRecognizer::CONTOUR, 00221 binCenter, 00222 staleCount); 00223 00224 drawCircle(*outputImg, *binCenter, 2, PixRGB <byte> (255, 0,0), 3); 00225 #endif 00226 inplacePaste(dispImg, *outputImg, Point2D<int>(w,h)); 00227 00228 00229 dispWin->drawImage(dispImg, 0, 0); 00230 00231 00232 // if(binCenter->i > 0 && binCenter->j > 0 && staleCount < 25)// && binCenter->i < 320 && binCenter->j < 240) 00233 // { 00234 // int xErr = (binCenter->i-(160)); 00235 // int yErr = (binCenter->j-(120)); 00236 // int desiredHeading = (int)(xErr*-1); 00237 00238 // LINFO("xErr:%d,yErr:%d",binCenter->i,binCenter->j); 00239 00240 // if(xErr > .15 * 320) 00241 // { 00242 // subController->setHeading(subController->getHeading() 00243 // + desiredHeading); 00244 // } 00245 // else if(xErr < .15 * 320) 00246 // { 00247 // subController->setHeading(subController->getHeading()); 00248 // subController->setSpeed(50); 00249 // } 00250 // else if(yErr < .15 * 240) 00251 // { 00252 // subController->setSpeed(0); 00253 // } 00254 // } 00255 // else 00256 00257 int minY = -1; //minimum midpoint y coordinate found 00258 int followLineIndex = -1; //index of pipeline with minimum y coordinate 00259 00260 //iterates through pipelines and finds the topmost one in the image 00261 for(uint i = 0; i < pipelines.size(); i++) 00262 { 00263 LineSegment2D pipeline = pipelines[i]; 00264 Point2D<int> midpoint = (pipeline.point1() + pipeline.point2())/2; 00265 00266 if(midpoint.j < minY || minY == -1) 00267 { 00268 minY = midpoint.j; 00269 followLineIndex = i; 00270 } 00271 } 00272 00273 //if we found a pipeline 00274 if(followLineIndex != -1) 00275 { 00276 00277 LineSegment2D followLine = pipelines[followLineIndex]; 00278 Point2D<int> midpoint = (followLine.point1() + followLine.point2())/2; 00279 00280 projPoint.i = (int)(midpoint.i+30*cos(followLine.angle())); 00281 projPoint.j = (int)(midpoint.j+30*sin(followLine.angle())); 00282 00283 drawLine(*pipelineOutputImg, midpoint, projPoint, PixRGB <byte> (255, 255,0), 3); 00284 00285 00286 inplacePaste(dispImg, *pipelineOutputImg, Point2D<int>(0,h)); 00287 00288 00289 int desiredHeading = ((int)((followLine.angle()) * 180 / M_PI)); 00290 00291 if(desiredHeading > 360) desiredHeading = desiredHeading - 360; 00292 if(desiredHeading < 0) desiredHeading = desiredHeading + 360; 00293 00294 int absHeading = (subController->getHeading() + desiredHeading) % 360; 00295 subController->setHeading(absHeading); 00296 00297 //Wait for new heading to get to heading 00298 if(!((desiredHeading >= 270 && desiredHeading <= 275) || (desiredHeading <= 90 && desiredHeading >= 85))) 00299 { 00300 usleep(100000); 00301 } 00302 else 00303 { 00304 subController->setHeading(subController->getHeading()); 00305 subController->setSpeed(75); 00306 } 00307 00308 } 00309 else 00310 { 00311 subController->setHeading(subController->getHeading()); 00312 } 00313 } 00314 00315 // get ready to terminate: 00316 manager.stop(); 00317 return 0; 00318 } 00319 00320 // ###################################################################### 00321 /* So things look consistent in everyone's emacs... */ 00322 /* Local Variables: */ 00323 /* indent-tabs-mode: nil */ 00324 /* End: */