iCub-main
Loading...
Searching...
No Matches
TouchSensor.h
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: Alessandro Scalzo alessandro.scalzo@iit.it
6 * CopyPolicy: Released under the terms of the GNU GPL v2.0.
7 *
8 */
9
10#include <gsl/gsl_math.h>
11#include <memory.h>
12
13#include <stdio.h>
14
15#ifndef __ALE_TOUCHSENSOR_H__
16#define __ALE_TOUCHSENSOR_H__
17
18#define MAX_TAXELS 192
19
21{
22protected:
23
25
27 {
28 for (int n = 0; n < MAX_TAXELS; ++n)
29 {
30 connected[n] = true;
31 }
32 }
33
34public:
35
36 void setColor(unsigned char r, unsigned char g, unsigned char b)
37 {
38 R_MAX = r;
39 G_MAX = g;
40 B_MAX = b;
41 }
42
43 void setCalibrationFlag (bool use_calibrated_skin)
44 {
45 calibrated_skin=use_calibrated_skin;
46 }
47
48 void resize(int width,int height,int margin)
49 {
50 if (3*margin>=width || 3*margin>=height) margin=0;
51
52 double scaleX=double(width -2*margin)/(dXmax-dXmin);
53 double scaleY=double(height-2*margin)/(dYmax-dYmin);
54 double scale=scaleX<scaleY?scaleX:scaleY;
55
57
59
60 double dXmid=0.5*(dXmin+dXmax);
61 double dYmid=0.5*(dYmin+dYmax);
62
63 int w2=width /2;
64 int h2=height/2;
65
66 for (int i=0; i<nTaxels; ++i)
67 {
68 x[i]=w2+int(scale*(dX[i]-dXmid));
69 y[i]=h2+int(scale*(dY[i]-dYmid));
70 }
71
72 for (int i=0; i<nVerts; ++i)
73 {
74 xv[i]=w2+int(scale*(dXv[i]-dXmid));
75 yv[i]=h2+int(scale*(dYv[i]-dYmid));
76 }
77
78 double sigma=0.5*5.55*scale;
79 int maxRange=int(2.5*sigma);
80
81 if (maxRange!=m_maxRange)
82 {
83 m_maxRange=maxRange;
84
85 delete [] Exponential;
86 Exponential=new double[maxRange];
87
88 double k=-0.5/(sigma*sigma);
89 for (int x=0; x<maxRange; ++x)
90 {
91 Exponential[x]=exp(k*double(x*x));
92 }
93 }
94
95 xMin=w2+int(scale*(dXc-dXmid-15.0))-maxRange;
96 xMax=w2+int(scale*(dXc-dXmid+15.0))+maxRange;
97 yMin=h2+int(scale*(dYc-dYmid-15.0))-maxRange;
98 yMax=h2+int(scale*(dYc-dYmid+15.0))+maxRange;
99
100 if (xMin<0) xMin=0;
101 if (xMax>width) xMax=width;
102 if (yMin<0) yMin=0;
103 if (yMax>height) yMax=height;
104
105 m_Width=width;
106 m_Height=height;
107 }
108
109 virtual ~TouchSensor()
110 {
111 if (Exponential)
112 {
113 delete [] Exponential;
114 Exponential=0;
115 }
116 }
117
118 int Abs(int x)
119 {
120 return x>=0?x:-x;
121 }
122
124 {
125 return nTaxels;
126 }
127
128 void eval_light(unsigned char *image)
129 {
130 int act;
131 int dx,dy;
132 int Y0,Y1;
133 int dya,dyb,dxa,dxb;
134
135 switch (ilayoutNum)
136 {
137 case 0:
138 for (int i=0; i<nTaxels; ++i) remapped_activation[i]=activation[i];
139 break;
140 case 1:
141 for (int i=0; i<nTaxels; ++i) remapped_activation[nTaxels-1-i]=activation[i];
142 break;
143 default:
144 for (int i=0; i<nTaxels; ++i) remapped_activation[i]=activation[i];
145 printf("WARN: unkwnown layout number.\n");
146 break;
147 }
148
149 int maxRange2=m_maxRangeLight*m_maxRangeLight;
150
151 for (int i=0; i<nTaxels; ++i) if (connected[i] && remapped_activation[i]>0.0)
152 {
153 act=int(dGain*remapped_activation[i]);
154 Y0=(m_Height-y[i]-1)*m_Width+x[i];
155
156 dya=(y[i]>=m_maxRangeLight)?-m_maxRangeLight:-y[i];
158
159 dxa=(x[i]>=m_maxRangeLight)?-m_maxRangeLight:-x[i];
161
162 for (dy=dya; dy<=dyb; ++dy)
163 {
164 Y1=Y0-dy*m_Width;
165
166 for (dx=dxa; dx<=dxb; ++dx)
167 {
168 if (dx*dx+dy*dy<=maxRange2)
169 {
170 image[(dx+Y1)*3]=act<255?act:255;
171 }
172 }
173 }
174 }
175 }
176
177 void eval(unsigned char *image)
178 {
179 int act;
180 int dx,dy;
181 int Y0,Y1;
182 int index;
183 double k0,k1;
184 int dya,dyb,dxa,dxb;
185
186 switch (ilayoutNum)
187 {
188 case 0:
189 for (int i=0; i<nTaxels; ++i) remapped_activation[i]=activation[i];
190 break;
191 case 1:
192 for (int i=0; i<nTaxels; ++i) remapped_activation[nTaxels-1-i]=activation[i];
193 break;
194 default:
195 for (int i=0; i<nTaxels; ++i) remapped_activation[i]=activation[i];
196 printf("WARN: unkwnown layout number.\n");
197 break;
198 }
199
200 for (int i=0; i<nTaxels; ++i) if (connected[i] && remapped_activation[i]>0.0)
201 {
203 Y0=(m_Height-y[i]-1)*m_Width+x[i];
204
205 dya=(y[i]>=m_maxRange)?-m_maxRange:-y[i];
207
208 dxa=(x[i]>=m_maxRange)?-m_maxRange:-x[i];
209 dxb=(x[i]+m_maxRange<m_Width)?m_maxRange:m_Width-x[i]-1;
210
211 for (dy=dya; dy<=dyb; ++dy)
212 {
213 k1=k0*Exponential[Abs(dy)];
214 Y1=Y0-dy*m_Width;
215
216 for (dx=dxa; dx<=dxb; ++dx)
217 {
218 index=(dx+Y1)*3;
219
220 if (image[index]<R_MAX || image[index+1]<G_MAX || image[index+2]<B_MAX)
221 {
222 act=int(k1*Exponential[Abs(dx)]);
223
224 int actR=image[index ]+(act*R_MAX)/255;
225 int actG=image[index+1]+(act*G_MAX)/255;
226 int actB=image[index+2]+(act*B_MAX)/255;
227
228 image[index ]=actR<R_MAX?actR:R_MAX;
229 image[index+1]=actG<G_MAX?actG:G_MAX;
230 image[index+2]=actB<B_MAX?actB:B_MAX;
231 }
232 }
233 }
234 }
235 }
236
237 void setActivationFirst7(unsigned char* data)
238 {
239 for (int i=0; i<7; ++i)
240 {
241 activation[i]=data[i+1]<=244?double(244-data[i+1]):0.0;
242 }
243 }
244 void setActivationLast5(unsigned char* data)
245 {
246 for (int i=1; i<=5; ++i)
247 {
248 activation[i+6]=data[i]<=244?double(244-data[i]):0.0;
249 }
250 }
251
252 void setActivationFromPortData(double val, int id)
253 {
254 if (calibrated_skin)
255 {
256 if (val>244.0)
257 {
258 activation[id]=244.0;
259 }
260 else if (val<0.0)
261 {
262 activation[id]=0.0;
263 }
264 else
265 {
266 activation[id]=val;
267 }
268 }
269 else
270 {
271 activation[id]=val<=244?double(244-val):0.0;
272 }
273 }
274
275 virtual void draw(unsigned char *image)
276 {
277 for (int i=0; i<nVerts; ++i)
278 {
279 drawLine(image,xv[i],yv[i],xv[(i+1)%nVerts],yv[(i+1)%nVerts]);
280 }
281
282 for (int i=0; i<nTaxels; ++i)
283 {
284 drawCircle(image,x[i],y[i],m_Radius);
285 }
286 }
287
288protected:
289 void dither(int x,int y,unsigned char *image)
290 {
291 static const unsigned char R1=0x80,G1=0x50,B1=0x00;
292 static const unsigned char R2=3*R1/4,G2=3*G1/4,B2=3*B1/4;
293 static const unsigned char R4=3*R2/4,G4=3*G2/4,B4=3*B2/4;
294
295 //y=m_Width-y-1;
296 //int bytePos=(x+(y-1)*m_Width)*3;
297 int bytePos=(x+(m_Height-y-2)*m_Width)*3;
298
299 if (image[bytePos-3]<R4) image[bytePos-3]=R4;
300 if (image[bytePos-2]<G4) image[bytePos-2]=G4;
301 //if (image[bytePos-1]<B4) image[bytePos-1]=B4;
302
303 if (image[bytePos ]<R2) image[bytePos ]=R2;
304 if (image[bytePos+1]<G2) image[bytePos+1]=G2;
305 //if (image[bytePos+2]<B2) image[bytePos+2]=B2;
306
307 if (image[bytePos+3]<R4) image[bytePos+3]=R4;
308 if (image[bytePos+4]<G4) image[bytePos+4]=G4;
309 //if (image[bytePos+5]<B4) image[bytePos+5]=B4;
310
311 bytePos+=m_Width*3;
312
313 if (image[bytePos-3]<R2) image[bytePos-3]=R2;
314 if (image[bytePos-2]<G2) image[bytePos-2]=G2;
315 //if (image[bytePos-1]<B2) image[bytePos-1]=B2;
316
317 if (image[bytePos ]<R1) image[bytePos ]=R1;
318 if (image[bytePos+1]<G1) image[bytePos+1]=G1;
319 //if (image[bytePos+2]<B1) image[bytePos+2]=B1;
320
321 if (image[bytePos+3]<R2) image[bytePos+3]=R2;
322 if (image[bytePos+4]<G2) image[bytePos+4]=G2;
323 //if (image[bytePos+5]<B2) image[bytePos+5]=B2;
324
325 bytePos+=m_Width*3;
326
327 if (image[bytePos-3]<R4) image[bytePos-3]=R4;
328 if (image[bytePos-2]<G4) image[bytePos-2]=G4;
329 //if (image[bytePos-1]<B4) image[bytePos-1]=B4;
330
331 if (image[bytePos ]<R2) image[bytePos ]=R2;
332 if (image[bytePos+1]<G2) image[bytePos+1]=G2;
333 //if (image[bytePos+2]<B2) image[bytePos+2]=B2;
334
335 if (image[bytePos+3]<R4) image[bytePos+3]=R4;
336 if (image[bytePos+4]<G4) image[bytePos+4]=G4;
337 //if (image[bytePos+5]<B4) image[bytePos+5]=B4;
338 }
339
340 void drawLine(unsigned char *image,int x0,int y0,int x1,int y1)
341 {
342 if (x1==x0 && y1==y0) return;
343 double Vx=double(x1-x0);
344 double Vy=double(y1-y0);
345 double dt=1.0/sqrt(Vx*Vx+Vy*Vy);
346
347 for (double t=0.0; t<=1.0; t+=dt)
348 {
349 dither(x0+int(t*Vx),y0+int(t*Vy),image);
350 }
351 }
352
353 void drawCircle(unsigned char *image,int cx,int cy,double radius)
354 {
355 double dt=1.0/(2*M_PI*radius);
356
357 int dx,dy;
358
359 double cs,sn;
360
361 for (double t=0.0; t<=M_PI_4; t+=dt)
362 {
363 cs=cos(t);
364 sn=sin(t);
365
366 dx=int(radius*cs);
367 dy=int(radius*sn);
368
369 dither(cx+dx,cy+dy,image);
370 dither(cx+dx,cy-dy,image);
371 dither(cx-dx,cy-dy,image);
372 dither(cx-dx,cy+dy,image);
373
374 dither(cx+dy,cy+dx,image);
375 dither(cx+dy,cy-dx,image);
376 dither(cx-dy,cy-dx,image);
377 dither(cx-dy,cy+dx,image);
378 }
379 }
380
381 // original
383 static double dXmin,dXmax,dYmin,dYmax;
384 double dXv[8],dYv[8];
385 double dXc,dYc;
386 double dGain;
389
394
395 unsigned char R_MAX, G_MAX, B_MAX;
396
398 static int m_maxRange;
399 static double *Exponential;
400
401 // scaled
403 int xv[8],yv[8];
404
407
409
411
412 public:
415};
416
417#endif
@ data
#define MAX_TAXELS
Definition TouchSensor.h:18
#define M_PI
Definition XSensMTx.cpp:24
double dX[MAX_TAXELS]
int Abs(int x)
bool connected[MAX_TAXELS]
unsigned char R_MAX
bool calibrated_skin
Definition TouchSensor.h:24
double m_Radius
int x[MAX_TAXELS]
virtual ~TouchSensor()
double activation[MAX_TAXELS]
double m_RadiusOrig
static double dXmin
double remapped_activation[MAX_TAXELS]
void setActivationFromPortData(double val, int id)
void eval(unsigned char *image)
void resize(int width, int height, int margin)
Definition TouchSensor.h:48
void setCalibrationFlag(bool use_calibrated_skin)
Definition TouchSensor.h:43
static double * Exponential
static double dYmax
double dXv[8]
int get_nTaxels()
void setActivationFirst7(unsigned char *data)
double dY[MAX_TAXELS]
void drawLine(unsigned char *image, int x0, int y0, int x1, int y1)
void setActivationLast5(unsigned char *data)
virtual void draw(unsigned char *image)
static double dXmax
void dither(int x, int y, unsigned char *image)
double dYv[8]
int m_maxRangeLight
int y[MAX_TAXELS]
void drawCircle(unsigned char *image, int cx, int cy, double radius)
static int m_maxRange
unsigned char G_MAX
static double dYmin
unsigned char B_MAX
void setColor(unsigned char r, unsigned char g, unsigned char b)
Definition TouchSensor.h:36
void eval_light(unsigned char *image)
exp(-x3 *T)]
int n