iCub-main
SkinMeshThreadPort.cpp
Go to the documentation of this file.
1 // -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*-
2 
3 /*
4  * Copyright (C) 2009 RobotCub Consortium
5  * Author: Marco Randazzo, Marco Maggiali, Alessandro Scalzo
6  * CopyPolicy: Released under the terms of the GNU GPL v2.0.
7  *
8  */
9 
11 
12 #include <yarp/os/Time.h>
13 
14 #define SKIN_THRESHOLD 15.0
15 
16 SkinMeshThreadPort::SkinMeshThreadPort(Searchable& config,int period) : PeriodicThread((double)period/1000.0)
17 {
18  yDebug("SkinMeshThreadPort running at %d ms.",(int)(1000.0*getPeriod()));
19  mbSimpleDraw=config.check("light");
20 
21  sensorsNum=0;
22  for (int t=0; t<MAX_SENSOR_NUM; ++t)
23  {
24  sensor[t]=NULL;
25  }
26 
27  std::string part="/skinGui/";
28  std::string part_virtual="";
29  if (config.check("name"))
30  {
31  part ="/";
32  part+=config.find("name").asString();
33  part+="/";
34  }
35  part.append(config.find("robotPart").asString());
36  part_virtual = part;
37  part_virtual.append("_virtual");
38  part.append(":i");
39  part_virtual.append(":i");
40 
41  skin_port.open(part);
42 
43  // Ideally, we would use a --virtual flag. since this would make the skinmanager xml file unflexible,
44  // let's keep the code structure without incurring in any problem whatsoever
45  // if (config.check("virtual"))
46  if (true)
47  {
48  skin_port_virtual.open(part_virtual);
49  }
50 
51  int width =config.find("width" ).asInt32();
52  int height=config.find("height").asInt32();
53 
54  bool useCalibration = config.check("useCalibration");
55  if (useCalibration==true) yInfo("Using calibrated skin values (0-255)");
56  else yDebug("Using raw skin values (255-0)");
57 
58  Bottle *color = config.find("color").asList();
59  unsigned char r=255, g=0, b=0;
60  if(color)
61  {
62  if(color->size()<3 || !color->get(0).isInt32() || !color->get(1).isInt32() || !color->get(2).isInt32())
63  {
64  yError("Error while reading the parameter color: three integer values should be specified (%s).", color->toString().c_str());
65  }
66  else
67  {
68  r = color->get(0).asInt32();
69  g = color->get(1).asInt32();
70  b = color->get(2).asInt32();
71  yInfo("Using specified color: %d %d %d", r, g, b);
72  }
73  }
74  else
75  {
76  yDebug("Using red as default color.");
77  }
78  defaultColor.push_back(r);
79  defaultColor.push_back(g);
80  defaultColor.push_back(b);
81 
82  skinThreshold = config.check("skinThreshold")?config.find("skinThreshold").asFloat64():SKIN_THRESHOLD;
83  yDebug("Skin Threshold set to %g", skinThreshold);
84 
85  yarp::os::Bottle sensorSetConfig=config.findGroup("SENSORS").tail();
86 
87  for (int t=0; t<sensorSetConfig.size(); ++t)
88  {
89  yarp::os::Bottle sensorConfig(sensorSetConfig.get(t).toString());
90  std::string type(sensorConfig.get(0).asString());
91 
92  if (type=="triangle" ||
93  type=="fingertip" ||
94  type=="fingertip2L" ||
95  type=="fingertip2R" ||
96  type=="fingertip3L" ||
97  type=="fingertip3R" ||
98  type=="fingertip4L" ||
99  type=="fingertip4R" ||
100  type=="fingertipMID" ||
101  type=="triangle_10pad" ||
102  type=="quad16" ||
103  type=="palmR" ||
104  type=="fakePalm" ||
105  type=="palmL" ||
106  type == "cer_sh_pdl" ||
107  type == "cer_sh_pdr" ||
108  type == "cer_sh_pp" ||
109  type == "cer_sh_td" ||
110  type == "cer_sh_tp")
111  {
112  int id=sensorConfig.get(1).asInt32();
113  double xc=sensorConfig.get(2).asFloat64();
114  double yc=sensorConfig.get(3).asFloat64();
115  double th=sensorConfig.get(4).asFloat64();
116  double gain=sensorConfig.get(5).asFloat64();
117  int lrMirror=sensorConfig.get(6).asInt32();
118  int layoutNum=sensorConfig.get(7).asInt32();
119 
120  yDebug("%s %d %f",type.c_str(),id,gain);
121 
122  if (id>=0 && id<MAX_SENSOR_NUM)
123  {
124  if (sensor[id])
125  {
126  yError("Triangle %d already exists.",id);
127  }
128  else
129  {
130  if (type=="triangle")
131  {
132  sensor[id]=new Triangle(xc,yc,th,gain,layoutNum,lrMirror);
133  }
134  else if (type=="triangle_10pad")
135  {
136  sensor[id]=new Triangle_10pad(xc,yc,th,gain,layoutNum,lrMirror);
137  }
138  else if (type=="fingertip")
139  {
140  sensor[id]=new Fingertip(xc,yc,th,gain,layoutNum,lrMirror);
141  }
142  else if (type=="fingertip2L")
143  {
144  sensor[id]=new Fingertip2L(xc,yc,th,gain,layoutNum,lrMirror);
145  }
146  else if (type=="fingertip2R")
147  {
148  sensor[id]=new Fingertip2R(xc,yc,th,gain,layoutNum,lrMirror);
149  }
150  else if (type=="fingertip3L")
151  {
152  sensor[id]=new Fingertip3L(xc,yc,th,gain,layoutNum,lrMirror);
153  }
154  else if (type=="fingertip3R")
155  {
156  sensor[id]=new Fingertip3R(xc,yc,th,gain,layoutNum,lrMirror);
157  }
158  else if (type=="fingertip4L")
159  {
160  sensor[id]=new Fingertip4L(xc,yc,th,gain,layoutNum,lrMirror);
161  }
162  else if (type=="fingertip4R")
163  {
164  sensor[id]=new Fingertip4R(xc,yc,th,gain,layoutNum,lrMirror);
165  }
166  if (type=="fingertipMID")
167  {
168  sensor[id]=new FingertipMID(xc,yc,th,gain,layoutNum,lrMirror);
169  }
170  else if (type=="quad16")
171  {
172  sensor[id]=new Quad16(xc,yc,th,gain,layoutNum,lrMirror);
173  }
174  else if (type == "cer_sh_pdl")
175  {
176  sensor[id] = new CER_SH_PDL(xc, yc, th, gain, layoutNum, lrMirror);
177  }
178  else if (type=="palmR")
179  {
180  sensor[id]=new PalmR(xc,yc,th,gain,layoutNum,lrMirror);
181  }
182  else if (type=="fakePalm")
183  {
184  sensor[id]=new fakePalm(xc,yc,th,gain,layoutNum,lrMirror);
185  }
186  else if (type=="palmL")
187  {
188  sensor[id]=new PalmL(xc,yc,th,gain,layoutNum,lrMirror);
189  }
190  else if (type == "cer_sh_pdl")
191  {
192  sensor[id] = new CER_SH_PDL(xc, yc, th, gain, layoutNum, lrMirror);
193  }
194  else if (type == "cer_sh_pdr")
195  {
196  sensor[id] = new CER_SH_PDR(xc, yc, th, gain, layoutNum, lrMirror);
197  }
198  else if (type == "cer_sh_pp")
199  {
200  sensor[id] = new CER_SH_PP(xc, yc, th, gain, layoutNum, lrMirror);
201  }
202  else if (type == "cer_sh_td")
203  {
204  sensor[id] = new CER_SH_TD(xc, yc, th, gain, layoutNum, lrMirror);
205  }
206  else if (type == "cer_sh_tp")
207  {
208  sensor[id] = new CER_SH_TP(xc, yc, th, gain, layoutNum, lrMirror);
209  }
210 
211  sensor[id]->setCalibrationFlag(useCalibration);
212  ++sensorsNum;
213  }
214  }
215  else
216  {
217  yWarning(" %d is invalid triangle Id [0:%d].",id, MAX_SENSOR_NUM-1);
218  }
219  }
220  else
221  {
222  yWarning(" sensor type %s unknown, discarded.",type.c_str());
223  }
224  }
225 
226  int max_tax=0;
227  for (int t=0; t<MAX_SENSOR_NUM; ++t)
228  {
229 
230  if (sensor[t])
231  {
232  sensor[t]->min_tax=max_tax;
233  max_tax = sensor[t]->min_tax+sensor[t]->get_nTaxels();
234  sensor[t]->max_tax=max_tax-1;
235  sensor[t]->setColor(r, g, b);
236  }
237  else
238  {
239  //this deals with the fact that some traingles can be not present,
240  //but they anyway broadcast an array of zeros...
241  max_tax += 12;
242  }
243  }
244 
245  resize(width,height);
246 }
247 
249 {
250  yDebug("SkinMeshThreadPort initialising..");
251  yDebug("..done!");
252 
253  yInfo("Waiting for port connection..");
254  return true;
255 }
256 
258 {
259  std::lock_guard<std::mutex> lck(mtx);
260 
261  bool gotRealData=false;
262  bool gotVirtualData=false;
263  yarp::sig::Vector skin_value;
264  yarp::sig::Vector skin_value_virtual;
265  std::vector<unsigned char> skin_color_virtual;
266 
267  // Read data from the real contacts
268  if (Bottle *input=skin_port.read(false))
269  {
270  yTrace("Reading from real contacts...");
271  gotRealData=true;
272 
273  skin_value.resize(input->size(),0.0);
274  for (int i=0; i<input->size(); i++)
275  {
276  skin_value[i]=input->get(i).asFloat64();
277  }
278  }
279 
280  // Read data from the virtual contacts
281  if (Bottle *input_virtual=skin_port_virtual.read(false))
282  {
283  yTrace("Reading from virtual contacts...");
284  gotVirtualData=true;
285 
286  Bottle *data_virtual = input_virtual->get(0).asList();
287  skin_value_virtual.resize(data_virtual->size(),0.0);
288  Bottle *color_virtual = input_virtual->get(1).asList();
289 
290  for (int i=0; i<data_virtual->size(); i++)
291  {
292  skin_value_virtual[i] = data_virtual->get(i).asFloat64();
293  }
294 
295  for (int i = 0; i<color_virtual->size(); i++)
296  {
297  skin_color_virtual.push_back(color_virtual->get(i).asInt32());
298  }
299 
300  yTrace("Virtual contacts: %s",skin_value_virtual.toString(3,3).c_str());
301  yTrace("\n");
302  yTrace("Virtual contacts color: %i %i %i",skin_color_virtual[0],skin_color_virtual[1],skin_color_virtual[2]);
303  }
304 
305  for (int sensorId=0; sensorId<MAX_SENSOR_NUM; sensorId++)
306  {
307  if (sensor[sensorId]==0) continue;
308 
309  // First, let's see if this touchSensor is over threshold in the real skin
310  bool isRealSensorOverThreshold=false;
311  if (gotRealData)
312  {
313  for (int i=sensor[sensorId]->min_tax; i<=sensor[sensorId]->max_tax; i++)
314  {
315  if (skin_value[i]>skinThreshold)
316  {
317  isRealSensorOverThreshold = true;
318  break;
319  }
320  }
321  }
322 
323  // Second, let's see if this touchSensor is over threshold in the virtual skin
324  bool isVirtualSensorOverThreshold=false;
325  if (gotVirtualData)
326  {
327  for (int i=sensor[sensorId]->min_tax; i<=sensor[sensorId]->max_tax; i++)
328  {
329  if (skin_value_virtual[i]>skinThreshold)
330  {
331  isVirtualSensorOverThreshold = true;
332  break;
333  }
334  }
335  }
336 
337  // Then, let's process the sensor with either the real or the virtual (or none)
338  // EVerything will be clearly decoupled, a couple lines more do not hurt
339 
340  // If there are both, handle them
341  if (gotRealData && gotVirtualData)
342  {
343  // Then, let's process the sensor with either the real or the virtual skin
344  for (int i=sensor[sensorId]->min_tax; i<=sensor[sensorId]->max_tax; i++)
345  {
346  int curr_tax = i-sensor[sensorId]->min_tax;
347 
348  if (isRealSensorOverThreshold)
349  {
350  sensor[sensorId]->setActivationFromPortData(skin_value[i],curr_tax);
352  }
353  else if(isVirtualSensorOverThreshold)
354  {
355  sensor[sensorId]->setActivationFromPortData(skin_value_virtual[i],curr_tax);
356  sensor[sensorId]->setColor(skin_color_virtual[0],skin_color_virtual[1],skin_color_virtual[2]);
357  }
358  else
359  {
360  sensor[sensorId]->setActivationFromPortData(skin_value[i],curr_tax);
362  }
363  }
364  }
365  else if (gotRealData || gotVirtualData)
366  {
367  for (int sensorId=0; sensorId<MAX_SENSOR_NUM; sensorId++)
368  {
369  if (sensor[sensorId]==0) continue;
370 
371  for (int i=sensor[sensorId]->min_tax; i<=sensor[sensorId]->max_tax; i++)
372  {
373  int curr_tax = i-sensor[sensorId]->min_tax;
374 
375  if (gotRealData)
376  {
377  sensor[sensorId]->setActivationFromPortData(skin_value[i],curr_tax);
379  }
380  else if (gotVirtualData)
381  {
382  sensor[sensorId]->setActivationFromPortData(skin_value_virtual[i],curr_tax);
383  sensor[sensorId]->setColor(skin_color_virtual[0],skin_color_virtual[1],skin_color_virtual[2]);
384  }
385  }
386  }
387  }
388  }
389 }
390 
392 {
393  yDebug("SkinMeshThreadPort releasing...");
394  skin_port.close();
395  skin_port_virtual.close();
396  yDebug("... done.");
397 }
#define SKIN_THRESHOLD
Definition: PalmLeft.h:16
Definition: Quad16.h:16
BufferedPort< Bottle > skin_port_virtual
std::vector< unsigned char > defaultColor
void resize(int width, int height)
virtual void threadRelease()
static const int MAX_SENSOR_NUM
SkinMeshThreadPort(Searchable &config, int period)
BufferedPort< Bottle > skin_port
TouchSensor * sensor[MAX_SENSOR_NUM]
void setActivationFromPortData(double val, int id)
Definition: TouchSensor.h:252
void setCalibrationFlag(bool use_calibrated_skin)
Definition: TouchSensor.h:43
int get_nTaxels()
Definition: TouchSensor.h:123
void setColor(unsigned char r, unsigned char g, unsigned char b)
Definition: TouchSensor.h:36