iol
main.cpp
1 /*
2  * Copyright (C) 2011 Department of Robotics Brain and Cognitive Sciences - Istituto Italiano di Tecnologia
3  * Author: Carlo Ciliberto
4  * email: carlo.ciliberto@iit.it
5  * Permission is granted to copy, distribute, and/or modify this program
6  * under the terms of the GNU General Public License, version 2 or any
7  * later version published by the Free Software Foundation.
8  *
9  * A copy of the license can be found at
10  * http://www.robotcub.org/icub/license/gpl.txt
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15  * Public License for more details
16 */
17 
68 #include <mutex>
69 
70 #include <yarp/os/Network.h>
71 #include <yarp/os/BufferedPort.h>
72 #include <yarp/os/RFModule.h>
73 #include <yarp/os/PeriodicThread.h>
74 #include <yarp/os/Time.h>
75 #include <yarp/os/Stamp.h>
76 
77 #include <yarp/sig/Image.h>
78 #include <yarp/sig/Vector.h>
79 
80 #include <yarp/cv/Cv.h>
81 
82 #include <opencv2/opencv.hpp>
83 
84 #include <string>
85 #include <list>
86 #include <cmath>
87 
88 #include <iostream>
89 #include <fstream>
90 
91 
92 using namespace std;
93 using namespace yarp::os;
94 using namespace yarp::sig;
95 using namespace yarp::cv;
96 
97 
98 #define IDLE 0
99 #define TRACKING 1
100 #define POINTING 2
101 
102 
103 class PointingThread: public PeriodicThread, public BufferedPort<Bottle>
104 {
105 private:
106  ResourceFinder &rf;
107  BufferedPort<ImageOf<PixelRgb>> inPort;
108  BufferedPort<ImageOf<PixelRgb>> outPort;
109  BufferedPort<Vector> pointPort;
110 
111  double internal_time;
112  double tracking_thresh;
113  double pointing_thresh;
114 
115  list<Vector> positions;
116  Vector lastPoint;
117 
118  mutex mtx;
119  int state;
120 
121 public:
122  PointingThread(ResourceFinder &_rf)
123  : PeriodicThread(0.005),rf(_rf) { }
124 
125  virtual bool threadInit()
126  {
127  string name=rf.find("name").asString();
128  tracking_thresh=rf.check("tracking_threshold",Value(0.5)).asFloat64();
129  pointing_thresh=rf.check("pointing_threshold",Value(2.5)).asFloat64();
130 
131  inPort.open("/"+name+"/img:i");
132  outPort.open("/"+name+"/img:o");
133  pointPort.open("/"+name+"/point:o");
134 
135  this->useCallback();
136  this->open("/"+name+"/blobs:i");
137 
138  internal_time=0.0;
139 
140  positions.clear();
141  lastPoint.resize(2,0.0);
142 
143  state=IDLE;
144  return true;
145  }
146 
147  virtual void run()
148  {
149  lock_guard<mutex> lg(mtx);
150  if(ImageOf<PixelRgb> *imgIn=inPort.read(false))
151  {
152  ImageOf<PixelRgb> &imgOut=outPort.prepare();
153  imgOut=*imgIn;
154  cv::Mat imgOutMat=toCvMat(imgOut);
155 
156  if(positions.size()>0)
157  {
158  switch(state)
159  {
160  case(IDLE):
161  {
162  break;
163  }
164  case(TRACKING):
165  {
166  if(Time::now()-internal_time>tracking_thresh)
167  state=POINTING;
168  else
169  cv::circle(imgOutMat,cv::Point((int)round(positions.back()[0]),
170  (int)round(positions.back()[1])),5,cv::Scalar(255),5);
171  break;
172  }
173  case(POINTING):
174  {
175  cv::circle(imgOutMat,cv::Point((int)round(positions.back()[0]),
176  (int)round(positions.back()[1])),5,cv::Scalar(0,0,255),5);
177  cv::circle(imgOutMat,cv::Point((int)round(positions.back()[0]),
178  (int)round(positions.back()[1])),10,cv::Scalar(0,255),5);
179 
180  if ((positions.back()[0]!=lastPoint[0]) || (positions.back()[1]!=lastPoint[1]))
181  {
182  lastPoint=positions.back();
183  pointPort.prepare()=lastPoint;
184  pointPort.writeStrict();
185  }
186  break;
187  }
188  }
189  }
190  imgOut=fromCvMat<PixelRgb>(imgOutMat);
191  outPort.writeStrict();
192  }
193  }
194 
195  virtual void onRead(Bottle &bot)
196  {
197  lock_guard<mutex> lg(mtx);
198  double curr_time=Time::now();
199 
200  if(bot.size()>0)
201  {
202  switch(state)
203  {
204  case(IDLE):
205  {
206  positions.clear();
207 
208  Bottle *blob=bot.get(0).asList();
209  Vector v(2);
210  v[0]=blob->get(0).asInt32();
211  v[1]=blob->get(1).asInt32();
212 
213  state=TRACKING;
214  internal_time=curr_time;
215  break;
216  }
217 
218  case(TRACKING):
219  {
220  positions.clear();
221 
222  Bottle *blob=bot.get(0).asList();
223  Vector v(2);
224  v[0]=blob->get(0).asInt32();
225  v[1]=blob->get(1).asInt32();
226 
227  positions.push_back(v);
228  break;
229  }
230 
231  case(POINTING):
232  {
233  if(curr_time-internal_time>pointing_thresh)
234  {
235  state=TRACKING;
236  internal_time=curr_time;
237  }
238  break;
239  }
240  }
241  }
242  }
243 
244  virtual void threadRelease()
245  {
246  inPort.close();
247  outPort.close();
248  pointPort.close();
249  this->close();
250  }
251 
252  bool execReq(const Bottle &command, Bottle &reply)
253  {
254  return false;
255  }
256 };
257 
258 
259 class DetectorModule: public RFModule
260 {
261 private:
262  PointingThread *thr;
263  Port rpcPort;
264 
265 public:
266  virtual bool configure(ResourceFinder &rf)
267  {
268  thr=new PointingThread(rf);
269 
270  if(!thr->start())
271  {
272  delete thr;
273  return false;
274  }
275 
276  string name=rf.find("name").asString();
277  rpcPort.open("/"+name+"/rpc");
278  attach(rpcPort);
279 
280  return true;
281  }
282 
283  virtual bool interruptModule()
284  {
285  rpcPort.interrupt();
286 
287  return true;
288  }
289 
290  virtual bool close()
291  {
292  thr->stop();
293  delete thr;
294 
295  rpcPort.close();
296 
297  return true;
298  }
299 
300  virtual double getPeriod()
301  {
302  return 0.1;
303  }
304 
305  virtual bool updateModule()
306  {
307  return true;
308  }
309 
310  virtual bool respond(const Bottle &command, Bottle &reply)
311  {
312  if(thr->execReq(command,reply))
313  return true;
314  else
315  return RFModule::respond(command,reply);
316  }
317 };
318 
319 
320 int main(int argc, char *argv[])
321 {
322  Network yarp;
323 
324  if (!yarp.checkNetwork())
325  return 1;
326 
327  ResourceFinder rf;
328  rf.setDefault("name","blobSelector");
329  rf.configure(argc,argv);
330 
331  DetectorModule mod;
332 
333  return mod.runModule(rf);
334 }
335