19#include <yarp/os/Time.h>
20#include <yarp/math/Math.h>
25#define FOR_ALL_PORTS(i) for(unsigned int i=0;i<portNum;i++)
28using namespace yarp::os;
29using namespace yarp::sig;
30using namespace yarp::math;
35 int addThreshold,
float minBaseline,
bool zeroUpRawData,
36 int period,
bool binarization,
bool smoothFilter,
float smoothFactor)
38 PeriodicThread((double)period/1000.0), moduleName(name), compensationGain(_compensationGain),
39 contactCompensationGain(_contactCompensationGain),
40 ADD_THRESHOLD(addThreshold), robotName(robotName),
41 binarization(binarization), smoothFilter(smoothFilter), smoothFactor(smoothFactor)
44 this->minBaseline = minBaseline;
45 this->zeroUpRawData = zeroUpRawData;
46 initializationFinished =
false;
51 yTrace(
"[CompensationThread] threadInit()\n");
56 calibrationCounter = 0;
57 CAL_SAMPLES = (int)((
double)CAL_TIME/getPeriod());
60 string monitorPortName =
"/" + moduleName +
"/monitor:o";
61 string infoPortName =
"/" + moduleName +
"/info:o";
62 if(!monitorPort.open(monitorPortName.c_str())){
63 stringstream msg; msg<<
"Unable to open port " << monitorPortName << endl;
64 sendErrorMsg(msg.str());
65 initializationFinished =
true;
68 if(!infoPort.open(infoPortName.c_str())){
69 stringstream msg; msg<<
"Unable to open port " << infoPortName << endl;
70 sendErrorMsg(msg.str());
71 initializationFinished =
true;
76 if(!rf->check(
"outputPorts") || !rf->check(
"inputPorts")){
77 stringstream msg; msg<<
"Input ports and/or output ports missing. Closing the module.";
78 sendErrorMsg(msg.str());
79 initializationFinished =
true;
83 Bottle* outputPortList = rf->find(
"outputPorts").asList();
84 Bottle* inputPortList = rf->find(
"inputPorts").asList();
85 portNum = outputPortList->size();
86 if(portNum<=0 || portNum!=inputPortList->size()){
88 msg<<
"No input port specified or mismatching number of input and output ports ("
89 << portNum<<
" out ports; "<< inputPortList->size()<<
" in ports).";
90 sendErrorMsg(msg.str());
91 initializationFinished =
true;
95 compensators.resize(portNum);
96 compWorking.resize(portNum);
97 compEnable.resize(portNum,
true);
98 compensatorCounter = portNum;
100 cout<< portNum<<
" input ports found in the configuration file\n";
102 string outputPortName = outputPortList->get(i).asString().c_str();
103 string inputPortName = inputPortList->get(i).asString().c_str();
105 yInfo(
"Input port: %s -> Output port: %s",inputPortName.c_str(),outputPortName.c_str());
107 name<< moduleName<< i;
108 compensators[i] =
new Compensator(name.str(), robotName, outputPortName, inputPortName, &infoPort,
109 compensationGain, contactCompensationGain, ADD_THRESHOLD, minBaseline, zeroUpRawData, binarization,
110 smoothFilter, smoothFactor);
111 SKIN_DIM += compensators[i]->getNumTaxels();
116 compWorking[i] = compensators[i]->isWorking();
119 msg<<
" Compensator "<< compensators[i]->getInputPortName().c_str()
120 <<
" did not open correctly. Removing the port.";
121 sendErrorMsg(msg.str());
122 if(compensatorCounter==1){
124 msg<<
"No input port left. Stopping the thread.";
125 sendErrorMsg(msg.str());
127 initializationFinished =
true;
130 compensatorCounter--;
131 SKIN_DIM -= compensators[i]->getNumTaxels();
137 skinEventsOn =
false;
138 Bottle &skinEventsConf = rf->findGroup(
"SKIN_EVENTS");
139 if(!skinEventsConf.isNull()){
140 yDebug(
"SKIN_EVENTS section found");
141 string eventPortName =
"/" + moduleName +
"/skin_events:o";
142 if(!skinEventsPort.open(eventPortName.c_str()))
143 sendErrorMsg(
"Unable to open port "+eventPortName);
147 if(skinEventsConf.check(
"skinParts")){
148 Bottle* skinPartList = skinEventsConf.find(
"skinParts").asList();
149 if(skinPartList->size() != portNum){
151 msg<<
"ERROR: the number of skin part ids is not equal to the number of input ports ("
152 << skinPartList->size()<<
"!="<< portNum<<
"). Skin parts will not be set.";
153 sendDebugMsg(msg.str());
157 yDebug(
"Skin part %s",
SkinPart_s[skinPartList->get(i).asInt32()].c_str());
158 compensators[i]->setSkinPart((
SkinPart)skinPartList->get(i).asInt32());
163 if(skinEventsConf.check(
"taxelPositionFiles")){
164 Bottle *taxelPosFiles = skinEventsConf.find(
"taxelPositionFiles").asList();
165 if(portNum!=taxelPosFiles->size()){
167 msg<<
"Mismatching number of taxel position files and input ports ("
168 <<portNum<<
" in ports; "<< taxelPosFiles->size()<<
" taxel position files). ";
169 msg<<
"Taxel positions will not be set.";
170 msg<<
". Taxel position file list: "<< taxelPosFiles->toString().c_str();
171 sendDebugMsg(msg.str());
176 yInfo(
"Max neighbor distance: %f m\n", maxNeighDist);
179 string taxelPosFile = taxelPosFiles->get(i).asString().c_str();
180 string filePath(rf->findFile(taxelPosFile.c_str()));
181 compensators[i]->setMaxNeighborDistance(maxNeighDist);
182 compensators[i]->setTaxelPosesFromFile(filePath.c_str());
189 sendDebugMsg(
"Skin events ENABLED.");
191 sendDebugMsg(
"Skin events DISABLED.");
193 initializationFinished =
true;
198 lock_guard<mutex> lck(stateSem);
201 calibrationCounter = 0;
213 if(compensators[i]->readRawAndWriteCompensatedData()){
215 compensators[i]->updateBaseline();
227 if(calibrationCounter==0)
228 compensators[i]->calibrationInit();
230 compensators[i]->calibrationDataCollection();
232 if(calibrationCounter==CAL_SAMPLES){
233 compensators[i]->calibrationFinish();
238 calibrationCounter++;
242 sendDebugMsg(
"[ERROR] Unknown state in CompensationThread. Suspending the thread.\n");
251void CompensationThread::sendSkinEvents(){
258 if(compWorking[i] && compEnable[i]){
259 temp = compensators[i]->getContacts();
260 timestamp = compensators[i]->getTimestamp();
261 skinEvents.insert(skinEvents.end(), temp.begin(), temp.end());
265 if(skinEvents.size()>0)
266 printf(
"SkinContacts size: %d\n", skinEvents.size());
270 skinEventsPort.setEnvelope(timestamp);
271 skinEventsPort.write();
274void CompensationThread::checkErrors(){
277 compWorking[i] = compensators[i]->isWorking();
279 if(compensatorCounter==1){
280 fprintf(stderr,
"No input port left. Stopping the compensation thread\n");
286 compensatorCounter--;
287 SKIN_DIM -= compensators[i]->getNumTaxels();
292 unsigned int taxInd, compInd;
293 double baseline, initialBaseline;
294 if(doesBaselineExceed(compInd, taxInd, baseline, initialBaseline)){
296 msg<<
"Baseline of the taxel "<< taxInd<<
" of port "<< compensators[compInd]->getInputPortName()
297 <<
" saturated (current baseline="<< baseline<<
"; initial baseline="<< initialBaseline<<
298 ")! A skin calibration is suggested.";
299 sendDebugMsg(msg.str());
303bool CompensationThread::doesBaselineExceed(
unsigned int &compInd,
unsigned int &taxInd,
double &baseline,
double &initialBaseline){
309 if(compWorking[i] && compensators[i]->doesBaselineExceed(taxInd, baseline, initialBaseline)){
321 delete compensators[i];
326 monitorPort.interrupt();
327 infoPort.interrupt();
333void CompensationThread::sendMonitorData(){
335 if(monitorPort.getOutputCount()>0){
336 int originalSkinDim = 0;
338 originalSkinDim += compensators[i]->getNumTaxels();
340 Vector &b = monitorPort.prepare();
342 b.resize(1+ 2*originalSkinDim);
343 b[0] = 1.0/getEstimatedPeriod();
351 b.setSubvector(index, compensators[i]->getCompensation());
353 index += compensators[i]->getNumTaxels();
357 b.setSubvector(index, compensators[i]->getRawData());
359 index += compensators[i]->getNumTaxels();
368void CompensationThread::sendDebugMsg(
string msg){
370 yDebug(
"[CompensationThread] %s", msg.c_str());
371 Bottle& b = infoPort.prepare();
373 b.addString(msg.c_str());
374 infoPort.write(
true);
377void CompensationThread::sendErrorMsg(
string msg){
379 yError(
"[CompensationThread] %s", msg.c_str());
380 Bottle& b = infoPort.prepare();
382 b.addString(msg.c_str());
383 infoPort.write(
true);
388 if(initializationFinished){
389 Bottle& nameB = res.addList();
390 nameB.addString(
"Name: ");
391 nameB.addString(moduleName.c_str());
392 Bottle& robotB = res.addList();
393 robotB.addString(
"Robot Name: ");
394 robotB.addString(robotName.c_str());
395 Bottle& portB = res.addList();
398 compName = compensators[i]->getInputPortName().c_str();
400 compName = compName +
" (NOT WORKING)";
401 portB.addString(compName.c_str());
402 portB.addInt32(compensators[i]->getNumTaxels());
405 res.addString(
"Module initialization has not been completed yet.");
411 binarization = value;
413 compensators[i]->setBinarization(value);
417 if(smoothFilter != value){
418 lock_guard<mutex> lck(stateSem);
419 smoothFilter = value;
421 compensators[i]->setSmoothFilter(value);
426 if(value<0 || value>1)
430 smoothFactor = value;
432 compensators[i]->setSmoothFactor(value);
439 res = res && compensators[i]->setAddThreshold(thr);
449 res = res && compensators[i]->setCompensationGain(gain);
452 compensationGain = gain;
459 res = res && compensators[i]->setContactCompensationGain(gain);
462 contactCompensationGain = gain;
468 res = res && compensators[i]->setMaxNeighborDistance(dist);
476 if(compensators[i]->getSkinPart()==sp){
477 return compensators[i]->setTaxelPosition(taxelId, position);
484 if(compensators[i]->getSkinPart()==sp){
485 return compensators[i]->setTaxelPositions(positions);
492 if(compensators[i]->getSkinPart()==sp){
493 return compensators[i]->setTaxelOrientation(taxelId, orientation);
500 if(compensators[i]->getSkinPart()==sp){
501 return compensators[i]->setTaxelOrientations(orientations);
508 if(compensators[i]->getSkinPart()==sp){
509 return compensators[i]->setTaxelPose(taxelId, pose);
516 if(compensators[i]->getSkinPart()==sp){
517 return compensators[i]->setTaxelPoses(poses);
524 if(compensators[i]->getSkinPart()==sp){
525 unsigned int numTax = compensators[i]->getNumTaxels();
526 if(poses.size()==6*numTax){
528 vector<Vector>
p(numTax);
529 for(
unsigned int j=0; j<numTax; j++){
530 p[j] = poses.subVector(6*j, 6*j+5);
532 return compensators[i]->setTaxelPoses(
p);
534 else if(poses.size()==7*numTax){
535 vector<Vector>
p(numTax);
536 for(
unsigned int j=0; j<numTax; j++){
537 p[j] = poses.subVector(7*j, 7*j+6);
539 return compensators[i]->setTaxelPoses(
p);
554 Vector res(SKIN_DIM);
558 Vector temp = compensators[i]->getTouchThreshold();
559 memcpy(res.data()+currentDim, temp.data(), temp.size()*
sizeof(
double));
560 currentDim += temp.size();
567 return ADD_THRESHOLD;
570 return compensationGain;
573 return contactCompensationGain;
582 lock_guard<mutex> lck(stateSem);
591 if(compensators[i]->getSkinPart()==sp){
592 return compensators[i]->getTaxelPosition(taxelId);
601 vector<Vector> temp = compensators[i]->getTaxelPositions();
602 res.insert(res.end(), temp.begin(), temp.end());
607 if(compensators[i]->getSkinPart()==sp){
608 return compensators[i]->getTaxelPositions();
611 return vector<Vector>();
615 if(compensators[i]->getSkinPart()==sp){
616 return compensators[i]->getTaxelOrientation(taxelId);
625 vector<Vector> temp = compensators[i]->getTaxelOrientations();
626 res.insert(res.end(), temp.begin(), temp.end());
631 if(compensators[i]->getSkinPart()==sp){
632 return compensators[i]->getTaxelOrientations();
635 return vector<Vector>();
639 if(compensators[i]->getSkinPart()==sp){
640 return compensators[i]->getTaxelPose(taxelId);
649 vector<Vector> temp = compensators[i]->getTaxelPoses();
650 res.insert(res.end(), temp.begin(), temp.end());
655 if(compensators[i]->getSkinPart()==sp){
656 return compensators[i]->getTaxelPoses();
659 return vector<Vector>();
664 if(compensators[i]->getSkinPart()==sp){
665 return compensators[i]->getPoseConfidence(taxelId);
673 if(compensators[i]->getSkinPart()==sp){
674 return compensators[i]->getPoseConfidences();
681 vector<SkinPart> res(compensators.size());
683 res[i] = compensators[i]->getSkinPart();
688 if(compensators[i]->getSkinPart()==sp){
689 compEnable[i] =
true;
696 if(compensators[i]->getSkinPart()==sp){
697 compEnable[i] =
false;
704 if(compensators[i]->getSkinPart()==sp)
705 return compEnable[i];
bool setTaxelPosition(SkinPart sp, unsigned int taxelId, const Vector &position)
unsigned int getAddThreshold()
Vector getPoseConfidences(SkinPart sp)
Vector getTaxelPose(SkinPart sp, unsigned int taxelId)
Vector getTaxelOrientation(SkinPart sp, unsigned int taxelId)
bool setTaxelPose(SkinPart sp, unsigned int taxelId, const Vector &pose)
bool enableSkinPart(SkinPart sp)
vector< SkinPart > getSkinParts()
bool setSmoothFactor(float value)
double getPoseConfidence(SkinPart sp, unsigned int taxelId)
vector< Vector > getTaxelPoses(SkinPart sp=SKIN_PART_ALL)
double getCompensationGain()
bool setContactCompensationGain(double gain)
bool setTaxelPositions(SkinPart sp, const Vector &positions)
bool setCompensationGain(double gain)
CompensationThread(string name, ResourceFinder *rf, string robotName, double _compensationGain, double _contactCompensationGain, int addThreshold, float minBaseline, bool zeroUpRawData, int period, bool binarization, bool smoothFilter, float smoothFactor)
double getContactCompensationGain()
bool setTaxelPoses(SkinPart sp, const vector< Vector > &poses)
bool disableSkinPart(SkinPart sp)
Vector getTaxelPosition(SkinPart sp, unsigned int taxelId)
bool isSkinEnabled(SkinPart sp)
bool setTaxelOrientation(SkinPart sp, unsigned int taxelId, const Vector &orientation)
Vector getTouchThreshold()
bool setAddThreshold(unsigned int thr)
bool setMaxNeighborDistance(double dist)
void setBinarization(bool value)
bool setTaxelOrientations(SkinPart sp, const vector< Vector > &orientations)
vector< Vector > getTaxelPositions(SkinPart sp=SKIN_PART_ALL)
void setSmoothFilter(bool value)
vector< Vector > getTaxelOrientations(SkinPart sp=SKIN_PART_ALL)
const std::string SkinPart_s[]
static const double MAX_NEIGHBOR_DISTANCE