00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
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"
00063 #include "Raster/DeBayer.H"
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
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
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
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
00206 Image<byte> ima(640,480,ZEROS);
00207 pthread_t frameStreams[MAXSAVETHREAD], laserStream;
00208 uint64 t;
00209
00210
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
00224 if (manager.parseCommandLine(argc, argv, "<basename1> <basename2> <basename3> <basename 4>..<laserdatafile> <metaDataVideo> <metaDataLaser>",4, MAXSAVETHREAD+3) == false)
00225 return(1);
00226
00227
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
00234 for (uint i = 0; i < manager.numExtraArgs(); i ++)
00235 base.push_back(manager.getExtraArg(i));
00236
00237 manager.start();
00238
00239
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
00250
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
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
00279
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
00318
00319
00320
00321
00322