111 #include <yarp/os/all.h>
112 #include <yarp/dev/all.h>
113 #include <yarp/sig/all.h>
114 #include <yarp/math/Math.h>
116 #include <iCub/ctrl/math.h>
119 using namespace yarp::os;
120 using namespace yarp::sig;
121 using namespace yarp::dev;
122 using namespace yarp::math;
123 using namespace iCub::ctrl;
127 class KarmaMotor:
public RFModule,
public PortReader
137 ICartesianControl *iCartCtrlL;
138 ICartesianControl *iCartCtrlR;
139 ICartesianControl *iCartCtrl;
150 double elbow_height,elbow_weight;
152 BufferedPort<Bottle> visionPort;
153 RpcClient finderPort;
158 double dist(
const Matrix &M)
161 for (
int r=0; r<M.rows(); r++)
162 for (
int c=0; c<M.cols(); c++)
169 bool read(ConnectionReader &connection)
171 Bottle cmd; cmd.read(connection);
177 bool respond(
const Bottle &command, Bottle &reply)
179 int ack=Vocab::encode(
"ack");
180 int nack=Vocab::encode(
"nack");
182 int cmd=command.get(0).asVocab();
186 case createVocab(
'p',
'u',
's',
'h'):
188 Bottle payload=command.tail();
189 if (payload.size()>=5)
195 c[0]=payload.get(0).asDouble();
196 c[1]=payload.get(1).asDouble();
197 c[2]=payload.get(2).asDouble();
198 theta=payload.get(3).asDouble();
199 radius=payload.get(4).asDouble();
201 push(c,theta,radius,pushHand,toolFrame);
209 case createVocab(
'd',
'r',
'a',
'w'):
210 case createVocab(
'v',
'd',
'r',
'a'):
212 Bottle payload=command.tail();
213 if (payload.size()>=6)
220 c[0]=payload.get(0).asDouble();
221 c[1]=payload.get(1).asDouble();
222 c[2]=payload.get(2).asDouble();
223 theta=payload.get(3).asDouble();
224 radius=payload.get(4).asDouble();
225 dist=payload.get(5).asDouble();
227 double res=draw(cmd==createVocab(
'v',
'd',
'r',
'a'),c,theta,
228 radius,dist,pushHand,toolFrame);
231 if (cmd==createVocab(
'v',
'd',
'r',
'a'))
232 reply.addDouble(res);
239 case createVocab(
'f',
'i',
'n',
'd'):
241 Bottle payload=command.tail();
242 if (payload.size()>=2)
244 string arm=payload.get(0).asString();
245 string eye=payload.get(1).asString();
248 if (findToolTip(arm,eye,solution))
251 reply.append(solution.tail());
254 reply.addVocab(nack);
261 case createVocab(
't',
'o',
'o',
'l'):
263 if (command.size()>1)
265 Bottle subcommand=command.tail();
266 int tag=subcommand.get(0).asVocab();
267 if (tag==Vocab::encode(
"attach"))
269 Bottle payload=subcommand.tail();
270 if (payload.size()>=4)
272 pushHand=payload.get(0).asString();
275 point[0]=payload.get(1).asDouble();
276 point[1]=payload.get(2).asDouble();
277 point[2]=payload.get(3).asDouble();
282 r[3]=atan2(-point[1],point[0]);
283 toolFrame=axis2dcm(r);
284 toolFrame.setCol(3,point);
289 else if (tag==Vocab::encode(
"get"))
292 reply.addString(pushHand);
293 reply.addDouble(toolFrame(0,3));
294 reply.addDouble(toolFrame(1,3));
295 reply.addDouble(toolFrame(2,3));
297 else if (tag==Vocab::encode(
"remove"))
299 pushHand=
"selectable";
312 return RFModule::respond(command,reply);
320 void changeElbowHeight()
325 Bottle &optTask2=tweakOptions.addList();
326 optTask2.addString(
"task_2");
327 Bottle &plTask2=optTask2.addList();
329 Bottle &posPart=plTask2.addList();
330 posPart.addDouble(0.0);
331 posPart.addDouble(0.0);
332 posPart.addDouble(elbow_height);
333 Bottle &weightsPart=plTask2.addList();
334 weightsPart.addDouble(0.0);
335 weightsPart.addDouble(0.0);
336 weightsPart.addDouble(elbow_weight);
337 iCartCtrl->tweakSet(tweakOptions);
342 void push(
const Vector &c,
const double theta,
const double radius,
343 const string &armType=
"selectable",
const Matrix &frame=eye(4,4))
347 Matrix H0(4,4); H0.zero();
351 H0(0,3)=c[0]; H0(1,3)=c[1]; H0(2,3)=c[2]; H0(3,3)=1.0;
353 double theta_rad=CTRL_DEG2RAD*theta;
354 double _c=cos(theta_rad);
355 double _s=sin(theta_rad);
356 double _theta=CTRL_RAD2DEG*atan2(_s,_c);
361 Matrix H1(4,4); H1.zero();
362 H1(0,0)=-_s; H1(1,0)=_c;
364 H1(0,2)=-_c; H1(1,2)=-_s;
365 H1(0,3)=radius*_c; H1(1,3)=radius*_s; H1(3,3)=1.0;
369 Matrix H2(4,4); H2.zero();
370 H2(0,0)=_s; H2(1,0)=-_c;
372 H2(0,2)=_c; H2(1,2)=_s;
373 H2(0,3)=radius*_c; H2(1,3)=radius*_s; H2(3,3)=1.0;
376 Matrix H1eps=H1; Matrix H2eps=H2;
377 H1eps(0,3)+=epsilon*_c; H1eps(1,3)+=epsilon*_s;
378 H2eps(0,3)+=epsilon*_c; H2eps(1,3)+=epsilon*_s;
381 Matrix invFrame=SE3inv(frame);
384 H1eps=H0*H1eps*invFrame;
385 H2eps=H0*H2eps*invFrame;
387 Vector xd1=H1.getCol(3).subVector(0,2);
388 Vector od1=dcm2axis(H1);
390 Vector xd2=H2.getCol(3).subVector(0,2);
391 Vector od2=dcm2axis(H2);
393 Vector xd1eps=H1eps.getCol(3).subVector(0,2);
394 Vector od1eps=dcm2axis(H1eps);
396 Vector xd2eps=H2eps.getCol(3).subVector(0,2);
397 Vector od2eps=dcm2axis(H2eps);
399 printf(
"identified locations...\n");
400 printf(
"xd1=(%s) od1=(%s)\n",xd1.toString(3,3).c_str(),od1.toString(3,3).c_str());
401 printf(
"xd2=(%s) od2=(%s)\n",xd2.toString(3,3).c_str(),od2.toString(3,3).c_str());
404 if (armType==
"selectable")
407 iCartCtrl=iCartCtrlR;
409 iCartCtrl=iCartCtrlL;
411 else if (armType==
"left")
412 iCartCtrl=iCartCtrlL;
414 iCartCtrl=iCartCtrlR;
418 iCartCtrl->storeContext(&context);
421 Bottle &straightOpt=options.addList();
422 straightOpt.addString(
"straightness");
423 straightOpt.addDouble(10.0);
424 iCartCtrl->tweakSet(options);
428 iCartCtrl->getDOF(dof);
431 iCartCtrl->setDOF(dof,dof);
433 Vector xdhat1,odhat1,xdhat2,odhat2;
437 iCartCtrl->askForPose(xd1,od1,xdhat1,odhat1,dummy);
438 iCartCtrl->askForPose(xd2,od2,xdhat2,odhat2,dummy);
440 Matrix Hhat1=axis2dcm(odhat1); Hhat1(0,3)=xdhat1[0]; Hhat1(1,3)=xdhat1[1]; Hhat1(2,3)=xdhat1[2];
441 Matrix Hhat2=axis2dcm(odhat2); Hhat2(0,3)=xdhat2[0]; Hhat2(1,3)=xdhat2[1]; Hhat2(2,3)=xdhat2[2];
443 double d1=dist(H1-Hhat1);
444 double d2=dist(H2-Hhat2);
446 printf(
"solutions...\n");
447 printf(
"#1: xdhat1=(%s) odhat1=(%s); e=%.3f\n",xdhat1.toString(3,3).c_str(),odhat1.toString(3,3).c_str(),d1);
448 printf(
"#2: xdhat2=(%s) odhat2=(%s); e=%.3f\n",xdhat2.toString(3,3).c_str(),odhat2.toString(3,3).c_str(),d2);
449 printf(
"selection: ");
453 if (fabs(_theta-90.0)<45.0)
455 printf(
"(detected singularity) ");
456 if (iCartCtrl==iCartCtrlR)
467 else if (fabs(_theta+90.0)<45.0)
469 printf(
"(detected singularity) ");
470 if (iCartCtrl==iCartCtrlR)
497 if ((iCartCtrl==iCartCtrlR) && (_theta<0.0) && (xd==&xd2))
499 printf(
"(increased radius)");
503 else if ((iCartCtrl==iCartCtrlL) && (_theta<0.0) && (xd==&xd1))
505 printf(
"(increased radius)");
510 printf(
": xd=(%s); od=(%s)\n",xd->toString(3,3).c_str(),od->toString(3,3).c_str());
513 Vector offs(3,0.0); offs[2]=0.1;
518 printf(
"moving to: x=(%s); o=(%s)\n",x.toString(3,3).c_str(),od->toString(3,3).c_str());
519 iCartCtrl->goToPoseSync(x,*od,1.0);
520 iCartCtrl->waitMotionDone(0.1,4.0);
525 printf(
"moving to: x=(%s); o=(%s)\n",xd->toString(3,3).c_str(),od->toString(3,3).c_str());
526 iCartCtrl->goToPoseSync(*xd,*od,1.0);
527 iCartCtrl->waitMotionDone(0.1,4.0);
530 double rmin,rmax,tmin,tmax;
531 if (((fabs(theta)<10.0) || (fabs(theta-180.0)<10.0)))
533 rmin=0.04; rmax=0.18;
534 tmin=0.40; tmax=0.60;
538 rmin=0.04; rmax=0.18;
539 tmin=0.50; tmax=0.80;
543 if (armType!=
"selectable")
549 double trajTime=tmin+((tmax-tmin)/(rmax-rmin))*(radius-rmin);
550 trajTime=std::max(std::min(tmax,trajTime),tmin);
554 Matrix H=axis2dcm(*od);
555 Vector center=c; center.push_back(1.0);
557 Vector x=-1.0*frame.getCol(3); x[3]=1.0;
560 printf(
"moving to: x=(%s); o=(%s)\n",x.toString(3,3).c_str(),od->toString(3,3).c_str());
561 iCartCtrl->goToPoseSync(x,*od,trajTime);
562 iCartCtrl->waitMotionDone(0.1,3.0);
567 printf(
"moving to: x=(%s); o=(%s)\n",xd->toString(3,3).c_str(),od->toString(3,3).c_str());
568 iCartCtrl->goToPoseSync(*xd,*od,1.0);
569 iCartCtrl->waitMotionDone(0.1,2.0);
572 iCartCtrl->restoreContext(context);
573 iCartCtrl->deleteContext(context);
577 double draw(
bool simulation,
const Vector &c,
const double theta,
const double radius,
578 const double dist,
const string &armType,
const Matrix &frame=eye(4,4))
586 Matrix H0(4,4); H0.zero();
590 H0(0,3)=c_sag[0]; H0(1,3)=c_sag[1]; H0(2,3)=c_sag[2]; H0(3,3)=1.0;
592 double theta_rad=CTRL_DEG2RAD*theta;
593 double _c=cos(theta_rad);
594 double _s=sin(theta_rad);
598 H1(0,3)=radius*_c; H1(1,3)=radius*_s;
609 Matrix R(3,3); R.zero();
614 H1.setSubmatrix(R,0,0);
615 H2.setSubmatrix(R,0,0);
617 Vector xd1=H1.getCol(3).subVector(0,2);
618 Vector od1=dcm2axis(H1);
620 Vector xd2=H2.getCol(3).subVector(0,2);
621 Vector od2=dcm2axis(H2);
623 printf(
"identified locations on the sagittal plane...\n");
624 printf(
"xd1=(%s) od1=(%s)\n",xd1.toString(3,3).c_str(),od1.toString(3,3).c_str());
625 printf(
"xd2=(%s) od2=(%s)\n",xd2.toString(3,3).c_str(),od2.toString(3,3).c_str());
628 if (armType==
"selectable")
631 iCartCtrl=iCartCtrlR;
633 iCartCtrl=iCartCtrlL;
635 else if (armType==
"left")
636 iCartCtrl=iCartCtrlL;
638 iCartCtrl=iCartCtrlR;
645 r[3]=atan2(c[1],fabs(c[0]));
646 Matrix H=axis2dcm(r);
651 H1(0,3)=H1(1,3)=H1(2,3)=0.0;
657 H2(0,3)=H2(1,3)=H2(2,3)=0.0;
660 xd1=H1.getCol(3).subVector(0,2);
663 xd2=H2.getCol(3).subVector(0,2);
667 printf(
"in-place locations...\n");
668 printf(
"xd1=(%s) od1=(%s)\n",xd1.toString(3,3).c_str(),od1.toString(3,3).c_str());
669 printf(
"xd2=(%s) od2=(%s)\n",xd2.toString(3,3).c_str(),od2.toString(3,3).c_str());
672 Matrix invFrame=SE3inv(frame);
676 xd1=H1.getCol(3).subVector(0,2);
679 xd2=H2.getCol(3).subVector(0,2);
682 printf(
"apply tool (if any)...\n");
683 printf(
"xd1=(%s) od1=(%s)\n",xd1.toString(3,3).c_str(),od1.toString(3,3).c_str());
684 printf(
"xd2=(%s) od2=(%s)\n",xd2.toString(3,3).c_str(),od2.toString(3,3).c_str());
688 iCartCtrl->storeContext(&context);
691 Bottle &straightOpt=options.addList();
692 straightOpt.addString(
"straightness");
693 straightOpt.addDouble(30.0);
694 iCartCtrl->tweakSet(options);
698 iCartCtrl->getDOF(dof);
701 iCartCtrl->setDOF(dof,dof);
708 Vector xdhat1,odhat1,xdhat2,odhat2,qdhat;
709 iCartCtrl->askForPose(xd1,od1,xdhat1,odhat1,qdhat);
710 iCartCtrl->askForPose(qdhat,xd2,od2,xdhat2,odhat2,qdhat);
712 double e_x1=norm(xd1-xdhat1);
713 double e_o1=norm(od1-odhat1);
714 printf(
"testing x=(%s); o=(%s) => xhat=(%s); ohat=(%s) ... |e_x|=%g; |e_o|=%g\n",
715 xd1.toString(3,3).c_str(),od1.toString(3,3).c_str(),
716 xdhat1.toString(3,3).c_str(),odhat1.toString(3,3).c_str(),
719 double e_x2=norm(xd2-xdhat2);
720 double e_o2=norm(od2-odhat2);
721 printf(
"testing x=(%s); o=(%s) => xhat=(%s); ohat=(%s) ... |e_x|=%g; |e_o|=%g\n",
722 xd2.toString(3,3).c_str(),od2.toString(3,3).c_str(),
723 xdhat2.toString(3,3).c_str(),odhat2.toString(3,3).c_str(),
726 double nearness_penalty=((norm(xdhat1)<0.15)||(norm(xdhat2)<0.15)?10.0:0.0);
727 printf(
"nearness penalty=%g\n",nearness_penalty);
728 res=e_x1+e_o1+e_x2+e_o2+nearness_penalty;
729 printf(
"final quality=%g\n",res);
734 Vector offs(3,0.0); offs[2]=0.05;
739 printf(
"moving to: x=(%s); o=(%s)\n",x.toString(3,3).c_str(),od1.toString(3,3).c_str());
740 iCartCtrl->goToPoseSync(x,od1,2.0);
741 iCartCtrl->waitMotionDone(0.1,5.0);
746 printf(
"moving to: x=(%s); o=(%s)\n",xd1.toString(3,3).c_str(),od1.toString(3,3).c_str());
747 iCartCtrl->goToPoseSync(xd1,od1,1.5);
748 iCartCtrl->waitMotionDone(0.1,5.0);
753 printf(
"moving to: x=(%s); o=(%s)\n",xd2.toString(3,3).c_str(),od2.toString(3,3).c_str());
754 iCartCtrl->goToPoseSync(xd2,od2,3.5);
755 iCartCtrl->waitMotionDone(0.1,5.0);
759 iCartCtrl->restoreContext(context);
760 iCartCtrl->deleteContext(context);
769 IVelocityControl *ivel;
771 if (handUsed==
"left")
783 ienc->getEncoder(shake_joint,&pos);
785 double e=flip_hand-pos;
786 if ((flip_hand>0.0) && (e<0.0) ||
787 (flip_hand<0.0) && (e>0.0))
789 flip_hand=-flip_hand;
793 ivel->velocityMove(shake_joint,120.0*sign(e));
797 void stopHand(
const string &hand)
799 IVelocityControl *ivel;
809 void moveTool(
const string &arm,
const string &eye,
const Vector &xd,
const Vector &od,
810 const Vector &xOffset,
const int maxItems)
812 iGaze->restoreContext(0);
816 iGaze->setTrackingMode(
true);
817 iGaze->lookAtFixationPoint(xd+xOffset);
818 iCartCtrl->goToPoseSync(xd,od,1.0);
819 iCartCtrl->waitMotionDone(0.1);
822 iGaze->setSaccadesMode(
false);
823 iGaze->setNeckTrajTime(2.5);
824 iGaze->setEyesTrajTime(1.5);
829 driverHL.view(imode);
831 driverHR.view(imode);
832 imode->setControlMode(shake_joint,VOCAB_CM_VELOCITY);
837 int cnt=0;
bool done=
false;
838 double t0=Time::now();
839 while (!interrupting && !done)
841 double t1=Time::now();
842 if (Bottle *target=visionPort.read(
false))
844 if (target->size()>=2)
847 px[0]=target->get(0).asDouble();
848 px[1]=target->get(1).asDouble()+50.0;
849 iGaze->lookAtMonoPixel(eye==
"left"?0:1,px);
859 done=fabs(pxCum[1]/cnt-120)<30.0;
870 Bottle command,reply;
871 command.addVocab(Vocab::encode(
"enable"));
872 finderPort.write(command,reply);
875 command.addVocab(Vocab::encode(
"num"));
876 finderPort.write(command,reply);
877 int curItems=reply.get(1).asInt();
880 while (!interrupting && (nItems<curItems+maxItems))
882 finderPort.write(command,reply);
883 nItems=reply.get(1).asInt();
885 if (Bottle *target=visionPort.read(
false))
887 if (target->size()>=2)
890 px[0]=target->get(0).asDouble();
891 px[1]=target->get(1).asDouble()+50.0;
892 iGaze->lookAtMonoPixel(eye==
"left"?0:1,px);
900 command.addVocab(Vocab::encode(
"disable"));
901 finderPort.write(command,reply);
908 bool findToolTip(
const string &arm,
const string &eye, Bottle &reply)
911 iCartCtrl=iCartCtrlL;
912 else if (arm==
"right")
913 iCartCtrl=iCartCtrlR;
917 int context_arm,context_gaze;
918 iCartCtrl->storeContext(&context_arm);
919 iGaze->storeContext(&context_gaze);
922 iCartCtrl->getDOF(dof);
923 dof=1.0; dof[0]=dof[1]=0.0;
924 iCartCtrl->setDOF(dof,dof);
927 command.addVocab(Vocab::encode(
"clear"));
928 finderPort.write(command,reply);
932 command.addVocab(Vocab::encode(
"select"));
933 command.addString(arm);
934 command.addString(eye);
935 finderPort.write(command,reply);
942 Vector r(4,0.0); r[0]=-1.0;
944 Vector offset(3,0.0); offset[2]=0.1;
948 od=dcm2axis(axis2dcm(r)*R);
951 moveTool(arm,eye,xd,od,offset,25);
954 r[3]=CTRL_DEG2RAD*(arm==
"left"?30.0:-30.0);
955 od=dcm2axis(axis2dcm(r)*R);
956 xd[1]=(arm==
"left")?-0.15:0.15;
957 offset[1]=(arm==
"left")?0.1:-0.1;
958 moveTool(arm,eye,xd,od,offset,25);
961 r[3]=CTRL_DEG2RAD*(arm==
"left"?20.0:-20.0);
962 od=dcm2axis(axis2dcm(r)*R);
964 offset[1]=(arm==
"left")?0.2:-0.2;
966 moveTool(arm,eye,xd,od,offset,25);
969 r[3]=CTRL_DEG2RAD*(arm==
"left"?10.0:-10.0);
970 od=dcm2axis(axis2dcm(r)*R);
972 xd[1]=(arm==
"left")?-0.05:0.05;
974 moveTool(arm,eye,xd,od,offset,25);
977 r[3]=CTRL_DEG2RAD*(arm==
"left"?45.0:-45.0);
978 od=dcm2axis(axis2dcm(r)*R);
980 xd[1]=(arm==
"left")?-0.05:0.05;
982 offset[1]=(arm==
"left")?0.1:-0.1;
983 moveTool(arm,eye,xd,od,offset,25);
987 xd[1]=(arm==
"left")?-0.1:0.1;
989 Vector r1(4,0.0); r1[2]=(arm==
"left")?-1.0:1.0; r1[3]=CTRL_DEG2RAD*45.0;
990 Vector r2(4,0.0); r2[0]=(arm==
"left")?1.0:-1.0; r2[3]=CTRL_DEG2RAD*45.0;
991 od=dcm2axis(axis2dcm(r2)*axis2dcm(r1)*R);
993 offset[1]=(arm==
"left")?-0.05:0.05;
996 moveTool(arm,eye,xd,od,offset,50);
1000 command.addVocab(Vocab::encode(
"find"));
1001 finderPort.write(command,reply);
1003 iCartCtrl->restoreContext(context_arm);
1004 iCartCtrl->deleteContext(context_arm);
1006 iGaze->restoreContext(context_gaze);
1007 iGaze->deleteContext(context_gaze);
1014 bool configure(ResourceFinder &rf)
1016 string name=rf.check(
"name",Value(
"karmaMotor")).asString();
1017 string robot=rf.check(
"robot",Value(
"icub")).asString();
1018 elbow_set=rf.check(
"elbow_set");
1021 if (Bottle *pB=rf.find(
"elbow_set").asList())
1023 elbow_height=pB->get(0).asDouble();
1024 elbow_weight=pB->get(1).asDouble();
1033 Property optionG(
"(device gazecontrollerclient)");
1034 optionG.put(
"remote",
"/iKinGazeCtrl");
1035 optionG.put(
"local",
"/"+name+
"/gaze_ctrl");
1037 Property optionL(
"(device cartesiancontrollerclient)");
1038 optionL.put(
"remote",
"/"+robot+
"/cartesianController/left_arm");
1039 optionL.put(
"local",
"/"+name+
"/cart_ctrl/left_arm");
1041 Property optionR(
"(device cartesiancontrollerclient)");
1042 optionR.put(
"remote",
"/"+robot+
"/cartesianController/right_arm");
1043 optionR.put(
"local",
"/"+name+
"/cart_ctrl/right_arm");
1045 Property optionHL(
"(device remote_controlboard)");
1046 optionHL.put(
"remote",
"/"+robot+
"/left_arm");
1047 optionHL.put(
"local",
"/"+name+
"/hand_ctrl/left_arm");
1049 Property optionHR(
"(device remote_controlboard)");
1050 optionHR.put(
"remote",
"/"+robot+
"/right_arm");
1051 optionHR.put(
"local",
"/"+name+
"/hand_ctrl/right_arm");
1053 if (!driverG.open(optionG))
1056 if (!driverL.open(optionL))
1062 if (!driverR.open(optionR))
1069 if (!driverHL.open(optionHL))
1077 if (!driverHR.open(optionHR))
1086 driverG.view(iGaze);
1087 driverL.view(iCartCtrlL);
1088 driverR.view(iCartCtrlR);
1090 visionPort.open(
"/"+name+
"/vision:i");
1091 finderPort.open(
"/"+name+
"/finder:rpc");
1092 rpcPort.open(
"/"+name+
"/rpc");
1093 stopPort.open(
"/"+name+
"/stop:i");
1095 stopPort.setReader(*
this);
1101 pushHand=
"selectable";
1108 bool interruptModule()
1112 iGaze->stopControl();
1113 iCartCtrlL->stopControl();
1114 iCartCtrlR->stopControl();
1116 if (handUsed!=
"null")
1150 if (!interrupting && (handUsed!=
"null"))
1159 int main(
int argc,
char *argv[])
1162 if (!yarp.checkNetwork())
1164 printf(
"YARP server not available!\n");
1169 rf.configure(argc,argv);
1171 KarmaMotor karmaMotor;
1172 return karmaMotor.runModule(rf);