funny-things
All Modules
main.cpp
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
71#include <cstdio>
72#include <cmath>
73#include <sstream>
74#include <string>
75#include <limits>
76#include <map>
77
78#include <yarp/os/all.h>
79#include <yarp/dev/all.h>
80#include <yarp/sig/all.h>
81#include <yarp/math/Math.h>
82
83using namespace std;
84using namespace yarp::os;
85using namespace yarp::dev;
86using namespace yarp::sig;
87using namespace yarp::math;
88
89constexpr double DEG2RAD = M_PI / 180.0;
90
91
92/*********************************************/
93class PosturesModule : public RFModule
94{
95protected:
96 PolyDriver drvArmL,drvArmR;
97 PolyDriver drvCartL,drvCartR,drvGaze;
98 IEncoders *iencsL,*iencsR;
99 IPositionControl *ipossL,*ipossR;
100 ICartesianControl *icartL,*icartR;
101 IGazeControl *igaze;
102 int nEncs;
103
104 map<string,Bottle> emotionsRaw;
105
106 RpcServer rpcPort;
107 RpcClient iolPortStatus;
108 RpcClient iolPortHuman;
109 Port emotionsPort;
110
111 /*********************************************/
112 void handHelper(const string &type, const Vector &poss)
113 {
114 Vector vels(9,0.0);
115 vels[0]=80.0;
116 vels[1]=80.0;
117 vels[2]=80.0;
118 vels[3]=80.0;
119 vels[4]=80.0;
120 vels[5]=80.0;
121 vels[6]=80.0;
122 vels[7]=80.0;
123 vels[8]=200.0;
124
125 IControlMode *imode;
126 IPositionControl *iposs;
127 if (type=="left")
128 {
129 drvArmL.view(imode);
130 drvArmL.view(iposs);
131 }
132 else
133 {
134 drvArmR.view(imode);
135 drvArmR.view(iposs);
136 }
137
138 int i0=nEncs-poss.length();
139 for (int i=i0; i<nEncs; i++)
140 {
141 imode->setControlMode(i,VOCAB_CM_POSITION);
142 iposs->setRefAcceleration(i,std::numeric_limits<double>::max());
143 iposs->setRefSpeed(i,vels[i-i0]);
144 iposs->positionMove(i,poss[i-i0]);
145 }
146 }
147
148 /*********************************************/
149 void openHand(const string &type)
150 {
151 Vector poss(9,0.0);
152 poss[0]=20.0;
153
154 printf("open hand\n");
155 handHelper(type,poss);
156 }
157
158 /*********************************************/
159 void closeHand(const string &type)
160 {
161 Vector poss(9,0.0);
162 poss[0]=40.0;
163 poss[1]=30.0;
164 poss[2]=20.0;
165 poss[3]=90.0;
166 poss[4]=70.0;
167 poss[5]=100.0;
168 poss[6]=70.0;
169 poss[7]=100.0;
170 poss[8]=200.0;
171
172 printf("open hand\n");
173 handHelper(type,poss);
174 }
175
176 /*********************************************/
177 void karateHand(const string &type)
178 {
179 Vector poss(9,0.0);
180 poss[0]=60.0;
181 poss[1]=0.0;
182 poss[2]=50.0;
183
184 printf("karate hand\n");
185 handHelper(type,poss);
186 }
187
188 /*********************************************/
189 void pointHand(const string &type)
190 {
191 Vector poss(9,0.0);
192 poss[0]=40.0;
193 poss[1]=30.0;
194 poss[2]=20.0;
195 poss[3]=90.0;
196 poss[4]=00.0;
197 poss[5]=00.0;
198 poss[6]=70.0;
199 poss[7]=100.0;
200 poss[8]=200.0;
201
202 printf("point hand\n");
203 handHelper(type,poss);
204 }
205
206 /*********************************************/
207 void postureHelper(const string &priority,
208 const Matrix &targetL,
209 const Matrix &targetR,
210 const Vector &targetG,
211 const Vector &torso=Vector(3,0.0))
212 {
213 int ctxtL,ctxtR,ctxtG;
214 Vector dof;
215
216 if (targetG.length()>=3)
217 {
218 printf("looking at target\n");
219 igaze->storeContext(&ctxtG);
220 igaze->blockNeckRoll(0.0);
221 igaze->lookAtAbsAngles(targetG);
222 }
223
224 icartL->storeContext(&ctxtL);
225 icartL->getDOF(dof); dof=1.0;
226 icartL->setDOF(dof,dof);
227 icartL->setLimits(0,torso[0],torso[0]);
228 icartL->setLimits(1,torso[1],torso[1]);
229 icartL->setLimits(2,torso[2],torso[2]);
230 icartL->setPosePriority(priority.c_str());
231 icartL->setTrajTime(0.8);
232
233 printf("reaching for left target\n");
234 icartL->goToPoseSync(targetL.getCol(3),dcm2axis(targetL));
235
236 icartR->storeContext(&ctxtR);
237 icartR->getDOF(dof); dof=1.0;
238 dof[0]=dof[1]=dof[2]=0.0;
239 icartR->setDOF(dof,dof);
240 icartR->setTrackingMode(true);
241 icartR->setPosePriority(priority.c_str());
242 icartR->setTrajTime(0.8);
243
244 printf("reaching for right target\n");
245 icartR->goToPoseSync(targetR.getCol(3),dcm2axis(targetR));
246
247 printf("waiting for right arm... ");
248 icartR->waitMotionDone();
249 printf("done\n");
250
251 printf("waiting for left arm... ");
252 icartL->waitMotionDone();
253 printf("done\n");
254
255 icartL->restoreContext(ctxtL);
256 icartL->deleteContext(ctxtL);
257
258 icartR->restoreContext(ctxtR);
259 icartR->deleteContext(ctxtR);
260
261 if (targetG.length()>=3)
262 {
263 igaze->restoreContext(ctxtG);
264 igaze->deleteContext(ctxtG);
265 }
266 }
267
268 /*********************************************/
269 void beSuspicious(const Vector &lim=Vector(3,0.0))
270 {
271 int ctxt;
272 igaze->storeContext(&ctxt);
273
274 igaze->blockNeckPitch(lim[0]);
275 igaze->blockNeckRoll(lim[1]);
276 igaze->blockNeckYaw(lim[2]);
277
278 Vector targetG(3,0.0);
279
280 targetG[0]=-30.0;
281 igaze->lookAtAbsAngles(targetG);
282 Time::delay(1.0);
283
284 targetG[0]=30.0;
285 igaze->lookAtAbsAngles(targetG);
286 Time::delay(0.7);
287
288 targetG[0]=0.0;
289 igaze->lookAtAbsAngles(targetG);
290 igaze->waitMotionDone();
291
292 igaze->restoreContext(ctxt);
293 igaze->deleteContext(ctxt);
294 }
295
296 /*********************************************/
297 int beHappy(const double roll)
298 {
299 int ctxt;
300 igaze->storeContext(&ctxt);
301
302 igaze->blockNeckPitch(-20.0);
303 igaze->blockNeckRoll(roll);
304 igaze->blockNeckYaw(0.0);
305 igaze->blockEyes(0.0);
306
307 Vector targetG(3,0.0);
308 igaze->lookAtAbsAngles(targetG);
309
310 return ctxt;
311 }
312
313 /*********************************************/
314 bool posture(const string &part,
315 const string &type,
316 const Vector &x=Vector(3,0.0))
317 {
318 Vector targetG(3,0.0);
319 Matrix targetL=zeros(4,4);
320 Matrix targetR=zeros(4,4);
321 targetL(3,3)=targetR(3,3)=1.0;
322
323 if (type=="home")
324 {
325 targetL(0,0)=targetR(0,0)=-1.0;
326 targetL(2,1)=targetR(2,1)=-1.0;
327 targetL(1,2)=targetR(1,2)=-1.0;
328
329 targetL(0,3)=targetR(0,3)=-0.25;
330 targetL(2,3)=targetR(2,3)=0.05;
331
332 targetL(1,3)=-0.3;
333 targetR(1,3)=0.3;
334
335 openHand("left");
336 openHand("right");
337
338 postureHelper("position",targetL,targetR,targetG);
339 return true;
340 }
341 else if (type=="pinch")
342 {
343 say("ouch!");
344 if (part!="torso")
345 {
346 printf("looking at (%s)\n",x.toString(3,3).c_str());
347 igaze->lookAtFixationPoint(x);
348 Time::delay(2.0);
349 igaze->stopControl();
350 }
351
352 emotion(type);
353 say("that hurt");
354
355 karateHand("left");
356 karateHand("right");
357
358 targetL(2,0)=targetR(2,0)=1.0;
359 targetL(0,1)=targetR(0,1)=-1.0;
360 targetL(1,2)=targetR(1,2)=-1.0;
361
362 targetL(0,3)=-0.35;
363 targetL(1,3)=-0.03;
364 targetL(2,3)=0.20;
365
366 targetR(0,3)=-0.25;
367 targetR(1,3)=0.03;
368 targetR(2,3)=0.15;
369
370 Vector r(4,0.0);
371 r[1]=-1.0; r[3]=DEG2RAD*30.0;
372 targetL=axis2dcm(r)*targetL;
373 targetR=axis2dcm(r)*targetR;
374
375 targetG=0.0;
376
377 Vector lim(3,0.0); lim[2]=30.0;
378 postureHelper("orientation",targetL,targetR,targetG,lim);
379 say("go ahead, make my day");
380 beSuspicious(lim);
381 Time::delay(1.0);
382
383 say("I'm watching you!");
384 posture(part,"home");
385 emotion("happy");
386 return true;
387 }
388 else if (type=="poke")
389 {
390 emotion(type);
391 say("what was that?");
392 if (part=="torso")
393 {
394 targetL(0,0)=targetR(0,0)=-1.0;
395 targetL(2,1)=targetR(2,1)=-1.0;
396 targetL(1,2)=targetR(1,2)=-1.0;
397
398 targetL(0,3)=targetR(0,3)=-0.25;
399 targetL(2,3)=targetR(2,3)=0.0;
400
401 targetL(1,3)=-0.25;
402 targetR(1,3)=0.25;
403
404 Vector r(4,0.0);
405 r[2]=1.0; r[3]=DEG2RAD*20.0;
406 targetL=axis2dcm(r)*targetL;
407
408 r[2]=-1.0;
409 targetR=axis2dcm(r)*targetR;
410
411 targetG[1]=-90.0;
412
413 openHand("left");
414 openHand("right");
415
416 Vector lim(3,0.0); lim[0]=-5.0;
417 postureHelper("orientation",targetL,targetR,targetG,lim);
418 }
419 else
420 {
421 printf("looking at (%s)\n",x.toString(3,3).c_str());
422 igaze->lookAtFixationPoint(x);
423 Time::delay(2.0);
424 igaze->stopControl();
425 }
426
427 if (part=="right_arm")
428 {
429 targetR(0,0)=-1.0;
430 targetR(2,1)=-1.0;
431 targetR(1,2)=-1.0;
432 targetR(0,3)=-0.25;
433 targetR(1,3)=0.15;
434 targetR(2,3)=0.0;
435
436 targetL(0,0)=-1.0;
437 targetL(2,1)=-1.0;
438 targetL(1,2)=-1.0;
439 targetL(0,3)=-0.25;
440 targetL(1,3)=0.05;
441 targetL(2,3)=0.2;
442
443 Vector r(4,0.0);
444 r[2]=-1.0; r[3]=DEG2RAD*50.0;
445 targetL=axis2dcm(r)*targetL;
446
447 targetG[0]=40.0;
448 targetG[1]=10.0;
449
450 pointHand("left");
451 openHand("right");
452 }
453 else
454 {
455 targetL(0,0)=-1.0;
456 targetL(2,1)=-1.0;
457 targetL(1,2)=-1.0;
458 targetL(0,3)=-0.25;
459 targetL(1,3)=-0.15;
460 targetL(2,3)=0.0;
461
462 if (part=="torso")
463 {
464 targetR(0,0)=-1.0;
465 targetR(2,1)=-1.0;
466 targetR(1,2)=-1.0;
467 targetR(0,3)=-0.3;
468 targetR(1,3)=0.10;
469 targetR(2,3)=0.15;
470
471 targetG=0.0;
472 }
473 else
474 {
475 targetR(0,0)=-1.0;
476 targetR(2,1)=-1.0;
477 targetR(1,2)=-1.0;
478 targetR(0,3)=-0.25;
479 targetR(1,3)=-0.05;
480 targetR(2,3)=0.2;
481
482 Vector r(4,0.0);
483 r[2]=1.0; r[3]=DEG2RAD*50.0;
484 targetR=axis2dcm(r)*targetR;
485
486 targetG[0]=-40.0;
487 targetG[1]=10.0;
488 }
489
490 pointHand("right");
491 openHand("left");
492 }
493
494 emotion("you");
495 say("was it you?");
496 postureHelper("orientation",targetL,targetR,targetG);
497 Time::delay(2.0);
498
499 posture(part,"home");
500 emotion("happy");
501 return true;
502 }
503 if (type=="caress")
504 {
505 targetL(0,0)=targetR(0,0)=-1.0;
506 targetL(2,1)=targetR(2,1)=-1.0;
507 targetL(1,2)=targetR(1,2)=-1.0;
508
509 targetL(0,3)=targetR(0,3)=-0.25;
510 targetL(2,3)=targetR(2,3)=0.1;
511
512 targetL(1,3)=-0.15;
513 targetR(1,3)=0.15;
514
515 Vector r(4,0.0);
516 r[1]=1.0; r[3]=DEG2RAD*20.0;
517 targetL=axis2dcm(r)*targetL;
518 targetR=axis2dcm(r)*targetR;
519
520 closeHand("left");
521 closeHand("right");
522
523 double roll=0.0;
524 if (part=="left_arm")
525 roll=-30.0;
526 else if (part=="right_arm")
527 roll=30.0;
528
529 emotion(type);
530 say("he, he he he");
531 int ctxt=beHappy(roll);
532
533 Vector nolook(1);
534 postureHelper("orientation",targetL,targetR,nolook);
535 Time::delay(2.0);
536
537 igaze->restoreContext(ctxt);
538 igaze->deleteContext(ctxt);
539
540 emotion("happy");
541 posture(part,"home");
542 return true;
543 }
544 else
545 return false;
546 }
547
548 /*********************************************/
549 bool getGrant()
550 {
551 if (iolPortHuman.getOutputCount()==0)
552 return true;
553
554 Bottle cmd,reply;
555 cmd.addVocab32("status");
556 if (iolPortStatus.write(cmd,reply))
557 {
558 if (reply.size()>1)
559 {
560 if ((reply.get(0).asString()=="ack") &&
561 (reply.get(1).asString()=="idle"))
562 {
563 cmd.clear();
564 cmd.addVocab32("attention");
565 cmd.addString("stop");
566 printf("sending: %s\n",cmd.toString().c_str());
567 bool ok=iolPortHuman.write(cmd,reply);
568 printf("received: %s\n",reply.toString().c_str());
569 if (ok)
570 return (reply.get(0).asString()=="ack");
571 }
572 }
573 }
574
575 return false;
576 }
577
578 /*********************************************/
579 bool giveGrant()
580 {
581 if (iolPortHuman.getOutputCount()==0)
582 return true;
583
584 Bottle cmd,reply;
585 cmd.addVocab32("attention");
586 cmd.addString("start");
587 printf("sending: %s\n",cmd.toString().c_str());
588 bool ok=iolPortHuman.write(cmd,reply);
589 printf("received: %s\n",reply.toString().c_str());
590 if (ok)
591 return (reply.get(0).asString()=="ack");
592
593 return false;
594 }
595
596 /*********************************************/
597 bool say(const string &sentence)
598 {
599 if (iolPortHuman.getOutputCount()>0)
600 {
601 Bottle cmd,reply;
602 cmd.addVocab32("say");
603 cmd.addString(sentence.c_str());
604 if (iolPortHuman.write(cmd,reply))
605 return (reply.get(0).asString()=="ack");
606 }
607
608 return false;
609 }
610
611 /*********************************************/
612 bool emotion(const string &type)
613 {
614 if (emotionsPort.getOutputCount()>0)
615 {
616 map<string,Bottle>::iterator it=emotionsRaw.find(type);
617 if (it!=emotionsRaw.end())
618 {
619 Bottle &b=it->second;
620 for (int i=0; i<b.size(); i++)
621 {
622 Bottle cmd;
623 cmd.addString(b.get(i).asString());
624 emotionsPort.write(cmd);
625 Time::delay(0.001);
626 }
627
628 return true;
629 }
630 }
631
632 return false;
633 }
634
635 /*********************************************/
636 void configureEmotions(ResourceFinder &rf)
637 {
638 int numEmotions=rf.check("num_emotions",Value(0)).asInt32();
639 for (int i=0; i<numEmotions; i++)
640 {
641 ostringstream tag;
642 tag<<"emotion_"<<i;
643
644 Bottle &emotion=rf.findGroup(tag.str().c_str());
645 if (!emotion.isNull())
646 {
647 if (emotion.check("name"))
648 {
649 string name=emotion.find("name").asString().c_str();
650 if (Bottle *raw=emotion.find("raw").asList())
651 emotionsRaw[name]=*raw;
652 }
653 }
654 }
655 }
656
657public:
658 /*********************************************/
659 bool configure(ResourceFinder &rf)
660 {
661 string robot=rf.check("robot",Value("icub")).asString().c_str();
662 string name=rf.check("name",Value("funnyPostures")).asString().c_str();
663
664 rpcPort.open(("/"+name+"/rpc").c_str());
665 iolPortStatus.open(("/"+name+"/iol/status:rpc").c_str());
666 iolPortHuman.open(("/"+name+"/iol/human:rpc").c_str());
667 emotionsPort.open(("/"+name+"/emotions/raw").c_str());
668
669 // open drivers
670 Property optionArmL("(device remote_controlboard)");
671 optionArmL.put("remote",("/"+robot+"/left_arm").c_str());
672 optionArmL.put("local",("/"+name+"/joint/left").c_str());
673 if (!drvArmL.open(optionArmL))
674 printf("Position left_arm controller not available!\n");
675
676 Property optionArmR("(device remote_controlboard)");
677 optionArmR.put("remote",("/"+robot+"/right_arm").c_str());
678 optionArmR.put("local",("/"+name+"/joint/right").c_str());
679 if (!drvArmR.open(optionArmR))
680 printf("Position right_arm controller not available!\n");
681
682 Property optionCartL("(device cartesiancontrollerclient)");
683 optionCartL.put("remote",("/"+robot+"/cartesianController/left_arm").c_str());
684 optionCartL.put("local",("/"+name+"/cartesian/left").c_str());
685 if (!drvCartL.open(optionCartL))
686 printf("Cartesian left_arm controller not available!\n");
687
688 Property optionCartR("(device cartesiancontrollerclient)");
689 optionCartR.put("remote",("/"+robot+"/cartesianController/right_arm").c_str());
690 optionCartR.put("local",("/"+name+"/cartesian/right").c_str());
691 if (!drvCartR.open(optionCartR))
692 printf("Cartesian right_arm controller not available!\n");
693
694 Property optionGaze("(device gazecontrollerclient)");
695 optionGaze.put("remote","/iKinGazeCtrl");
696 optionGaze.put("local",("/"+name+"/gaze").c_str());
697 if (!drvGaze.open(optionGaze))
698 printf("Gaze controller not available!\n");
699
700 // quitting condition
701 if (!drvArmL.isValid() || !drvArmR.isValid() ||
702 !drvCartL.isValid() || !drvCartR.isValid() ||
703 !drvGaze.isValid())
704 {
705 printf("Something wrong occured while configuring drivers... quitting!\n");
706 terminate();
707 return false;
708 }
709
710 // open devices views
711 drvArmL.view(iencsL); drvArmL.view(ipossL); drvCartL.view(icartL);
712 drvArmR.view(iencsR); drvArmR.view(ipossR); drvCartR.view(icartR);
713 drvGaze.view(igaze);
714 iencsL->getAxes(&nEncs);
715
716 attach(rpcPort);
717
718 configureEmotions(rf);
719
720 return true;
721 }
722
723 /*********************************************/
724 double getPeriod()
725 {
726 return 1.0;
727 }
728
729 /*********************************************/
730 bool updateModule()
731 {
732 return true;
733 }
734
735 /*********************************************/
736 bool respond(const Bottle &cmd, Bottle &reply)
737 {
738 int ack=Vocab32::encode("ack");
739 int nack=Vocab32::encode("nack");
740
741 Value item=cmd.get(0);
742 if (item.isString())
743 {
744 if (item.asString()=="home")
745 {
746 if (getGrant())
747 {
748 posture("foo","home");
749 giveGrant();
750 reply.addVocab32(ack);
751 }
752 else
753 reply.addVocab32(nack);
754
755 return true;
756 }
757 }
758
759 int ans=nack;
760 if (Bottle *what=item.asList())
761 {
762 if (what->size()>1)
763 {
764 string part=what->get(0).asString().c_str();
765 string type=what->get(1).asString().c_str();
766
767 Vector x(3,0.0);
768 if (cmd.size()>1)
769 if (Bottle *where=cmd.get(1).asList())
770 for (int i=0; i<where->size(); i++)
771 x[i]=where->get(i).asFloat64();
772
773 if (getGrant())
774 {
775 ans=posture(part,type,x)?ack:nack;
776 giveGrant();
777 }
778 else
779 ans=nack;
780 }
781 }
782
783 Bottle rep;
784 if (ans==ack)
785 reply.addVocab32(ack);
786 else if (RFModule::respond(cmd,rep))
787 reply=rep;
788 else
789 reply.addVocab32(nack);
790
791 return true;
792 }
793
794 /*********************************************/
795 void terminate()
796 {
797 rpcPort.close();
798 iolPortStatus.close();
799 iolPortHuman.close();
800 emotionsPort.close();
801
802 if (drvArmL.isValid())
803 drvArmL.close();
804
805 if (drvArmR.isValid())
806 drvArmR.close();
807
808 if (drvCartL.isValid())
809 drvCartL.close();
810
811 if (drvCartR.isValid())
812 drvCartR.close();
813
814 if (drvGaze.isValid())
815 drvGaze.close();
816 }
817
818 /*********************************************/
819 bool close()
820 {
821 terminate();
822 return true;
823 }
824
825};
826
827
828/****************************************************************/
829int main(int argc, char *argv[])
830{
831 Network yarp;
832 if (!yarp.checkNetwork())
833 {
834 printf("YARP server not available!\n");
835 return 1;
836 }
837
838 ResourceFinder rf;
839 rf.setDefaultContext("funny-things");
840 rf.setDefaultConfigFile("emotions.ini");
841 rf.configure(argc,argv);
842
843 PosturesModule mod;
844 return mod.runModule(rf);
845}
846
847