00001 /*!@file AppDevices/locust_videoAndLaser.H record from high speed camera XC and 00002 Hokuyo Laser Range finder and save to disk*/ 00003 00004 // //////////////////////////////////////////////////////////////////// // 00005 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00006 // University of Southern California (USC) and the iLab at USC. // 00007 // See http://iLab.usc.edu for information about this project. // 00008 // //////////////////////////////////////////////////////////////////// // 00009 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00010 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00011 // in Visual Environments, and Applications'' by Christof Koch and // 00012 // Laurent Itti, California Institute of Technology, 2001 (patent // 00013 // pending; application number 09/912,225 filed July 23, 2001; see // 00014 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00015 // //////////////////////////////////////////////////////////////////// // 00016 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00017 // // 00018 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00019 // redistribute it and/or modify it under the terms of the GNU General // 00020 // Public License as published by the Free Software Foundation; either // 00021 // version 2 of the License, or (at your option) any later version. // 00022 // // 00023 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00024 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00025 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00026 // PURPOSE. See the GNU General Public License for more details. // 00027 // // 00028 // You should have received a copy of the GNU General Public License // 00029 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00030 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00031 // Boston, MA 02111-1307 USA. // 00032 // //////////////////////////////////////////////////////////////////// // 00033 // 00034 // Primary maintainer for this file: farhan 00035 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/AppDevices/locust_videoAndLaser.C $ 00036 // $Id: locust_videoAndLaser.C 12962 2010-03-06 02:13:53Z irock $ 00037 // 00038 #include "Component/ModelManager.H" 00039 #include "Devices/RangeFinder.H" 00040 #include "Component/OptionManager.H" 00041 #include "Devices/Serial.H" 00042 #include "Devices/FrameGrabberConfigurator.H" 00043 #include "Devices/DeviceOpts.H" 00044 #include "Image/DrawOps.H" 00045 #include "Image/Image.H" 00046 #include "Image/ShapeOps.H" 00047 #include "Image/CutPaste.H" 00048 #include "Image/ImageCache.H" 00049 #include "Image/Pixels.H" 00050 #include "Image/MathOps.H" 00051 #include "Image/IO.H" 00052 #include "Image/Layout.H" 00053 #include "GUI/SDLdisplay.H" 00054 #include "GUI/GUIOpts.H" 00055 #include "Raster/Raster.H" 00056 #include "Media/FrameSeries.H" 00057 #include "Transport/FrameIstream.H" 00058 #include "Transport/FrameInfo.H" 00059 #include "Util/Timer.H" 00060 #include "Util/log.H" 00061 #include "Util/sformat.H" 00062 #include "Video/RgbConversion.H" // for toVideoYUV422() 00063 #include "Raster/DeBayer.H" // for debayer() 00064 #include "Raster/PlaintextWriter.H" 00065 #include "Robots/LoBot/io/LoLaserRangeFinder.H" 00066 #include <pthread.h> 00067 #include <algorithm> 00068 #include <iterator> 00069 #include <queue> 00070 #include <fstream> 00071 #include <iostream> 00072 00073 using namespace std; 00074 00075 #define MAXSAVETHREAD 4 00076 std::vector<std::string> base; 00077 ImageCache<byte> cacheVideo; 00078 ImageCache<PixRGB<byte> > cacheLaserVid; 00079 std::queue<Image<int> > cacheLaser; 00080 pthread_mutex_t qmutex_cache,qmutex_timer, qmutex_laser; 00081 lobot::LaserRangeFinder* lrf = new lobot::LaserRangeFinder(); 00082 bool haveLaser = false, haveFrames = false; 00083 uint frameNum = 0,laserNum=0; 00084 std::ofstream laserData, metaVideo, metaLaser; 00085 Timer tim; 00086 00087 00088 static void* saveLaser(void *arg) 00089 { 00090 00091 while(1) 00092 { 00093 Image<int> dists; 00094 Image<int>::iterator aptr, stop; 00095 float rad; 00096 int min,max; 00097 long int startAng; 00098 Image<PixRGB<byte> > laserImg(512,512,ZEROS); 00099 uint64 t; 00100 00101 lrf->update(); 00102 dists = lrf->get_distances(); 00103 pthread_mutex_lock(&qmutex_laser); 00104 cacheLaser.push(dists); 00105 haveLaser = true; 00106 laserNum++; 00107 00108 pthread_mutex_unlock(&qmutex_laser); 00109 00110 //write to file 00111 const int w = dists.getWidth(); 00112 const int h = dists.getHeight(); 00113 00114 Image<int>::const_iterator itr = dists.begin(); 00115 for (int y = 0; y < h; ++y) 00116 { 00117 for (int x = 0; x < w; ++x) 00118 { 00119 laserData<<" "<<*itr; 00120 ++itr; 00121 } 00122 laserData<<"\n"; 00123 } 00124 00125 laserData<<"\n"; 00126 00127 t = tim.get(); 00128 metaLaser<<t<<" \t"<<laserNum<<std::endl; 00129 00130 //try drawing here to see if its faster that way 00131 00132 if(!cacheLaser.empty()) 00133 { 00134 dists = cacheLaser.front(); 00135 cacheLaser.pop(); 00136 haveLaser = false; 00137 aptr = dists.beginw(); 00138 stop = dists.endw(); 00139 startAng = -141; 00140 00141 while(aptr!=stop) 00142 { 00143 rad = *aptr++; 00144 //some scaling 00145 getMinMax(dists, min, max); 00146 rad = ((rad - min)/(max-min))*256; 00147 00148 if (rad < 0) 00149 rad =1; 00150 00151 Point2D<int> pt; 00152 pt.i = 256 - (int) (rad*sin(startAng*M_PI/180.0)); 00153 pt.j = 256 - (int) (rad*cos(startAng*M_PI/180.0)); 00154 00155 drawCircle(laserImg, pt, 3, PixRGB<byte>(255,0,0)); 00156 drawLine(laserImg, Point2D<int>(256,256),pt, 00157 PixRGB<byte>(0,255,0)); 00158 startAng = startAng+1; 00159 if(startAng > 140) 00160 startAng = -140; 00161 } 00162 pthread_mutex_lock(&qmutex_laser); 00163 cacheLaserVid.push_back(laserImg); 00164 pthread_mutex_unlock(&qmutex_laser); 00165 } 00166 } 00167 00168 return NULL; 00169 } 00170 00171 static void* saveFrames(void *arg) 00172 { 00173 00174 while(1) 00175 { 00176 00177 Image<byte> savImg; 00178 uint64 t; 00179 haveFrames = false; 00180 pthread_mutex_lock(&qmutex_cache); 00181 if(cacheVideo.size()) 00182 { 00183 savImg = cacheVideo.pop_front(); 00184 frameNum++; 00185 00186 if(cacheVideo.size()) haveFrames = true; 00187 00188 if (savImg.initialized()) 00189 { 00190 const char *b = base[frameNum % (base.size()-3)].c_str(); 00191 Raster::WriteGray(savImg, sformat("%s%06u.pgm", b, frameNum)); 00192 } 00193 t = tim.get(); 00194 metaVideo<<t<<"\t"<<frameNum<<std::endl; 00195 } 00196 pthread_mutex_unlock(&qmutex_cache); 00197 if(haveFrames == false) usleep(1000); 00198 } 00199 00200 return NULL; 00201 } 00202 00203 static int submain(const int argc, char** argv) 00204 { 00205 // Image<PixRGB<byte> > dispImg(640,1024,ZEROS); 00206 Image<byte> ima(640,480,ZEROS); 00207 pthread_t frameStreams[MAXSAVETHREAD], laserStream; 00208 uint64 t; 00209 00210 // instantiate a model manager: 00211 ModelManager manager("locust recording camera + laser"); 00212 00213 nub::ref<OutputFrameSeries> ofs(new OutputFrameSeries(manager)); 00214 manager.addSubComponent(ofs); 00215 00216 nub::soft_ref<FrameGrabberConfigurator> 00217 gbc(new FrameGrabberConfigurator(manager)); 00218 manager.addSubComponent(gbc); 00219 00220 manager.setOptionValString(&OPT_FrameGrabberType, "XC"); 00221 manager.setOptionValString(&OPT_FrameGrabberDims, "640x478"); 00222 00223 // Parse command-line: 00224 if (manager.parseCommandLine(argc, argv, "<basename1> <basename2> <basename3> <basename 4>..<laserdatafile> <metaDataVideo> <metaDataLaser>",4, MAXSAVETHREAD+3) == false) 00225 return(1); 00226 00227 // do post-command-line configs: 00228 nub::soft_ref<FrameIstream> gb = gbc->getFrameGrabber(); 00229 00230 if (gb.isInvalid()) 00231 LFATAL("You need to have XC camera and XClibrary"); 00232 00233 // get the basename: 00234 for (uint i = 0; i < manager.numExtraArgs(); i ++) 00235 base.push_back(manager.getExtraArg(i)); 00236 00237 manager.start(); 00238 00239 //start streaming camera 00240 gb->startStream(); 00241 00242 laserData.open(base[4].c_str(), ios::out | ios::ate); 00243 metaVideo.open(base[5].c_str(), ios::out | ios::ate); 00244 metaLaser.open(base[6].c_str(), ios::out | ios::ate); 00245 00246 for(int ii = 0; ii<(int)base.size()-3; ii++) 00247 pthread_create(frameStreams+ii, NULL, &saveFrames, (void *)NULL); 00248 00249 //Laser Range finder setup 00250 //declare a new laserRangeFinder object 00251 int rc2 = pthread_create(&laserStream, NULL, &saveLaser, NULL); 00252 if(rc2) 00253 { 00254 LFATAL("cannot create thread"); 00255 exit(-1); 00256 } 00257 00258 Image<PixRGB<byte> > laserImg(512,512,ZEROS); 00259 00260 while(1) 00261 { 00262 //read from grabber 00263 ima = gb->readGray(); 00264 laserImg.clear(); 00265 00266 pthread_mutex_lock(&qmutex_cache); 00267 cacheVideo.push_back(ima); 00268 pthread_mutex_unlock(&qmutex_cache); 00269 00270 pthread_mutex_lock(&qmutex_laser); 00271 if(cacheLaserVid.size()) 00272 laserImg = cacheLaserVid.pop_front(); 00273 pthread_mutex_unlock(&qmutex_laser); 00274 00275 Image<PixRGB<byte> > imgByte = ima; 00276 Layout<PixRGB<byte> > dispLayout(imgByte); 00277 dispLayout = vcat(dispLayout,laserImg); 00278 //inplacePaste(dispImg, imgByte, Point2D<int>(0,0)); 00279 //inplacePaste(dispImg, laserImg, Point2D<int>(0,490)); 00280 00281 ofs->writeRgbLayout(dispLayout,"Output",FrameInfo("output",SRC_POS)); 00282 00283 t = tim.get(); 00284 if(t >5000) 00285 { 00286 laserData.close(); 00287 metaVideo.close(); 00288 metaLaser.close(); 00289 manager.stop(); 00290 exit(1); 00291 } 00292 } 00293 00294 laserData.close(); 00295 metaVideo.close(); 00296 metaLaser.close(); 00297 manager.stop(); 00298 } 00299 00300 00301 00302 extern "C" int main(const int argc, char** argv) 00303 { 00304 try 00305 { 00306 return submain(argc, argv); 00307 } 00308 catch (...) 00309 { 00310 REPORT_CURRENT_EXCEPTION; 00311 } 00312 00313 return 1; 00314 } 00315 00316 // ###################################################################### 00317 /* So things look consistent in everyone's emacs... */ 00318 /* Local Variables: */ 00319 /* indent-tabs-mode: nil */ 00320 /* End: */ 00321 00322