iCub-main
Loading...
Searching...
No Matches
main.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010 RobotCub Consortium, European Commission FP6 Project IST-004370
3 * Authors: Carlo Ciliberto, Ugo Pattacini
4 * email: carlo.ciliberto@iit.it, ugo.pattacini@iit.it
5 * website: www.robotcub.org
6 * Permission is granted to copy, distribute, and/or modify this program
7 * under the terms of the GNU General Public License, version 2 or any
8 * later version published by the Free Software Foundation.
9 *
10 * A copy of the license can be found at
11 * http://www.robotcub.org/icub/license/gpl.txt
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16 * Public License for more details
17*/
18
19#include <cmath>
20#include <string>
21#include <set>
22#include <vector>
23#include <deque>
24#include <algorithm>
25#include <utility>
26#include <iostream>
27
28#include <opencv2/opencv.hpp>
29
30#include <yarp/os/all.h>
31#include <yarp/sig/all.h>
32#include <yarp/cv/Cv.h>
33
34// in BGR format
35#define NODE_OFF Scalar(0,0,255)
36#define NODE_ON Scalar(0,255,0)
37
38using namespace std;
39using namespace cv;
40using namespace yarp::os;
41using namespace yarp::sig;
42using namespace yarp::cv;
43
44
45/************************************************************************/
46class Blob
47{
48public:
49 Point centroid;
50 int size;
51
52 /************************************************************************/
54 {
55 centroid.x=0;
56 centroid.y=0;
57 size=0;
58 }
59};
60
61
62/************************************************************************/
63class ProcessThread : public Thread
64{
65protected:
66 ResourceFinder &rf;
67
68 string name;
74 double recogThres;
82 int nodesX;
83 int nodesY;
84
85 ImageOf<PixelMono> imgMonoIn;
86 ImageOf<PixelMono> imgMonoPrev;
87 vector<Mat> pyrPrev;
88 vector<Mat> pyrCurr;
89
90 vector<Point2f> nodesPrev;
91 vector<Point2f> nodesCurr;
92 vector<uchar> featuresFound;
93 vector<float> featuresErrors;
94 vector<int> nodesPersistence;
95
97 deque<Blob> blobSortedList;
98
99 BufferedPort<ImageOf<PixelBgr>> inPort;
100 BufferedPort<ImageOf<PixelBgr>> outPort;
101 BufferedPort<ImageOf<PixelMono>> optPort;
102 BufferedPort<ImageOf<PixelBgr>> cropPort;
103 BufferedPort<Bottle> nodesPort;
104 BufferedPort<Bottle> blobsPort;
105
106public:
107 /************************************************************************/
108 ProcessThread(ResourceFinder &_rf) : rf(_rf) { }
109
110 /************************************************************************/
112 {
113 name=rf.check("name",Value("motionCUT")).asString();
114 coverXratio=rf.check("coverXratio",Value(0.75)).asFloat64();
115 coverYratio=rf.check("coverYratio",Value(0.75)).asFloat64();
116 nodesStep=rf.check("nodesStep",Value(6)).asInt32();
117 winSize=rf.check("winSize",Value(15)).asInt32();
118 recogThres=rf.check("recogThres",Value(0.01)).asFloat64();
119 adjNodesThres=rf.check("adjNodesThres",Value(4)).asInt32();
120 blobMinSizeThres=rf.check("blobMinSizeThres",Value(10)).asInt32();
121 framesPersistence=rf.check("framesPersistence",Value(3)).asInt32();
122 verbosity=rf.check("verbosity");
123
124 cropSize=0;
125 if (rf.check("cropSize"))
126 {
127 Value &vCropSize=rf.find("cropSize");
128 if (!vCropSize.isString())
129 cropSize=vCropSize.asInt32();
130 }
131
133 inhibition=false;
134
135 // thresholding
136 coverXratio=std::min(coverXratio,1.0);
137 coverYratio=std::min(coverYratio,1.0);
138
139 inPort.open("/"+name+"/img:i");
140 outPort.open("/"+name+"/img:o");
141 optPort.open("/"+name+"/opt:o");
142 nodesPort.open("/"+name+"/nodes:o");
143 blobsPort.open("/"+name+"/blobs:o");
144 cropPort.open("/"+name+"/crop:o");
145
147
148 return true;
149 }
150
151 /************************************************************************/
152 void afterStart(bool s)
153 {
154 if (s)
155 {
156 yInfo("Process started successfully");
157 yInfo("Using ...");
158 yInfo("name = %s",name.c_str());
159 yInfo("coverXratio = %g",coverXratio);
160 yInfo("coverYratio = %g",coverYratio);
161 yInfo("nodesStep = %d",nodesStep);
162 yInfo("winSize = %d",winSize);
163 yInfo("recogThres = %g",recogThres);
164 yInfo("recogThresAbs = %g",recogThresAbs);
165 yInfo("adjNodesThres = %d",adjNodesThres);
166 yInfo("blobMinSizeThres = %d",blobMinSizeThres);
167 yInfo("framesPersistence = %d",framesPersistence);
168 if (cropSize>0)
169 yInfo("cropSize = %d",cropSize);
170 else
171 yInfo("cropSize = auto");
172 yInfo("verbosity = %s",verbosity?"on":"off");
173 }
174 else
175 yError("Process did not start");
176 }
177
178 /************************************************************************/
179 void run()
180 {
181 double latch_t, dt0, dt1, dt2;
182
183 while (!isStopping())
184 {
185 // acquire new image
186 ImageOf<PixelBgr> *pImgBgrIn=inPort.read(true);
187 if (isStopping() || (pImgBgrIn==NULL))
188 break;
189
190 // get the envelope from the image
191 Stamp stamp;
192 inPort.getEnvelope(stamp);
193
194 double t0=Time::now();
195
196 // consistency check
197 if (firstConsistencyCheck || (pImgBgrIn->width()!=imgMonoIn.width()) ||
198 (pImgBgrIn->height()!=imgMonoIn.height()))
199 {
201
202 imgMonoIn.resize(*pImgBgrIn);
203 imgMonoPrev.resize(*pImgBgrIn);
204
205 int min_x=(int)(((1.0-coverXratio)/2.0)*imgMonoIn.width());
206 int min_y=(int)(((1.0-coverYratio)/2.0)*imgMonoIn.height());
207
208 nodesX=((int)imgMonoIn.width()-2*min_x)/nodesStep+1;
209 nodesY=((int)imgMonoIn.height()-2*min_y)/nodesStep+1;
210
211 int nodesNum=nodesX*nodesY;
212 nodesPrev.assign(nodesNum,Point2f(0.0f,0.0f));
213 nodesCurr.assign(nodesNum,Point2f(0.0f,0.0f));
214 featuresFound.assign(nodesNum,0);
215 featuresErrors.assign(nodesNum,0.0f);
216 nodesPersistence.assign(nodesNum,0);
217
218 // populate grid
219 size_t cnt=0;
220 for (int y=min_y; y<=(imgMonoIn.height()-min_y); y+=nodesStep)
221 for (int x=min_x; x<=(imgMonoIn.width()-min_x); x+=nodesStep)
222 nodesPrev[cnt++]=Point2f((float)x,(float)y);
223
224 // convert to gray-scale
225 cvtColor(toCvMat(*pImgBgrIn),toCvMat(imgMonoPrev),CV_BGR2GRAY);
226
227 if (verbosity)
228 {
229 // log message
230 yInfo("Detected image of size %zdx%zd; using %dx%d=%d nodes; populated %zd nodes",
231 imgMonoIn.width(),imgMonoIn.height(),nodesX,nodesY,nodesNum,cnt);
232 }
233
234 // skip to the next cycle
235 continue;
236 }
237
238 // convert the input image to gray-scale
239 cvtColor(toCvMat(*pImgBgrIn),toCvMat(imgMonoIn),CV_BGR2GRAY);
240
241 // copy input image into output image
242 ImageOf<PixelBgr> imgBgrOut=*pImgBgrIn;
243 Mat imgBgrOutMat=toCvMat(imgBgrOut);
244
245 // get optFlow image
246 ImageOf<PixelMono> imgMonoOpt;
247 imgMonoOpt.resize(imgBgrOut);
248 imgMonoOpt.zero();
249 Mat imgMonoOptMat=toCvMat(imgMonoOpt);
250
251 // declare output bottles
252 Bottle nodesBottle;
253 Bottle blobsBottle;
254
255 Bottle &nodesStepBottle=nodesBottle.addList();
256 nodesStepBottle.addString("nodesStep");
257 nodesStepBottle.addInt32(nodesStep);
258
259 // purge the content of variables
260 activeNodesIndexSet.clear();
261 blobSortedList.clear();
262
263 // compute optical flow
264 latch_t=Time::now();
265 constexpr int maxLevel=5;
266 Size ws(winSize,winSize);
267 buildOpticalFlowPyramid(toCvMat(imgMonoPrev),pyrPrev,ws,maxLevel);
268 buildOpticalFlowPyramid(toCvMat(imgMonoIn),pyrCurr,ws,maxLevel);
269 calcOpticalFlowPyrLK(pyrPrev,pyrCurr,nodesPrev,nodesCurr,
270 featuresFound,featuresErrors,ws,maxLevel,
271 TermCriteria(TermCriteria::COUNT+TermCriteria::EPS,30,0.3));
272 dt0=Time::now()-latch_t;
273
274 // assign status to the grid nodes
275 latch_t=Time::now();
276 for (size_t i=0; i<nodesPrev.size(); i++)
277 {
278 bool persistentNode=false;
279 Point node=Point((int)nodesPrev[i].x,(int)nodesPrev[i].y);
280
281 // handle the node persistence
282 if (!inhibition && (nodesPersistence[i]!=0))
283 {
284 circle(imgBgrOutMat,node,1,NODE_ON,2);
285 circle(imgMonoOptMat,node,1,Scalar(255),2);
286
287 Bottle &nodeBottle=nodesBottle.addList();
288 nodeBottle.addInt32((int)nodesPrev[i].x);
289 nodeBottle.addInt32((int)nodesPrev[i].y);
290
291 // update the active nodes set
292 activeNodesIndexSet.insert((int)i);
293
294 nodesPersistence[i]--;
295 persistentNode=true;
296 }
297 else
298 circle(imgBgrOutMat,node,1,NODE_OFF,1);
299
300 // do not consider the border nodes and skip if inhibition is on
301 int row=i%nodesX;
302 bool skip=inhibition || (i<nodesX) || (i>=(nodesPrev.size()-nodesX)) || (row==0) || (row==(nodesX-1));
303
304 if (!skip && (featuresFound[i]!=0) && (featuresErrors[i]>recogThresAbs))
305 {
306 // count the neighbour nodes that are ON
307 // start from -1 to avoid counting the current node
308 int cntAdjNodesOn=-1;
309
310 // scroll per lines
311 for (int j=i-nodesX; j<=(i+nodesX); j+=nodesX)
312 for (int k=j-1; k<=(j+1); k++)
313 cntAdjNodesOn+=(int)((featuresFound[k]!=0)&&(featuresErrors[k]>recogThresAbs));
314
315 // highlight independent moving node if over threhold
316 if (cntAdjNodesOn>=adjNodesThres)
317 {
318 // init the node persistence timeout
320
321 // update only if the node was not persistent
322 if (!persistentNode)
323 {
324 circle(imgBgrOutMat,node,1,NODE_ON,2);
325 circle(imgMonoOptMat,node,1,Scalar(255),2);
326
327 Bottle &nodeBottle=nodesBottle.addList();
328 nodeBottle.addInt32((int)nodesPrev[i].x);
329 nodeBottle.addInt32((int)nodesPrev[i].y);
330
331 // update the active nodes set
332 activeNodesIndexSet.insert((int)i);
333 }
334 }
335 }
336 }
337 dt1=Time::now()-latch_t;
338
339 latch_t=Time::now();
340 findBlobs();
341
342 // prepare the blobs output list and draw their
343 // centroids location
344 for (int i=0; i<(int)blobSortedList.size(); i++)
345 {
346 Blob &blob=blobSortedList[i];
347 int blueLev=255-((100*i)%255);
348 int redLev=(100*i)%255;
349
350 Point centroid=Point(blob.centroid.x,blob.centroid.y);
351
352 Bottle &blobBottle=blobsBottle.addList();
353 blobBottle.addInt32(centroid.x);
354 blobBottle.addInt32(centroid.y);
355 blobBottle.addInt32(blob.size);
356
357 circle(imgBgrOutMat,centroid,4,Scalar(blueLev,0,redLev),3);
358 }
359 dt2=Time::now()-latch_t;
360
361 // send out images, propagating the time-stamp
362 if (outPort.getOutputCount()>0)
363 {
364 outPort.prepare()=imgBgrOut;
365 outPort.setEnvelope(stamp);
366 outPort.write();
367 }
368
369 if (optPort.getOutputCount()>0)
370 {
371 optPort.prepare()=imgMonoOpt;
372 optPort.setEnvelope(stamp);
373 optPort.write();
374 }
375
376 // send out data bottles, propagating the time-stamp
377 if ((nodesPort.getOutputCount()>0) && (nodesBottle.size()>1))
378 {
379 nodesPort.prepare()=nodesBottle;
380 nodesPort.setEnvelope(stamp);
381 nodesPort.write();
382 }
383
384 if ((blobsPort.getOutputCount()>0) && (blobsBottle.size()>0))
385 {
386 blobsPort.prepare()=blobsBottle;
387 blobsPort.setEnvelope(stamp);
388 blobsPort.write();
389 }
390
391 if ((cropPort.getOutputCount()>0) && (blobsBottle.size()>0))
392 {
393 Bottle &blob=*blobsBottle.get(0).asList();
394 int x=blob.get(0).asInt32();
395 int y=blob.get(1).asInt32();
396 int d=(cropSize>0)?cropSize:(int)(nodesStep*sqrt((double)blob.get(2).asInt32()));
397 int d2=d>>1;
398
399 Point tl=Point(std::max(x-d2,0),std::max(y-d2,0));
400 Point br=Point(std::min(x+d2,(int)pImgBgrIn->width()-1),std::min(y+d2,(int)pImgBgrIn->height()-1));
401 Point cropSize=Point(br.x-tl.x,br.y-tl.y);
402
403 ImageOf<PixelBgr> &cropImg=cropPort.prepare();
404 cropImg.resize(cropSize.x,cropSize.y);
405 toCvMat(*pImgBgrIn)(Rect(tl.x,tl.y,cropSize.x,cropSize.y)).copyTo(toCvMat(cropImg));
406
407 cropPort.setEnvelope(stamp);
408 cropPort.write();
409 }
410
411 // save data for next cycle
413
414 double t1=Time::now();
415 if (verbosity)
416 {
417 // dump statistics
418 yInfo("cycle timing [ms]: optflow(%g), colorgrid(%g), blobdetection(%g), overall(%g)",
419 1000.0*dt0,1000.0*dt1,1000.0*dt2,1000.0*(t1-t0));
420 }
421 }
422 }
423
424 /************************************************************************/
425 void onStop()
426 {
427 inPort.interrupt();
428 }
429
430 /************************************************************************/
432 {
433 inPort.close();
434 outPort.close();
435 optPort.close();
436 nodesPort.close();
437 blobsPort.close();
438 cropPort.close();
439 }
440
441 /************************************************************************/
442 string getName()
443 {
444 return name;
445 }
446
447 /************************************************************************/
449 {
450 // iterate until the set is empty
451 while (activeNodesIndexSet.size())
452 {
453 Blob blob;
454
455 // the nodes connected to the current one
456 // will be removed from the list
457 floodFill(*(activeNodesIndexSet.begin()),&blob);
458
459 // update centroid
460 blob.centroid.x/=blob.size;
461 blob.centroid.y/=blob.size;
462
463 // insert iff the blob is big enough
464 if (blob.size>blobMinSizeThres)
465 insertBlob(blob);
466 }
467 }
468
469 /************************************************************************/
470 void floodFill(const int i, Blob *pBlob)
471 {
472 auto el=activeNodesIndexSet.find(i);
473 if ((el!=activeNodesIndexSet.end()) && (pBlob!=NULL))
474 {
475 // update blob
476 pBlob->centroid.x+=(int)nodesPrev[i].x;
477 pBlob->centroid.y+=(int)nodesPrev[i].y;
478 pBlob->size++;
479
480 // remove element from the set
481 activeNodesIndexSet.erase(el);
482
483 // perform recursive exploration
484 for (int j=i-nodesX; j<=(i+nodesX); j+=nodesX)
485 for (int k=j-1; k<=(j+1); k++)
486 if (k!=i)
487 floodFill(k,pBlob);
488 }
489 }
490
491 /************************************************************************/
492 void insertBlob(const Blob &blob)
493 {
494 // insert the blob keeping the decreasing order of the list wrt the size attribute
495 for (deque<Blob>::iterator el=blobSortedList.begin(); el!=blobSortedList.end(); el++)
496 {
497 if (el->size<blob.size)
498 {
499 blobSortedList.insert(el,blob);
500 return;
501 }
502 }
503
504 // reaching this point means that
505 // we have to append the blob
506 blobSortedList.push_back(blob);
507 }
508
509 /************************************************************************/
510 bool execReq(const Bottle &req, Bottle &reply)
511 {
512 if (req.size())
513 {
514 string cmd=req.get(0).asString();
515
516 if (cmd=="set")
517 {
518 if (req.size()<3)
519 return false;
520
521 string subcmd=req.get(1).asString();
522
523 if (subcmd=="winSize")
524 {
525 winSize=req.get(2).asInt32();
526 reply.addString("ack");
527 }
528 else if (subcmd=="recogThres")
529 {
530 recogThres=req.get(2).asFloat64();
532 reply.addString("ack");
533 }
534 else if (subcmd=="adjNodesThres")
535 {
536 adjNodesThres=req.get(2).asInt32();
537 reply.addString("ack");
538 }
539 else if (subcmd=="blobMinSizeThres")
540 {
541 blobMinSizeThres=req.get(2).asInt32();
542 reply.addString("ack");
543 }
544 else if (subcmd=="framesPersistence")
545 {
546 framesPersistence=req.get(2).asInt32();
547 reply.addString("ack");
548 }
549 else if (subcmd=="cropSize")
550 {
551 Value &vCropSize=req.get(2);
552 if (!vCropSize.isString())
553 cropSize=vCropSize.asInt32();
554 else
555 cropSize=0;
556
557 reply.addString("ack");
558 }
559 else if (subcmd=="verbosity")
560 {
561 verbosity=req.get(2).asString()=="on";
562 reply.addString("ack");
563 }
564 else if (subcmd=="inhibition")
565 {
566 inhibition=req.get(2).asString()=="on";
567 reply.addString("ack");
568 }
569 else
570 return false;
571 }
572 else if (cmd=="get")
573 {
574 if (req.size()<2)
575 return false;
576
577 string subcmd=req.get(1).asString();
578
579 if (subcmd=="winSize")
580 reply.addInt32(winSize);
581 else if (subcmd=="recogThres")
582 reply.addFloat64(recogThres);
583 else if (subcmd=="adjNodesThres")
584 reply.addInt32(adjNodesThres);
585 else if (subcmd=="blobMinSizeThres")
586 reply.addInt32(blobMinSizeThres);
587 else if (subcmd=="framesPersistence")
588 reply.addInt32(framesPersistence);
589 else if (subcmd=="cropSize")
590 {
591 if (cropSize>0)
592 reply.addInt32(cropSize);
593 else
594 reply.addString("auto");
595 }
596 else if (subcmd=="verbosity")
597 reply.addString(verbosity?"on":"off");
598 else if (subcmd=="inhibition")
599 reply.addString(inhibition?"on":"off");
600 else
601 return false;
602 }
603 else
604 return false;
605
606 return true;
607 }
608 else
609 return false;
610 }
611};
612
613
614/************************************************************************/
615class ProcessModule: public RFModule
616{
617private:
618 ProcessThread *thr;
619 Port rpcPort;
620
621public:
622 /************************************************************************/
623 ProcessModule() : thr(NULL) { }
624
625 /************************************************************************/
626 bool configure(ResourceFinder &rf)
627 {
628 thr=new ProcessThread(rf);
629 if (!thr->start())
630 {
631 delete thr;
632 return false;
633 }
634
635 rpcPort.open("/"+thr->getName()+"/rpc");
636 attach(rpcPort);
637
638 return true;
639 }
640
641 /************************************************************************/
642 bool respond(const Bottle &command, Bottle &reply)
643 {
644 if (thr->execReq(command,reply))
645 return true;
646 else
647 return RFModule::respond(command,reply);
648 }
649
650 /************************************************************************/
651 bool close()
652 {
653 if (thr!=NULL)
654 {
655 thr->stop();
656 delete thr;
657 }
658
659 rpcPort.interrupt();
660 rpcPort.close();
661
662 return true;
663 }
664
665 /************************************************************************/
666 double getPeriod()
667 {
668 return 1.0;
669 }
670
671 /************************************************************************/
673 {
674 return true;
675 }
676};
677
678
679/************************************************************************/
680int main(int argc, char *argv[])
681{
682 Network yarp;
683
684 ResourceFinder rf;
685 rf.configure(argc,argv);
686
687 if (rf.check("help"))
688 {
689 cout<<"Available options:"<<endl;
690 cout<<"\t--name <string>"<<endl;
691 cout<<"\t--coverXratio <double>"<<endl;
692 cout<<"\t--coverYratio <double>"<<endl;
693 cout<<"\t--nodesStep <int>"<<endl;
694 cout<<"\t--winSize <int>"<<endl;
695 cout<<"\t--recogThres <double>"<<endl;
696 cout<<"\t--adjNodesThres <int>"<<endl;
697 cout<<"\t--blobMinSizeThres <int>"<<endl;
698 cout<<"\t--framesPersistence <int>"<<endl;
699 cout<<"\t--cropSize \"auto\" or <int>"<<endl;
700 cout<<"\t--verbosity"<<endl;
701 cout<<endl;
702 return 0;
703 }
704
705 if (!yarp.checkNetwork())
706 {
707 yError("YARP server not available!");
708 return 1;
709 }
710
711 ProcessModule mod;
712 return mod.runModule(rf);
713}
Definition main.cpp:47
Blob()
Definition main.cpp:53
Point centroid
Definition main.cpp:49
int size
Definition main.cpp:50
bool configure(ResourceFinder &rf)
Definition main.cpp:626
double getPeriod()
Definition main.cpp:666
bool updateModule()
Definition main.cpp:672
bool respond(const Bottle &command, Bottle &reply)
Definition main.cpp:642
bool close()
Definition main.cpp:651
bool verbosity
Definition main.cpp:80
bool inhibition
Definition main.cpp:81
void run()
Definition main.cpp:179
void onStop()
Definition main.cpp:425
ProcessThread(ResourceFinder &_rf)
Definition main.cpp:108
BufferedPort< ImageOf< PixelBgr > > cropPort
Definition main.cpp:102
void floodFill(const int i, Blob *pBlob)
Definition main.cpp:470
bool firstConsistencyCheck
Definition main.cpp:69
int blobMinSizeThres
Definition main.cpp:77
string name
Definition main.cpp:68
void insertBlob(const Blob &blob)
Definition main.cpp:492
int nodesStep
Definition main.cpp:72
BufferedPort< ImageOf< PixelBgr > > outPort
Definition main.cpp:100
vector< Point2f > nodesPrev
Definition main.cpp:90
void threadRelease()
Definition main.cpp:431
ImageOf< PixelMono > imgMonoIn
Definition main.cpp:85
void findBlobs()
Definition main.cpp:448
double coverYratio
Definition main.cpp:71
double recogThresAbs
Definition main.cpp:75
vector< Mat > pyrCurr
Definition main.cpp:88
ResourceFinder & rf
Definition main.cpp:66
bool threadInit()
Definition main.cpp:111
ImageOf< PixelMono > imgMonoPrev
Definition main.cpp:86
string getName()
Definition main.cpp:442
int cropSize
Definition main.cpp:79
double recogThres
Definition main.cpp:74
int framesPersistence
Definition main.cpp:78
BufferedPort< Bottle > nodesPort
Definition main.cpp:103
int winSize
Definition main.cpp:73
set< int > activeNodesIndexSet
Definition main.cpp:96
deque< Blob > blobSortedList
Definition main.cpp:97
BufferedPort< ImageOf< PixelBgr > > inPort
Definition main.cpp:99
vector< uchar > featuresFound
Definition main.cpp:92
BufferedPort< Bottle > blobsPort
Definition main.cpp:104
BufferedPort< ImageOf< PixelMono > > optPort
Definition main.cpp:101
vector< Mat > pyrPrev
Definition main.cpp:87
int adjNodesThres
Definition main.cpp:76
vector< Point2f > nodesCurr
Definition main.cpp:91
double coverXratio
Definition main.cpp:70
vector< float > featuresErrors
Definition main.cpp:93
void afterStart(bool s)
Definition main.cpp:152
vector< int > nodesPersistence
Definition main.cpp:94
bool execReq(const Bottle &req, Bottle &reply)
Definition main.cpp:510
cmd
Definition dataTypes.h:30
#define NODE_OFF
Definition main.cpp:35
#define NODE_ON
Definition main.cpp:36
int main()
Definition main.cpp:67
Copyright (C) 2008 RobotCub Consortium.