iCub-main
Loading...
Searching...
No Matches
module.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2014 iCub Facility - Istituto Italiano di Tecnologia
3 * Author: Ugo Pattacini
4 * email: ugo.pattacini@iit.it
5 * Permission is granted to copy, distribute, and/or modify this program
6 * under the terms of the GNU General Public License, version 2 or any
7 * later version published by the Free Software Foundation.
8 *
9 * A copy of the license can be found at
10 * http://www.robotcub.org/icub/license/gpl.txt
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15 * Public License for more details
16*/
17
18#include <cstdlib>
19#include <string>
20#include <sstream>
21#include <fstream>
22#include <iomanip>
23#include <cmath>
24#include <limits>
25#include <algorithm>
26#include <utility>
27
28#include <yarp/cv/Cv.h>
29#include <opencv2/imgproc/imgproc_c.h>
30#include <yarp/math/Math.h>
31#include <yarp/math/Rand.h>
32#include <yarp/math/NormRand.h>
33
34#include <iCub/ctrl/math.h>
36
37#include "module.h"
38
39using namespace std;
40using namespace yarp::cv;
41using namespace yarp::math;
42using namespace iCub::ctrl;
43using namespace iCub::iKin;
44using namespace iCub::optimization;
45
46
47/************************************************************************/
48void DisparityProcessor::onRead(ImageOf<PixelMono> &imgIn)
49{
50 module->onRead(imgIn);
51}
52
53/************************************************************************/
55{
56 this->module=module;
57}
58
59
60/************************************************************************/
61bool CalibModule::attach(RpcServer &source)
62{
63 return this->yarp().attachAsServer(source);
64}
65
66
67/************************************************************************/
68bool CalibModule::createTargets(const Vector &c, const Vector &size)
69{
70 if ((c.length()<3) || (size.length()<2))
71 return false;
72
73 double a=std::max(fabs(size[0]),0.04);
74 double b=std::max(fabs(size[1]),0.02);
75
76 Vector ax1(4,0.0);
77 ax1[2]=1.0;
78 ax1[3]=90.0*CTRL_DEG2RAD;
79
80 Matrix H=axis2dcm(ax1);
81 H(0,3)=c[0];
82 H(1,3)=c[1];
83 H(2,3)=c[2];
84 H(3,3)=1.0;
85
86 targets.clear();
87 for (int i=0; i<2; i++)
88 {
89 for (double theta=0.0; theta<=2.0*M_PI; theta+=(2.0*M_PI)/50.0)
90 {
91 Vector x(4);
92 x[0]=a*cos(theta);
93 x[1]=b*sin(theta);
94 x[2]=0.0;
95 x[3]=1.0;
96 x=H*x;
97 x.pop_back();
98 targets.push_back(x);
99 yInfo("created point #%d=(%s)",(int)targets.size(),x.toString(3,3).c_str());
100 }
101
102 Vector ax2(4,0.0);
103 ax2[1]=1.0;
104 ax2[3]=90.0*CTRL_DEG2RAD;
105 H=axis2dcm(ax2)*axis2dcm(ax1);
106 H(0,3)=c[0];
107 H(1,3)=c[1];
108 H(2,3)=c[2];
109 H(3,3)=1.0;
110 }
111
113 return true;
114}
115
116
117/************************************************************************/
118bool CalibModule::isTypeValid(const string &type)
119{
120 return ((type=="se3") || (type=="se3+scale") ||
121 (type=="affine") || (type=="lssvm"));
122}
123
124
125/************************************************************************/
127{
129 if ((type=="se3") || (type=="se3+scale") || (type=="affine"))
131 else if (type=="lssvm")
132 calibrator=new LSSVMCalibrator(type);
133
134 calibrated=false;
135 return calibrator;
136}
137
138
139/************************************************************************/
141{
142 if (!v.check("arm") || !v.check("type"))
143 return false;
144
145 string arm=v.find("arm").asString();
146 string type=v.find("type").asString();
147 if ((arm!="left") && (arm!="right"))
148 return false;
149
150 if (isTypeValid(type))
151 {
152 Property info;
153 info.fromString(v.toString());
154
155 Calibrator *c=factory(type);
156 if (c->fromProperty(info))
157 {
158 c->toProperty(info);
159 yInfo("loaded %s calibrator: %s",arm.c_str(),info.toString().c_str());
160 ((arm=="left")?expertsL:expertsR)<<*c;
161 return true;
162 }
163 }
164
165 return false;
166}
167
168
169/************************************************************************/
170cv::Rect CalibModule::extractFingerTip(ImageOf<PixelMono> &imgIn, ImageOf<PixelBgr> &imgOut,
171 const Vector &c, Vector &px)
172{
173 cv::Mat imgInMat=toCvMat(imgIn);
174
175 // produce a colored image
176 imgOut.resize(imgIn);
177 cv::Mat imgOutMat=toCvMat(imgOut);
178
179 // proceed iff the center is within the image plane
180 if ((c[0]<10.0) || (c[0]>imgIn.width()-10) ||
181 (c[1]<10.0) || (c[1]>imgIn.height()-10))
182 {
183 cv::cvtColor(imgInMat,imgOutMat,CV_GRAY2BGR);
184 return cv::Rect();
185 }
186
187 // saturate the top-left and bottom-right corners
188 int roi_side2=roi_side>>1;
189 cv::Point ct((int)c[0],(int)c[1]);
190 cv::Point tl((int)(c[0]-roi_side2),(int)(c[1]-roi_side2));
191 cv::Point br((int)(c[0]+roi_side2),(int)(c[1]+roi_side2));
192 tl.x=std::max(1,tl.x); tl.x=std::min(tl.x,(int)imgIn.width()-1);
193 tl.y=std::max(1,tl.y); tl.y=std::min(tl.y,(int)imgIn.height()-1);
194 br.x=std::max(1,br.x); br.x=std::min(br.x,(int)imgIn.width()-1);
195 br.y=std::max(1,br.y); br.y=std::min(br.y,(int)imgIn.height()-1);
196 cv::Rect rect(tl,br);
197
198 // run Otsu algorithm to segment out the finger
199 cv::Mat imgInMatRoi(imgInMat,rect);
200 cv::threshold(imgInMatRoi,imgInMatRoi,0,255,cv::THRESH_BINARY|cv::THRESH_OTSU);
201 cv::cvtColor(imgInMat,imgOutMat,CV_GRAY2BGR);
202
203 px.resize(2,0.0);
204 bool ok=false;
205 for (int y=tl.y; y<br.y; y++)
206 {
207 for (int x=tl.x; x<br.x; x++)
208 {
209 if (imgIn(x,y)>0)
210 {
211 // predict the center of the finger a bit shifted
212 x+=3; y+=5;
213 px[0]=x; px[1]=y;
214 cv::circle(imgOutMat,cv::Point(x,y),5,cv::Scalar(0,0,255),-1);
215 ok=true;
216 break;
217 }
218 }
219
220 if (ok)
221 break;
222 }
223
224 cv::circle(imgOutMat,ct,5,cv::Scalar(0,255,0),-1);
225 cv::rectangle(imgOutMat,tl,br,cv::Scalar(255,255,255),4);
226 return rect;
227}
228
229
230/************************************************************************/
232{
233 Bottle info;
234 igaze->getInfo(info);
235 return info.find("min_allowed_vergence").asFloat64();
236}
237
238
239/************************************************************************/
240bool CalibModule::getGazeParams(const string &eye, const string &type, Matrix &M)
241{
242 if (((eye!="left") && (eye!="right")) ||
243 ((type!="intrinsics") && (type!="extrinsics")))
244 return false;
245
246 Bottle info;
247 igaze->getInfo(info);
248 if (Bottle *pB=info.find("camera_"+type+"_"+eye).asList())
249 {
250 M.resize((type=="intrinsics")?3:4,4);
251
252 int cnt=0;
253 for (int r=0; r<M.rows(); r++)
254 for (int c=0; c<M.cols(); c++)
255 M(r,c)=pB->get(cnt++).asFloat64();
256
257 return true;
258 }
259 else
260 return false;
261}
262
263
264/************************************************************************/
265bool CalibModule::pushExtrinsics(const string &eye, const Matrix &H)
266{
267 if ((eye!="left") && (eye!="right"))
268 return false;
269
270 Bottle options;
271 Bottle &ext=options.addList();
272 ext.addString(eye=="left"?"camera_extrinsics_left":"camera_extrinsics_right");
273 Bottle &val=ext.addList();
274 for (int r=0; r<H.rows(); r++)
275 for (int c=0; c<H.cols(); c++)
276 val.addFloat64(H(r,c));
277
278 return igaze->tweakSet(options);
279}
280
281
282/************************************************************************/
283bool CalibModule::getDepth(const Vector &px, Vector &x, Vector &pxr)
284{
285 Bottle cmd,reply;
286 cmd.addInt32((int)px[0]);
287 cmd.addInt32((int)px[1]);
288 depthRpcPort.write(cmd,reply);
289
290 if (reply.size()<5)
291 return false;
292
293 x.resize(3);
294 pxr.resize(2);
295 x[0]=reply.get(0).asFloat64();
296 x[1]=reply.get(1).asFloat64();
297 x[2]=reply.get(2).asFloat64();
298 pxr[0]=reply.get(3).asInt32();
299 pxr[1]=reply.get(4).asInt32();
300
301 return (norm(x)>0.0);
302}
303
304
305/************************************************************************/
306bool CalibModule::getDepthAveraged(const Vector &px, Vector &x, Vector &pxr,
307 const int maxSamples)
308{
309 x.resize(3,0.0);
310 pxr.resize(2,0.0);
311
312 Vector depth,pixel;
313 double cnt=0.0;
314 for (int i=0; i<maxSamples; i++)
315 {
316 if (getDepth(px,depth,pixel))
317 {
318 x+=depth;
319 pxr+=pixel;
320 cnt+=1.0;
321 }
322 }
323
324 if (norm(x)==0.0)
325 return false;
326
327 x/=cnt;
328 pxr/=cnt;
329 return true;
330}
331
332
333/************************************************************************/
334void CalibModule::openHand(IControlMode *imod, IPositionControl *ipos)
335{
336 Vector poss(9,0.0);
337 Vector vels(9,0.0);
338
339 poss[0]=20.0; vels[0]=50.0;
340 poss[1]=90.0; vels[1]=50.0;
341 poss[2]=0.0; vels[2]=50.0;
342 poss[3]=0.0; vels[3]=50.0;
343 poss[4]=0.0; vels[4]=50.0;
344 poss[5]=0.0; vels[5]=50.0;
345 poss[6]=0.0; vels[6]=50.0;
346 poss[7]=0.0; vels[7]=50.0;
347 poss[8]=0.0; vels[8]=100.0;
348
349 yInfo("opening hand");
350 int i0=nEncs-(int)poss.length();
351 for (int i=i0; i<nEncs; i++)
352 imod->setControlMode(i,VOCAB_CM_POSITION);
353
354 for (int i=i0; i<nEncs; i++)
355 {
356 ipos->setRefAcceleration(i,std::numeric_limits<double>::max());
357 ipos->setRefSpeed(i,vels[i-i0]);
358 ipos->positionMove(i,poss[i-i0]);
359 }
360}
361
362
363/************************************************************************/
364void CalibModule::postureHelper(const Vector &gaze_ang, const Matrix &targetL,
365 const Matrix &targetR)
366{
367 IControlMode *imod;
368 IPositionControl *ipos;
369 ICartesianControl *icart;
370 int ctxtL,ctxtR;
371 Vector dof;
372
373 yInfo("looking at target");
374 igaze->lookAtAbsAngles(gaze_ang);
375
376 if (useArmL)
377 {
378 drvArmL.view(imod);
379 drvArmL.view(ipos);
380 openHand(imod,ipos);
381
382 drvCartL.view(icart);
383 icart->storeContext(&ctxtL);
384 icart->getDOF(dof);
385 dof=1.0;
386 icart->setDOF(dof,dof);
387 icart->setLimits(0,0.0,0.0);
388 icart->setLimits(1,0.0,0.0);
389 icart->setLimits(2,0.0,0.0);
390 icart->setTrajTime(1.0);
391
392 yInfo("reaching for left target");
393 icart->goToPoseSync(targetL.getCol(3),dcm2axis(targetL));
394 }
395
396 if (useArmR)
397 {
398 drvArmR.view(imod);
399 drvArmR.view(ipos);
400 openHand(imod,ipos);
401
402 drvCartR.view(icart);
403 icart->storeContext(&ctxtR);
404 icart->getDOF(dof);
405 dof=1.0;
406 dof[0]=dof[1]=dof[2]=0.0;
407 icart->setDOF(dof,dof);
408 icart->setTrackingMode(true);
409 icart->setTrajTime(1.0);
410
411 yInfo("reaching for right target");
412 icart->goToPoseSync(targetR.getCol(3),dcm2axis(targetR));
413
414 yInfo("waiting for right arm... ");
415 icart->waitMotionDone();
416 yInfo("done");
417 }
418
419 if (useArmL)
420 {
421 drvCartL.view(icart);
422
423 yInfo("waiting for left arm... ");
424 icart->waitMotionDone();
425 yInfo("done");
426
427 icart->restoreContext(ctxtL);
428 icart->deleteContext(ctxtL);
429 }
430
431 if (useArmR)
432 {
433 drvCartR.view(icart);
434 icart->restoreContext(ctxtR);
435 icart->deleteContext(ctxtR);
436 }
437}
438
439
440/************************************************************************/
441bool CalibModule::posture(const string &type)
442{
443 Vector gaze_ang(3,0.0);
444 Matrix targetL=zeros(4,4);
445 Matrix targetR=zeros(4,4);
446 targetL(3,3)=targetR(3,3)=1.0;
447
448 if (type=="home")
449 {
450 targetL(0,0)=targetR(0,0)=-1.0;
451 targetL(2,1)=targetR(2,1)=-1.0;
452 targetL(1,2)=targetR(1,2)=-1.0;
453
454 targetL(0,3)=targetR(0,3)=-0.25;
455 targetL(2,3)=targetR(2,3)=0.0;
456
457 targetL(1,3)=-0.15;
458 targetR(1,3)=0.15;
459 }
460 else if (type=="look_hands")
461 {
462 gaze_ang[1]=-35.0;
463 gaze_ang[2]=block_eyes;
464
465 targetL(2,0)=1.0;
466 targetL(1,1)=-1.0;
467 targetL(0,2)=1.0;
468 targetL(0,3)=-0.25;
469 targetL(1,3)=-0.04;
470 targetL(2,3)=0.12;
471
472 targetR(2,0)=1.0;
473 targetR(1,1)=1.0;
474 targetR(0,2)=-1.0;
475 targetR(0,3)=-0.32;
476 targetR(1,3)=0.04;
477 targetR(2,3)=0.12;
478 }
479 else
480 return false;
481
482 postureHelper(gaze_ang,targetL,targetR);
483 return true;
484}
485
486
487/************************************************************************/
489{
490 if (depthRpcPort.getOutputCount()>0)
491 {
492 posture("look_hands");
493 igaze->stopControl();
494 Time::delay(1.0);
495
496 Bottle cmd,reply;
497 cmd.addString("calibrate");
498 depthRpcPort.write(cmd,reply);
499 if (reply.get(0).asString()=="ACK")
500 {
501 cmd.clear();
502 cmd.addString("save");
503 depthRpcPort.write(cmd,reply);
504 if (reply.get(0).asString()=="ACK")
505 return true;
506 }
507 }
508
509 return false;
510}
511
512
513/************************************************************************/
515{
516 // drive the hand in pointing pose
517 Vector poss(9,0.0);
518 Vector vels(9,0.0);
519
520 poss[0]=40.0; vels[0]=50.0;
521 poss[1]=30.0; vels[1]=50.0;
522 poss[2]=20.0; vels[2]=50.0;
523 poss[3]=90.0; vels[3]=50.0;
524 poss[4]=00.0; vels[4]=50.0;
525 poss[5]=00.0; vels[5]=50.0;
526 poss[6]=70.0; vels[6]=50.0;
527 poss[7]=100.0; vels[7]=50.0;
528 poss[8]=200.0; vels[8]=100.0;
529
530 yInfo("configuring hand... ");
531 int i0=nEncs-(int)poss.length();
532 for (int i=i0; i<nEncs; i++)
533 imods->setControlMode(i,VOCAB_CM_POSITION);
534
535 for (int i=i0; i<nEncs; i++)
536 {
537 iposs->setRefAcceleration(i,std::numeric_limits<double>::max());
538 iposs->setRefSpeed(i,vels[i-i0]);
539 iposs->positionMove(i,poss[i-i0]);
540 }
541
542 bool done=false;
543 double t0=Time::now();
544 while (!done && (Time::now()-t0<3.0))
545 {
546 Time::delay(1.0);
547 iposs->checkMotionDone(i0+4,&done);
548 }
549
550 Vector encs(nEncs);
551 iencs->getEncoders(encs.data());
552 poss=encs.subVector(i0,nEncs-1);
553
554 double stamp;
555 Vector analogs(iencarray->getEncoderArraySize(0));
556 iencarray->getEncoderArrayMeasure(0,analogs,stamp);
557
558 Vector joints;
560 finger.getChainJoints(poss,analogs,joints);
561 Vector xf=finger.getH(CTRL_DEG2RAD*joints).getCol(3);
562
563 iarm->storeContext(&context_arm);
564
565 Vector dof;
566 iarm->getDOF(dof);
567 dof=1.0;
568 dof[1]=0.0;
569 iarm->setDOF(dof,dof);
570
571 double min, max;
572 iarm->getLimits(0,&min,&max);
573 iarm->setLimits(0,0.0,0.5*max);
574
575 iarm->setInTargetTol(exploration_intargettol);
576 iarm->setTrajTime(1.0);
577 iarm->attachTipFrame(xf,Vector(4,0.0));
578
579 igaze->storeContext(&context_gaze);
580 igaze->getNeckPitchRange(&min,&max);
581 igaze->bindNeckPitch(0.9*min,max);
582 igaze->blockNeckRoll(0.0);
583 igaze->setNeckTrajTime(0.8);
584}
585
586
587/************************************************************************/
589{
590 // calibrate using the current setting
591 double error;
593
594 deque<Vector> p_depth, p_kin;
595 calibrator->getPoints(p_depth,p_kin);
596
597 // compute the prediction errors
598 Vector e(p_depth.size());
599 for (size_t i=0; i<p_depth.size(); i++)
600 {
601 Vector x;
602 calibrator->retrieve(p_depth[i],x);
603 e[i]=norm(p_kin[i]-x);
604 }
605
606 // perform outliers removal
607 ModifiedThompsonTau detector;
608 set<size_t> idx=detector.detect(e,Property("(recursive)"));
609
610 // feed the calibrator with inliers only
611 if (!idx.empty())
612 {
614 for (size_t i=0; i<p_depth.size(); i++)
615 if (idx.find(i)==idx.end())
616 calibrator->addPoints(p_depth[i],p_kin[i]);
617 }
618
619 return (int)idx.size();
620}
621
622
623/************************************************************************/
625{
626 mtx.lock();
627
628 // skip if in idle
630 {
631 mtx.unlock();
632 return;
633 }
634
635 // end the movement
638 {
639 iarm->stopControl();
640 iarm->restoreContext(context_arm);
641 iarm->deleteContext(context_arm);
642
643 igaze->stopControl();
644 igaze->restoreContext(context_gaze);
645 igaze->deleteContext(context_gaze);
646
649
650 mtx.unlock();
651 return;
652 }
653
654 // generate new target
656 {
657 // set up target (position part)
658 Vector xd=targetsConsumed.front();
659 targetsConsumed.pop_front();
660
661 // set up target (orientation part)
662 Matrix Hd=zeros(4,4);
663 Hd(0,0)=-1.0;
664 Hd(1,1)=(arm=="left"?-1.0:1.0);
665 Hd(2,2)=(arm=="left"?1.0:-1.0);
666 Hd(3,3)=1.0;
667
668 Vector rot_y(4,0.0);
669 rot_y[1]=1.0;
670 rot_y[3]=(curExplorationCenter[2]>0.2?90.0:45.0)*CTRL_DEG2RAD;
671
672 Vector od=dcm2axis(axis2dcm(rot_y)*Hd);
673 yInfo("moving to xd=(%s); od=(%s); #%d remaining points",
674 xd.toString(3,3).c_str(),od.toString(3,3).c_str(),(int)targetsConsumed.size());
675
676 iarm->goToPoseSync(xd,od);
677 igaze->lookAtFixationPoint(xd);
678
680 }
681 // check if target has been attained
683 {
684 bool done=false;
685 iarm->checkMotionDone(&done);
686 if (done)
687 {
688 igaze->stopControl();
689 mtx.unlock();
690 Time::delay(exploration_wait);
691 mtx.lock();
693 }
694 }
695
696 mtx.unlock();
697}
698
699
700/************************************************************************/
701void CalibModule::doTouch(const Vector &xd)
702{
703 prepareRobot();
704
705 // set up target (orientation part)
706 Matrix Hd=zeros(4,4);
707 Hd(0,0)=-1.0;
708 Hd(1,1)=(arm=="left"?-1.0:1.0);
709 Hd(2,2)=(arm=="left"?1.0:-1.0);
710 Hd(3,3)=1.0;
711
712 Vector od=dcm2axis(Hd);
713 igaze->setTrackingMode(true);
714 igaze->lookAtFixationPoint(xd);
715
716 Vector x=xd; x[2]+=0.05;
717 yInfo("moving to xd=(%s); od=(%s)",x.toString(3,3).c_str(),od.toString(3,3).c_str());
718 iarm->goToPoseSync(x,od);
719 iarm->waitMotionDone();
720
721 yInfo("moving to xd=(%s); od=(%s)",xd.toString(3,3).c_str(),od.toString(3,3).c_str());
722 iarm->setInTargetTol(touch_intargettol);
723 iarm->goToPoseSync(xd,od);
724 iarm->waitMotionDone(0.1,5.0);
725
726 Time::delay(2.0);
727
728 yInfo("moving to xd=(%s); od=(%s)",x.toString(3,3).c_str(),od.toString(3,3).c_str());
729 iarm->setInTargetTol(exploration_intargettol);
730 iarm->goToPoseSync(x,od);
731 iarm->waitMotionDone();
732
733 x[0]=-0.35;
734 x[1]=(arm=="left"?-0.2:0.2);
735 x[2]=0.1;
736 yInfo("moving to xd=(%s); od=(%s)",x.toString(3,3).c_str(),od.toString(3,3).c_str());
737 iarm->setLimits(0,0.0,0.0);
738 iarm->setLimits(2,0.0,0.0);
739 iarm->goToPoseSync(x,od);
740 iarm->waitMotionDone();
741
742 iarm->restoreContext(context_arm);
743 iarm->deleteContext(context_arm);
744
745 igaze->stopControl();
746 igaze->restoreContext(context_gaze);
747 igaze->deleteContext(context_gaze);
748}
749
750
751/************************************************************************/
753{
754 yInfo("running test #%d",test);
755 Rand::init();
756
757 Vector x_rad(6);
758 x_rad[0]=0.0;
759 x_rad[1]=0.0;
760 x_rad[2]=0.015;
761 x_rad[3]=CTRL_DEG2RAD*0.0;
762 x_rad[4]=CTRL_DEG2RAD*5.0;
763 x_rad[5]=CTRL_DEG2RAD*2.3;
764
765 Vector x_deg=x_rad.subVector(0,2);
766 x_deg=cat(x_deg,CTRL_RAD2DEG*x_rad.subVector(3,5));
767 Matrix H=computeH(x_rad);
768 Matrix invH=SE3inv(H);
769
770 bool ok=false;
771 switch (test)
772 {
773 //*******************
774 case 0:
775 {
776 yInfo("#0a \"check solver's robustness against seg-fault\"");
777 yInfo("#0b \"check correctness of first-order derivative\"");
778
779 Vector p2d(2); p2d[0]=160.0; p2d[1]=120.0;
780 Vector p3d(4); p3d[0]=-0.5; p3d[1]=0.0; p3d[2]=0.34; p3d[3]=1.0;
781 aligner.addPoints(p2d,p3d);
782 Matrix T; double error;
784 ok=true;
785
786 break;
787 }
788
789 //*******************
790 case 1:
791 {
792 yInfo("#1a \"check solver's functionality\"");
793
794 // generate synthetic data
795 Matrix Prj=aligner.getProjection();
796 for (int i=0; i<100; i++)
797 {
798 Vector p3d(4);
799 p3d[0]=Rand::scalar(-0.5,0.5);
800 p3d[1]=Rand::scalar(-0.5,0.5);
801 p3d[2]=Rand::scalar(0.1,1.0);
802 p3d[3]=1.0;
803
804 Vector p2d=Prj*invH*p3d;
805 p2d=p2d/p2d[2];
806 p2d.pop_back();
807 p2d+=NormRand::vector(2,0.0,5.0); // add up some noise
808
809 aligner.addPoints(p2d,p3d);
810 }
811
812 Matrix H1; double error;
814 Vector x1=cat(H1.getCol(3).subVector(0,2),
815 CTRL_RAD2DEG*dcm2rpy(H1));
816
817 yInfo("x=(%s)",x_deg.toString(5,5).c_str());
818 yInfo("H\n%s",H.toString(5,5).c_str());
819 yInfo("solution_x=(%s)",x1.toString(5,5).c_str());
820 yInfo("solution_H\n%s",H1.toString(5,5).c_str());
821 yInfo("error=%g",error);
822
823 break;
824 }
825
826 //*******************
827 case 2:
828 {
829 yInfo("#2a \"check exploration space\"");
830 ok=setExplorationSpaceDelta(0.0,0.0,0.0,0.0,0.0);
831
832 break;
833 }
834
835 //*******************
836 case 3:
837 {
838 yInfo("#3a \"check saving data\"");
839
840 // generate synthetic data
841 for (int i=0; i<10; i++)
842 {
843 Vector p(4);
844 p[0]=Rand::scalar(-0.5,0.5);
845 p[1]=Rand::scalar(-0.5,0.5);
846 p[2]=Rand::scalar(0.1,1.0);
847 p[3]=1.0;
848
850 }
851
852 arm="left";
854 Property ret=calibrate(false);
856 yInfo("H\n%s",H.toString(5,5).c_str());
857 yInfo("calibration output: %s",ret.toString().c_str());
858 ok=save();
859
860 yInfo("#3b \"check retrieving data\"");
861
862 Vector in(4);
863 in[0]=1.0;
864 in[1]=-1.0;
865 in[2]=2.0;
866 in[3]=1.0;
867
868 Vector out=H*in;
869 Vector pred;
870 ok&=experts->retrieve(in,pred);
871 yInfo("in=(%s); out=H*in=(%s); pred=(%s)",
872 in.subVector(0,2).toString(3,3).c_str(),
873 out.subVector(0,2).toString(3,3).c_str(),
874 pred.toString(3,3).c_str());
875
876 yInfo("#3c \"check logging data\"");
877 ok&=log("experts");
878 }
879 }
880
881 yInfo("test #%d %s!",test,ok?"passed":"failed/unknown");
882}
883
884
885/************************************************************************/
886CalibModule::CalibModule() : depthInPort(this) { }
887
888
889/************************************************************************/
890bool CalibModule::configure(ResourceFinder &rf)
891{
892 this->rf=&rf;
893 string robot=rf.check("robot",Value("icub")).asString();
894 string name=rf.check("name",Value("depth2kin")).asString();
895 string type=rf.check("type",Value("se3+scale")).asString();
896 test=rf.check("test",Value(-1)).asInt32();
897 max_dist=fabs(rf.check("max_dist",Value(0.25)).asFloat64());
898 roi_side=abs(rf.check("roi_side",Value(100)).asInt32());
899 block_eyes=fabs(rf.check("block_eyes",Value(5.0)).asFloat64());
900 exploration_wait=fabs(rf.check("exploration_wait",Value(0.5)).asFloat64());
901 exploration_intargettol=fabs(rf.check("exploration_intargettol",Value(0.01)).asFloat64());
902 touch_intargettol=fabs(rf.check("touch_intargettol",Value(0.001)).asFloat64());
903
906
907 enabled=false;
908 isSaved=true;
909 closing=false;
910 exp_depth2kin=true;
911 exp_aligneyes=false;
912 touchWithExperts=true;
913
914 if (!isTypeValid(type))
915 {
916 yError("Unknown method %s!",type.c_str());
917 return false;
918 }
919
920 load();
921 calibrator=factory(type);
922
923 Vector min(6),max(6);
924 min[0]=-0.005; max[0]=0.005;
925 min[1]=-0.005; max[1]=0.005;
926 min[2]=-0.01; max[2]=0.01;
927 min[3]=-CTRL_DEG2RAD*15.0; max[3]=CTRL_DEG2RAD*15.0; // roll
928 min[4]=-CTRL_DEG2RAD*15.0; max[4]=CTRL_DEG2RAD*15.0; // pitch
929 min[5]=-CTRL_DEG2RAD*15.0; max[5]=CTRL_DEG2RAD*15.0; // yaw
930 aligner.setBounds(min,max);
931 aligner.setInitialGuess(eye(4,4));
932
933 if (test>=0)
934 {
935 Matrix K=eye(3,4);
936 K(0,0)=257.34; K(1,1)=257.34;
937 K(0,2)=160.0; K(1,2)=120.0;
938
940 return true;
941 }
942
943 // open drivers
944 Property optionArmL("(device remote_controlboard)");
945 optionArmL.put("remote","/"+robot+"/left_arm");
946 optionArmL.put("local","/"+name+"/joint/left");
947 if (!drvArmL.open(optionArmL))
948 yWarning("Position left_arm controller not available!");
949
950 Property optionArmR("(device remote_controlboard)");
951 optionArmR.put("remote","/"+robot+"/right_arm");
952 optionArmR.put("local","/"+name+"/joint/right");
953 if (!drvArmR.open(optionArmR))
954 yWarning("Position right_arm controller not available!");
955
956 Property optionMAIS_L("(device multipleanalogsensorsclient)");
957 optionMAIS_L.put("remote","/"+robot+"/left_hand/MAIS");
958 optionMAIS_L.put("local","/"+name+"/MAIS/left");
959 if (!drvMAIS_L.open(optionMAIS_L))
960 yWarning("MAIS left_hand sensor not available!");
961
962 Property optionMAIS_R("(device multipleanalogsensorsclient)");
963 optionMAIS_R.put("remote","/"+robot+"/right_hand/MAIS");
964 optionMAIS_R.put("local","/"+name+"/MAIS/right");
965 if (!drvMAIS_R.open(optionMAIS_R))
966 yWarning("MAIS right_hand sensor not available!");
967
968 Property optionCartL("(device cartesiancontrollerclient)");
969 optionCartL.put("remote","/"+robot+"/cartesianController/left_arm");
970 optionCartL.put("local","/"+name+"/cartesian/left");
971 if (!drvCartL.open(optionCartL))
972 yWarning("Cartesian left_arm controller not available!");
973
974 Property optionCartR("(device cartesiancontrollerclient)");
975 optionCartR.put("remote","/"+robot+"/cartesianController/right_arm");
976 optionCartR.put("local","/"+name+"/cartesian/right");
977 if (!drvCartR.open(optionCartR))
978 yWarning("Cartesian right_arm controller not available!");
979
980 Property optionGaze("(device gazecontrollerclient)");
981 optionGaze.put("remote","/iKinGazeCtrl");
982 optionGaze.put("local","/"+name+"/gaze");
983 if (!drvGaze.open(optionGaze))
984 yWarning("Gaze controller not available!");
985
986 // set up some global vars
987 useArmL=(drvArmL.isValid() && drvMAIS_L.isValid() && drvCartL.isValid());
988 useArmR=(drvArmR.isValid() && drvMAIS_R.isValid() && drvCartR.isValid());
990
991 // quitting condition
992 if (!drvGaze.isValid() || (!useArmL && !useArmR))
993 {
994 yError("Something wrong occured while configuring drivers... quitting!");
995 terminate();
996 return false;
997 }
998
999 // set up initial arm and experts
1000 arm=(useArmL?"left":"right");
1001 experts=&(arm=="left"?expertsL:expertsR);
1002
1003 // open devices views
1004 IControlLimits *ilim;
1005 (arm=="left")?drvArmL.view(imods):drvArmR.view(imods);
1006 (arm=="left")?drvArmL.view(iencs):drvArmR.view(iencs);
1007 (arm=="left")?drvArmL.view(iposs):drvArmR.view(iposs);
1008 (arm=="left")?drvArmL.view(ilim):drvArmR.view(ilim);
1009 (arm=="left")?drvMAIS_L.view(iencarray):drvMAIS_R.view(iencarray);
1010 (arm=="left")?drvCartL.view(iarm):drvCartR.view(iarm);
1011 drvGaze.view(igaze);
1012 iencs->getAxes(&nEncs);
1013
1014 Matrix Prj;
1015 if (!getGazeParams("left","intrinsics",Prj))
1016 {
1017 yError("Intrinsic parameters for left camera not available!");
1018 terminate();
1019 return false;
1020 }
1022
1023 finger=iCubFinger(arm+"_index");
1024 deque<IControlLimits*> lim;
1025 lim.push_back(ilim);
1027
1028 double minVer=getMinVer();
1029 if (block_eyes<minVer)
1030 {
1031 block_eyes=minVer;
1032 yWarning("blockEyes saturated at minimum allowed vergence angle %g",block_eyes);
1033 }
1034
1035 touchInPort.open("/"+name+"/touch:i");
1036 depthInPort.open("/"+name+"/depth:i");
1037 depthOutPort.open("/"+name+"/depth:o");
1038 depthRpcPort.open("/"+name+"/depth:rpc");
1039 rpcPort.open("/"+name+"/rpc");
1040 depthInPort.useCallback();
1041 attach(rpcPort);
1042
1043 setExplorationSpaceDelta(0.0,0.0,0.0,0.0,0.0);
1044
1045 return true;
1046}
1047
1048
1049/************************************************************************/
1050void CalibModule::onRead(ImageOf<PixelMono> &imgIn)
1051{
1052 lock_guard<mutex> lck(mtx);
1053
1054 Vector kinPoint,o;
1055 iarm->getPose(kinPoint,o);
1056
1057 Vector c,tipl(2,0.0),tipr(2,0.0);
1058 igaze->get2DPixel(0,kinPoint,c);
1059
1060 ImageOf<PixelBgr> imgOut;
1061 cv::Rect rect=extractFingerTip(imgIn,imgOut,c,tipl);
1062
1063 bool holdImg=false;
1065 {
1066 cv::Scalar color=cv::Scalar(0,0,255);
1067 string tag="discarded";
1068
1069 if (enabled && (depthRpcPort.getOutputCount()>0))
1070 {
1071 Vector depthPoint;
1072 if (getDepthAveraged(tipl,depthPoint,tipr))
1073 {
1074 // consistency check
1075 double dist=norm(depthPoint-kinPoint);
1076 if (dist<max_dist)
1077 {
1078 color=cv::Scalar(0,255,0);
1079 tag="matched";
1080
1081 if (exp_depth2kin)
1082 {
1083 calibrator->addPoints(depthPoint,kinPoint);
1084 yInfo("collecting calibration points: p_depth=(%s); p_kin=(%s);",
1085 depthPoint.toString(3,3).c_str(),kinPoint.toString(3,3).c_str());
1086
1087 tag="acquired";
1088 }
1089
1090 if (exp_aligneyes)
1091 {
1092 Vector kinPoint4=kinPoint;
1093 kinPoint4.push_back(1.0);
1094
1095 Vector xe,oe,kinPoint_e;
1096 Matrix He;
1097
1098 igaze->getLeftEyePose(xe,oe);
1099 He=axis2dcm(oe);
1100 xe.push_back(1.0);
1101 He.setCol(3,xe);
1102 kinPoint_e=SE3inv(He)*kinPoint4;
1103
1104 aligner.addPoints(tipl,kinPoint_e);
1105 yInfo("collecting points for aligning eye: tip=(%s); p_kin=(%s);",
1106 tipl.toString(3,3).c_str(),kinPoint_e.toString(3,3).c_str());
1107
1108 tag="acquired";
1109 }
1110 }
1111 else
1112 yInfo("discarding calibration points: p_depth=(%s); p_kin=(%s); (|p_depth-p_kin|=%g)>%g",
1113 depthPoint.toString(3,3).c_str(),kinPoint.toString(3,3).c_str(),dist,max_dist);
1114 }
1115 else
1116 {
1117 yInfo("unavailable depth; discarding...");
1118 tag="no-depth";
1119 }
1120 }
1121
1122 cv::Mat img=toCvMat(imgOut);
1123 cv::putText(img,tag,cv::Point(rect.x+5,rect.y+15),CV_FONT_HERSHEY_SIMPLEX,0.5,color);
1124
1126 holdImg=true;
1127 }
1128
1129 if (depthOutPort.getOutputCount()>0)
1130 {
1131 depthOutPort.prepare()=imgOut;
1132 depthOutPort.write();
1133 if (holdImg)
1134 Time::delay(0.5);
1135 }
1136}
1137
1138
1139/************************************************************************/
1141{
1142 lock_guard<mutex> lck(mtx);
1143 return (int)experts->size();
1144}
1145
1146
1147/************************************************************************/
1149{
1150 lock_guard<mutex> lck(mtx);
1151 experts->clear();
1152 return true;
1153}
1154
1155
1156/************************************************************************/
1158{
1159 string fileName=rf->findFile("calibrationFile");
1160 if (fileName.empty())
1161 {
1162 yWarning("calibration file not found");
1163 return false;
1164 }
1165
1166 Property data; data.fromConfigFile(fileName);
1167 Bottle b; b.read(data);
1168
1169 lock_guard<mutex> lck(mtx);
1170 yInfo("loading experts from file: %s",fileName.c_str());
1171 for (int i=0; i<b.size(); i++)
1172 factory(b.get(i));
1173 return true;
1174}
1175
1176
1177/************************************************************************/
1179{
1180 lock_guard<mutex> lck(mtx);
1181 if (!isSaved)
1182 {
1183 ofstream fout;
1184 string contextPath=rf->getHomeContextPath();
1185 string fileName=rf->find("calibrationFile").asString();
1186 fileName=contextPath+"/"+fileName;
1187
1188 yInfo("saving experts into file: %s",fileName.c_str());
1189 fout.open(fileName.c_str());
1190
1191 if (fout.is_open())
1192 {
1193 for (size_t i=0; i<expertsL.size(); i++)
1194 {
1195 Property info;
1196 expertsL[i]->toProperty(info);
1197 info.put("arm","left");
1198 ostringstream entry;
1199 entry<<"expert_left_"<<i;
1200 fout<<entry.str()<<" "<<info.toString()<<endl;
1201 }
1202
1203 for (size_t i=0; i<expertsR.size(); i++)
1204 {
1205 Property info;
1206 expertsR[i]->toProperty(info);
1207 info.put("arm","right");
1208 ostringstream entry;
1209 entry<<"expert_right_"<<i;
1210 fout<<entry.str()<<" "<<info.toString()<<endl;
1211 }
1212
1213 fout.close();
1214 isSaved=true;
1215 }
1216 }
1217
1218 return isSaved;
1219}
1220
1221
1222/************************************************************************/
1223bool CalibModule::log(const string &type)
1224{
1225 if ((type!="experts") && (type!="calibrator"))
1226 return false;
1227
1228 if ((type=="calibrator") && !calibrated)
1229 return false;
1230
1231 lock_guard<mutex> lck(mtx);
1232 deque<Vector> p_depth, p_kin;
1233 calibrator->getPoints(p_depth,p_kin);
1234
1235 ofstream fout;
1236 string contextPath=rf->getHomeContextPath();
1237 string fileName=contextPath+"/points_"+arm+"_"+type+".log";
1238
1239 yInfo("logging data into file: %s",fileName.c_str());
1240 fout.open(fileName.c_str());
1241
1242 bool ret=false;
1243 bool useExperts=(type=="experts");
1244 if (fout.is_open())
1245 {
1246 size_t i;
1247 for (i=0; i<p_depth.size(); i++)
1248 {
1249 Vector x;
1250 if (!(useExperts?experts->retrieve(p_depth[i],x):
1251 calibrator->retrieve(p_depth[i],x)))
1252 break;
1253
1254 fout<<p_depth[i].toString(3,3);
1255 fout<<" ";
1256 fout<<p_kin[i].toString(3,3);
1257 fout<<" ";
1258 fout<<x.toString(3,3);
1259 fout<<" ";
1260 fout<<norm(p_kin[i]-x);
1261 fout<<endl;
1262 }
1263
1264 fout.close();
1265 ret=(i>=p_depth.size());
1266 }
1267
1268 return ret;
1269}
1270
1271
1272/************************************************************************/
1274{
1275 prepareRobot();
1278 enabled=true;
1279
1280 return true;
1281}
1282
1283
1284/************************************************************************/
1286{
1287 lock_guard<mutex> lck(mtx);
1288 yInfo("received stop command => stopping exploration...");
1290 return true;
1291}
1292
1293
1294/************************************************************************/
1295bool CalibModule::setMaxDist(const double max_dist)
1296{
1297 this->max_dist=fabs(max_dist);
1298 return true;
1299}
1300
1301
1302/************************************************************************/
1304{
1305 return max_dist;
1306}
1307
1308
1309/************************************************************************/
1310bool CalibModule::setRoi(const int side)
1311{
1312 this->roi_side=abs(side);
1313 return true;
1314}
1315
1316
1317/************************************************************************/
1319{
1320 return roi_side;
1321}
1322
1323
1324/************************************************************************/
1325bool CalibModule::setBlockEyes(const double block_eyes)
1326{
1327 if (block_eyes>=getMinVer())
1328 {
1329 this->block_eyes=block_eyes;
1330 return true;
1331 }
1332 else
1333 return false;
1334}
1335
1336
1337/************************************************************************/
1339{
1340 return block_eyes;
1341}
1342
1343
1344/************************************************************************/
1346{
1347 if (igaze->blockEyes(block_eyes))
1348 return igaze->waitMotionDone();
1349 else
1350 return false;
1351}
1352
1353
1354/************************************************************************/
1356{
1357 return igaze->clearEyes();
1358}
1359
1360
1361/************************************************************************/
1362bool CalibModule::setArm(const string &arm)
1363{
1364 if (!selectArmEnabled || ((arm!="left") && (arm!="right")))
1365 return false;
1366
1367 this->arm=arm;
1368 experts=&(arm=="left"?expertsL:expertsR);
1369 (arm=="left")?drvCartL.view(iarm):drvCartR.view(iarm);
1370 (arm=="left")?drvArmL.view(iencs):drvArmR.view(iencs);
1371 (arm=="left")?drvArmL.view(iposs):drvArmR.view(iposs);
1372 (arm=="left")?drvMAIS_L.view(iencarray):drvMAIS_R.view(iencarray);
1373 finger=iCubFinger(arm+"_index");
1374 return true;
1375}
1376
1377
1378/************************************************************************/
1380{
1381 return arm;
1382}
1383
1384
1385/************************************************************************/
1386bool CalibModule::setCalibrationType(const string &type, const string &extrapolation)
1387{
1388 if (isTypeValid(type))
1389 {
1390 delete calibrator;
1391 calibrator=factory(type);
1392 (extrapolation=="auto")?calibrator->setExtrapolation(type!="lssvm"):
1393 calibrator->setExtrapolation(extrapolation=="true");
1394
1395 return true;
1396 }
1397 else
1398 return false;
1399}
1400
1401
1402/************************************************************************/
1404{
1405 return calibrator->getType();
1406}
1407
1408
1409/************************************************************************/
1410Property CalibModule::calibrate(const bool rm_outliers)
1411{
1412 lock_guard<mutex> lck(mtx);
1413 double error;
1414 Matrix H;
1415 Property reply;
1416
1417 if (exp_depth2kin)
1418 {
1419 if (rm_outliers)
1420 reply.put("outliers_removed",removeOutliers());
1421
1423 reply.put("calibrator",error);
1424 calibrated=true;
1425 }
1426
1427 if (exp_aligneyes)
1428 {
1430 reply.put("aligner",error);
1431
1432 Matrix HL,HR;
1433 if (getGazeParams("left","extrinsics",HL) && getGazeParams("right","extrinsics",HR))
1434 {
1435 Bottle cmd,reply;
1436 cmd.addString("getH");
1437 depthRpcPort.write(cmd,reply);
1438 Matrix HRL; reply.write(HRL);
1439 Matrix HLR=SE3inv(HRL);
1440
1441 Vector x,o;
1442 igaze->getLeftEyePose(x,o);
1443 Matrix TL=axis2dcm(o);
1444 TL.setSubcol(x,0,3);
1445
1446 igaze->getRightEyePose(x,o);
1447 Matrix TR=axis2dcm(o);
1448 TR.setSubcol(x,0,3);
1449
1450 HL=HL*H;
1451 HR=SE3inv(TR)*(TL*HL*HLR);
1452
1453 pushExtrinsics("left",HL);
1454 pushExtrinsics("right",HR);
1455 }
1456 }
1457
1458 return reply;
1459}
1460
1461
1462/************************************************************************/
1464{
1465 lock_guard<mutex> lck(mtx);
1466 bool ret=false;
1467 if (calibrated)
1468 {
1469 (*experts)<<*calibrator;
1470 isSaved=false;
1471 ret=true;
1472 }
1473 return ret;
1474}
1475
1476
1477/************************************************************************/
1479{
1480 if ((sw!="on") && (sw!="off"))
1481 return false;
1482
1483 touchWithExperts=(sw=="on");
1484 return true;
1485}
1486
1487
1488/************************************************************************/
1490{
1491 return (touchWithExperts?"on":"off");
1492}
1493
1494
1495/************************************************************************/
1496bool CalibModule::touch(const int u, const int v)
1497{
1498 Vector px(2);
1499 px[0]=u;
1500 px[1]=v;
1501
1502 yInfo("received touch request for pixel=(%d %d);",u,v);
1503
1504 Vector in,pxr;
1505 if (getDepthAveraged(px,in,pxr))
1506 {
1507 yInfo("=> p_depth=(%s);",in.toString(3,3).c_str());
1508
1509 Vector out=in;
1510 if (touchWithExperts)
1511 {
1512 yInfo("=> apply correction;");
1513 if (!experts->retrieve(in,out))
1514 yWarning("no experts available!");
1515 }
1516
1517 yInfo("=> p_kin=(%s);",out.toString(3,3).c_str());
1518 doTouch(out);
1519
1520 return true;
1521 }
1522 else
1523 {
1524 yInfo("unavailable depth; discarding...");
1525 return false;
1526 }
1527}
1528
1529
1530/************************************************************************/
1531PointReq CalibModule::getPoint(const string &arm, const double x, const double y,
1532 const double z)
1533{
1534 Vector in(3);
1535 in[0]=x;
1536 in[1]=y;
1537 in[2]=z;
1538
1540
1541 Vector out;
1542 PointReq reply("fail",x,y,z);
1543 if (experts->retrieve(in,out))
1544 {
1545 reply.result="ok";
1546 reply.x=out[0];
1547 reply.y=out[1];
1548 reply.z=out[2];
1549 }
1550
1551 return reply;
1552}
1553
1554
1555/************************************************************************/
1556vector<PointReq> CalibModule::getPoints(const string &arm,
1557 const vector<double> &coordinates)
1558{
1560 vector<PointReq> reply;
1561
1562 for (size_t i=0; (i<coordinates.size()) && (i+2<coordinates.size()); i+=3)
1563 {
1564 Vector in(3);
1565 in[0]=coordinates[i];
1566 in[1]=coordinates[i+1];
1567 in[2]=coordinates[i+2];
1568
1569 Vector out;
1570 PointReq point("fail",in[0],in[1],in[2]);
1571 if (experts->retrieve(in,out))
1572 {
1573 point.result="ok";
1574 point.x=out[0];
1575 point.y=out[1];
1576 point.z=out[2];
1577 }
1578
1579 reply.push_back(point);
1580 }
1581
1582 return reply;
1583}
1584
1585
1586/************************************************************************/
1587bool CalibModule::setExperiment(const string &exp, const string &v)
1588{
1589 if ((v!="on") && (v!="off"))
1590 return false;
1591
1592 if (exp=="depth2kin")
1593 {
1594 exp_depth2kin=(v=="on");
1595 return true;
1596 }
1597 else if (exp=="aligneyes")
1598 {
1599 exp_aligneyes=(v=="on");
1600 return true;
1601 }
1602 else
1603 return false;
1604}
1605
1606
1607/************************************************************************/
1608string CalibModule::getExperiment(const string &exp)
1609{
1610 if (exp=="depth2kin")
1611 return (exp_depth2kin?"on":"off");
1612 else if (exp=="aligneyes")
1613 return (exp_aligneyes?"on":"off");
1614 else
1615 return string("");
1616}
1617
1618
1619/************************************************************************/
1620Vector CalibModule::getExtrinsics(const string &eye)
1621{
1622 Matrix H;
1623 Vector reply(6,0.0);
1624 if (getGazeParams(eye,"extrinsics",H))
1625 reply=cat(H.getCol(3).subVector(0,2),
1626 CTRL_RAD2DEG*dcm2rpy(H));
1627
1628 return reply;
1629}
1630
1631
1632/************************************************************************/
1633bool CalibModule::resetExtrinsics(const string &eye)
1634{
1635 return pushExtrinsics(eye,yarp::math::eye(4,4));
1636}
1637
1638
1639/************************************************************************/
1640bool CalibModule::setExplorationWait(const double wait)
1641{
1642 exploration_wait=fabs(wait);
1643 return true;
1644}
1645
1646
1647/************************************************************************/
1649{
1650 return exploration_wait;
1651}
1652
1653
1654/************************************************************************/
1656{
1657 exploration_intargettol=fabs(tol);
1658 return true;
1659}
1660
1661
1662/************************************************************************/
1667
1668
1669/************************************************************************/
1671{
1672 touch_intargettol=fabs(tol);
1673 return true;
1674}
1675
1676
1677/************************************************************************/
1679{
1680 return touch_intargettol;
1681}
1682
1683
1684/************************************************************************/
1685bool CalibModule::setExplorationSpace(const double cx, const double cy,
1686 const double cz, const double a,
1687 const double b)
1688{
1689 Vector c(3),size(2);
1690 c[0]=cx;
1691 c[1]=cy;
1692 c[2]=cz;
1693 size[0]=a;
1694 size[1]=b;
1695
1696 return createTargets(c,size);
1697}
1698
1699
1700/************************************************************************/
1701bool CalibModule::setExplorationSpaceDelta(const double dcx, const double dcy,
1702 const double dcz, const double da,
1703 const double db)
1704{
1705 Vector dc(3),dsize(2);
1706 dc[0]=dcx;
1707 dc[1]=dcy;
1708 dc[2]=dcz;
1709 dsize[0]=da;
1710 dsize[1]=db;
1711
1712 Vector c(3),size(2);
1713 c[0]=-0.4; c[1]=0.0; c[2]=0.05;
1714 size[0]=0.10; size[1]=0.05;
1715 return createTargets(c+dc,size+dsize);
1716}
1717
1718
1719/************************************************************************/
1721{
1722 lock_guard<mutex> lck(mtx);
1723 Property reply;
1724
1725 reply.put("status",(motorExplorationState==motorExplorationStateIdle?"idle":"ongoing"));
1726 reply.put("total_points",(int)targets.size());
1727 reply.put("remaining_points",(int)targetsConsumed.size());
1728 reply.put("calibrator_points",(int)calibrator->getNumPoints());
1729 reply.put("aligner_points",(int)aligner.getNumPoints());
1730
1731 return reply;
1732}
1733
1734
1735/************************************************************************/
1737{
1738 lock_guard<mutex> lck(mtx);
1739 if (exp_depth2kin)
1741
1742 if (exp_aligneyes)
1744
1745 return true;
1746}
1747
1748
1749/************************************************************************/
1751{
1752 return closing=true;
1753}
1754
1755
1756/************************************************************************/
1758{
1759 return 0.03;
1760}
1761
1762
1763/************************************************************************/
1765{
1766 if (test>=0)
1767 {
1768 doTest();
1769 return false;
1770 }
1771
1773
1774 // handle touch request
1775 if (Bottle *touchData=touchInPort.read(false))
1776 {
1777 if (touchData->size()>=2)
1778 touch(touchData->get(0).asInt32(),touchData->get(1).asInt32());
1779 }
1780
1781 return !closing;
1782}
1783
1784
1785/************************************************************************/
1787{
1788 if (!touchInPort.isClosed())
1789 {
1790 touchInPort.close();
1791 depthInPort.close();
1792 depthOutPort.close();
1793 depthRpcPort.close();
1794 rpcPort.close();
1795 }
1796
1797 if (drvArmL.isValid())
1798 drvArmL.close();
1799
1800 if (drvArmR.isValid())
1801 drvArmR.close();
1802
1803 if (drvMAIS_L.isValid())
1804 drvMAIS_L.close();
1805
1806 if (drvMAIS_R.isValid())
1807 drvMAIS_R.close();
1808
1809 if (drvCartL.isValid())
1810 drvCartL.close();
1811
1812 if (drvCartR.isValid())
1813 drvCartR.close();
1814
1815 if (drvGaze.isValid())
1816 drvGaze.close();
1817}
1818
1819
1820/************************************************************************/
1822{
1823 save();
1824 terminate();
1825 delete calibrator;
1826 return true;
1827}
1828
1829
@ data
#define CTRL_RAD2DEG
Definition XSensMTx.cpp:25
#define CTRL_DEG2RAD
Definition XSensMTx.cpp:26
#define M_PI
Definition XSensMTx.cpp:24
void prepareRobot()
Definition module.cpp:514
ICartesianControl * iarm
Definition module.h:76
bool isSaved
Definition module.h:100
bool attach(RpcServer &source)
Definition module.cpp:61
bool motorExplorationAsyncStop
Definition module.h:107
void openHand(IControlMode *imod, IPositionControl *ipos)
Definition module.cpp:334
enum CalibModule::@38 motorExplorationState
bool exp_aligneyes
Definition module.h:103
IEncoderArrays * iencarray
Definition module.h:75
double getExplorationWait()
Return the current wait timeout used during exploration between two consecutive data points.
Definition module.cpp:1648
bool setTouchWithExperts(const string &sw)
Enable/disable the use of experts for touch test.
Definition module.cpp:1478
PolyDriver drvMAIS_L
Definition module.h:67
iCubFinger finger
Definition module.h:80
bool closing
Definition module.h:101
double getExplorationInTargetTol()
Return the current cartesian tolerance used during exploration.
Definition module.cpp:1663
bool enabled
Definition module.h:98
bool explore()
Start the exploration phase.
Definition module.cpp:1273
void doTouch(const Vector &xd)
Definition module.cpp:701
bool getGazeParams(const string &eye, const string &type, Matrix &M)
Definition module.cpp:240
void doMotorExploration()
Definition module.cpp:624
PolyDriver drvGaze
Definition module.h:71
Vector curExplorationCenter
Definition module.h:81
int removeOutliers()
Definition module.cpp:588
double getTouchInTargetTol()
Return the current cartesian tolerance used during touch actions.
Definition module.cpp:1678
string getCalibrationType()
Return the current calibration type.
Definition module.cpp:1403
string arm
Definition module.h:87
PointReq getPoint(const string &arm, const double x, const double y, const double z)
Retrieve the compensated kinematic point corresponding to the input depth point.
Definition module.cpp:1531
void onRead(ImageOf< PixelMono > &imgIn)
Definition module.cpp:1050
bool posture(const string &type)
Make the robot reach a predefined posture.
Definition module.cpp:441
bool stop()
Yield an asynchronous stop of the exploration phase.
Definition module.cpp:1285
bool load()
Reload the list of experts stored within the configuration file.
Definition module.cpp:1157
Vector getExtrinsics(const string &eye)
Retrieve the current extrinsics camera parameters.
Definition module.cpp:1620
double exploration_intargettol
Definition module.h:93
bool setMaxDist(const double max_dist)
Set the maximum allowed distance between the depth point and kinematic prediction to enable data coll...
Definition module.cpp:1295
bool quit()
Quit the module.
Definition module.cpp:1750
string getExperiment(const string &exp)
Return the current status of the experiment.
Definition module.cpp:1608
double getMaxDist()
Return the maximum allowed distance between depth point and kinematic prediction to enable data colle...
Definition module.cpp:1303
RpcServer rpcPort
Definition module.h:120
bool pushExtrinsics(const string &eye, const Matrix &H)
Definition module.cpp:265
Calibrator * calibrator
Definition module.h:83
bool setRoi(const int side)
Definition module.cpp:1310
bool touchWithExperts
Definition module.h:104
PolyDriver drvArmL
Definition module.h:65
@ motorExplorationStateTrigger
Definition module.h:109
@ motorExplorationStateLog
Definition module.h:111
@ motorExplorationStateReach
Definition module.h:110
@ motorExplorationStateIdle
Definition module.h:108
bool useArmL
Definition module.h:88
int context_gaze
Definition module.h:114
bool setArm(const string &arm)
Select the arm to deal with.
Definition module.cpp:1362
bool setBlockEyes(const double block_eyes)
Set the vergence angle used to keep the gaze fixed.
Definition module.cpp:1325
double getMinVer() const
Definition module.cpp:231
DisparityProcessor depthInPort
Definition module.h:117
bool clearExperts()
Clear the list of currently available experts.
Definition module.cpp:1148
bool pushCalibrator()
Push the current calibrator in the list of experts.
Definition module.cpp:1463
double getPeriod()
Definition module.cpp:1757
double block_eyes
Definition module.h:91
bool clearExplorationData()
Clean up the internal list of explored points pairs.
Definition module.cpp:1736
EyeAligner aligner
Definition module.h:85
PolyDriver drvArmR
Definition module.h:66
double exploration_wait
Definition module.h:92
int context_arm
Definition module.h:113
RpcClient depthRpcPort
Definition module.h:119
bool setCalibrationType(const string &type, const string &extrapolation)
Set up the calibrator type.
Definition module.cpp:1386
bool setExplorationInTargetTol(const double tol)
Set up the cartesian tolerance used during exploration.
Definition module.cpp:1655
bool updateModule()
Definition module.cpp:1764
bool setExplorationSpace(const double cx, const double cy, const double cz, const double a, const double b)
Set up the internally coded exploration space composed by two co-centered ellipses,...
Definition module.cpp:1685
PolyDriver drvMAIS_R
Definition module.h:68
bool setExplorationWait(const double wait)
Set up the wait timeout used during exploration between two consecutive data points.
Definition module.cpp:1640
bool calibrated
Definition module.h:99
ResourceFinder * rf
Definition module.h:64
int getNumExperts()
Return the number of available experts.
Definition module.cpp:1140
bool setExperiment(const string &exp, const string &v)
Set on/off an experiment.
Definition module.cpp:1587
LocallyWeightedExperts expertsR
Definition module.h:84
IGazeControl * igaze
Definition module.h:77
bool getDepthAveraged(const Vector &px, Vector &x, Vector &pxr, const int maxSamples=5)
Definition module.cpp:306
Property calibrate(const bool rm_outliers)
Ask the current calibrator to carry out the calibration.
Definition module.cpp:1410
PolyDriver drvCartL
Definition module.h:69
IControlMode * imods
Definition module.h:72
bool close()
Definition module.cpp:1821
bool log(const string &type)
Store on file the log of system response computed out of the explored set of input-output pairs.
Definition module.cpp:1223
bool clearEyes()
Remove the block on the eyes.
Definition module.cpp:1355
bool blockEyes()
Tell the gaze to immediately steer the eyes to the stored vergence angle and stay still.
Definition module.cpp:1345
void terminate()
Definition module.cpp:1786
bool isTypeValid(const string &type)
Definition module.cpp:118
bool setTouchInTargetTol(const double tol)
Set up the cartesian tolerance used during a touch actions.
Definition module.cpp:1670
bool useArmR
Definition module.h:88
int nEncs
Definition module.h:96
BufferedPort< ImageOf< PixelBgr > > depthOutPort
Definition module.h:118
vector< PointReq > getPoints(const string &arm, const vector< double > &coordinates)
Retrieve the compensated kinematic points corresponding to the input depth points.
Definition module.cpp:1556
string getTouchWithExperts()
Return the current status of the switch for experts usage during touch test.
Definition module.cpp:1489
double touch_intargettol
Definition module.h:94
IPositionControl * iposs
Definition module.h:74
bool selectArmEnabled
Definition module.h:89
void doTest()
Definition module.cpp:752
IEncoders * iencs
Definition module.h:73
bool exp_depth2kin
Definition module.h:102
bool setExplorationSpaceDelta(const double dcx, const double dcy, const double dcz, const double da, const double db)
Set up the exploration space in terms of differences with respect to the internally coded couple of e...
Definition module.cpp:1701
Property getExplorationData()
Return some progress about the ongoing exploration.
Definition module.cpp:1720
bool resetExtrinsics(const string &eye)
Reset the extrinsics matrix to default eye matrix.
Definition module.cpp:1633
mutex mtx
Definition module.h:79
BufferedPort< Bottle > touchInPort
Definition module.h:116
Calibrator * factory(const string &type)
Definition module.cpp:126
bool save()
Save the current list of experts into the configuration file.
Definition module.cpp:1178
int roi_side
Definition module.h:95
int test
Definition module.h:97
bool touch(const int u, const int v)
Definition module.cpp:1496
LocallyWeightedExperts * experts
Definition module.h:84
deque< Vector > targetsConsumed
Definition module.h:106
PolyDriver drvCartR
Definition module.h:70
string getArm()
Return the current arm.
Definition module.cpp:1379
bool createTargets(const Vector &c, const Vector &size)
Definition module.cpp:68
bool configure(ResourceFinder &rf)
Definition module.cpp:890
double getBlockEyes()
Return the current angle to keep the vergence at.
Definition module.cpp:1338
cv::Rect extractFingerTip(ImageOf< PixelMono > &imgIn, ImageOf< PixelBgr > &imgOut, const Vector &c, Vector &px)
Definition module.cpp:170
deque< Vector > targets
Definition module.h:106
int getRoi()
Return the side of the squared window used to filter data collection in the image plane.
Definition module.cpp:1318
bool getDepth(const Vector &px, Vector &x, Vector &pxr)
Definition module.cpp:283
double max_dist
Definition module.h:90
LocallyWeightedExperts expertsL
Definition module.h:84
void postureHelper(const Vector &gaze_ang, const Matrix &targetL, const Matrix &targetR)
Definition module.cpp:364
bool calibrateDepth()
Put the robot in a suitable predefined posture and then execute depth calibration.
Definition module.cpp:488
virtual bool clearPoints()=0
virtual bool retrieve(const yarp::sig::Vector &in, yarp::sig::Vector &out)=0
virtual bool toProperty(yarp::os::Property &info) const
Definition methods.cpp:130
virtual bool getPoints(std::deque< yarp::sig::Vector > &in, std::deque< yarp::sig::Vector > &out) const =0
virtual bool addPoints(const yarp::sig::Vector &in, const yarp::sig::Vector &out)=0
virtual void setExtrapolation(const bool extrapolation)
Definition methods.h:62
virtual bool fromProperty(const yarp::os::Property &info)
Definition methods.cpp:149
virtual bool calibrate(double &error)=0
virtual size_t getNumPoints() const
Definition methods.h:66
virtual std::string getType() const
Definition methods.h:60
DisparityProcessor(CalibModule *module)
Definition module.cpp:54
CalibModule *void onRead(ImageOf< PixelMono > &imgIn)
Definition module.cpp:48
bool setInitialGuess(const yarp::sig::Matrix &H)
Definition nlp.cpp:415
size_t getNumPoints() const
Definition nlp.cpp:408
void setBounds(const yarp::sig::Vector &min, const yarp::sig::Vector &max)
Definition nlp.cpp:371
bool calibrate(yarp::sig::Matrix &H, double &error, const int max_iter=ALIGN_IPOPT_MAX_ITER, const int print_level=0, const std::string &derivative_test="none")
Definition nlp.cpp:434
bool addPoints(const yarp::sig::Vector &p2di, const yarp::sig::Vector &p3di)
Definition nlp.cpp:385
bool setProjection(const yarp::sig::Matrix &Prj)
Definition nlp.cpp:351
void clearPoints()
Definition nlp.cpp:400
yarp::sig::Matrix getProjection() const
Definition nlp.cpp:364
virtual size_t size() const
Definition methods.h:125
virtual bool retrieve(const yarp::sig::Vector &in, yarp::sig::Vector &out)
Definition methods.cpp:522
virtual void clear()
Definition methods.cpp:571
PointReq IDL structure to send/receive points.
Definition PointReq.h:23
double y
the y-coordinate.
Definition PointReq.h:37
std::string result
contain [ok]/[fail] on success/failure.
Definition PointReq.h:29
double x
the x-coordinate.
Definition PointReq.h:33
double z
the z-coordinate.
Definition PointReq.h:41
Perform modified Thompson tau technique for outlier detection.
std::set< size_t > detect(const yarp::sig::Vector &data, const yarp::os::Property &options)
Perform outliers detection over the provided data.
A class for defining the iCub Finger.
Definition iKinFwd.h:1233
virtual bool alignJointsBounds(const std::deque< yarp::dev::IControlLimits * > &lim)
Alignes the finger joints bounds with current values set aboard the iCub.
Definition iKinFwd.cpp:2143
virtual bool getChainJoints(const yarp::sig::Vector &motorEncoders, yarp::sig::Vector &chainJoints)
Retrieves the vector of actual finger's joint values (to be used in conjuction with the iKinLimb meth...
yarp::sig::Matrix getH(const unsigned int i, const bool allLink=false)
Returns the rigid roto-translation matrix from the root reference frame to the ith frame in Denavit-H...
Definition iKinFwd.cpp:732
zeros(2, 2) eye(2
exp(-x3 *T)]
cmd
Definition dataTypes.h:30
bool error
static uint32_t idx[BOARD_NUM]
double norm(const yarp::sig::Matrix &M, int col)
Returns the norm of the vector given in the form: matrix(:,col).
bool done
Definition main.cpp:42
Matrix computeH(const Vector &x)
Copyright (C) 2008 RobotCub Consortium.
#define ALIGN_IPOPT_MAX_ITER
Definition nlp.h:28
out
Definition sine.m:8