25 #include <yarp/math/Math.h>
33 using namespace yarp::os;
35 using namespace yarp::sig;
36 using namespace yarp::math;
43 bool SpringyFinger::fromProperty(
const Property &options)
45 if (!options.check(
"name"))
53 name=options.find(
"name").asString();
55 scaler.setLowerBoundIn(0.0);
56 scaler.setUpperBoundIn(255.0);
57 scaler.setLowerBoundOut(0.0);
58 scaler.setUpperBoundOut(1.0);
60 lssvm.setDomainSize(1);
62 lssvm.getKernel()->setGamma(500.0);
64 double defaultCalibVel;
65 if ((name==
"thumb") || (name==
"index") || (name==
"middle"))
67 lssvm.setCoDomainSize(2);
70 else if ((name==
"ring") || (name==
"little"))
72 lssvm.setCoDomainSize(3);
78 calibratingVelocity=options.check(
"calib_vel",Value(defaultCalibVel)).asFloat64();
79 outputGain=options.check(
"output_gain",Value(1.0)).asFloat64();
80 calibrated=(options.check(
"calibrated",Value(
"false")).asString()==
"true");
82 if (options.check(
"scaler"))
84 Bottle *pB=options.find(
"scaler").asList();
85 scaler.fromString(pB->toString());
88 if (options.check(
"lssvm"))
90 Bottle *pB=options.find(
"lssvm").asList();
91 lssvm.fromString(pB->toString());
99 void SpringyFinger::toProperty(Property &options)
const
102 options.put(
"name",name);
103 options.put(
"calib_vel",calibratingVelocity);
104 options.put(
"output_gain",outputGain);
105 options.put(
"calibrated",calibrated?
"true":
"false");
106 options.put(
"scaler",
"("+scaler.toString()+
")");
107 options.put(
"lssvm",
"("+lssvm.toString()+
")");
112 bool SpringyFinger::toStream(ostream &str)
const
114 str<<
"name "<<name<<endl;
115 str<<
"calib_vel "<<calibratingVelocity<<endl;
116 str<<
"output_gain "<<outputGain<<endl;
117 str<<
"calibrated "<<(calibrated?
"true":
"false")<<endl;
118 str<<
"scaler "<<
"("+scaler.toString()+
")"<<endl;
119 str<<
"lssvm "<<
"("+lssvm.toString()+
")"<<endl;
126 bool SpringyFinger::getSensorsData(Value &
data)
const
128 map<string,Sensor*>::const_iterator In_0=sensors.find(
"In_0");
129 map<string,Sensor*>::const_iterator Out_0=sensors.find(
"Out_0");
130 map<string,Sensor*>::const_iterator Out_1=sensors.find(
"Out_1");
131 map<string,Sensor*>::const_iterator Out_2=sensors.find(
"Out_2");
134 ok&=In_0!=sensors.end();
135 ok&=Out_0!=sensors.end();
136 ok&=Out_1!=sensors.end();
138 if (lssvm.getCoDomainSize()>2)
139 ok&=Out_2!=sensors.end();
144 Value val_in, val_out[3];
145 In_0->second->getOutput(val_in);
146 Out_0->second->getOutput(val_out[0]);
147 Out_1->second->getOutput(val_out[1]);
149 Vector in(lssvm.getDomainSize());
150 in[0]=val_in.asFloat64();
152 Vector
out(lssvm.getCoDomainSize());
153 out[0]=val_out[0].asFloat64();
154 out[1]=val_out[1].asFloat64();
156 if (lssvm.getCoDomainSize()>2)
158 Out_2->second->getOutput(val_out[2]);
159 out[2]=val_out[2].asFloat64();
165 b.addList().read(in);
166 prop.put(
"in",b.get(0));
168 b.addList().read(
out);
169 prop.put(
"out",b.get(1));
171 b.addList().read(prop);
179 bool SpringyFinger::extractSensorsData(Vector &in, Vector &
out)
const
184 if (getSensorsData(
data))
186 if (Bottle *b1=
data.asList())
188 if (Bottle *b2=b1->find(
"in").asList())
190 in.resize(b2->size());
191 for (
size_t i=0; i<in.length(); i++)
192 in[i]=b2->get(i).asFloat64();
195 if (Bottle *b2=b1->find(
"out").asList())
197 out.resize(b2->size());
198 for (
size_t i=0; i<
out.length(); i++)
199 out[i]=b2->get(i).asFloat64();
211 bool SpringyFinger::getOutput(Value &
out)
const
214 if (!extractSensorsData(i,o))
217 i[0]=scaler.transform(i[0]);
218 Vector pred=lssvm.predict(i).getPrediction();
220 for (
size_t j=0; j<pred.length(); j++)
221 pred[j]=scaler.unTransform(pred[j]);
223 out=Value(outputGain*
norm(o-pred));
232 if (options.check(
"reset"))
235 if (options.check(
"feed"))
238 if (extractSensorsData(in,
out))
240 in[0]=scaler.transform(in[0]);
241 for (
size_t i=0; i<
out.length(); i++)
242 out[i]=scaler.transform(
out[i]);
244 lssvm.feedSample(in,
out);
250 if (options.check(
"train"))
261 SpringyFingersModel::SpringyFingersModel()
268 bool SpringyFingersModel::fromProperty(
const Property &options)
270 if (!options.check(
"name") || !options.check(
"type"))
272 printMessage(
log::error,1,
"missing mandatory options \"name\" and/or \"type\"");
279 name=options.find(
"name").asString();
280 type=options.find(
"type").asString();
281 robot=options.check(
"robot",Value(
"icub")).asString();
282 carrier=options.check(
"carrier",Value(
"udp")).asString();
283 verbosity=options.check(
"verbosity",Value(0)).asInt32();
285 string part_motor=string(type+
"_arm");
286 string part_analog=string(type+
"_hand");
289 propEncs.put(
"device",
"remote_controlboard");
290 propEncs.put(
"remote",
"/"+robot+
"/"+part_motor);
291 propEncs.put(
"local",
"/"+name+
"/"+part_motor);
292 if (!drvEncs.open(propEncs))
296 propMAIS.put(
"device",
"multipleanalogsensorsclient");
297 propMAIS.put(
"remote",
"/"+robot+
"/"+part_analog+
"/MAIS");
298 propMAIS.put(
"local",
"/"+name+
"/"+part_analog+
"/MAIS");
299 if (!drvMAIS.open(propMAIS))
301 printMessage(
log::error,1,
"unable to connect to %s",propMAIS.find(
"remote").asString().c_str());
306 printMessage(
log::info,1,
"configuring joint encoders sensors ...");
307 IEncoders *ienc; drvEncs.view(ienc);
308 int nAxes; ienc->getAxes(&nAxes);
311 propGen.put(
"name",
"In_0");
312 propGen.put(
"size",nAxes);
314 Property propThumb=propGen; propThumb.put(
"index",10);
315 Property propIndex=propGen; propIndex.put(
"index",12);
316 Property propMiddle=propGen; propMiddle.put(
"index",14);
317 Property propRing=propGen; propRing.put(
"index",15);
318 Property propLittle=propGen; propLittle.put(
"index",15);
320 bool sensors_ok=
true;
321 void *pEncs=
static_cast<void*
>(ienc);
322 sensors_ok&=sensEncs[0].configure(pEncs,propThumb);
323 sensors_ok&=sensEncs[1].configure(pEncs,propIndex);
324 sensors_ok&=sensEncs[2].configure(pEncs,propMiddle);
325 sensors_ok&=sensEncs[3].configure(pEncs,propRing);
326 sensors_ok&=sensEncs[4].configure(pEncs,propLittle);
328 printMessage(
log::info,1,
"configuring analog encoders sensors ...");
329 IEncoderArrays *iencarray; drvMAIS.view(iencarray);
332 propGen.put(
"num_arrays",(
int)iencarray->getNrOfEncoderArrays());
333 propGen.put(
"index_array",0);
335 Property thumb_mp=propGen; thumb_mp.put(
"name",
"Out_0"); thumb_mp.put(
"index_element",
"1");
336 Property thumb_ip=propGen; thumb_ip.put(
"name",
"Out_1"); thumb_ip.put(
"index_element",
"2");
337 Property index_mp=propGen; index_mp.put(
"name",
"Out_0"); index_mp.put(
"index_element",
"4");
338 Property index_ip=propGen; index_ip.put(
"name",
"Out_1"); index_ip.put(
"index_element",
"5");
339 Property middle_mp=propGen; middle_mp.put(
"name",
"Out_0"); middle_mp.put(
"index_element",
"7");
340 Property middle_ip=propGen; middle_ip.put(
"name",
"Out_1"); middle_ip.put(
"index_element",
"8");
341 Property ring_mp=propGen; ring_mp.put(
"name",
"Out_0"); ring_mp.put(
"index_element",
"9");
342 Property ring_pip=propGen; ring_pip.put(
"name",
"Out_1"); ring_pip.put(
"index_element",
"10");
343 Property ring_dip=propGen; ring_dip.put(
"name",
"Out_2"); ring_dip.put(
"index_element",
"11");
344 Property little_mp=propGen; little_mp.put(
"name",
"Out_0"); little_mp.put(
"index_element",
"12");
345 Property little_pip=propGen; little_pip.put(
"name",
"Out_1"); little_pip.put(
"index_element",
"13");
346 Property little_dip=propGen; little_dip.put(
"name",
"Out_2"); little_dip.put(
"index_element",
"14");
348 void *pEncArrays=
static_cast<void*
>(iencarray);
349 sensors_ok&=sensEncArrays[0].configure(pEncArrays,thumb_mp);
350 sensors_ok&=sensEncArrays[1].configure(pEncArrays,thumb_ip);
351 sensors_ok&=sensEncArrays[2].configure(pEncArrays,index_mp);
352 sensors_ok&=sensEncArrays[3].configure(pEncArrays,index_ip);
353 sensors_ok&=sensEncArrays[4].configure(pEncArrays,middle_mp);
354 sensors_ok&=sensEncArrays[5].configure(pEncArrays,middle_ip);
355 sensors_ok&=sensEncArrays[6].configure(pEncArrays,ring_mp);
356 sensors_ok&=sensEncArrays[7].configure(pEncArrays,ring_pip);
357 sensors_ok&=sensEncArrays[8].configure(pEncArrays,ring_dip);
358 sensors_ok&=sensEncArrays[9].configure(pEncArrays,little_mp);
359 sensors_ok&=sensEncArrays[10].configure(pEncArrays,little_pip);
360 sensors_ok&=sensEncArrays[11].configure(pEncArrays,little_dip);
364 printMessage(
log::error,1,
"some errors occured");
369 printMessage(
log::info,1,
"configuring fingers ...");
370 Property thumb(options.findGroup(
"thumb").toString().c_str());
371 Property index(options.findGroup(
"index").toString().c_str());
372 Property middle(options.findGroup(
"middle").toString().c_str());
373 Property ring(options.findGroup(
"ring").toString().c_str());
374 Property little(options.findGroup(
"little").toString().c_str());
376 bool fingers_ok=
true;
377 fingers_ok&=fingers[0].fromProperty(thumb);
378 fingers_ok&=fingers[1].fromProperty(index);
379 fingers_ok&=fingers[2].fromProperty(middle);
380 fingers_ok&=fingers[3].fromProperty(ring);
381 fingers_ok&=fingers[4].fromProperty(little);
385 printMessage(
log::error,1,
"some errors occured");
390 printMessage(
log::info,1,
"attaching sensors to fingers ...");
391 fingers[0].attachSensor(sensEncs[0]);
392 fingers[0].attachSensor(sensEncArrays[0]);
393 fingers[0].attachSensor(sensEncArrays[1]);
395 fingers[1].attachSensor(sensEncs[1]);
396 fingers[1].attachSensor(sensEncArrays[2]);
397 fingers[1].attachSensor(sensEncArrays[3]);
399 fingers[2].attachSensor(sensEncs[2]);
400 fingers[2].attachSensor(sensEncArrays[4]);
401 fingers[2].attachSensor(sensEncArrays[5]);
403 fingers[3].attachSensor(sensEncs[3]);
404 fingers[3].attachSensor(sensEncArrays[6]);
405 fingers[3].attachSensor(sensEncArrays[7]);
406 fingers[3].attachSensor(sensEncArrays[8]);
408 fingers[4].attachSensor(sensEncs[4]);
409 fingers[4].attachSensor(sensEncArrays[9]);
410 fingers[4].attachSensor(sensEncArrays[10]);
411 fingers[4].attachSensor(sensEncArrays[11]);
413 attachNode(fingers[0]);
414 attachNode(fingers[1]);
415 attachNode(fingers[2]);
416 attachNode(fingers[3]);
417 attachNode(fingers[4]);
419 printMessage(
log::info,1,
"configuration complete");
420 return configured=
true;
425 void SpringyFingersModel::toProperty(Property &options)
const
432 fingers[0].toProperty(prop[0]);
433 fingers[1].toProperty(prop[1]);
434 fingers[2].toProperty(prop[2]);
435 fingers[3].toProperty(prop[3]);
436 fingers[4].toProperty(prop[4]);
438 string thumb=
"(thumb ";
439 thumb+=prop[0].toString();
442 string index=
"(index ";
443 index+=prop[1].toString();
446 string middle=
"(middle ";
447 middle+=prop[2].toString();
450 string ring=
"(ring ";
451 ring+=prop[3].toString();
454 string little=
"(little ";
455 little+=prop[4].toString();
458 options.fromString(thumb+index+middle+ring+little);
459 options.put(
"name",name);
460 options.put(
"type",type);
461 options.put(
"robot",robot);
468 bool SpringyFingersModel::toStream(ostream &str)
const
472 str<<
"name "<<name<<endl;
473 str<<
"type "<<type<<endl;
474 str<<
"robot "<<robot<<endl;
478 str<<
"[thumb]"<<endl;
479 fingers[0].toStream(str);
482 str<<
"[index]"<<endl;
483 fingers[1].toStream(str);
486 str<<
"[middle]"<<endl;
487 fingers[2].toStream(str);
491 fingers[3].toStream(str);
494 str<<
"[little]"<<endl;
495 fingers[4].toStream(str);
509 Value fng=options.find(
"finger");
512 printMessage(
log::error,1,
"unspecified option \"finger\"");
516 IControlMode *imod; drvEncs.view(imod);
517 IControlLimits *ilim; drvEncs.view(ilim);
518 IEncoders *ienc; drvEncs.view(ienc);
519 IPositionControl *ipos; drvEncs.view(ipos);
521 int nAxes; ienc->getAxes(&nAxes);
522 Vector qmin(nAxes),qmax(nAxes),vel(nAxes),
acc(nAxes);
524 printMessage(
log::info,1,
"steering the hand to a suitable starting configuration");
525 for (
int j=7; j<nAxes; j++)
527 imod->setControlMode(j,VOCAB_CM_POSITION);
528 ilim->getLimits(j,&qmin[j],&qmax[j]);
530 ipos->getRefAcceleration(j,&
acc[j]);
531 ipos->getRefSpeed(j,&vel[j]);
534 ipos->setRefSpeed(j,60.0);
535 ipos->positionMove(j,(j==8)?qmax[j]:qmin[j]);
538 printMessage(
log::info,1,
"proceeding with the calibration");
543 string tag=options.check(
"finger",Value(
"all")).asString();
546 calibrateFinger(fingers[0],10,qmin[10],qmax[10]);
548 else if (tag==
"index")
550 calibrateFinger(fingers[1],12,qmin[12],qmax[12]);
552 else if (tag==
"middle")
554 calibrateFinger(fingers[2],14,qmin[14],qmax[14]);
556 else if (tag==
"ring")
558 calibrateFinger(fingers[3],15,qmin[15],qmax[15]);
560 else if (tag==
"little")
562 calibrateFinger(fingers[4],15,qmin[15],qmax[15]);
564 else if ((tag==
"all") || (tag==
"all_serial"))
566 calibrateFinger(fingers[0],10,qmin[10],qmax[10]);
567 calibrateFinger(fingers[1],12,qmin[12],qmax[12]);
568 calibrateFinger(fingers[2],14,qmin[14],qmax[14]);
569 calibrateFinger(fingers[3],15,qmin[15],qmax[15]);
570 calibrateFinger(fingers[4],15,qmin[15],qmax[15]);
572 else if (tag==
"all_parallel")
575 Bottle &bl=b.addList();
576 bl.addString(
"thumb");
577 bl.addString(
"index");
578 bl.addString(
"middle");
579 bl.addString(
"ring");
580 bl.addString(
"little");
590 deque<CalibThread*> db;
591 set<string> singletons;
593 Bottle *items=fng.asList();
594 for (
int i=0; i<items->size(); i++)
596 string tag=items->get(i).asString();
599 if (singletons.find(tag)==singletons.end())
601 CalibThread *thr=
new CalibThread;
602 thr->setInfo(
this,fingers[0],10,qmin[10],qmax[10]);
605 singletons.insert(tag);
608 else if (tag==
"index")
610 if (singletons.find(tag)==singletons.end())
612 CalibThread *thr=
new CalibThread;
613 thr->setInfo(
this,fingers[1],12,qmin[12],qmax[12]);
616 singletons.insert(tag);
619 else if (tag==
"middle")
621 if (singletons.find(tag)==singletons.end())
623 CalibThread *thr=
new CalibThread;
624 thr->setInfo(
this,fingers[2],14,qmin[14],qmax[14]);
627 singletons.insert(tag);
630 else if (tag==
"ring")
632 if (singletons.find(tag)==singletons.end())
634 CalibThread *thr=
new CalibThread;
635 thr->setInfo(
this,fingers[3],15,qmin[15],qmax[15]);
638 singletons.insert(tag);
641 else if (tag==
"little")
643 if (singletons.find(tag)==singletons.end())
645 CalibThread *thr=
new CalibThread;
646 thr->setInfo(
this,fingers[4],15,qmin[15],qmax[15]);
649 singletons.insert(tag);
663 db.erase(db.begin()+i);
675 if (!fng.isString() && !fng.isList())
679 printMessage(
log::error,1,
"unknown finger request %s",fng.toString().c_str());
681 for (
int j=7; j<nAxes; j++)
683 ipos->setRefAcceleration(j,
acc[j]);
684 ipos->setRefSpeed(j,vel[j]);
695 bool SpringyFingersModel::getOutput(Value &
out)
const
700 fingers[0].getOutput(val[0]);
701 fingers[1].getOutput(val[1]);
702 fingers[2].getOutput(val[2]);
703 fingers[3].getOutput(val[3]);
704 fingers[4].getOutput(val[4]);
706 Bottle bOut; Bottle &ins=bOut.addList();
707 ins.addFloat64(val[0].asFloat64());
708 ins.addFloat64(val[1].asFloat64());
709 ins.addFloat64(val[2].asFloat64());
710 ins.addFloat64(val[3].asFloat64());
711 ins.addFloat64(val[4].asFloat64());
722 void SpringyFingersModel::calibrateFinger(
SpringyFinger &finger,
const int joint,
723 const double min,
const double max)
725 printMessage(
log::info,1,
"calibrating finger %s ...",finger.
getName().c_str());
726 double margin=0.1*(
max-
min);
727 double _min=
min+margin;
728 double _max=
max-margin;
732 double *tol=&tol_min;
733 double timeout=2.0*(_max-_min)/finger.
getCalibVel();
736 IControlMode *imod; drvEncs.view(imod);
737 IEncoders *ienc; drvEncs.view(ienc);
738 IPositionControl *ipos; drvEncs.view(ipos);
750 Property reset(
"(reset)");
751 Property feed(
"(feed)");
752 Property train(
"(train)");
757 imod->setControlMode(joint,VOCAB_CM_POSITION);
761 for (
int i=0; i<5; i++)
764 ipos->positionMove(joint,*val);
769 double t0=Time::now();
775 double fb; ienc->getEncoder(joint,&fb);
778 if (fabs(fb-fbOld)>0.5)
784 done=(fabs(*val-fb)<*tol)||(Time::now()-t0>timeout);
800 printMessage(
log::info,1,
"training finger %s ...",finger.
getName().c_str());
807 bool SpringyFingersModel::isCalibrated()
const
809 return (fingers[0].isCalibrated()&&
810 fingers[1].isCalibrated()&&
811 fingers[2].isCalibrated()&&
812 fingers[3].isCalibrated()&&
813 fingers[4].isCalibrated());
818 void SpringyFingersModel::close()
822 if (drvEncs.isValid())
825 if (drvMAIS.isValid())
835 SpringyFingersModel::~SpringyFingersModel()
std::string getName() const
Retrieve the node name.
An implementation of the Node class that represents the springy finger.
double getCalibVel() const
Return the finger actuation velocity used while calibrating.
bool calibrate(const yarp::os::Property &options)
Allow to send calibration commands to the finger.
double norm(const yarp::sig::Matrix &M, int col)
Returns the norm of the vector given in the form: matrix(:,col).