iCub-main
Loading...
Searching...
No Matches
compensator.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2009 RobotCub Consortium, European Commission FP6 Project IST-004370
3 * Authors: Andrea Del Prete, Alexander Schmitz
4 * email: andrea.delprete@iit.it, alexander.schmitz@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#include <yarp/os/Time.h>
19#include <yarp/math/Math.h>
20#include <yarp/math/Rand.h> // TEMP
21#include "math.h"
22#include <algorithm>
24
25
26using namespace std;
27using namespace yarp::os;
28using namespace yarp::sig;
29using namespace yarp::math;
30using namespace iCub::skinManager;
31using namespace iCub::skinDynLib;
32
33const double Compensator::BIN_TOUCH = 100.0;
34const double Compensator::BIN_NO_TOUCH = 0.0;
35
36Compensator::Compensator(string _name, string _robotName, string outputPortName, string inputPortName, BufferedPort<Bottle>* _infoPort,
37 double _compensationGain, double _contactCompensationGain, int addThreshold, float _minBaseline, bool _zeroUpRawData,
38 bool _binarization, bool _smoothFilter, float _smoothFactor, unsigned int _linkNum)
39 :
40 compensationGain(_compensationGain), contactCompensationGain(_contactCompensationGain),
41 addThreshold(addThreshold), infoPort(_infoPort),
42 minBaseline(_minBaseline), binarization(_binarization), smoothFilter(_smoothFilter),
43 smoothFactor(_smoothFactor), robotName(_robotName), name(_name), linkNum(_linkNum)
44{
45 this->zeroUpRawData = _zeroUpRawData;
46 _isWorking = init(_name, _robotName, outputPortName, inputPortName);
47}
48
50 if(tactileSensorDevice){
51 tactileSensorDevice->close();
52 delete tactileSensorDevice;
53 }
54
55 compensatedTactileDataPort.interrupt();
56 compensatedTactileDataPort.close();
57}
58
59bool Compensator::init(string name, string robotName, string outputPortName, string inputPortName){
61 bodyPart = BODY_PART_UNKNOWN;
62
63 if (!compensatedTactileDataPort.open(outputPortName.c_str())) {
64 stringstream msg; msg<< "Unable to open output port "<< outputPortName;
65 sendInfoMsg(msg.str());
66 return false; // unable to open
67 }
68
69 Property options;
70 stringstream localPortName;
71 localPortName<< "/"<< name<< "/input";
72 options.put("robot", robotName.c_str());
73 options.put("local", localPortName.str().c_str());
74 options.put("remote", inputPortName.c_str());
75 options.put("device", "analogsensorclient");
76 tactileSensorDevice_inputPortName=inputPortName.c_str();
77
78 // create a new device driver
79 tactileSensorDevice = new PolyDriver(options);
80 if (!tactileSensorDevice->isValid()){
81 sendInfoMsg("Device not available.\n");
82 //printf("%s", Drivers::factory().toString().c_str());
83 return false;
84 }
85 // open the sensor interface
86 bool ok = tactileSensorDevice->view(tactileSensor);
87 if (!ok) {
88 sendInfoMsg("Problems acquiring interfaces");
89 return false;
90 }
91
92 // (temp) open port to read skin data with timestamp (because device driver doesn't provide timestamps)
93 localPortName<< "_temp";
94 if(!inputPort.open(localPortName.str().c_str()))
95 {
96 stringstream msg; msg<< "Unable to open input data port "<< localPortName.str();
97 sendInfoMsg(msg.str());
98 return false;
99 }
100
101 if( !Network::connect(inputPortName.c_str(), localPortName.str().c_str()))
102 {
103 stringstream msg;
104 msg<< "Problems trying to connect ports %s and %s."<< inputPortName.c_str()<< localPortName.str().c_str();
105 sendInfoMsg(msg.str());
106 return false;
107 }
108
109 int getChannelsCounter = 0;
110 skinDim = tactileSensor->getChannels();
111 while(skinDim<=0){
112 // getChannels() returns 0 if it hasn't performed the first reading yet
113 // so wait for 1/50 sec, then try again
114 if(++getChannelsCounter==50){
115 // after 50 failed trials give up and use the default value
116 skinDim = 192;
117 sendInfoMsg("Error reading the number of channels of the port. Using 192 as default value.");
118 break;
119 }
120 Time::delay(0.02);
121 skinDim = tactileSensor->getChannels();
122 }
123 readErrorCounter = 0;
124 rawData.resize(skinDim);
125 baselines.resize(skinDim);
126 touchThresholds.resize(skinDim);
127 touchDetected.resize(skinDim);
128 subTouchDetected.resize(skinDim);
129 touchDetectedFilt.resize(skinDim);
130 compensatedData.resize(skinDim);
131 compensatedDataOld.resize(skinDim);
132 compensatedDataFilt.resize(skinDim);
133 taxelPos.resize(skinDim, zeros(3));
134 taxelOri.resize(skinDim, zeros(3));
135 taxelPoseConfidence.resize(skinDim,0.0);
136 maxNeighDist = MAX_NEIGHBOR_DISTANCE;
137 // by default every taxel is neighbor with all the other taxels
138 list<int> defaultNeighbors(skinDim);
139 int i=0;
140 for(list<int>::iterator it=defaultNeighbors.begin();it!=defaultNeighbors.end();it++, i++)
141 *it = i;
142 neighborsXtaxel.resize(skinDim, defaultNeighbors);
143
144 // test read to check if the skin is broken (all taxel output is 0)
145 if(robotName!="icubSim" && readInputData(compensatedData)){
146 bool skinBroken = true;
147 for(unsigned int i=0; i<skinDim; i++){
148 if(compensatedData[i]!=0.0){
149 skinBroken = false;
150 break;
151 }
152 }
153 if(skinBroken)
154 sendInfoMsg("The output of all the taxels is 0. Probably there is a hardware problem.");
155 return !skinBroken;
156 }
157
158 return true;
159}
160
162 // take the semaphore so that the touchThreshold can't be read during the calibration phase
163 lock_guard<mutex> lck(touchThresholdSem);
164
165 // send a command to the microcontroller for calibrating the skin sensors
166 if(robotName!="icubSim"){ // this feature isn't implemented in the simulator and causes a runtime error
167 tactileSensor->calibrateSensor();
168 }
169
170 // initialize
171 calibrationRead = 0;
172 saturatedTaxels.resize(0);
173 start_sum.assign(skinDim, 0);
174 skin_empty.assign(skinDim, vector<int>(MAX_SKIN+1, 0));
175}
176
178 Vector skin_values(skinDim);
179 if(!readInputData(skin_values))
180 return;
181 calibrationRead++;
182
183 for (unsigned int j=0; j<skinDim; j++) {
184 if (zeroUpRawData==false)
185 skin_values[j] = MAX_SKIN - skin_values[j];
186
187 if(skin_values[j]<0 || skin_values[j]>MAX_SKIN)
188 sendInfoMsg("Error while reading the tactile data! Data out of range: "+toString(skin_values[j]));
189 else{
190 skin_empty[j][int(skin_values[j])]++;
191 start_sum[j] += int(skin_values[j]);
192 }
193 }
194}
195
197
198 //vector<float> standard_dev(skinDim, 0);
199 //get percentile
200 for (unsigned int i=0; i<skinDim; i++) {
201 //avg start value
202 baselines[i] = start_sum[i]/ (calibrationRead!=0.0 ? calibrationRead : 1.0);
203
204 //cumulative values
205 for (int j=1; j<=MAX_SKIN; j++) {
206 //standard_dev[i] += fabs(j-baselines[i]) * skin_empty[i][j];
207 skin_empty[i][j] += skin_empty[i][j-1] ;
208 }
209 //standard_dev[i] /= (CAL_TIME*PERIOD);
210
211 //when do we cross the threshold? Compute 95 percentile
212 if( skin_empty[i][MAX_SKIN] < 0.95*calibrationRead )
213 {
214 sendInfoMsg("Error during calibration. Most readings were out of range.");
215 _isWorking = false;
216 }
217 else
218 {
219 for (int j=0; j<=MAX_SKIN; j++)
220 {
221 if (skin_empty[i][j] > (calibrationRead*0.95))
222 {
223 // the threshold can not be less than MIN_TOUCH_THR
224 touchThresholds[i] = (double)j - baselines[i];
225 j = MAX_SKIN; // break
226 }
227 }
228 }
229
230
231 }
232 // store the initial baseline to compute the drift compensated later
233 initialBaselines = baselines;
234
235 // set the "old output value" for the smoothing filter to the baseline value to get a smooth start
236 compensatedDataOld = baselines;
237
238 // test to check if the skin is broken (all taxel baselines are 255 OR thresholds are 0)
239 bool baseline255 = true, thresholdZero = true;
240 for(unsigned int i=0; i<skinDim; i++){
241 if(baselines[i]!=255){
242 baseline255 = false;
243 }
244 if(robotName=="icubSim" || touchThresholds[i]>1e-5){
245 thresholdZero = false;
246 }
247 }
248 if(baseline255 || thresholdZero){
249 _isWorking = false;
250// if(baseline255)
251// sendInfoMsg("The baselines of all the taxels are 255. Probably there is a hardware problem.");
252// if(thresholdZero)
253// sendInfoMsg("The noise of all taxels is 0. Probably there is a hardware problem.");
254 }
255 for (unsigned int i=0; i<skinDim; i++)
256 touchThresholds[i] = max<double>(MIN_TOUCH_THR, touchThresholds[i]);
257
258 // print to console
259 /*if(_isWorking){
260 printf("\n[%s (%s)] Baselines:\n", name.c_str(), getSkinPartName().c_str());
261 for (unsigned int i=0; i<skinDim; i++) {
262 if(!(i%12)) fprintf(stderr, "\n");
263 fprintf(stderr,"%5.1f ", baselines[i]);
264 }
265 printf("\n[%s (%s)] Thresholds (95 percentile):\n", name.c_str(), getSkinPartName().c_str());
266 for (unsigned int i=0; i<skinDim; i++) {
267 if(!(i%12)) fprintf(stderr, "\n");
268 touchThresholds[i] = max<double>(MIN_TOUCH_THR, touchThresholds[i]);
269 fprintf(stderr,"%3.1f ", touchThresholds[i]);
270 }
271 printf("\n");
272 }*/
273 sendInfoMsg("Calibration finished");
274}
275
276bool Compensator::readInputData(Vector& skin_values){
277 Vector *tmp=0;
278 if((tmp=inputPort.read(false))==0){
279 readErrorCounter++;
280 if(readErrorCounter>MAX_READ_ERROR){
281 _isWorking = false;
282 sendInfoMsg("Too many errors in a row. Stopping the compensator.");
283 }
284 return false;
285 }
286 //try to read envelope of input data port
287 inputPort.getEnvelope(timestamp);
288
289 skin_values = *tmp; // copy data
290
291 if(skin_values.size() != skinDim){
292 readErrorCounter++;
293 sendInfoMsg("Unexpected size of the input array (raw tactile data): "+toString(skin_values.size()));
294 if(readErrorCounter>MAX_READ_ERROR){
295 _isWorking = false;
296 sendInfoMsg("Too many errors in a row. Stopping the compensator.");
297 }
298 return false;
299 }
300
301 readErrorCounter = 0;
302 return true;
303/*
304 int err;
305 if((err=tactileSensor->read(skin_values))!=IAnalogSensor::AS_OK){
306 readErrorCounter++;
307
308 stringstream msg;
309 if(err == IAnalogSensor::AS_TIMEOUT)
310 msg<< "Timeout error reading tactile sensor.";
311 else if(err == IAnalogSensor::AS_OVF)
312 msg<< "Ovf error reading tactile sensor.";
313 else if(err == IAnalogSensor::AS_ERROR)
314 msg<< "Generic error reading tactile sensor.";
315 sendInfoMsg(msg.str());
316
317 if(readErrorCounter>MAX_READ_ERROR){
318 _isWorking = false;
319 sendInfoMsg("Too many errors in a row. Stopping the compensator.");
320 }
321 return false;
322 }
323
324 if(skin_values.size() != skinDim){
325 readErrorCounter++;
326 sendInfoMsg("Unexpected size of the input array (raw tactile data): "+toString(skin_values.size()));
327 if(readErrorCounter>MAX_READ_ERROR){
328 _isWorking = false;
329 sendInfoMsg("Too many errors in a row. Stopping the compensator.");
330 }
331 return false;
332 }
333
334 readErrorCounter = 0;
335 return true;*/
336}
337
339 if(!readInputData(rawData))
340 return false;
341
342 Vector& compensatedData2Send = compensatedTactileDataPort.prepare();
343 compensatedData2Send.resize(skinDim); // local variable with data to send
344 compensatedData.resize(skinDim); // global variable with data to store
345
346 double d;
347 for(unsigned int i=0; i<skinDim; i++){
348 // baseline compensation
349 d = (double)( zeroUpRawData ? rawData(i)-baselines[i] : MAX_SKIN-rawData(i)-baselines[i] );
350 d = min<double>( MAX_SKIN, d);
351 compensatedData[i] = d; // save the data before applying filtering
352
353 // detect touch (before applying filtering, so the compensation algorithm is not affected by the filters)
354 touchDetected[i] = (d > touchThresholds[i] + addThreshold);
355
356 // detect subtouch
357 subTouchDetected[i] = (d < -touchThresholds[i] - addThreshold);
358
359 // smooth filter
360 if(smoothFilter){
361 lock_guard<mutex> lck(smoothFactorSem);
362 d = (1-smoothFactor)*d + smoothFactor*compensatedDataOld(i);
363 compensatedDataOld(i) = d; // update old value
364 }
365 compensatedDataFilt[i] = d;
366
367 // binarization filter
368 // here we don't use the touchDetected array because, if the smooth filter is on,
369 // we want to use the filtered values
370 touchDetectedFilt[i] = (d > touchThresholds[i] + addThreshold);
371 if(binarization)
372 d = ( touchDetectedFilt[i] ? BIN_TOUCH : BIN_NO_TOUCH );
373
374 compensatedData2Send[i] = max<double>(0.0, d); // trim only data to send because you need negative values for update baseline
375 }
376
377 compensatedTactileDataPort.write();
378 return true;
379}
380
382 double mean_change = 0, change, gain;
383 unsigned int non_touching_taxels = 0;
384 double d;
385
386 for(unsigned int j=0; j<skinDim; j++) {
387 // *** Algorithm 1
388 /*if(!touchDetected[j]){
389 if(d > 0.5) {
390 baselines[j] += compensationGain;
391 mean_change += compensationGain; //for changing the taxels where we detected touch
392 }else if(d < -0.5) {
393 baselines[j] -= compensationGain;
394 mean_change -= compensationGain; //for changing the taxels where we detected touch
395 }
396 }*/
397
398 // *** Algorithm 2
399 /*if(!(touchDetected[j] || subTouchDetected[j])){
400 non_touching_taxels++; //for changing the taxels where we detected touch
401 d = compensatedData(j);
402 if(fabs(d)>0.5){
403 change = (compensationGain/50)*d/touchThresholds[j];
404 baselines[j] += change;
405 mean_change += change;
406 }
407 }*/
408
409 d = compensatedData(j);
410 if(touchDetected[j]){
411 gain = contactCompensationGain*0.02;
412 }else{
413 gain = compensationGain*0.02;
414 non_touching_taxels++;
415 }
416 change = gain*d/touchThresholds[j];
417 baselines[j] += change;
418 mean_change += change;
419
420 // if(j<5)
421 // printf("%d touch detected %s, change %.6f, gain: %.3f\n", j, touchDetected[j]?"yes":"no", change, touchDetected[j]?contactCompensationGain:compensationGain);
422
423 if(baselines[j]<0){
424 char* temp = new char[300];
425 sprintf(temp, "ERROR-Negative baseline. Port %s; tax %d; baseline %.2f; gain: %.4f; d: %.2f; raw: %.2f; change: %f; touchThr: %.2f",
426 SkinPart_s[skinPart].c_str(), j, baselines[j], gain, d, rawData[j], change, touchThresholds[j]);
427 sendInfoMsg(temp);
428 }
429 }
430
431 //for compensating the taxels where we detected touch
432 /*if (non_touching_taxels>0 && non_touching_taxels<skinDim && mean_change!=0){
433 mean_change /= non_touching_taxels;
434 for(unsigned int j=0; j<skinDim; j++) {
435 if (touchDetected[j]) {
436 baselines[j] += mean_change;
437 if(baselines[j]<0){
438 char* temp = new char[300];
439 sprintf(temp, "ERROR-Negative baseline. Taxel %d; baseline %.2f; meanchange: %f", j, baselines[j], mean_change);
440 sendInfoMsg(temp);
441 }
442 }
443 }
444 }*/
445}
446
447bool Compensator::doesBaselineExceed(unsigned int &taxelIndex, double &baseline, double &initialBaseline){
448 vector<unsigned int>::iterator it;
449 for(unsigned int i=0; i<skinDim; i++){
450 if(baselines[i]<minBaseline || baselines[i]>MAX_SKIN-minBaseline){
451 it = find(saturatedTaxels.begin(), saturatedTaxels.end(), i);
452 if(it==saturatedTaxels.end()){ // if the taxel hasn't been already signalled
453 //fprintf(stderr, "Baseline %d exceeds: %f\n", i, baselines[i]);
454 saturatedTaxels.push_back(i);
455 baseline = baselines[i];
456 initialBaseline = initialBaselines[i];
457 taxelIndex = i;
458 return true;
459 }
460 }
461 }
462 return false;
463}
464
466 vector<int> contactXtaxel(skinDim, -1); // contact for each taxel (-1 means no contact)
467 deque<deque<int> > taxelsXcontact; // taxels for each contact
468 int contactId = 0; // id of the next contact to create
469 int neighCont; // id of the contact of the current neighbor
470
471 poseSem.lock();
472 {
473 for(unsigned int i=0; i<skinDim; i++){
474 if(touchDetectedFilt[i] ){ // && contactXtaxel[i]<0 (second condition should always be true)
475 list<int> *neighbors = &(neighborsXtaxel[i]);
476 //printf("Taxel %d active. Going to check its %d neighbors\n", i, neighbors->size());
477 for(list<int>::iterator it=neighbors->begin(); it!=neighbors->end(); it++){
478 neighCont = contactXtaxel[(*it)];
479 if(neighCont >= 0){ // ** if neighbor belongs to a contact
480 if(contactXtaxel[i]<0){ // ** add taxel to pre-existing contact
481 contactXtaxel[i] = neighCont;
482 taxelsXcontact[neighCont].push_back(i);
483 //printf("Add taxel to pre existing contact %d (neighbor %d)\n", neighCont, (*neighbors)[n]);
484 }else if(contactXtaxel[i]!=neighCont){ // ** merge 2 contacts
485 //mergeContacts(contactXtaxel[i], neighCont);
486 int newId = min(contactXtaxel[i], neighCont);
487 int oldId = max(contactXtaxel[i], neighCont);
488 deque<int> tax2move = taxelsXcontact[oldId];
489 for(deque<int>::iterator it=tax2move.begin(); it!=tax2move.end(); it++){
490 contactXtaxel[(*it)] = newId; // assign new contact id
491 taxelsXcontact[newId].push_back((*it)); // add taxel ids to contact
492 }
493 taxelsXcontact[oldId].clear(); // clear the list of taxels belonging to the merged contact
494 //printf("Merge two contacts: %d and %d\n", oldId, newId);
495 }
496 }
497
498 }
499 if(contactXtaxel[i]<0){ // ** if no neighbor belongs to a contact -> create new contact
500 contactXtaxel[i] = contactId;
501 taxelsXcontact.resize(contactId+1);
502 taxelsXcontact[contactId].push_back(i);
503 contactId++;
504 //printf("New contact created: %d\n", contactId-1);
505 }
506 }
507 }
508 }
509 poseSem.unlock();
510
511 skinContactList contactList;
512 Vector CoP(3), geoCenter(3), normal(3);
513 double pressure, pressureCoP, pressureNormal, out;
514 int activeTaxels, activeTaxelsGeo;
515 vector<unsigned int> taxelList;
516 for( deque<deque<int> >::iterator it=taxelsXcontact.begin(); it!=taxelsXcontact.end(); it++){
517 activeTaxels = it->size();
518 if(activeTaxels==0) continue;
519
520 taxelList.resize(activeTaxels);
521 CoP.zero();
522 geoCenter.zero();
523 normal.zero();
524 pressure = pressureCoP = pressureNormal = 0.0;
525 activeTaxelsGeo = 0;
526 int i=0;
527 for( deque<int>::iterator tax=it->begin(); tax!=it->end(); tax++, i++){
528 out = max(compensatedDataFilt[(*tax)], 0.0);
529 if(norm(taxelPos[(*tax)])!=0.0){ // if the taxel position estimate exists
530 CoP += taxelPos[(*tax)] * out;
531 pressureCoP += out;
532 activeTaxelsGeo++;
533 geoCenter += taxelPos[(*tax)];
534 }
535 if(norm(taxelOri[(*tax)])!=0.0){ // if the taxel orientation estimate exists
536 normal += taxelOri[(*tax)] * out;
537 pressureNormal += out;
538 }
539 pressure += out;
540 taxelList[i] = *tax;
541 }
542 // if this is not the only contact and no taxel in this contact has a position => discard it
543 if(taxelsXcontact.size()>1 && activeTaxelsGeo==0)
544 continue;
545 if(pressureCoP!=0.0) CoP /= pressureCoP;
546 if(pressureNormal!=0.0) normal /= pressureNormal;
547 if(activeTaxelsGeo!=0) geoCenter /= activeTaxelsGeo;
548 pressure /= activeTaxels;
549 skinContact c(bodyPart, skinPart, linkNum, CoP, geoCenter, taxelList, pressure, normal);
550 // set an estimate of the force that is with normal direction and intensity equal to the pressure
551 c.setForce(-0.05*activeTaxels*pressure*normal);
552 contactList.push_back(c);
553 }
554 //printf("ContactList: %s\n", contactList.toString().c_str());
555
556 return contactList;
557}
558
560 if(smoothFilter != value){
561 smoothFilter = value;
562 if(value){
563 // set the old output value of the smooth filter to the last read, to get a smooth start
564 compensatedDataOld = compensatedData;
565 }
566 }
567}
569 if(value<0.0 || value>1.0)
570 return false;
571 if(value==1.0)
572 value = 0.99f; // otherwise with 1 the values don't update
573 lock_guard<mutex> lck(smoothFactorSem);
574 smoothFactor = value;
575 return true;
576}
577
579 this->skinPart = _skinPart;
580 this->bodyPart = skinDynLib::getBodyPart(skinPart);
581 this->linkNum = skinDynLib::getLinkNum(skinPart);
582}
583
584bool Compensator::setAddThreshold(unsigned int thr){
585 if(thr>=MAX_SKIN)
586 return false;
587 addThreshold = thr;
588 return true;
589}
590
592 if(gain<=0.0)
593 return false;
594 compensationGain = gain;
595 return true;
596}
597
599 if(gain<0.0)
600 return false;
601 contactCompensationGain = gain;
602 return true;
603}
604
606 if(_isWorking)
607 return skinDim;
608 return 0;
609}
610
611Vector Compensator::getCompensation(){ return baselines-initialBaselines; }
612
614 lock_guard<mutex> lck(touchThresholdSem);
615 return touchThresholds;
616}
617
619 lock_guard<mutex> lck(smoothFactorSem);
620 return smoothFactor;
621}
622Vector Compensator::getTaxelPosition(unsigned int taxelId){
623 if(taxelId>=skinDim)
624 return zeros(0);
625 lock_guard<mutex> lck(poseSem);
626 Vector res = taxelPos[taxelId];
627 res.push_back(taxelPoseConfidence[taxelId]);
628 return res;
629}
631 lock_guard<mutex> lck(poseSem);
632 vector<Vector> res = taxelPos;
633 for(unsigned int i=0; i<res.size(); i++)
634 res[i].push_back(taxelPoseConfidence[i]);
635 return res;
636}
637Vector Compensator::getTaxelOrientation(unsigned int taxelId){
638 if(taxelId>=skinDim)
639 return zeros(0);
640 lock_guard<mutex> lck(poseSem);
641 Vector res = taxelOri[taxelId];
642 res.push_back(taxelPoseConfidence[taxelId]);
643 return res;
644}
646 lock_guard<mutex> lck(poseSem);
647 vector<Vector> res = taxelOri;
648 for(unsigned int i=0; i<res.size(); i++)
649 res[i].push_back(taxelPoseConfidence[i]);
650 return res;
651}
652Vector Compensator::getTaxelPose(unsigned int taxelId){
653 if(taxelId>=skinDim)
654 return zeros(0);
655 lock_guard<mutex> lck(poseSem);
656 Vector res = cat(taxelPos[taxelId], taxelOri[taxelId]);
657 res.push_back(taxelPoseConfidence[taxelId]);
658 return res;
659}
661 vector<Vector> res(skinDim);
662 lock_guard<mutex> lck(poseSem);
663 for(unsigned int i=0; i<skinDim; i++){
664 res[i] = cat(taxelPos[i], taxelOri[i]);
665 res[i].push_back(taxelPoseConfidence[i]);
666 }
667 return res;
668}
669
670double Compensator::getPoseConfidence(unsigned int taxelId){
671 if(taxelId>=skinDim)
672 return -1.0;
673 lock_guard<mutex> lck(poseSem);
674 return taxelPoseConfidence[taxelId];
675}
676
678 lock_guard<mutex> lck(poseSem);
679 return taxelPoseConfidence;
680}
681
683 if(d<0.0)
684 return false;
685 maxNeighDist = d;
686 lock_guard<mutex> lck(poseSem);
687 computeNeighbors();
688 return true;
689}
690
691bool Compensator::setTaxelPosesFromFile(const char *filePath){
692 yarp::os::ResourceFinder rf;
693 rf.setDefaultContext("skinGui"); //overridden by --context parameter
694 rf.setDefaultConfigFile(filePath); //overridden by --from parameter
695 rf.configure(0,NULL);
696
697 yarp::os::Bottle &calibration = rf.findGroup("calibration");
698 if (calibration.isNull())
699 {
700 return setTaxelPosesFromFileOld(filePath);
701 }
702 else
703 {
704 lock_guard<mutex> lck(poseSem);
705 int size=calibration.size()-1;
706 skinDim=size;
707 taxelPos.resize(skinDim, zeros(3));
708 taxelOri.resize(skinDim, zeros(3));
709 taxelPoseConfidence.resize(skinDim, 0.0);
710 for (int i = 0; i < size; ++i)
711 {
712 if (i<(int)taxelPos.size())
713 {
714 Vector taxelPosNrm(6,0.0);
715 taxelPosNrm = iCub::skinDynLib::vectorFromBottle(*(calibration.get(i+1).asList()),0,6);
716 taxelPos[i] = taxelPosNrm.subVector(0,2);
717 taxelOri[i] = taxelPosNrm.subVector(3,5);
718 }
719 if(norm(taxelPos[i])>0.0)
720 taxelPoseConfidence[i] = 1.0;
721 }
722 computeNeighbors();
723 }
724
725 return true;
726}
727
728bool Compensator::setTaxelPosesFromFileOld(const char *filePath){
729 ifstream posFile;
730 posFile.open(filePath);
731 if (!posFile.is_open())
732 return false;
733
734 string posLine;
735 int totalLines = 0;
736 while (getline(posFile,posLine)){
737 posLine.erase(posLine.find_last_not_of(" \n\r\t")+1);
738 if(!posLine.empty())totalLines++;
739 }
740 posFile.clear();
741 posFile.seekg(0, std::ios::beg);//rewind iterator
742 if(totalLines!=skinDim){
743 char* temp = new char[200];
744 sprintf(temp, "Error while reading taxel position file %s: num of lines %d is not equal to num of taxels %d.\n",
745 filePath, totalLines, skinDim);
746 sendInfoMsg(temp);
747 }
748 lock_guard<mutex> lck(poseSem);
749 {
750 for(unsigned int i= 0; getline(posFile,posLine); i++) {
751 posLine.erase(posLine.find_last_not_of(" \n\r\t")+1);
752 if(posLine.empty())
753 continue;
754 string number;
755 istringstream iss(posLine, istringstream::in);
756 for(unsigned int j = 0; iss >> number; j++ ){
757 if(i<taxelPos.size()){
758 if(j<3)
759 taxelPos[i][j] = strtod(number.c_str(),NULL);
760 else
761 taxelOri[i][j-3] = strtod(number.c_str(),NULL);
762 }
763 }
764 if(norm(taxelPos[i])>0.0)
765 taxelPoseConfidence[i] = 1.0;
766 }
767 computeNeighbors();
768 }
769 return true;
770}
771bool Compensator::setTaxelPoses(const vector<Vector> &poses){
772 if(poses.size()!=skinDim)
773 return false;
774 lock_guard<mutex> lck(poseSem);
775 {
776 for(unsigned int i=0; i<skinDim; i++){
777 taxelPos[i] = poses[i].subVector(0,2);
778 taxelOri[i] = poses[i].subVector(3,5);
779 if(poses[i].size() == 7)
780 taxelPoseConfidence[i] = poses[i][6];
781 }
782 }
783 computeNeighbors();
784 return true;
785}
786bool Compensator::setTaxelPose(unsigned int taxelId, const Vector &pose){
787 if(taxelId>=skinDim || pose.size()!=6)
788 return false;
789 lock_guard<mutex> lck(poseSem);
790 {
791 taxelPos[taxelId] = pose.subVector(0,2);
792 taxelOri[taxelId] = pose.subVector(3,5);
793 if(pose.size() == 7)
794 taxelPoseConfidence[taxelId] = pose[6];
795 }
796 updateNeighbors(taxelId);
797 return true;
798}
799bool Compensator::setTaxelPositions(const Vector &positions){
800 lock_guard<mutex> lck(poseSem);
801 if(skinDim*3 == positions.size()){
802 for(unsigned int j=0; j<skinDim; j++){
803 taxelPos[j] = positions.subVector(3*j, 3*j+2);
804 }
805 }
806 else if(skinDim*4 == positions.size()){
807 for(unsigned int j=0; j<skinDim; j++){
808 taxelPos[j] = positions.subVector(4*j, 4*j+2);
809 taxelPoseConfidence[j] = positions[4*j+3];
810 }
811 }
812 else
813 return false;
814
815 computeNeighbors();
816 return true;
817}
818
819bool Compensator::setTaxelPosition(unsigned int taxelId, const Vector &position){
820 if(taxelId>=skinDim || (position.size()!=3 && position.size()!=4))
821 return false;
822 lock_guard<mutex> lck(poseSem);
823 taxelPos[taxelId] = position.subVector(0,2);
824 if(position.size()==4)
825 taxelPoseConfidence[taxelId] = position[3];
826 updateNeighbors(taxelId);
827 return true;
828}
829bool Compensator::setTaxelOrientations(const vector<Vector> &orientations){
830 if(orientations.size()!=skinDim)
831 return false;
832 lock_guard<mutex> lck(poseSem);
833 taxelOri = orientations;
834 return true;
835}
836bool Compensator::setTaxelOrientation(unsigned int taxelId, const Vector &orientation){
837 if(taxelId>=skinDim || (orientation.size()!=3 && orientation.size()!=4))
838 return false;
839 lock_guard<mutex> lck(poseSem);
840 taxelOri[taxelId] = orientation.subVector(0,2);
841 if(orientation.size()==4)
842 taxelPoseConfidence[taxelId] = orientation[3];
843 return true;
844}
845void Compensator::computeNeighbors(){
846 neighborsXtaxel.clear();
847 neighborsXtaxel.resize(skinDim, list<int>(0));
848 Vector v;
849 double d2 = maxNeighDist*maxNeighDist;
850 for(unsigned int i=0; i<skinDim; i++){
851 for(unsigned int j=i+1; j<skinDim; j++){
852 //if(taxelPos[i][0]!=0.0 || taxelPos[i][1]!=0.0 || taxelPos[i][2]!=0.0){ // if the taxel exists
853 v = taxelPos[i]-taxelPos[j];
854 if( dot(v,v) <= d2){
855 neighborsXtaxel[i].push_back(j);
856 neighborsXtaxel[j].push_back(i);
857 //printf("Taxels %d (%s) and %d (%s) are neighbors\n", i, taxelPos[i].toString().c_str(), j, taxelPos[j].toString().c_str());
858 }
859 //}
860 }
861 }
862
863 int minNeighbors=skinDim, maxNeighbors=0, ns;
864 for(unsigned int i=0; i<skinDim; i++){
865 //if(taxelPos[i][0]!=0.0 || taxelPos[i][1]!=0.0 || taxelPos[i][2]!=0.0){ // if the taxel exists
866 ns = neighborsXtaxel[i].size();
867 if(ns>maxNeighbors) maxNeighbors = ns;
868 if(ns<minNeighbors) minNeighbors = ns;
869 }
870 stringstream ss;
871 ss<<"Neighbors computed. Min neighbors: "<<minNeighbors<<"; max neighbors: "<<maxNeighbors;
872 sendInfoMsg(ss.str());
873}
874void Compensator::updateNeighbors(unsigned int taxelId){
875 Vector v;
876 double d2 = maxNeighDist*maxNeighDist;
877 // remove all the neighbors of the taxel with id=taxelId
878 neighborsXtaxel[taxelId].clear();
879
880 for(unsigned int i=0; i<skinDim; i++){
881 //if(taxelPos[i][0]!=0.0 || taxelPos[i][1]!=0.0 || taxelPos[i][2]!=0.0){ // if the taxel exists
882 // remove taxelId from the neighbor list (if there is)
883 neighborsXtaxel[i].remove(taxelId);
884 // check whether they are neighbors
885 v = taxelPos[i]-taxelPos[taxelId];
886 if( dot(v,v) <= d2){
887 neighborsXtaxel[i].push_back(taxelId);
888 neighborsXtaxel[taxelId].push_back(i);
889 }
890 }
891}
892
893void Compensator::sendInfoMsg(string msg){
894 yInfo("[%s]: %s", getInputPortName().c_str(), msg.c_str());
895 Bottle& b = infoPort->prepare();
896 b.clear();
897 b.addString(getInputPortName().c_str());
898 b.addString((": " + msg).c_str());
899 infoPort->write(true);
900}
virtual bool setForce(const yarp::sig::Vector &_F)
Set the contact force.
Class representing a list of external contacts acting on the iCub' skin.
Class representing an external contact acting on the iCub' skin.
Definition skinContact.h:50
Class that encloses everything relate to a skinPart.
Definition skinPart.h:146
bool setTaxelPoses(const vector< Vector > &poses)
bool setTaxelPose(unsigned int taxelId, const Vector &pose)
bool setTaxelPosesFromFile(const char *filePath)
vector< Vector > getTaxelOrientations()
Compensator(string name, string robotName, string outputPortName, string inputPortName, BufferedPort< Bottle > *_infoPort, double _compensationGain, double _contactCompensationGain, int addThreshold, float _minBaseline, bool _zeroUpRawData, bool _binarization, bool _smoothFilter, float _smoothFactor, unsigned int _linkId=0)
vector< Vector > getTaxelPoses()
bool setSmoothFactor(float value)
bool setTaxelOrientations(const vector< Vector > &orientations)
bool setTaxelPosition(unsigned int taxelId, const Vector &position)
double getPoseConfidence(unsigned int taxelId)
bool setAddThreshold(unsigned int thr)
bool setContactCompensationGain(double gain)
bool doesBaselineExceed(unsigned int &taxelIndex, double &baseline, double &initialBaseline)
bool setTaxelPosesFromFileOld(const char *filePath)
void setSkinPart(SkinPart _skinPart)
vector< Vector > getTaxelPositions()
Vector getTaxelPosition(unsigned int taxelId)
bool setTaxelOrientation(unsigned int taxelId, const Vector &orientation)
bool setTaxelPositions(const Vector &positions)
Vector getTaxelPose(unsigned int taxelId)
bool setCompensationGain(double gain)
Vector getTaxelOrientation(unsigned int taxelId)
zeros(2, 2) eye(2
double dot(const yarp::sig::Matrix &A, int colA, const yarp::sig::Matrix &B, int colB)
Returns the dot product between two vectors given in the form: matrix(:,col).
int getLinkNum(SkinPart s)
Get the link number associated to the specified skin part.
Definition common.cpp:34
yarp::sig::Vector vectorFromBottle(const yarp::os::Bottle b, int in, const int size)
Retrieves a vector from a bottle.
Definition common.cpp:89
BodyPart getBodyPart(SkinPart s)
Get the body part associated to the specified skin part.
Definition common.cpp:26
const std::string SkinPart_s[]
Definition common.h:64
std::string toString(const T &t)
static const double MAX_NEIGHBOR_DISTANCE
out
Definition sine.m:8