24 #include <yarp/cv/Cv.h>
25 #include <yarp/math/Math.h>
26 #include <yarp/math/Rand.h>
30 using namespace yarp::cv;
31 using namespace yarp::math;
41 BusyGate(
bool &g) : gate(g)
63 Tracker::Tracker(
const string &trackerType_,
const double trackerTmo_) :
64 trackerType(trackerType_), trackerState(idle),
65 trackerTmo(trackerTmo_), trackerTimer(0.0)
67 trackerResult.x=trackerResult.y=0;
68 trackerResult.width=trackerResult.height=0;
73 void Tracker::prepare()
75 if (trackerState==no_need)
81 void Tracker::latchBBox(
const cv::Rect &bbox)
83 trackerResult.x=bbox.x;
84 trackerResult.y=bbox.y;
85 trackerResult.width=bbox.width;
86 trackerResult.height=bbox.height;
92 void Tracker::track(ImageOf<PixelBgr> &img)
94 cv::Mat frame=toCvMat(img);
95 if (trackerState==init)
97 if (trackerType==
"MIL")
98 tracker=cv::TrackerMIL::create();
99 else if (trackerType==
"TLD")
100 tracker=cv::TrackerTLD::create();
101 else if (trackerType==
"KCF")
102 tracker=cv::TrackerKCF::create();
104 tracker=cv::TrackerBoosting::create();
106 tracker->init(frame,trackerResult);
107 trackerTimer=Time::now();
108 trackerState=tracking;
110 else if (trackerState==tracking)
112 if (Time::now()-trackerTimer<trackerTmo)
114 tracker->update(frame,trackerResult);
115 cv::Point tl((
int)trackerResult.x,(
int)trackerResult.y);
116 cv::Point br(tl.x+(
int)trackerResult.width,tl.y+(
int)trackerResult.height);
117 if ((tl.x<5) || (br.x>frame.cols-5) ||
118 (tl.y<5) || (br.y>frame.rows-5))
128 bool Tracker::is_tracking(cv::Rect &bbox)
const
130 bbox=cv::Rect((
int)trackerResult.x,(
int)trackerResult.y,
131 (
int)trackerResult.width,(
int)trackerResult.height);
132 return (trackerState!=idle);
137 int Manager::processHumanCmd(
const Bottle &cmd, Bottle &b)
139 int ret=Vocab32::encode(cmd.get(0).asString());
144 if (cmd.get(1).isList())
145 b=*cmd.get(1).asList();
155 Bottle Manager::skimBlobs(
const Bottle &blobs)
158 for (
int i=0; i<blobs.size(); i++)
160 cv::Point cog=getBlobCOG(blobs,i);
161 if ((cog.x==RET_INVALID) || (cog.y==RET_INVALID))
166 if (get3DPosition(cog,x))
168 if ((x[0]>skim_blobs_x_bounds[0])&&(x[0]<skim_blobs_x_bounds[1])&&
169 (x[1]>skim_blobs_y_bounds[0])&&(x[1]<skim_blobs_y_bounds[1]))
170 skimmedBlobs.add(blobs.get(i));
179 bool Manager::thresBBox(cv::Rect &bbox,
const Image &img)
181 cv::Point tl(bbox.x,bbox.y);
182 cv::Point br(tl.x+bbox.width,tl.y+bbox.height);
183 tl.x=std::min((
int)img.width(),std::max(tl.x,0));
184 tl.y=std::min((
int)img.height(),std::max(tl.y,0));
185 br.x=std::min((
int)img.width(),std::max(br.x,0));
186 br.y=std::min((
int)img.height(),std::max(br.y,0));
188 bbox=cv::Rect(tl.x,tl.y,br.x-tl.x,br.y-tl.y);
189 if ((bbox.width>tracker_min_blob_size[0]) &&
190 (bbox.height>tracker_min_blob_size[1]))
198 Bottle Manager::getBlobs()
201 mutexResources.lock();
203 if (Bottle *pBlobs=blobExtractor.read(
false))
205 lastBlobsArrivalTime=Time::now();
206 lastBlobs=skimBlobs(*pBlobs);
207 yInfo(
"Received blobs list: %s",lastBlobs.toString().c_str());
209 if (lastBlobs.size()==1)
211 if (lastBlobs.get(0).asVocab32()==Vocab32::encode(
"empty"))
215 else if (Time::now()-lastBlobsArrivalTime>blobs_detection_timeout)
219 mutexResources.unlock();
226 cv::Point Manager::getBlobCOG(
const Bottle &blobs,
const int i)
228 cv::Point cog(RET_INVALID,RET_INVALID);
229 if ((i>=0) && (i<blobs.size()))
232 Bottle *item=blobs.get(i).asList();
236 tl.x=(int)item->get(0).asFloat64();
237 tl.y=(int)item->get(1).asFloat64();
238 br.x=(int)item->get(2).asFloat64();
239 br.y=(int)item->get(3).asFloat64();
241 cog.x=(tl.x+br.x)>>1;
242 cog.y=(tl.y+br.y)>>1;
250 bool Manager::get3DPosition(
const cv::Point &point, Vector &x)
253 if (rpcGet3D.getOutputCount()>0)
259 cmd.addString(
"Rect");
260 cmd.addInt32(point.x-3);
261 cmd.addInt32(point.y-3);
267 yInfo(
"Sending get3D query: %s",cmd.toString().c_str());
268 rpcGet3D.write(cmd,reply);
269 yInfo(
"Received blob cartesian coordinates: %s",reply.toString().c_str());
273 if ((sz>0) && ((sz%3)==0))
278 for (
int i=0; i<sz; i+=3)
280 tmp[0]=reply.get(i+0).asFloat64();
281 tmp[1]=reply.get(i+1).asFloat64();
282 tmp[2]=reply.get(i+2).asFloat64();
294 yWarning(
"get3DPosition failed");
297 yError(
"SFM replied with wrong size");
300 return (norm(x)>0.0);
305 void Manager::acquireImage(
const bool rtlocalization)
308 mutexResources.lock();
311 if (ImageOf<PixelBgr> *tmp=imgIn.read())
320 mutexResources.unlock();
325 void Manager::drawBlobs(
const Bottle &blobs,
const int i,
329 mutexResources.lock();
331 BufferedPort<ImageOf<PixelBgr> > *port=(scores==NULL)?&imgOut:&imgRtLocOut;
332 if (port->getOutputCount()>0)
334 cv::Scalar highlight(0,255,0);
335 cv::Scalar lowlight(150,125,125);
338 ImageOf<PixelBgr> img=(scores==NULL)?this->img:this->imgRtLoc;
339 cv::Mat imgMat=toCvMat(img);
340 for (
int j=0; j<blobs.size(); j++)
342 cv::Point tl,br,txtLoc;
343 Bottle *item=blobs.get(j).asList();
344 tl.x=(int)item->get(0).asFloat64();
345 tl.y=(int)item->get(1).asFloat64();
346 br.x=(int)item->get(2).asFloat64();
347 br.y=(int)item->get(3).asFloat64();
357 string object=db.findName(*scores,tag.str());
363 cv::rectangle(imgMat,tl,br,(j==i)?highlight:lowlight,2);
364 cv::putText(imgMat,tag.str(),txtLoc,cv::FONT_HERSHEY_SIMPLEX,0.5,(j==i)?highlight:lowlight,2);
372 mutexResources.unlock();
377 void Manager::rotate(cv::Mat &src,
const double angle,
380 int len=std::max(src.cols,src.rows);
381 cv::Point2f pt(len/2.0f,len/2.0f);
382 cv::Mat r=cv::getRotationMatrix2D(pt,angle,1.0);
383 cv::warpAffine(src,dst,r,cv::Size(len,len));
388 void Manager::drawScoresHistogram(
const Bottle &blobs,
389 const Bottle &scores,
const int i)
391 if (imgHistogram.getOutputCount()>0)
394 mutexResources.lock();
397 ImageOf<PixelBgr> imgConf;
398 imgConf.resize(600,600); imgConf.zero();
401 cv::Mat imgRtLocMat=toCvMat(imgRtLoc);
402 cv::Mat imgConfMat=toCvMat(imgConf);
408 if (Bottle *blobScores=scores.find(tag.str()).asList())
411 int maxHeight=(int)(imgConf.height()*0.8);
412 int minHeight=imgConf.height()-20;
413 int widthStep=(blobScores->size()>0)?(
int)(imgConf.width()/blobScores->size()):0;
414 set<string> gcFilters;
417 for (
int j=0; j<blobScores->size(); j++)
419 Bottle *item=blobScores->get(j).asList();
423 string name=item->get(0).asString();
424 double score=std::max(std::min(item->get(1).asFloat64(),1.0),0.0);
427 auto it=histFiltersPool.find(name);
430 if (it==histFiltersPool.end())
432 Vector num(histFilterLength,1.0);
433 Vector den(histFilterLength,0.0); den[0]=histFilterLength;
434 histFiltersPool[name]=
new Filter(num,den,Vector(1,score));
438 Vector scoreFilt=it->second->filt(Vector(1,score));
443 gcFilters.insert(name);
445 int classHeight=std::min(minHeight,(
int)imgConf.height()-(
int)(maxHeight*score));
447 cv::rectangle(imgConfMat,cv::Point(j*widthStep,classHeight),cv::Point((j+1)*widthStep,minHeight),
448 histColorsCode[j%(
int)histColorsCode.size()],cv::FILLED);
450 cv::Mat textImg=cv::Mat::zeros(imgConf.height(),imgConf.width(),CV_8UC3);
451 cv::putText(textImg,name,cv::Point(imgConf.width()-580,(j+1)*widthStep-10),cv::FONT_HERSHEY_SIMPLEX,0.8,cv::Scalar(255,255,255),2);
452 rotate(textImg,90.0,textImg);
454 cv::Mat orig=toCvMat(imgConf);
460 Bottle *item=blobs.get(i).asList();
461 tl.x=(int)item->get(0).asFloat64();
462 tl.y=(int)item->get(1).asFloat64();
463 br.x=(int)item->get(2).asFloat64();
464 br.y=(int)item->get(3).asFloat64();
469 ImageOf<PixelBgr> imgTmp1;
470 imgTmp1.resize(sz.x,sz.y);
471 cv::Mat imgRtLocRoi(imgRtLocMat,cv::Rect(tl.x,tl.y,sz.x,sz.y));
472 cv::Mat imgTmp1Mat=toCvMat(imgTmp1);
473 imgRtLocRoi.copyTo(imgTmp1Mat);
476 double resizeFact=sqrt((imgConf.width()*imgConf.height())/(imgTmp1.width()*imgTmp1.height()))/4.0;
477 size_t imgTmp2_width=(size_t)(resizeFact*imgTmp1.width());
478 size_t imgTmp2_height=(size_t)(resizeFact*imgTmp1.height());
479 if (imgTmp2_width>imgTmp2_height)
481 if (imgTmp2_width>imgConf.width()/4)
483 double r=(double)imgTmp2_height/(
double)imgTmp2_width;
484 imgTmp2_width=imgConf.width()/4;
485 imgTmp2_height=(size_t)(r*imgTmp2_width);
488 else if (imgTmp2_height>imgConf.height()/4)
490 double r=(double)imgTmp2_width/(
double)imgTmp2_height;
491 imgTmp2_height=imgConf.height()/4;
492 imgTmp2_width=(size_t)(r*imgTmp2_height);
495 ImageOf<PixelBgr> imgTmp2;
496 imgTmp2.resize(std::max((
size_t)1,imgTmp2_width),std::max((
size_t)1,imgTmp2_height));
497 cv::Mat imgTmp2Mat=toCvMat(imgTmp2);
498 cv::resize(imgTmp1Mat,imgTmp2Mat,imgTmp2Mat.size());
501 cv::Mat imgConfRoi(imgConfMat,cv::Rect(0,0,imgTmp2.width(),imgTmp2.height()));
502 imgTmp2Mat.copyTo(imgConfRoi);
503 cv::rectangle(imgConfMat,cv::Point(0,0),cv::Point(imgTmp2.width(),imgTmp2.height()),
504 cv::Scalar(255,255,255),3);
507 if ((
int)histFiltersPool.size()>blobScores->size())
509 for (
auto it=histFiltersPool.begin();
510 it!=histFiltersPool.end(); it++)
512 if (gcFilters.find(it->first)==gcFilters.end())
515 histFiltersPool.erase(it);
522 imgHistogram.prepare()=imgConf;
523 imgHistogram.write();
526 mutexResources.unlock();
532 int Manager::findClosestBlob(
const Bottle &blobs,
const cv::Point &loc)
535 double min_d2=std::numeric_limits<double>::max();
537 for (
int i=0; i<blobs.size(); i++)
539 cv::Point cog=getBlobCOG(blobs,i);
540 if ((cog.x==RET_INVALID) || (cog.y==RET_INVALID))
543 double dx=loc.x-cog.x;
544 double dy=loc.y-cog.y;
545 double d2=dx*dx+dy*dy;
559 int Manager::findClosestBlob(
const Bottle &blobs,
const Vector &loc)
562 double curMinDist=std::numeric_limits<double>::max();
564 for (
int i=0; i<blobs.size(); i++)
566 cv::Point cog=getBlobCOG(blobs,i);
567 if ((cog.x==RET_INVALID) || (cog.y==RET_INVALID))
571 if (get3DPosition(cog,x))
573 double dist=norm(loc-x);
587 Bottle Manager::classify(
const Bottle &blobs,
588 const bool rtlocalization)
591 mutexResources.lock();
594 imgClassifier.write(imgRtLoc);
596 imgClassifier.write(img);
599 cmd.addVocab32(
"classify");
600 Bottle &options=cmd.addList();
601 for (
int i=0; i<blobs.size(); i++)
605 Bottle &item=options.addList();
606 item.addString(tag.str());
607 item.addList()=*blobs.get(i).asList();
609 yInfo(
"Sending classification request: %s",cmd.toString().c_str());
610 rpcClassifier.write(cmd,reply);
611 yInfo(
"Received reply: %s",reply.toString().c_str());
614 mutexResources.unlock();
621 void Manager::burst(
const string &tag)
623 if (trainBurst && (tag!=
""))
626 cmd.addVocab32(
"burst");
629 yInfo(
"Sending burst training request: %s",cmd.toString().c_str());
630 rpcClassifier.write(cmd,reply);
631 yInfo(
"Received reply: %s",reply.toString().c_str());
637 void Manager::train(
const string &
object,
const Bottle &blobs,
641 mutexResources.lock();
643 imgClassifier.write(img);
646 cmd.addVocab32(
"train");
647 Bottle &options=cmd.addList().addList();
648 options.addString(
object);
653 options.addList().read(z);
656 options.add(blobs.get(i));
658 yInfo(
"Sending training request: %s",cmd.toString().c_str());
659 rpcClassifier.write(cmd,reply);
660 yInfo(
"Received reply: %s",reply.toString().c_str());
662 if (trainOnFlipped && (i>=0))
664 ImageOf<PixelBgr> imgFlipped=img;
665 if (Bottle *item=blobs.get(i).asList())
668 tl.x=(int)item->get(0).asFloat64();
669 tl.y=(int)item->get(1).asFloat64();
670 br.x=(int)item->get(2).asFloat64();
671 br.y=(int)item->get(3).asFloat64();
673 cv::Mat roi(toCvMat(imgFlipped),cv::Rect(tl.x,tl.y,br.x-tl.x,br.y-tl.y));
676 imgClassifier.write(imgFlipped);
678 yInfo(
"Sending training request (for flipped image): %s",cmd.toString().c_str());
679 rpcClassifier.write(cmd,reply);
680 yInfo(
"Received reply (for flipped image): %s",reply.toString().c_str());
685 mutexResources.unlock();
690 void Manager::improve_train(
const string &
object,
const Bottle &blobs,
693 cv::Point ref_cog=getBlobCOG(blobs,i);
694 if ((ref_cog.x==RET_INVALID) || (ref_cog.y==RET_INVALID))
697 double t0=Time::now();
698 while (Time::now()-t0<improve_train_period)
704 Bottle blobs=getBlobs();
712 double curMinDist=10.0;
713 double curMinDist2=curMinDist*curMinDist;
714 for (
int i=0; i<blobs.size(); i++)
716 cv::Point cog=getBlobCOG(blobs,i);
717 if ((cog.x==RET_INVALID) || (cog.y==RET_INVALID))
720 double dx=ref_cog.x-cog.x;
721 double dy=ref_cog.y-cog.y;
722 double dist2=dx*dx+dy*dy;
723 if (dist2<curMinDist2)
735 train(
object,blobs,exploredBlob);
738 drawBlobs(blobs,exploredBlob);
744 void Manager::home(
const string &part)
746 Bottle cmdMotor,replyMotor;
747 cmdMotor.addVocab32(
"home");
748 cmdMotor.addString(part);
749 rpcMotor.write(cmdMotor,replyMotor);
754 void Manager::calibTable()
756 Bottle cmdMotor,replyMotor;
757 cmdMotor.addVocab32(
"calib");
758 cmdMotor.addVocab32(
"table");
759 rpcMotor.write(cmdMotor,replyMotor);
764 bool Manager::calibKinStart(
const string &
object,
const string &hand,
765 const Vector &x,
const int recogBlob)
774 param.push_back(hand);
775 param.push_back(
"still");
778 if (interruptableAction(
"touch",¶m,
object,x,y))
780 Bottle cmdMotor,replyMotor;
781 cmdMotor.addVocab32(
"calib");
782 cmdMotor.addVocab32(
"kinematics");
783 cmdMotor.addString(
"start");
785 cmdMotor.addList().read(y);
786 cmdMotor.addString(hand);
787 rpcMotor.write(cmdMotor,replyMotor);
789 objectToBeKinCalibrated=object;
790 speaker.speak(
"Ok, now teach me the correct position");
791 replyHuman.addString(
"ack");
796 speaker.speak(
"I might be wrong");
797 replyHuman.addString(
"nack");
804 reply<<
"I am sorry, I cannot see any "<<object;
805 reply<<
" around. Should I try again?";
806 speaker.speak(reply.str());
807 replyHuman.addString(
"nack");
810 rpcHuman.reply(replyHuman);
816 void Manager::calibKinStop()
818 Bottle cmdMotor,replyMotor;
819 cmdMotor.addVocab32(
"calib");
820 cmdMotor.addVocab32(
"kinematics");
821 cmdMotor.addString(
"stop");
822 cmdMotor.addString(objectToBeKinCalibrated);
823 rpcMotor.write(cmdMotor,replyMotor);
825 speaker.speak(
"Thanks for the help");
831 void Manager::addDropPosition(Bottle &cmd)
833 if (dropPosition!=
nullptr)
835 if (dropPosition->size()>=3)
837 Bottle &sub1=cmd.addList();
838 sub1.addString(
"target");
839 Bottle &sub2=sub1.addList();
840 sub2.addString(
"cartesian");
841 sub2.addList()=*dropPosition;
848 void Manager::motorHelper(
const string &cmd,
const string &
object)
850 Bottle cmdMotor,replyMotor;
851 cmdMotor.addVocab32(cmd);
855 cmdMotor.addString(
object);
856 cmdMotor.addString(
"wait");
860 string hand; Vector x,y;
861 get3DPositionFromMemory(
object,x,
false);
862 if (getCalibratedLocation(
object,hand,x,y))
864 cmdMotor.addList().read(x);
865 cmdMotor.addString(hand);
868 reply<<
"I think this is the "<<object;
869 speaker.speak(reply.str());
872 rpcMotor.write(cmdMotor,replyMotor);
877 cmdMotor.addVocab32(
"home");
878 cmdMotor.addString(
"hands");
879 rpcMotor.write(cmdMotor,replyMotor);
885 bool Manager::getCalibratedLocation(
const string &
object,
890 hand=(x[1]>0.0?
"right":
"left");
891 if (rpcReachCalib.getOutputCount()>0)
894 cmd.addString(
"get_location");
896 cmd.addString(
object);
897 cmd.addString(
"iol-"+hand);
898 rpcReachCalib.write(cmd,rep);
901 y[0]=rep.get(1).asFloat64();
902 y[1]=rep.get(2).asFloat64();
903 y[2]=rep.get(3).asFloat64();
912 Vector Manager::applyObjectPosOffsets(
const string &
object,
916 if (rpcMemory.getOutputCount()>0)
918 mutexResourcesMemory.lock();
919 auto id=memoryIds.find(
object);
920 auto memoryIdsEnd=memoryIds.end();
921 mutexResourcesMemory.unlock();
923 if (
id!=memoryIdsEnd)
927 string prop(
"kinematic_offset_"+hand);
929 Bottle cmdMemory,replyMemory;
930 cmdMemory.addVocab32(
"get");
931 Bottle &content=cmdMemory.addList();
932 Bottle &list_bid=content.addList();
933 list_bid.addString(
"id");
934 list_bid.addInt32(id->second);
935 Bottle &list_propSet=content.addList();
936 list_propSet.addString(
"propSet");
937 Bottle &list_items=list_propSet.addList();
938 list_items.addString(prop);
939 rpcMemory.write(cmdMemory,replyMemory);
942 if (replyMemory.get(0).asVocab32()==Vocab32::encode(
"ack"))
944 if (Bottle *propField=replyMemory.get(1).asList())
946 if (propField->check(prop))
948 if (Bottle *pPos=propField->find(prop).asList())
952 offs[0]=pPos->get(0).asFloat64();
953 offs[1]=pPos->get(1).asFloat64();
954 offs[2]=pPos->get(2).asFloat64();
968 bool Manager::interruptableAction(
const string &action,
969 deque<string> *param,
970 const string &
object,
975 string actionRemapped=action;
976 if (actionRemapped==
"hold")
977 actionRemapped=
"take";
979 Bottle cmdMotor,replyMotor;
984 cmdMotor.addString(
"grasp");
985 cmdMotor.addString(
object);
986 cmdMotor.addString(x[1]>0.0?
"right":
"left");
991 bool calib=getCalibratedLocation(
object,hand,x,y);
994 cmdMotor.addVocab32(actionRemapped);
996 cmdMotor.addString(
"over");
1000 y+=applyObjectPosOffsets(
object,hand);
1001 cmdMotor.addList().read(y);
1004 cmdMotor.addString(
object);
1007 cmdMotor.addString(
"gently");
1010 for (
size_t i=0; i<param->size(); i++)
1011 cmdMotor.addString((*param)[i]);
1015 cmdMotor.addString(hand);
1018 actionInterrupted=
false;
1019 enableInterrupt=
true;
1020 port->write(cmdMotor,replyMotor);
1021 bool ack=(replyMotor.get(0).asVocab32()==Vocab32::encode(
"ack"));
1023 if ((action==
"grasp") && !ack)
1025 string why=replyMotor.get(1).asString();
1026 string sentence=
"Hmmm. The ";
1029 sentence+=
" seems too far. Could you push it closer?";
1031 sentence+=
" seems in bad position for me. Could you help moving it a little bit?";
1032 speaker.speak(sentence);
1037 if (actionInterrupted)
1043 else if (ack && ((action==
"take") || (action==
"grasp")))
1046 cmdMotor.addVocab32(
"drop");
1047 addDropPosition(cmdMotor);
1048 rpcMotor.write(cmdMotor,replyMotor);
1051 enableInterrupt=
false;
1052 return !actionInterrupted;
1057 void Manager::interruptMotor()
1059 if (enableInterrupt)
1061 actionInterrupted=
true;
1062 enableInterrupt=
false;
1063 Bottle cmdMotorStop,replyMotorStop;
1064 cmdMotorStop.addVocab32(
"interrupt");
1065 rpcMotorStop.write(cmdMotorStop,replyMotorStop);
1067 speaker.speak(
"Ouch!");
1073 void Manager::reinstateMotor(
const bool saySorry)
1075 Bottle cmdMotorStop,replyMotorStop;
1076 cmdMotorStop.addVocab32(
"reinstate");
1077 rpcMotorStop.write(cmdMotorStop,replyMotorStop);
1080 speaker.speak(
"Sorry");
1085 void Manager::point(
const string &
object)
1087 motorHelper(
"point",
object);
1092 void Manager::look(
const string &
object)
1094 motorHelper(
"look",
object);
1099 void Manager::look(
const Bottle &blobs,
const int i,
1100 const Bottle &options)
1102 cv::Point cog=getBlobCOG(blobs,i);
1103 if ((cog.x==RET_INVALID) || (cog.y==RET_INVALID))
1106 Bottle cmdMotor,replyMotor;
1107 cmdMotor.addVocab32(
"look");
1108 Bottle &opt=cmdMotor.addList();
1109 opt.addString(camera);
1110 opt.addInt32(cog.x);
1111 opt.addInt32(cog.y);
1112 cmdMotor.append(options);
1113 cmdMotor.addString(
"wait");
1114 rpcMotor.write(cmdMotor,replyMotor);
1119 int Manager::recognize(
const string &
object, Bottle &blobs,
1120 Classifier **ppClassifier)
1122 auto it=db.find(
object);
1126 db[object]=
new Classifier(
object,classification_threshold);
1127 trackersPool[object]=Tracker(tracker_type,tracker_timeout);
1129 yInfo(
"created classifier for %s",
object.c_str());
1139 if (blobs.size()==0)
1143 Bottle scores=classify(blobs);
1146 if (scores.size()==1)
1148 if (scores.get(0).asString()==
"failed")
1150 speaker.speak(
"Ooops! Sorry, something went wrong in my brain");
1156 int recogBlob=db.processScores(it->second,scores);
1159 drawBlobs(blobs,recogBlob);
1162 if (ppClassifier!=NULL)
1163 *ppClassifier=it->second;
1170 int Manager::recognize(Bottle &blobs, Bottle &scores,
string &
object)
1172 object=OBJECT_UNKNOWN;
1181 if (blobs.size()==0)
1185 scores=classify(blobs);
1188 if (scores.size()==1)
1190 if (scores.get(0).asString()==
"failed")
1192 speaker.speak(
"Ooops! Sorry, something went wrong in my brain");
1200 int closestBlob=findClosestBlob(blobs,whatLocation);
1201 drawBlobs(blobs,closestBlob);
1202 look(blobs,closestBlob);
1205 tag<<
"blob_"<<closestBlob;
1206 object=db.findName(scores,tag.str());
1211 speaker.speak(
"Ooops! Sorry, I missed where you pointed at");
1218 void Manager::execName(
const string &
object)
1223 speaker.speak(
"Ooops! Sorry, I missed where you pointed at");
1224 replyHuman.addString(
"nack");
1225 rpcHuman.reply(replyHuman);
1229 auto it=db.find(
object);
1233 db[object]=
new Classifier(
object,classification_threshold);
1234 trackersPool[object]=Tracker(tracker_type,tracker_timeout);
1236 yInfo(
"created classifier for %s",
object.c_str());
1243 Bottle blobs=getBlobs();
1246 if (blobs.size()==0)
1248 speaker.speak(
"Ooops! Sorry, I cannot see any object");
1249 replyHuman.addString(
"nack");
1250 rpcHuman.reply(replyHuman);
1255 Bottle scores=classify(blobs);
1258 if (scores.size()==1)
1260 if (scores.get(0).asString()==
"failed")
1262 speaker.speak(
"Ooops! Sorry, something went wrong in my brain");
1263 replyHuman.addString(
"nack");
1264 rpcHuman.reply(replyHuman);
1269 db.processScores(it->second,scores);
1272 int closestBlob=findClosestBlob(blobs,trackStopLocation);
1275 drawBlobs(blobs,closestBlob);
1279 train(
object,blobs,closestBlob);
1280 improve_train(
object,blobs,closestBlob);
1282 triggerRecogInfo(
object,blobs,closestBlob,
"creation");
1283 ostringstream reply;
1284 reply<<
"All right! Now I know what a "<<object;
1286 speaker.speak(reply.str());
1287 look(blobs,closestBlob);
1289 replyHuman.addString(
"ack");
1290 rpcHuman.reply(replyHuman);
1295 void Manager::execForget(
const string &
object)
1297 Bottle cmdClassifier,replyClassifier,replyHuman;
1300 mutexResources.lock();
1305 cmdClassifier.addVocab32(
"forget");
1306 cmdClassifier.addString(
"all");
1307 yInfo(
"Sending clearing request: %s",cmdClassifier.toString().c_str());
1308 rpcClassifier.write(cmdClassifier,replyClassifier);
1309 yInfo(
"Received reply: %s",replyClassifier.toString().c_str());
1312 if (rpcMemory.getOutputCount()>0)
1314 mutexResourcesMemory.lock();
1315 for (
auto id=memoryIds.begin();
id!=memoryIds.end();
id++)
1317 Bottle cmdMemory,replyMemory;
1318 cmdMemory.addVocab32(
"del");
1319 Bottle &bid=cmdMemory.addList().addList();
1320 bid.addString(
"id");
1321 bid.addInt32(id->second);
1322 rpcMemory.write(cmdMemory,replyMemory);
1325 mutexResourcesMemory.unlock();
1329 trackersPool.clear();
1330 speaker.speak(
"I have forgotten everything");
1331 replyHuman.addString(
"ack");
1335 ostringstream reply;
1336 auto it=db.find(
object);
1339 cmdClassifier.addVocab32(
"forget");
1340 cmdClassifier.addString(
object);
1341 yInfo(
"Sending clearing request: %s",cmdClassifier.toString().c_str());
1342 rpcClassifier.write(cmdClassifier,replyClassifier);
1343 yInfo(
"Received reply: %s",replyClassifier.toString().c_str());
1346 if (rpcMemory.getOutputCount()>0)
1348 mutexResourcesMemory.lock();
1349 auto id=memoryIds.find(
object);
1350 auto memoryIdsEnd=memoryIds.end();
1351 mutexResourcesMemory.unlock();
1353 if (
id!=memoryIdsEnd)
1355 Bottle cmdMemory,replyMemory;
1356 cmdMemory.addVocab32(
"del");
1357 Bottle &bid=cmdMemory.addList().addList();
1358 bid.addString(
"id");
1359 bid.addInt32(id->second);
1360 rpcMemory.write(cmdMemory,replyMemory);
1362 mutexResourcesMemory.lock();
1363 memoryIds.erase(
id);
1364 mutexResourcesMemory.unlock();
1369 trackersPool.erase(
object);
1370 reply<<
object<<
" forgotten";
1371 speaker.speak(reply.str());
1372 replyHuman.addString(
"ack");
1376 yInfo(
"%s object is unknown",
object.c_str());
1377 reply<<
"I do not know any "<<object;
1378 speaker.speak(reply.str());
1379 replyHuman.addString(
"nack");
1383 rpcHuman.reply(replyHuman);
1386 mutexResources.unlock();
1391 void Manager::execWhere(
const string &
object,
const Bottle &blobs,
1392 const int recogBlob, Classifier *pClassifier,
1393 const string &recogType)
1395 Bottle cmdHuman,valHuman,replyHuman;
1403 yInfo(
"I think the %s is blob %d",
object.c_str(),recogBlob);
1404 speaker.speak(
"Am I right?");
1406 replyHuman.addString(
"ack");
1407 replyHuman.addInt32(recogBlob);
1412 ostringstream reply;
1413 reply<<
"I have not found any "<<object;
1414 reply<<
", am I right?";
1415 speaker.speak(reply.str());
1416 yInfo(
"No object recognized");
1418 replyHuman.addString(
"nack");
1421 rpcHuman.reply(replyHuman);
1428 rpcHuman.read(cmdHuman,
true);
1433 int type=processHumanCmd(cmdHuman,valHuman);
1435 if (type==Vocab32::encode(
"skip"))
1437 speaker.speak(
"Skipped");
1438 replyHuman.addString(
"ack");
1442 else if (type==Vocab32::encode(
"ack"))
1445 if (!skipLearningUponSuccess && (recogBlob>=0) && (pClassifier!=NULL))
1448 train(
object,blobs,recogBlob);
1449 improve_train(
object,blobs,recogBlob);
1451 pClassifier->positive();
1452 triggerRecogInfo(
object,blobs,recogBlob,
"recognition");
1453 updateClassifierInMemory(pClassifier);
1456 speaker.speak(
"Cool!");
1457 replyHuman.addString(
"ack");
1461 else if (type==Vocab32::encode(
"nack"))
1464 if ((recogBlob>=0) && (pClassifier!=NULL))
1466 pClassifier->negative();
1467 updateClassifierInMemory(pClassifier);
1472 if (pointedLoc.getLoc(loc))
1474 int closestBlob=findClosestBlob(blobs,loc);
1476 train(
object,blobs,closestBlob);
1477 improve_train(
object,blobs,closestBlob);
1479 triggerRecogInfo(
object,blobs,closestBlob,recogType);
1480 speaker.speak(
"Oooh, I see");
1481 look(blobs,closestBlob);
1484 speaker.speak(
"Ooops! Sorry, I missed where you pointed at");
1486 replyHuman.addString(
"ack");
1491 speaker.speak(
"Hmmm hmmm hmmm! Try again");
1492 replyHuman.addString(
"nack");
1495 rpcHuman.reply(replyHuman);
1501 void Manager::execWhat(
const Bottle &blobs,
const int pointedBlob,
1502 const Bottle &scores,
const string &
object)
1504 Bottle cmdHuman,valHuman,replyHuman;
1505 Classifier *pClassifier=NULL;
1508 if (
object!=OBJECT_UNKNOWN)
1510 ostringstream reply;
1511 reply<<
"I think it is the "<<object;
1512 speaker.speak(reply.str());
1513 speaker.speak(
"Am I right?");
1514 yInfo(
"I think the blob %d is the %s",pointedBlob,
object.c_str());
1517 auto it=db.find(
object);
1519 pClassifier=it->second;
1521 replyHuman.addString(
"ack");
1522 replyHuman.addString(
object);
1527 speaker.speak(
"I do not know this object");
1528 speaker.speak(
"What is it?");
1529 yInfo(
"No object recognized");
1530 replyHuman.addString(
"nack");
1533 rpcHuman.reply(replyHuman);
1540 rpcHuman.read(cmdHuman,
true);
1545 int type=processHumanCmd(cmdHuman,valHuman);
1547 if (type==Vocab32::encode(
"skip"))
1549 speaker.speak(
"Skipped");
1550 replyHuman.addString(
"ack");
1554 else if ((
object!=OBJECT_UNKNOWN) && (type==Vocab32::encode(
"ack")))
1557 if (!skipLearningUponSuccess && (pointedBlob>=0) && (pClassifier!=NULL))
1560 train(
object,blobs,pointedBlob);
1561 improve_train(
object,blobs,pointedBlob);
1563 db.processScores(pClassifier,scores);
1564 pClassifier->positive();
1565 triggerRecogInfo(
object,blobs,pointedBlob,
"recognition");
1566 updateClassifierInMemory(pClassifier);
1569 speaker.speak(
"Cool!");
1570 replyHuman.addString(
"ack");
1574 else if (type==Vocab32::encode(
"nack"))
1577 if ((pointedBlob>=0) && (pClassifier!=NULL))
1579 db.processScores(pClassifier,scores);
1580 pClassifier->negative();
1581 updateClassifierInMemory(pClassifier);
1584 speaker.speak(
"Sorry");
1585 replyHuman.addString(
"ack");
1589 else if ((type==Vocab32::encode(
"name")) && (valHuman.size()>0))
1591 string objectName=valHuman.get(0).asString();
1595 auto it=db.find(objectName);
1598 db[objectName]=
new Classifier(objectName,classification_threshold);
1599 trackersPool[objectName]=Tracker(tracker_type,tracker_timeout);
1600 it=db.find(objectName);
1601 speaker.speak(
"Oooh, I see");
1602 yInfo(
"created classifier for %s",objectName.c_str());
1607 if ((pClassifier!=NULL) && (
object!=objectName) && (
object!=OBJECT_UNKNOWN))
1609 db.processScores(pClassifier,scores);
1610 pClassifier->negative();
1611 updateClassifierInMemory(pClassifier);
1614 ostringstream reply;
1615 reply<<
"Sorry, I should have recognized the "<<objectName;
1616 speaker.speak(reply.str());
1623 train(objectName,blobs,pointedBlob);
1624 improve_train(objectName,blobs,pointedBlob);
1626 triggerRecogInfo(objectName,blobs,pointedBlob,
1627 (
object==OBJECT_UNKNOWN)?
"creation":
"recognition");
1630 db.processScores(it->second,scores);
1632 replyHuman.addString(
"ack");
1637 speaker.speak(
"Hmmm hmmm hmmm! Try again");
1638 replyHuman.addString(
"nack");
1641 rpcHuman.reply(replyHuman);
1647 void Manager::execThis(
const string &
object,
const string &detectedObject,
1648 const Bottle &blobs,
const int &pointedBlob)
1654 string recogType=
"recognition";
1655 auto it=db.find(
object);
1659 db[object]=
new Classifier(
object,classification_threshold);
1660 trackersPool[object]=Tracker(tracker_type,tracker_timeout);
1662 yInfo(
"created classifier for %s",
object.c_str());
1663 recogType=
"creation";
1666 ostringstream reply;
1669 if (
object.compare(detectedObject)==0)
1670 reply<<
"Yes, I know that is a "<<
object<<
"!";
1671 else if(detectedObject.compare(OBJECT_UNKNOWN)==0)
1672 reply<<
"All right! Now I know what a "<<
object<<
" is!";
1675 reply<<
"Oh dear, I thought that was a "<<detectedObject<<
"?";
1677 auto it_detected=db.find(detectedObject);
1678 if (it_detected==db.end())
1680 it_detected->second->negative();
1681 updateClassifierInMemory(it_detected->second);
1686 train(
object,blobs,pointedBlob);
1687 improve_train(
object,blobs,pointedBlob);
1690 speaker.speak(reply.str());
1691 look(blobs,pointedBlob);
1693 replyHuman.addString(
"ack");
1694 rpcHuman.reply(replyHuman);
1700 void Manager::execExplore(
const string &
object)
1702 Bottle cmdMotor,replyMotor,replyHuman;
1705 if (get3DPositionFromMemory(
object,position))
1707 cmdMotor.addVocab32(
"look");
1708 cmdMotor.addString(
object);
1709 cmdMotor.addString(
"fixate");
1710 rpcMotor.write(cmdMotor,replyMotor);
1712 if (replyMotor.get(0).asVocab32()==Vocab32::encode(
"ack"))
1714 ostringstream reply;
1715 reply<<
"I will explore the "<<object;
1716 speaker.speak(reply.str());
1718 exploration.setInfo(
object,position);
1721 exploration.start();
1724 cmdMotor.addVocab32(
"explore");
1725 cmdMotor.addVocab32(
"torso");
1726 rpcMotor.write(cmdMotor,replyMotor);
1729 do Time::delay(0.1);
1730 while (exploration.isRunning());
1736 cmdMotor.addVocab32(
"idle");
1737 rpcMotor.write(cmdMotor,replyMotor);
1738 speaker.speak(
"I'm done");
1740 replyHuman.addString(
"ack");
1744 speaker.speak(
"Sorry, something went wrong with the exploration");
1745 replyHuman.addString(
"nack");
1750 speaker.speak(
"Sorry, something went wrong with the exploration");
1751 replyHuman.addString(
"nack");
1754 rpcHuman.reply(replyHuman);
1759 void Manager::execReinforce(
const string &
object,
1760 const Vector &position)
1763 if (db.find(
object)!=db.end())
1766 ret=doExploration(
object,position);
1770 Bottle replyHuman(ret?
"ack":
"nack");
1771 rpcHuman.reply(replyHuman);
1776 void Manager::execInterruptableAction(
const string &action,
1777 const string &
object,
1779 const Bottle &blobs,
1780 const int recogBlob)
1787 ostringstream reply;
1788 reply<<
"Ok, I will "<<action;
1791 reply<<
" the "<<object;
1792 speaker.speak(reply.str());
1793 yInfo(
"I think the %s is blob %d",
object.c_str(),recogBlob);
1797 if (interruptableAction(action,NULL,
object,x,y))
1799 replyHuman.addString(
"ack");
1800 replyHuman.addInt32(recogBlob);
1803 replyHuman.addString(
"nack");
1806 else if ((action==
"drop") && (
object==
""))
1808 speaker.speak(
"Ok");
1810 Bottle cmdMotor,replyMotor;
1811 cmdMotor.addVocab32(
"drop");
1812 addDropPosition(cmdMotor);
1813 actionInterrupted=
false;
1814 enableInterrupt=
true;
1815 rpcMotor.write(cmdMotor,replyMotor);
1817 if (replyMotor.get(0).asVocab32()==Vocab32::encode(
"nack"))
1819 speaker.speak(
"I have nothing in my hands");
1820 replyHuman.addString(
"nack");
1822 else if (actionInterrupted)
1826 replyHuman.addString(
"nack");
1829 replyHuman.addString(
"ack");
1831 enableInterrupt=
false;
1836 ostringstream reply;
1837 reply<<
"I am sorry, I cannot see any "<<object;
1839 speaker.speak(reply.str());
1841 replyHuman.addString(
"nack");
1844 rpcHuman.reply(replyHuman);
1849 void Manager::switchAttention()
1852 if (rpcMotor.getOutputCount()>0)
1854 lock_guard<mutex> lg(mutexAttention);
1857 Bottle blobs=getBlobs();
1858 for (
int i=0; i<blobs.size(); i++)
1861 int guess=(int)Rand::scalar(0.0,blobs.size());
1862 if (guess>=blobs.size())
1863 guess=blobs.size()-1;
1865 cv::Point cog=getBlobCOG(blobs,guess);
1866 if ((cog.x==RET_INVALID) || (cog.y==RET_INVALID))
1880 void Manager::doLocalization()
1885 Bottle blobs=getBlobs();
1887 Bottle scores=classify(blobs,
true);
1889 if (Bottle *loc=histObjLocPort.read(
false))
1894 clickLocation=cv::Point(loc->get(0).asInt32(),loc->get(1).asInt32());
1895 if (get3DPosition(clickLocation,x))
1900 int closestBlob=findClosestBlob(blobs,histObjLocation);
1902 drawBlobs(blobs,closestBlob,&scores);
1904 drawScoresHistogram(blobs,scores,closestBlob);
1907 mutexResourcesMemory.lock();
1909 memoryScores=scores;
1910 mutexResourcesMemory.unlock();
1915 bool Manager::get3DPositionFromMemory(
const string &
object,
1917 const bool lockMemory)
1920 if (rpcMemory.getOutputCount()>0)
1924 lock_guard<mutex> lg(mutexMemoryUpdate);
1926 mutexResourcesMemory.lock();
1927 auto id=memoryIds.find(
object);
1928 auto memoryIdsEnd=memoryIds.end();
1929 mutexResourcesMemory.unlock();
1931 if (
id!=memoryIdsEnd)
1935 Bottle cmdMemory,replyMemory;
1936 cmdMemory.addVocab32(
"get");
1937 Bottle &content=cmdMemory.addList();
1938 Bottle &list_bid=content.addList();
1939 list_bid.addString(
"id");
1940 list_bid.addInt32(id->second);
1941 Bottle &list_propSet=content.addList();
1942 list_propSet.addString(
"propSet");
1943 Bottle &list_items=list_propSet.addList();
1944 list_items.addString(
"position_3d");
1945 rpcMemory.write(cmdMemory,replyMemory);
1948 if (replyMemory.get(0).asVocab32()==Vocab32::encode(
"ack"))
1950 if (Bottle *propField=replyMemory.get(1).asList())
1952 if (propField->check(
"position_3d"))
1954 if (Bottle *pPos=propField->find(
"position_3d").asList())
1956 if (pPos->size()>=3)
1959 position[0]=pPos->get(0).asFloat64();
1960 position[1]=pPos->get(1).asFloat64();
1961 position[2]=pPos->get(2).asFloat64();
1976 bool Manager::doExploration(
const string &
object,
1977 const Vector &position)
1983 Bottle blobs=getBlobs();
1986 if (blobs.size()==0)
1990 int exploredBlob=RET_INVALID;
1991 double curMinDist=0.05;
1992 for (
int i=0; i<blobs.size(); i++)
1994 cv::Point cog=getBlobCOG(blobs,i);
1995 if ((cog.x==RET_INVALID) || (cog.y==RET_INVALID))
1999 if (get3DPosition(cog,x))
2001 double dist=norm(position-x);
2002 if (dist<curMinDist)
2015 train(
object,blobs,exploredBlob);
2018 drawBlobs(blobs,exploredBlob);
2024 void Manager::updateMemory()
2026 if (rpcMemory.getOutputCount()>0)
2029 mutexMemoryUpdate.lock();
2032 if (scheduleLoadMemory)
2035 scheduleLoadMemory=
false;
2039 ImageOf<PixelBgr> &imgLatch=imgTrackOut.prepare();
2040 cv::Mat imgLatchMat=toCvMat(imgLatch);
2042 mutexResourcesMemory.lock();
2043 Bottle blobs=memoryBlobs;
2044 Bottle scores=memoryScores;
2046 mutexResourcesMemory.unlock();
2049 for (
auto it=trackersPool.begin(); it!=trackersPool.end(); it++)
2050 it->second.prepare();
2053 std::map<string, double> scoresMap;
2055 for (
int j=0; j<blobs.size(); j++)
2057 Bottle *item=blobs.get(j).asList();
2066 mutexResources.lock();
2067 string object=db.findName(scores,tag.str(),&score);
2068 mutexResources.unlock();
2070 if (
object!=OBJECT_UNKNOWN)
2072 scoresMap[object] = score;
2076 tl.x=(int)item->get(0).asFloat64();
2077 tl.y=(int)item->get(1).asFloat64();
2078 br.x=(int)item->get(2).asFloat64();
2079 br.y=(int)item->get(3).asFloat64();
2081 cv::Rect bbox(tl.x,tl.y,br.x-tl.x,br.y-tl.y);
2082 if (thresBBox(bbox,imgLatch))
2084 auto tracker=trackersPool.find(
object);
2085 if (tracker!=trackersPool.end())
2086 tracker->second.latchBBox(bbox);
2092 set<int> avalObjIds;
2093 for (
auto it=trackersPool.begin(); it!=trackersPool.end(); it++)
2095 string object=it->first;
2096 it->second.track(imgLatch);
2099 if (it->second.is_tracking(bbox))
2102 if (!thresBBox(bbox,imgLatch))
2105 cv::Point tl(bbox.x,bbox.y);
2106 cv::Point br(bbox.x+bbox.width,bbox.y+bbox.height);
2107 cv::Point cog((tl.x+br.x)>>1,(tl.y+br.y)>>1);
2111 if (get3DPosition(cog,x))
2115 Bottle &list_2d=position_2d.addList();
2116 list_2d.addString(
"position_2d_"+camera);
2117 Bottle &list_2d_c=list_2d.addList();
2118 list_2d_c.addFloat64(tl.x);
2119 list_2d_c.addFloat64(tl.y);
2120 list_2d_c.addFloat64(br.x);
2121 list_2d_c.addFloat64(br.y);
2125 Bottle &list_3d=position_3d.addList();
2126 list_3d.addString(
"position_3d");
2127 list_3d.addList().read(x);
2131 auto it=scoresMap.find(
object);
2132 if (it!=scoresMap.end())
2134 Bottle &list_score=class_score.addList();
2135 list_score.addString(
"class_score");
2136 list_score.addFloat64(it->second);
2139 mutexResourcesMemory.lock();
2140 auto id=memoryIds.find(
object);
2141 auto memoryIdsEnd=memoryIds.end();
2142 mutexResourcesMemory.unlock();
2144 Bottle cmdMemory,replyMemory;
2145 if (
id==memoryIdsEnd)
2147 cmdMemory.addVocab32(
"add");
2148 Bottle &content=cmdMemory.addList();
2149 Bottle &list_entity=content.addList();
2150 list_entity.addString(
"entity");
2151 list_entity.addString(
"object");
2152 Bottle &list_name=content.addList();
2153 list_name.addString(
"name");
2154 list_name.addString(
object);
2155 content.append(position_2d);
2156 content.append(position_3d);
2157 if (class_score.size()>0)
2158 content.append(class_score);
2160 rpcMemory.write(cmdMemory,replyMemory);
2162 if (replyMemory.size()>1)
2165 if (replyMemory.get(0).asVocab32()==Vocab32::encode(
"ack"))
2167 if (Bottle *idField=replyMemory.get(1).asList())
2169 int id=idField->get(1).asInt32();
2170 mutexResourcesMemory.lock();
2171 memoryIds[object]=id;
2172 mutexResourcesMemory.unlock();
2174 avalObjIds.insert(
id);
2185 Bottle &list_bid=bid.addList();
2186 list_bid.addString(
"id");
2187 list_bid.addInt32(id->second);
2189 cmdMemory.addVocab32(
"set");
2190 Bottle &content=cmdMemory.addList();
2191 content.append(bid);
2192 content.append(position_2d);
2193 content.append(position_3d);
2194 if (class_score.size()>0)
2195 content.append(class_score);
2197 rpcMemory.write(cmdMemory,replyMemory);
2199 avalObjIds.insert(id->second);
2203 cv::rectangle(imgLatchMat,tl,br,cv::Scalar(255,0,0),2);
2204 cv::putText(imgLatchMat,
object,cv::Point(tl.x,tl.y-5),cv::FONT_HERSHEY_SIMPLEX,0.5,cv::Scalar(255,0,0),2);
2209 if (imgTrackOut.getOutputCount()>0)
2210 imgTrackOut.write();
2212 imgTrackOut.unprepare();
2215 mutexResourcesMemory.lock();
2216 for (
auto it=memoryIds.begin(); it!=memoryIds.end(); it++)
2219 if (avalObjIds.find(
id)==avalObjIds.end())
2221 Bottle cmdMemory,replyMemory;
2222 cmdMemory.addVocab32(
"del");
2223 Bottle &content=cmdMemory.addList();
2224 Bottle &list_bid=content.addList();
2225 list_bid.addString(
"id");
2226 list_bid.addInt32(
id);
2227 Bottle &list_propSet=content.addList();
2228 list_propSet.addString(
"propSet");
2229 Bottle &list_items=list_propSet.addList();
2230 list_items.addString(
"position_2d_"+camera);
2231 list_items.addString(
"position_3d");
2232 list_items.addString(
"class_score");
2233 rpcMemory.write(cmdMemory,replyMemory);
2236 mutexResourcesMemory.unlock();
2239 mutexMemoryUpdate.unlock();
2245 void Manager::updateClassifierInMemory(Classifier *pClassifier)
2247 if ((rpcMemory.getOutputCount()>0) && (pClassifier!=NULL))
2249 string objectName=pClassifier->getName();
2252 Bottle classifier_property;
2253 Bottle &list_classifier=classifier_property.addList();
2254 list_classifier.addString(
"classifier_thresholds");
2255 list_classifier.addList().append(pClassifier->toBottle());
2257 mutexResourcesMemory.lock();
2258 auto id=memoryIds.find(objectName);
2259 auto memoryIdsEnd=memoryIds.end();
2260 mutexResourcesMemory.unlock();
2262 Bottle cmdMemory,replyMemory;
2263 if (
id==memoryIdsEnd)
2265 cmdMemory.addVocab32(
"add");
2266 Bottle &content=cmdMemory.addList();
2267 Bottle &list_entity=content.addList();
2268 list_entity.addString(
"entity");
2269 list_entity.addString(
"object");
2270 Bottle &list_name=content.addList();
2271 list_name.addString(
"name");
2272 list_name.addString(objectName);
2273 content.append(classifier_property);
2274 rpcMemory.write(cmdMemory,replyMemory);
2276 if (replyMemory.size()>1)
2279 if (replyMemory.get(0).asVocab32()==Vocab32::encode(
"ack"))
2281 if (Bottle *idField=replyMemory.get(1).asList())
2283 mutexResourcesMemory.lock();
2284 memoryIds[objectName]=idField->get(1).asInt32();
2285 mutexResourcesMemory.unlock();
2294 Bottle &list_bid=bid.addList();
2295 list_bid.addString(
"id");
2296 list_bid.addInt32(id->second);
2298 cmdMemory.addVocab32(
"set");
2299 Bottle &content=cmdMemory.addList();
2300 content.append(bid);
2301 content.append(classifier_property);
2302 rpcMemory.write(cmdMemory,replyMemory);
2309 Vector Manager::updateObjCartPosInMemory(
const string &
object,
2310 const Bottle &blobs,
2314 if ((rpcMemory.getOutputCount()>0) && (i!=RET_INVALID) && (i<blobs.size()))
2316 mutexResourcesMemory.lock();
2317 auto id=memoryIds.find(
object);
2318 auto memoryIdsEnd=memoryIds.end();
2319 mutexResourcesMemory.unlock();
2321 Bottle *item=blobs.get(i).asList();
2322 if ((
id!=memoryIdsEnd) && (item!=NULL))
2324 cv::Point cog=getBlobCOG(blobs,i);
2325 if ((cog.x==RET_INVALID) || (cog.y==RET_INVALID))
2328 if (get3DPosition(cog,x))
2330 Bottle cmdMemory,replyMemory;
2334 Bottle &list_bid=bid.addList();
2335 list_bid.addString(
"id");
2336 list_bid.addInt32(id->second);
2340 Bottle &list_2d=position_2d.addList();
2341 list_2d.addString(
"position_2d_"+camera);
2342 Bottle &list_2d_c=list_2d.addList();
2343 list_2d_c.addFloat64(item->get(0).asFloat64());
2344 list_2d_c.addFloat64(item->get(1).asFloat64());
2345 list_2d_c.addFloat64(item->get(2).asFloat64());
2346 list_2d_c.addFloat64(item->get(3).asFloat64());
2350 Bottle &list_3d=position_3d.addList();
2351 list_3d.addString(
"position_3d");
2352 list_3d.addList().read(x);
2354 cmdMemory.addVocab32(
"set");
2355 Bottle &content=cmdMemory.addList();
2356 content.append(bid);
2357 content.append(position_2d);
2358 content.append(position_3d);
2359 rpcMemory.write(cmdMemory,replyMemory);
2369 void Manager::triggerRecogInfo(
const string &
object,
const Bottle &blobs,
2370 const int i,
const string &recogType)
2372 if ((recogTriggerPort.getOutputCount()>0) && (i!=RET_INVALID) && (i<blobs.size()))
2374 cv::Point cog=getBlobCOG(blobs,i);
2375 if ((cog.x==RET_INVALID) || (cog.y==RET_INVALID))
2379 if (get3DPosition(cog,x))
2381 Property &msg=recogTriggerPort.prepare();
2384 Bottle pos; pos.addList().read(x);
2385 msg.put(
"label",
object);
2386 msg.put(
"position_3d",pos.get(0));
2387 msg.put(
"type",recogType);
2389 recogTriggerPort.write();
2396 void Manager::loadMemory()
2398 yInfo(
"Loading memory ...");
2400 mutexResourcesMemory.lock();
2405 trackersPool.clear();
2408 Bottle cmdMemory,replyMemory,replyMemoryProp;
2409 cmdMemory.addVocab32(
"ask");
2410 Bottle &content=cmdMemory.addList().addList();
2411 content.addString(
"entity");
2412 content.addString(
"==");
2413 content.addString(
"object");
2414 rpcMemory.write(cmdMemory,replyMemory);
2416 if (replyMemory.size()>1)
2418 if (replyMemory.get(0).asVocab32()==Vocab32::encode(
"ack"))
2420 if (Bottle *idField=replyMemory.get(1).asList())
2422 if (Bottle *idValues=idField->get(1).asList())
2425 for (
int i=0; i<idValues->size(); i++)
2427 int id=idValues->get(i).asInt32();
2432 cmdMemory.addVocab32(
"get");
2433 Bottle &content=cmdMemory.addList();
2434 Bottle &list_bid=content.addList();
2435 list_bid.addString(
"id");
2436 list_bid.addInt32(
id);
2437 Bottle &list_propSet=content.addList();
2438 list_propSet.addString(
"propSet");
2439 Bottle &list_items=list_propSet.addList();
2440 list_items.addString(
"name");
2441 list_items.addString(
"classifier_thresholds");
2442 rpcMemory.write(cmdMemory,replyMemoryProp);
2445 if (replyMemoryProp.get(0).asVocab32()==Vocab32::encode(
"ack"))
2447 if (Bottle *propField=replyMemoryProp.get(1).asList())
2449 if (propField->check(
"name"))
2451 string object=propField->find(
"name").asString();
2452 memoryIds[object]=id;
2454 if (propField->check(
"classifier_thresholds"))
2455 db[object]=
new Classifier(*propField->find(
"classifier_thresholds").asList());
2457 db[object]=
new Classifier(
object,classification_threshold);
2458 trackersPool[object]=Tracker(tracker_type,tracker_timeout);
2468 yInfo(
"Objects in memory: %d",(
int)db.size());
2469 for (
auto it=db.begin(); it!=db.end(); it++)
2471 string object=it->first;
2472 string properties=it->second->toBottle().toString();
2473 yInfo(
"classifier for %s: memory_id=%d; properties=%s",
2474 object.c_str(),memoryIds[
object],properties.c_str());
2478 mutexResourcesMemory.unlock();
2479 yInfo(
"Memory loaded");
2484 bool Manager::configure(ResourceFinder &rf)
2486 name=rf.check(
"name",Value(
"iolStateMachineHandler")).asString();
2487 camera=rf.check(
"camera",Value(
"left")).asString();
2488 if ((camera!=
"left") && (camera!=
"right"))
2491 imgIn.open(
"/"+name+
"/img:i");
2492 blobExtractor.open(
"/"+name+
"/blobs:i");
2493 imgOut.open(
"/"+name+
"/img:o");
2494 imgRtLocOut.open(
"/"+name+
"/imgLoc:o");
2495 imgTrackOut.open(
"/"+name+
"/imgTrack:o");
2496 imgClassifier.open(
"/"+name+
"/imgClassifier:o");
2497 imgHistogram.open(
"/"+name+
"/imgHistogram:o");
2498 histObjLocPort.open(
"/"+name+
"/histObjLocation:i");
2499 recogTriggerPort.open(
"/"+name+
"/recog:o");
2501 rpcPort.open(
"/"+name+
"/rpc");
2502 rpcHuman.open(
"/"+name+
"/human:rpc");
2503 rpcClassifier.open(
"/"+name+
"/classify:rpc");
2504 rpcMotor.open(
"/"+name+
"/motor:rpc");
2505 rpcMotorGrasp.open(
"/"+name+
"/motor_grasp:rpc");
2506 rpcReachCalib.open(
"/"+name+
"/reach_calib:rpc");
2507 rpcGet3D.open(
"/"+name+
"/get3d:rpc");
2508 rpcMotorStop.open(
"/"+name+
"/motor_stop:rpc");
2509 rxMotorStop.open(
"/"+name+
"/motor_stop:i");
2510 rxMotorStop.setManager(
this);
2512 pointedLoc.open(
"/"+name+
"/point:i");
2513 speaker.open(
"/"+name+
"/speak:o");
2515 memoryReporter.setManager(
this);
2516 rpcMemory.setReporter(memoryReporter);
2517 rpcMemory.open(
"/"+name+
"/memory:rpc");
2519 skim_blobs_x_bounds.resize(2);
2520 skim_blobs_x_bounds[0]=-0.50;
2521 skim_blobs_x_bounds[1]=-0.10;
2522 if (rf.check(
"skim_blobs_x_bounds"))
2524 if (Bottle *bounds=rf.find(
"skim_blobs_x_bounds").asList())
2526 if (bounds->size()>=2)
2528 skim_blobs_x_bounds[0]=bounds->get(0).asFloat64();
2529 skim_blobs_x_bounds[1]=bounds->get(1).asFloat64();
2534 skim_blobs_y_bounds.resize(2);
2535 skim_blobs_y_bounds[0]=-0.30;
2536 skim_blobs_y_bounds[1]=+0.30;
2537 if (rf.check(
"skim_blobs_y_bounds"))
2539 if (Bottle *bounds=rf.find(
"skim_blobs_y_bounds").asList())
2541 if (bounds->size()>=2)
2543 skim_blobs_y_bounds[0]=bounds->get(0).asFloat64();
2544 skim_blobs_y_bounds[1]=bounds->get(1).asFloat64();
2551 clickLocation=cv::Point(0,0);
2552 histObjLocation.resize(3);
2553 histObjLocation[0]=-0.3;
2554 histObjLocation[1]=0.0;
2555 histObjLocation[2]=-0.1;
2557 attention.setManager(
this);
2560 doAttention=rf.check(
"attention",Value(
"on")).asString()==
"on";
2562 attention.suspend();
2564 lastBlobsArrivalTime=0.0;
2565 rtLocalization.setManager(
this);
2566 rtLocalization.setPeriod((
double)rf.check(
"rt_localization_period",Value(30)).asInt32()/1000.0);
2567 rtLocalization.start();
2569 exploration.setPeriod((
double)rf.check(
"exploration_period",Value(30)).asInt32()/1000.0);
2570 exploration.setManager(
this);
2572 memoryUpdater.setManager(
this);
2573 memoryUpdater.setPeriod((
double)rf.check(
"memory_update_period",Value(60)).asInt32()/1000.0);
2574 memoryUpdater.start();
2576 blobs_detection_timeout=rf.check(
"blobs_detection_timeout",Value(0.2)).asFloat64();
2577 improve_train_period=rf.check(
"improve_train_period",Value(0.0)).asFloat64();
2578 trainOnFlipped=rf.check(
"train_flipped_images",Value(
"off")).asString()==
"on";
2579 trainBurst=rf.check(
"train_burst_images",Value(
"off")).asString()==
"on";
2580 skipLearningUponSuccess=rf.check(
"skip_learning_upon_success",Value(
"off")).asString()==
"on";
2581 classification_threshold=rf.check(
"classification_threshold",Value(0.5)).asFloat64();
2582 tracker_type=rf.check(
"tracker_type",Value(
"BOOSTING")).asString();
2583 tracker_timeout=std::max(0.0,rf.check(
"tracker_timeout",Value(5.0)).asFloat64());
2585 tracker_min_blob_size.resize(2,0);
2586 if (rf.check(
"tracker_min_blob_size"))
2588 if (Bottle *size=rf.find(
"tracker_min_blob_size").asList())
2590 if (size->size()>=2)
2592 tracker_min_blob_size[0]=size->get(0).asInt32();
2593 tracker_min_blob_size[1]=size->get(1).asInt32();
2598 histFilterLength=std::max(1,rf.check(
"hist_filter_length",Value(10)).asInt32());
2599 blockEyes=rf.check(
"block_eyes",Value(-1.0)).asFloat64();
2600 dropPosition=rf.find(
"drop_position").asList();
2602 img.resize(320,240);
2603 imgRtLoc.resize(320,240);
2611 scheduleLoadMemory=
false;
2612 enableInterrupt=
false;
2613 trackStopGood=
false;
2615 skipGazeHoming=
false;
2617 objectToBeKinCalibrated=
"";
2619 histColorsCode.push_back(cv::Scalar( 65, 47,213));
2620 histColorsCode.push_back(cv::Scalar(122, 79, 58));
2621 histColorsCode.push_back(cv::Scalar(154,208, 72));
2622 histColorsCode.push_back(cv::Scalar( 71,196,249));
2623 histColorsCode.push_back(cv::Scalar(224,176, 96));
2624 histColorsCode.push_back(cv::Scalar( 22,118,238));
2631 bool Manager::interruptModule()
2635 imgRtLocOut.interrupt();
2636 imgTrackOut.interrupt();
2637 imgClassifier.interrupt();
2638 imgHistogram.interrupt();
2639 histObjLocPort.interrupt();
2640 recogTriggerPort.interrupt();
2641 rpcPort.interrupt();
2642 rpcHuman.interrupt();
2643 blobExtractor.interrupt();
2644 rpcClassifier.interrupt();
2645 rpcMotor.interrupt();
2646 rpcMotorGrasp.interrupt();
2647 rpcReachCalib.interrupt();
2648 rpcGet3D.interrupt();
2649 rpcMotorStop.interrupt();
2650 rxMotorStop.interrupt();
2651 pointedLoc.interrupt();
2652 speaker.interrupt();
2653 rpcMemory.interrupt();
2655 rtLocalization.stop();
2656 memoryUpdater.stop();
2664 bool Manager::close()
2668 imgRtLocOut.close();
2669 imgTrackOut.close();
2670 imgClassifier.close();
2671 imgHistogram.close();
2672 histObjLocPort.close();
2673 recogTriggerPort.close();
2676 blobExtractor.close();
2677 rpcClassifier.close();
2679 rpcMotorGrasp.close();
2680 rpcReachCalib.close();
2682 rpcMotorStop.close();
2683 rxMotorStop.close();
2689 for (
auto it=histFiltersPool.begin(); it!=histFiltersPool.end(); it++)
2697 bool Manager::updateModule()
2699 Bottle cmdHuman,valHuman,replyHuman;
2700 rpcHuman.read(cmdHuman,
true);
2702 BusyGate busyGate(busy);
2707 attention.suspend();
2709 int rxCmd=processHumanCmd(cmdHuman,valHuman);
2710 if ((rxCmd==Vocab32::encode(
"attention")) && (valHuman.size()>0))
2711 if (valHuman.get(0).asString()==
"stop")
2712 skipGazeHoming=
true;
2714 if (!skipGazeHoming)
2724 skipGazeHoming=
false;
2726 if (rxCmd==Vocab32::encode(
"home"))
2728 reinstateMotor(
false);
2730 replyHuman.addString(
"ack");
2731 rpcHuman.reply(replyHuman);
2733 else if (rxCmd==Vocab32::encode(
"cata"))
2736 replyHuman.addString(
"ack");
2737 rpcHuman.reply(replyHuman);
2739 else if ((rxCmd==Vocab32::encode(
"caki")) && (valHuman.size()>0))
2741 string type=valHuman.get(0).asString();
2745 string hand=cmdHuman.get(2).toString();
2746 string activeObject=cmdHuman.get(3).toString();
2748 mutexMemoryUpdate.lock();
2749 int recogBlob=recognize(activeObject,blobs);
2750 Vector x=updateObjCartPosInMemory(activeObject,blobs,recogBlob);
2751 if (calibKinStart(activeObject,hand,x,recogBlob))
2757 mutexMemoryUpdate.unlock();
2762 mutexMemoryUpdate.unlock();
2763 replyHuman.addString(
"ack");
2764 rpcHuman.reply(replyHuman);
2767 else if ((rxCmd==Vocab32::encode(
"track")) && (valHuman.size()>0))
2769 Bottle cmdMotor,replyMotor;
2770 string type=valHuman.get(0).asString();
2773 cmdMotor.addVocab32(
"track");
2774 cmdMotor.addVocab32(
"motion");
2775 cmdMotor.addString(
"no_sacc");
2776 rpcMotor.write(cmdMotor,replyMotor);
2777 speaker.speak(
"Great! Show me the new toy");
2778 trackStopGood=
false;
2783 cmdMotor.addVocab32(
"idle");
2784 rpcMotor.write(cmdMotor,replyMotor);
2789 trackStopGood=pointedLoc.getLoc(trackStopLocation);
2792 replyHuman.addString(
"ack");
2793 rpcHuman.reply(replyHuman);
2794 skipGazeHoming=
true;
2797 else if ((rxCmd==Vocab32::encode(
"name")) && (valHuman.size()>0))
2799 string activeObject=valHuman.get(0).asString();
2800 execName(activeObject);
2802 else if ((rxCmd==Vocab32::encode(
"forget")) && (valHuman.size()>0))
2804 string activeObject=valHuman.get(0).asString();
2806 mutexMemoryUpdate.lock();
2807 execForget(activeObject);
2808 mutexMemoryUpdate.unlock();
2810 else if ((rxCmd==Vocab32::encode(
"where")) && (valHuman.size()>0))
2813 Classifier *pClassifier;
2814 string activeObject=valHuman.get(0).asString();
2816 mutexMemoryUpdate.lock();
2817 string recogType=(db.find(activeObject)==db.end())?
"creation":
"recognition";
2818 int recogBlob=recognize(activeObject,blobs,&pClassifier);
2819 updateObjCartPosInMemory(activeObject,blobs,recogBlob);
2820 execWhere(activeObject,blobs,recogBlob,pClassifier,recogType);
2821 mutexMemoryUpdate.unlock();
2823 else if (rxCmd==Vocab32::encode(
"what"))
2828 whatGood=pointedLoc.getLoc(whatLocation);
2831 Bottle blobs,scores;
2832 string activeObject;
2833 int pointedBlob=recognize(blobs,scores,activeObject);
2834 execWhat(blobs,pointedBlob,scores,activeObject);
2836 else if ((rxCmd==Vocab32::encode(
"this")) && (valHuman.size()>0))
2839 string activeObject=valHuman.get(0).asString();
2842 if (valHuman.size()>=2)
2844 if (valHuman.get(1).asString()==
"click")
2846 whatLocation=clickLocation;
2855 whatGood=pointedLoc.getLoc(whatLocation);
2859 mutexMemoryUpdate.lock();
2860 Bottle blobs,scores;
2861 string detectedObject;
2862 int pointedBlob=recognize(blobs,scores,detectedObject);
2864 execThis(activeObject,detectedObject,blobs,pointedBlob);
2865 updateObjCartPosInMemory(activeObject,blobs,pointedBlob);
2866 mutexMemoryUpdate.unlock();
2868 else if ((rxCmd==Vocab32::encode(
"take")) || (rxCmd==Vocab32::encode(
"grasp")) ||
2869 (rxCmd==Vocab32::encode(
"touch")) || (rxCmd==Vocab32::encode(
"push")) ||
2870 (rxCmd==Vocab32::encode(
"hold")) || (rxCmd==Vocab32::encode(
"drop")))
2873 string activeObject=
"";
2874 int recogBlob=RET_INVALID;
2877 mutexMemoryUpdate.lock();
2878 if (valHuman.size()>0)
2880 activeObject=valHuman.get(0).asString();
2881 recogBlob=recognize(activeObject,blobs);
2882 if ((recogBlob>=0) && (rxCmd==Vocab32::encode(
"grasp")))
2887 Bottle &opt=lookOptions.addList();
2888 opt.addString(
"block_eyes");
2889 opt.addFloat64(blockEyes);
2892 look(blobs,recogBlob,lookOptions);
2894 recogBlob=recognize(activeObject,blobs);
2897 x=updateObjCartPosInMemory(activeObject,blobs,recogBlob);
2901 if (rxCmd==Vocab32::encode(
"take"))
2903 else if (rxCmd==Vocab32::encode(
"grasp"))
2905 else if (rxCmd==Vocab32::encode(
"touch"))
2907 else if (rxCmd==Vocab32::encode(
"push"))
2909 else if (rxCmd==Vocab32::encode(
"hold"))
2914 execInterruptableAction(action,activeObject,x,blobs,recogBlob);
2915 mutexMemoryUpdate.unlock();
2917 else if ((rxCmd==Vocab32::encode(
"explore")) && (valHuman.size()>0))
2919 string activeObject=valHuman.get(0).asString();
2920 execExplore(activeObject);
2922 else if ((rxCmd==Vocab32::encode(
"reinforce")) && (valHuman.size()>1))
2924 string activeObject=valHuman.get(0).asString();
2925 if (Bottle *pl=valHuman.get(1).asList())
2927 Vector position; pl->write(position);
2928 execReinforce(activeObject,position);
2931 replyHuman.addString(
"nack");
2933 else if ((rxCmd==Vocab32::encode(
"attention")) && (valHuman.size()>0))
2935 string type=valHuman.get(0).asString();
2939 replyHuman.addString(
"ack");
2941 else if (type==
"start")
2944 replyHuman.addString(
"ack");
2947 replyHuman.addString(
"nack");
2949 rpcHuman.reply(replyHuman);
2951 else if ((rxCmd==Vocab32::encode(
"say")) && (valHuman.size()>0))
2953 string speech=valHuman.get(0).asString();
2954 speaker.speak(speech);
2955 replyHuman.addString(
"ack");
2956 rpcHuman.reply(replyHuman);
2957 skipGazeHoming=
true;
2962 speaker.speak(
"I don't understand what you want me to do");
2963 replyHuman.addString(
"nack");
2964 rpcHuman.reply(replyHuman);
2975 bool Manager::respond(
const Bottle &command, Bottle &reply)
2979 Value cmd=command.get(0);
2981 string ans=nack;
string pl;
2982 if (cmd.isVocab32())
2984 if (cmd.asVocab32()==Vocab32::encode(
"status"))
2987 pl=busy?
"busy":
"idle";
2994 reply.addString(ack);
2995 reply.addString(pl);
2997 else if (RFModule::respond(command,rep))
3000 reply.addString(nack);
3007 double Manager::getPeriod()