iCub-main
Loading...
Searching...
No Matches
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
16SkinMeshThreadPort::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
BufferedPort< Bottle > skin_port_virtual
std::vector< unsigned char > defaultColor
void resize(int width, int height)
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)
void setCalibrationFlag(bool use_calibrated_skin)
Definition TouchSensor.h:43
int get_nTaxels()
void setColor(unsigned char r, unsigned char g, unsigned char b)
Definition TouchSensor.h:36