iCub-main
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 
39 using namespace std;
40 using namespace yarp::cv;
41 using namespace yarp::math;
42 using namespace iCub::ctrl;
43 using namespace iCub::iKin;
44 using namespace iCub::optimization;
45 
46 
47 /************************************************************************/
48 void DisparityProcessor::onRead(ImageOf<PixelMono> &imgIn)
49 {
50  module->onRead(imgIn);
51 }
52 
53 /************************************************************************/
55 {
56  this->module=module;
57 }
58 
59 
60 /************************************************************************/
61 bool CalibModule::attach(RpcServer &source)
62 {
63  return this->yarp().attachAsServer(source);
64 }
65 
66 
67 /************************************************************************/
68 bool 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 
112  curExplorationCenter=c;
113  return true;
114 }
115 
116 
117 /************************************************************************/
118 bool CalibModule::isTypeValid(const string &type)
119 {
120  return ((type=="se3") || (type=="se3+scale") ||
121  (type=="affine") || (type=="lssvm"));
122 }
123 
124 
125 /************************************************************************/
126 Calibrator *CalibModule::factory(const string &type)
127 {
128  Calibrator *calibrator=NULL;
129  if ((type=="se3") || (type=="se3+scale") || (type=="affine"))
130  calibrator=new MatrixCalibrator(type);
131  else if (type=="lssvm")
132  calibrator=new LSSVMCalibrator(type);
133 
134  calibrated=false;
135  return calibrator;
136 }
137 
138 
139 /************************************************************************/
140 bool CalibModule::factory(Value &v)
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 /************************************************************************/
170 cv::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 /************************************************************************/
240 bool 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 /************************************************************************/
265 bool 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 /************************************************************************/
283 bool 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 /************************************************************************/
306 bool 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 /************************************************************************/
334 void 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 /************************************************************************/
364 void 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 /************************************************************************/
441 bool 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;
559  iCubFinger finger=this->finger;
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;
592  calibrator->calibrate(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  {
613  calibrator->clearPoints();
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
629  if (motorExplorationState==motorExplorationStateIdle)
630  {
631  mtx.unlock();
632  return;
633  }
634 
635  // end the movement
636  if (motorExplorationAsyncStop ||
637  ((motorExplorationState==motorExplorationStateTrigger) && targetsConsumed.empty()))
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 
647  motorExplorationAsyncStop=enabled=false;
648  motorExplorationState=motorExplorationStateIdle;
649 
650  mtx.unlock();
651  return;
652  }
653 
654  // generate new target
655  if (motorExplorationState==motorExplorationStateTrigger)
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 
679  motorExplorationState=motorExplorationStateReach;
680  }
681  // check if target has been attained
682  else if (motorExplorationState==motorExplorationStateReach)
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();
692  motorExplorationState=motorExplorationStateLog;
693  }
694  }
695 
696  mtx.unlock();
697 }
698 
699 
700 /************************************************************************/
701 void 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;
783  aligner.calibrate(T,error,ALIGN_IPOPT_MAX_ITER,5,"first-order");
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;
813  ok=aligner.calibrate(H1,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 
849  calibrator->addPoints(p,H*p);
850  }
851 
852  arm="left";
853  experts=&expertsL;
854  Property ret=calibrate(false);
855  pushCalibrator();
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 /************************************************************************/
886 CalibModule::CalibModule() : depthInPort(this) { }
887 
888 
889 /************************************************************************/
890 bool 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
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  }
1021  aligner.setProjection(Prj);
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 /************************************************************************/
1050 void 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 /************************************************************************/
1223 bool 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 /************************************************************************/
1295 bool 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 /************************************************************************/
1310 bool 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 /************************************************************************/
1325 bool 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 /************************************************************************/
1362 bool 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 /************************************************************************/
1386 bool 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 /************************************************************************/
1410 Property 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 /************************************************************************/
1478 bool CalibModule::setTouchWithExperts(const string &sw)
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 /************************************************************************/
1496 bool 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 /************************************************************************/
1531 PointReq 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 /************************************************************************/
1556 vector<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 /************************************************************************/
1587 bool 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 /************************************************************************/
1608 string 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 /************************************************************************/
1620 Vector 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 /************************************************************************/
1633 bool CalibModule::resetExtrinsics(const string &eye)
1634 {
1635  return pushExtrinsics(eye,yarp::math::eye(4,4));
1636 }
1637 
1638 
1639 /************************************************************************/
1640 bool 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 /************************************************************************/
1664 {
1665  return exploration_intargettol;
1666 }
1667 
1668 
1669 /************************************************************************/
1670 bool CalibModule::setTouchInTargetTol(const double tol)
1671 {
1672  touch_intargettol=fabs(tol);
1673  return true;
1674 }
1675 
1676 
1677 /************************************************************************/
1679 {
1680  return touch_intargettol;
1681 }
1682 
1683 
1684 /************************************************************************/
1685 bool 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 /************************************************************************/
1701 bool 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)
1740  calibrator->clearPoints();
1741 
1742  if (exp_aligneyes)
1743  aligner.clearPoints();
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
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
@ motorExplorationStateIdle
Definition: module.h:108
bool useArmL
Definition: module.h:88
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
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
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
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
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)
const FSC max
Definition: strain.h:48
const FSC min
Definition: strain.h:49
Copyright (C) 2008 RobotCub Consortium.
#define ALIGN_IPOPT_MAX_ITER
Definition: nlp.h:28
out
Definition: sine.m:8