24 #include <yarp/os/all.h> 25 #include <yarp/sig/all.h> 26 #include <yarp/math/Math.h> 28 #include <iCub/ctrl/math.h> 29 #include <iCub/optimization/calibReference.h> 59 map<string, FrameInfo> frames;
60 string matricesFilePath;
64 Vector bboxMin,bboxMax;
65 Vector scaleMin,scaleMax;
75 setName( rf.check(
"name",Value(
"referenceFrameHandler")).asString().c_str() );
76 isVerbose = (rf.check(
"isVerbose",Value(0)).asInt() == 1);
77 bool isEmpty = rf.check(
"empty")||rf.check(
"empty");
80 bboxMin.resize(3); bboxMax.resize(3);
81 bboxMin[0]=-1.0; bboxMax[0]=1.0;
82 bboxMin[1]=-1.0; bboxMax[1]=1.0;
83 bboxMin[2]=-1.0; bboxMax[2]=1.0;
86 scaleMin.resize(3); scaleMax.resize(3);
87 scaleMin[0]=0.1; scaleMax[0]=10.0;
88 scaleMin[1]=0.1; scaleMax[1]=10.0;
89 scaleMin[2]=1.0; scaleMax[2]=1.0;
92 frames[
"icub"].name =
"icub";
93 frames[
"icub"].isCalibrated =
true;
94 frames[
"icub"].H = eye(4,4);
95 frames[
"icub"].S = eye(4,4);
96 frames[
"icub"].HInv = frames[
"icub"].H;
97 frames[
"icub"].SInv = frames[
"icub"].S;
100 string matricesFileName = rf.check(
"matricesFile",Value(
"frames.ini")).asString();
101 matricesFilePath = rf.findFile(matricesFileName);
102 Property matricesProp; matricesProp.fromConfigFile(matricesFilePath);
104 LoadMatrices(matricesProp);
107 matricesFilePath=rf.getHomeContextPath()+
"/"+matricesFileName;
109 opc.open(
"/" + getName() +
"/opc:rpc");
110 rpc.open(
"/" + getName() +
"/rpc");
124 out(0,0) = 1.0 / out(0,0);
125 out(1,1) = 1.0 / out(1,1);
126 out(2,2) = 1.0 / out(2,2);
135 Bottle &bFrames = prop.findGroup(
"frames");
136 for(
unsigned int f=1; f<bFrames.size(); f+=3)
138 string currentFrame = bFrames.get(f).toString().c_str();
139 Bottle *bH = bFrames.get(f+1).asList();
145 H(i,j)=bH->get(4*i+j).asDouble();
149 Bottle *bS = bFrames.get(f+2).asList();
155 S(i,j)=bS->get(4*i+j).asDouble();
159 frames[currentFrame].name = currentFrame;
160 frames[currentFrame].H = H;
161 frames[currentFrame].HInv = SE3inv(frames[currentFrame].H);
162 frames[currentFrame].S = S;
163 frames[currentFrame].SInv = inverseScale(frames[currentFrame].S);
164 frames[currentFrame].isCalibrated =
true;
166 cout<<
"Loading Frame"<<endl
167 <<frames[currentFrame].name<<endl
168 <<frames[currentFrame].H.toString(3,3)<<endl
169 <<frames[currentFrame].S.toString(3,3)<<endl;
180 ofstream file(fileName.c_str());
181 file<<
"[frames]"<<endl;
182 for(map<string, FrameInfo>::iterator it=frames.begin(); it!= frames.end(); it++)
184 if (it->second.isCalibrated)
186 file<<it->second.name<<endl;
194 b.addDouble(it->second.H(i,j));
198 file<< b.toString().c_str()<<endl;
206 bScale.addDouble(it->second.S(i,j));
209 file<< bScale.toString().c_str()<<endl;
211 cout<<
"Saving Frame"<<endl
212 <<it->second.name<<endl
213 <<it->second.H.toString(3,3)<<endl
215 <<it->second.S.toString(3,3)<<endl;
227 Bottle opcCmd,opcReply;
228 opcCmd.addVocab(Vocab::encode(
"ask"));
229 Bottle &query=opcCmd.addList();
231 opc.write(opcCmd,opcReply);
235 for(
unsigned int i=0; i<ids.size() ; i++)
238 opcCmd.addVocab(Vocab::encode(
"get"));
239 Bottle &query=opcCmd.addList();
240 Bottle &idProp=query.addList();
241 idProp.addString(
"id");
242 idProp.addInt(ids.get(i).asInt());
243 Bottle &propSet=query.addList();
244 propSet.addString(
"propSet");
245 Bottle &props=propSet.addList();
252 opc.write(opcCmd,reply);
254 if (reply.get(0).asVocab()==Vocab::encode(
"ack"))
256 if (Bottle *propList=reply.get(1).asList())
265 H(i,j)=bH->get(4*i+j).asDouble();
275 S(i,j)=bS->get(4*i+j).asDouble();
279 frames[currentFrame].name = currentFrame;
280 frames[currentFrame].H = H;
281 frames[currentFrame].HInv = SE3inv(frames[currentFrame].H);
282 frames[currentFrame].S = S;
283 frames[currentFrame].SInv = inverseScale(frames[currentFrame].S);
284 frames[currentFrame].isCalibrated =
true;
286 cout<<
"Reading Frame from OPC"<<endl
287 <<frames[currentFrame].name<<endl
288 <<frames[currentFrame].H.toString(3,3)<<endl
289 <<frames[currentFrame].S.toString(3,3)<<endl;
301 for(map<string, FrameInfo>::iterator it=frames.begin(); it!= frames.end(); it++)
303 if (it->second.isCalibrated)
306 Bottle opcCmd,opcReply;
307 opcCmd.addVocab(Vocab::encode(
"ask"));
308 Bottle &query=opcCmd.addList();
309 Bottle& checkName = query.addList();
311 checkName.addString(
"==");
312 checkName.addString(it->second.name.c_str());
319 opcCmd.addVocab(Vocab::encode(
"add"));
321 opcCmd.addVocab(Vocab::encode(
"set"));
323 Bottle &content = opcCmd.addList();
324 if (ids.size() != 0 )
326 Bottle &idUp = content.addList();
327 idUp.addString(
"id");
328 idUp.addInt(ids.get(0).asInt());
331 Bottle &name = content.addList();
333 name.addString(it->second.name.c_str());
335 Bottle &matrix = content.addList();
337 Bottle &bMat = matrix.addList();
343 bMat.addDouble(it->second.H(i,j));
347 Bottle &scale = content.addList();
349 Bottle &bSca = matrix.addList();
354 bSca.addDouble(it->second.S(i,j));
360 opc.write(opcCmd,lastReply);
361 cout<<
"Writing Frame 2 OPC"<<endl
362 <<it->second.name<<endl
363 <<it->second.H.toString(3,3)<<endl
365 <<it->second.S.toString(3,3)<<endl
366 <<lastReply.toString().c_str()<<endl;
372 bool respond(
const Bottle& cmd, Bottle& reply)
375 switch (cmd.get(0).asVocab())
378 case yarp::os::createVocab(
'o',
'p',
'c',
'w'):
381 reply.addString(
"ack");
382 reply.addString(
"written to OPC");
383 reply.addString(
"this method is deprecated!");
388 case yarp::os::createVocab(
'o',
'p',
'c',
'r'):
390 LoadMatricesFromOPC();
391 reply.addString(
"ack");
392 reply.addString(
"updated from OPC");
393 reply.addString(
"this method is deprecated!");
398 case yarp::os::createVocab(
's',
'a',
'v',
'e'):
400 SaveMatrices(matricesFilePath.c_str());
401 reply.addString(
"ack");
402 reply.addString(
"saved");
403 reply.addString( matricesFilePath.c_str() );
408 case yarp::os::createVocab(
'c',
'l',
'e',
'a'):
411 string frameName = cmd.get(1).asString().c_str();
412 std::cout<<
"Clearing the points for frame : "<<frameName<<std::endl;
413 std::cout<<
"Erasing "<<frames[frameName].calibrator.getNumPoints()<<std::endl;
415 if (frames.find(frameName) == frames.end() )
417 std::cout<<
"Frame "<< frameName<<
" was not present, creating it."<<std::endl;
418 frames[frameName].name = frameName;
419 frames[frameName].isCalibrated =
false;
420 frames[frameName].calibrator.setBounds(bboxMin,bboxMax);
421 frames[frameName].calibrator.setScalingBounds(scaleMin,scaleMax);
422 frames[frameName].S = eye(4,4);
423 frames[frameName].H = eye(4,4);
424 frames[frameName].SInv = eye(4,4);
425 frames[frameName].HInv = eye(4,4);
428 frames[frameName].calibrator.clearPoints();
430 std::cout<<
"After "<<frames[frameName].calibrator.getNumPoints()<<std::endl;
431 reply.addString(
"ack");
432 reply.addString(
"Cleared");
437 case yarp::os::createVocab(
'a',
'd',
'd'):
440 string frameName = cmd.get(1).asString().c_str();
443 if (frames.find(frameName) == frames.end() )
445 frames[frameName].name = frameName;
446 frames[frameName].isCalibrated =
false;
447 frames[frameName].calibrator.setBounds(bboxMin,bboxMax);
448 frames[frameName].calibrator.setScalingBounds(scaleMin,scaleMax);
449 frames[frameName].S = eye(4,4);
450 frames[frameName].H = eye(4,4);
451 frames[frameName].SInv = eye(4,4);
452 frames[frameName].HInv = eye(4,4);
456 Vector pOtherFrame(3), pPivotFrame(3);
457 for(
int i=0; i<3; i++)
459 pOtherFrame[i] = cmd.get(2).asList()->get(i).asDouble();
460 pPivotFrame[i] = cmd.get(3).asList()->get(i).asDouble();
462 frames[frameName].calibrator.addPoints(pOtherFrame,pPivotFrame);
463 reply.addString(
"ack");
464 reply.addString(
"Point added");
469 case yarp::os::createVocab(
'c',
'a',
'l'):
471 string frameName = cmd.get(1).asString().c_str();
474 if (frames.find(frameName) == frames.end() )
476 reply.addString(
"nack");
477 reply.addString(
"Reference frame does not exist.");
482 double t0=Time::now();
483 frames[frameName].calibrator.calibrate(frames[frameName].H,frames[frameName].calibrationError);
484 double dt=Time::now()-t0;
485 frames[frameName].HInv = SE3inv(frames[frameName].H);
486 frames[frameName].S=eye(4,4);
487 frames[frameName].SInv = inverseScale(frames[frameName].S);
490 cout<<
"Asked for calibration of "<<frameName<<endl;
491 cout<<
"H"<<endl<<frames[frameName].H.toString(3,3).c_str()<<endl;
492 cout<<
"H^-1"<<endl<<frames[frameName].HInv.toString(3,3).c_str()<<endl;
493 cout<<
"residual = "<<frames[frameName].calibrationError<<
" [m]"<<endl;
494 cout<<
"calibration performed in "<<dt<<
" [s]"<<endl;
496 frames[frameName].isCalibrated =
true;
498 reply.addString(
"ack");
499 reply.addString(frames[frameName].H.toString());
505 case yarp::os::createVocab(
's',
'c',
'a',
'l'):
507 string frameName = cmd.get(1).asString().c_str();
510 if (frames.find(frameName) == frames.end() )
512 reply.addString(
"nack");
513 reply.addString(
"Reference frame does not exist.");
519 double t0=Time::now();
520 frames[frameName].calibrator.calibrate(frames[frameName].H, vScale, frames[frameName].calibrationError);
521 double dt=Time::now()-t0;
522 frames[frameName].S = eye(4,4);
523 frames[frameName].S(0,0) = vScale(0);
524 frames[frameName].S(1,1) = vScale(1);
525 frames[frameName].S(2,2) = vScale(2);
527 frames[frameName].HInv = SE3inv(frames[frameName].H);
528 frames[frameName].SInv = inverseScale(frames[frameName].S);
530 cout<<
"Asked for calibration of "<<frameName<<endl;
531 cout<<
"H"<<endl<<frames[frameName].H.toString(3,3).c_str()<<endl;
532 cout<<
"H^-1"<<endl<<frames[frameName].HInv.toString(3,3).c_str()<<endl;
533 cout<<
"S"<<endl<<frames[frameName].S.toString(3,3).c_str()<<endl;
534 cout<<
"S^-1"<<endl<<frames[frameName].SInv.toString(3,3).c_str()<<endl;
535 cout<<
"residual = "<<frames[frameName].calibrationError<<
" [m]"<<endl;
536 cout<<
"calibration performed in "<<dt<<
" [s]"<<endl;
538 frames[frameName].isCalibrated =
true;
539 reply.addString(
"ack");
540 reply.addString(frames[frameName].H.toString());
546 case yarp::os::createVocab(
'i',
'c',
'a',
'l'):
548 string frameName = cmd.get(1).asString().c_str();
551 if (frames.find(frameName) == frames.end() )
553 reply.addString(
"nack");
554 reply.addString(
"Reference frame does not exist.");
560 double t0=Time::now();
561 frames[frameName].calibrator.calibrate(frames[frameName].H, vScale, frames[frameName].calibrationError);
562 double dt=Time::now()-t0;
563 frames[frameName].S = eye(4,4);
564 frames[frameName].S(0,0) = vScale;
565 frames[frameName].S(1,1) = vScale;
566 frames[frameName].S(2,2) = vScale;
568 frames[frameName].HInv = SE3inv(frames[frameName].H);
569 frames[frameName].SInv = inverseScale(frames[frameName].S);
571 cout<<
"Asked for calibration of "<<frameName<<endl;
572 cout<<
"H"<<endl<<frames[frameName].H.toString(3,3).c_str()<<endl;
573 cout<<
"H^-1"<<endl<<frames[frameName].HInv.toString(3,3).c_str()<<endl;
574 cout<<
"S"<<endl<<frames[frameName].S.toString(3,3).c_str()<<endl;
575 cout<<
"S^-1"<<endl<<frames[frameName].SInv.toString(3,3).c_str()<<endl;
576 cout<<
"residual = "<<frames[frameName].calibrationError<<
" [m]"<<endl;
577 cout<<
"calibration performed in "<<dt<<
" [s]"<<endl;
579 frames[frameName].isCalibrated =
true;
581 reply.addString(
"ack");
582 reply.addString(frames[frameName].H.toString());
587 case yarp::os::createVocab(
't',
'r',
'a',
'n'):
589 string frameName1 = cmd.get(1).asString().c_str();
590 string frameName2 = cmd.get(2).asString().c_str();
593 if (frames.find(frameName1) == frames.end() || frames.find(frameName2) == frames.end() )
595 reply.addString(
"nack");
596 reply.addString(
"Reference frame does not exist.");
601 if (!frames[frameName1].isCalibrated || !frames[frameName2].isCalibrated )
603 reply.addString(
"nack");
604 reply.addString(
"Reference frame is not calibrated.");
608 Vector p0(4),p1(4),p2(4);
610 p0[i] = cmd.get(3).asList()->get(i).asDouble();
614 Matrix H = frames[frameName1].H;
615 Matrix S = frames[frameName1].S;
619 H = frames[frameName2].HInv;
620 S = frames[frameName2].SInv;
625 cout<<
"Point in "<<frameName1<<
" frame"<<p0.toString()<<endl;
626 cout<<
"Point in iCub frame"<<p1.toString()<<endl;
627 cout<<
"Point in "<<frameName2<<
" frame"<<p2.toString()<<endl;
629 reply.addString(
"ack");
630 Bottle &bVect = reply.addList();
631 bVect.addDouble(p2[0]);bVect.addDouble(p2[1]);bVect.addDouble(p2[2]);
635 case yarp::os::createVocab(
's',
'm',
'a',
't'):
637 string frameName1 = cmd.get(1).asString().c_str();
638 string frameName2 = cmd.get(2).asString().c_str();
639 cout<<
"Received set matrix "<<frameName1<<
" => "<<frameName2<<endl;
641 if (frameName2 !=
"icub")
643 reply.addString(
"nack");
644 reply.addString(
"Can only set matrices to the icub pivot frame");
647 frames[frameName1].name = frameName1;
648 frames[frameName1].isCalibrated =
true;
649 frames[frameName1].H = eye(4,4);
650 frames[frameName1].S = eye(4,4);
651 Bottle *matrixList = cmd.get(3).asList();
653 for(
int i=0; i<4; i++)
655 for(
int j=0; j<4; j++)
657 frames[frameName1].H(i,j) = matrixList->get(4*j+i).asDouble();
660 frames[frameName1].HInv = SE3inv(frames[frameName1].H);
661 frames[frameName1].SInv = inverseScale(frames[frameName1].S);
662 reply.addString(
"ack");
664 cout<<
"H"<<endl<<frames[frameName1].H.toString(3,3).c_str()<<endl;
665 cout<<
"H^-1"<<endl<<frames[frameName1].HInv.toString(3,3).c_str()<<endl;
670 case yarp::os::createVocab(
'm',
'a',
't'):
672 string frameName1 = cmd.get(1).asString().c_str();
673 string frameName2 = cmd.get(2).asString().c_str();
676 if (frames.find(frameName1) == frames.end() || frames.find(frameName2) == frames.end() )
678 reply.addString(
"nack");
679 reply.addString(
"Reference frame does not exist.");
684 if (!frames[frameName1].isCalibrated || !frames[frameName2].isCalibrated )
686 reply.addString(
"nack");
687 reply.addString(
"Reference frame is not calibrated.");
691 reply.addString(
"ack");
692 Matrix h1h2 = frames[frameName1].S*frames[frameName1].H * frames[frameName2].HInv*frames[frameName2].SInv;
693 std::cout<<std::endl<<std::endl;
694 std::cout<<frameName1<<
" H : "<<frames[frameName1].H.toString(3,3)<<std::endl;
695 std::cout<<frameName1<<
" S : "<<frames[frameName1].S.toString(3,3)<<std::endl;
696 std::cout<<frameName2<<
" Hinv : "<<frames[frameName2].HInv.toString(3,3)<<std::endl;
697 std::cout<<frameName2<<
" Sinv : "<<frames[frameName2].SInv.toString(3,3)<<std::endl;
698 std::cout<<
"Result H : "<<h1h2.toString(3,3)<<std::endl;
700 Bottle &matrixList = reply.addList();
701 for(
int i=0; i<4; i++)
703 for(
int j=0; j<4; j++)
705 matrixList.addDouble(h1h2(i,j));
711 cout<<
"Retrieved H for "<<frameName1<<
"-->"<<frameName2<<endl
712 <<h1h2.toString(3,3)<<endl
719 default: { reply.addString(getName()+
" : unknown command.");
return false; }
760 if (!yarp.checkNetwork())
765 rf.setDefaultContext(
"referenceFrameHandler");
766 rf.setDefaultConfigFile(
"config.ini");
767 rf.configure(argc,argv);
770 return mod.runModule(rf);
void SaveMatrices2OPC()
Saves the calibration matrices to the OPC.
CalibReferenceWithMatchedPoints calibrator
void SaveMatrices(const string &fileName)
Saves the matrices to a file; this file can later be loaded using LoadMatrices
void LoadMatricesFromOPC()
Loads the calibration matrices from the OPC.
Matrix inverseScale(const Matrix &in)
Inverts the scale of the provided matrix.
bool configure(ResourceFinder &rf)
yarp::os::Bottle opcGetIdsFromAsk(const yarp::os::Bottle &reply)
Allow retrieving the list of unique identifiers of those items verifying the set of conditions querie...
void LoadMatrices(Property &prop)
LoadMatrices - reads the matrices from the specified matricesFile file.
bool respond(const Bottle &cmd, Bottle &reply)