107 #include <yarp/os/all.h>
108 #include <yarp/sig/all.h>
109 #include <yarp/dev/all.h>
110 #include <yarp/math/Math.h>
111 #include <yarp/cv/Cv.h>
113 #include <IpTNLP.hpp>
114 #include <IpIpoptApplication.hpp>
116 #include <opencv2/opencv.hpp>
119 using namespace yarp::os;
120 using namespace yarp::dev;
121 using namespace yarp::sig;
122 using namespace yarp::math;
123 using namespace yarp::cv;
127 class FindToolTipNLP :
public Ipopt::TNLP
130 const deque<Vector> &p;
131 const deque<Matrix> &H;
140 FindToolTipNLP(
const deque<Vector> &_p,
141 const deque<Matrix> &_H,
142 const Vector &_min,
const Vector &_max) :
151 void set_x0(
const Vector &x0)
153 size_t len=std::min(this->x0.length(),x0.length());
154 for (
size_t i=0; i<len; i++)
159 Vector get_result()
const
165 bool get_nlp_info(Ipopt::Index &n, Ipopt::Index &m, Ipopt::Index &nnz_jac_g,
166 Ipopt::Index &nnz_h_lag, IndexStyleEnum &index_style)
169 m=nnz_jac_g=nnz_h_lag=0;
170 index_style=TNLP::C_STYLE;
176 bool get_bounds_info(Ipopt::Index n, Ipopt::Number *x_l, Ipopt::Number *x_u,
177 Ipopt::Index m, Ipopt::Number *g_l, Ipopt::Number *g_u)
179 for (Ipopt::Index i=0; i<n; i++)
189 bool get_starting_point(Ipopt::Index n,
bool init_x, Ipopt::Number *x,
190 bool init_z, Ipopt::Number *z_L, Ipopt::Number *z_U,
191 Ipopt::Index m,
bool init_lambda, Ipopt::Number *lambda)
193 for (Ipopt::Index i=0; i<n; i++)
200 bool eval_f(Ipopt::Index n,
const Ipopt::Number *x,
bool new_x,
201 Ipopt::Number &obj_value)
212 for (
size_t i=0; i<p.size(); i++)
218 obj_value+=norm2(p[i]-pi);
228 bool eval_grad_f(Ipopt::Index n,
const Ipopt::Number* x,
bool new_x,
229 Ipopt::Number *grad_f)
237 grad_f[0]=grad_f[1]=grad_f[2]=0.0;
240 for (
size_t i=0; i<p.size(); i++)
248 double u_num=dot(H[i].getRow(0),_x);
249 double v_num=dot(H[i].getRow(1),_x);
251 double lambda=dot(H[i].getRow(2),_x);
252 double lambda2=lambda*lambda;
255 dp_dx1[0]=(H[i](0,0)*lambda-H[i](2,0)*u_num)/lambda2;
256 dp_dx1[1]=(H[i](1,0)*lambda-H[i](2,0)*v_num)/lambda2;
259 dp_dx2[0]=(H[i](0,1)*lambda-H[i](2,1)*u_num)/lambda2;
260 dp_dx2[1]=(H[i](1,1)*lambda-H[i](2,1)*v_num)/lambda2;
263 dp_dx3[0]=(H[i](0,2)*lambda-H[i](2,2)*u_num)/lambda2;
264 dp_dx3[1]=(H[i](1,2)*lambda-H[i](2,2)*v_num)/lambda2;
266 grad_f[0]-=2.0*dot(d,dp_dx1);
267 grad_f[1]-=2.0*dot(d,dp_dx2);
268 grad_f[2]-=2.0*dot(d,dp_dx3);
271 for (Ipopt::Index i=0; i<n; i++)
279 bool eval_g(Ipopt::Index n,
const Ipopt::Number *x,
bool new_x,
280 Ipopt::Index m, Ipopt::Number *g)
286 bool eval_jac_g(Ipopt::Index n,
const Ipopt::Number *x,
bool new_x,
287 Ipopt::Index m, Ipopt::Index nele_jac, Ipopt::Index *iRow,
288 Ipopt::Index *jCol, Ipopt::Number *values)
295 bool eval_h(Ipopt::Index n,
const Ipopt::Number *x,
bool new_x,
296 Ipopt::Number obj_factor, Ipopt::Index m,
const Ipopt::Number *lambda,
297 bool new_lambda, Ipopt::Index nele_hess, Ipopt::Index *iRow,
298 Ipopt::Index *jCol, Ipopt::Number *values)
305 void finalize_solution(Ipopt::SolverReturn status, Ipopt::Index n,
306 const Ipopt::Number *x,
const Ipopt::Number *z_L,
307 const Ipopt::Number *z_U, Ipopt::Index m,
308 const Ipopt::Number *g,
const Ipopt::Number *lambda,
309 Ipopt::Number obj_value,
const Ipopt::IpoptData *ip_data,
310 Ipopt::IpoptCalculatedQuantities *ip_cq)
313 for (Ipopt::Index i=0; i<n; i++)
332 double evalError(
const Vector &x)
341 for (
size_t i=0; i<p.size(); i++)
347 error+=norm(p[i]-pi);
360 min.resize(3); max.resize(3);
361 min[0]=-1.0; max[0]=1.0;
362 min[1]=-1.0; max[1]=1.0;
363 min[2]=-1.0; max[2]=1.0;
369 void setBounds(
const Vector &min,
const Vector &max)
371 size_t len_min=std::min(this->min.length(),min.length());
372 size_t len_max=std::min(this->max.length(),max.length());
374 for (
size_t i=0; i<len_min; i++)
377 for (
size_t i=0; i<len_max; i++)
382 bool addItem(
const Vector &pi,
const Matrix &Hi)
384 if ((pi.length()>=2) && (Hi.rows()>=3) && (Hi.cols()>=4))
386 Vector _pi=pi.subVector(0,1);
387 Matrix _Hi=Hi.submatrix(0,2,0,3);
406 size_t getNumItems()
const
412 bool setInitialGuess(
const Vector &x0)
414 size_t len=std::min(x0.length(),this->x0.length());
415 for (
size_t i=0; i<len; i++)
422 bool solve(Vector &x,
double &error)
426 Ipopt::SmartPtr<Ipopt::IpoptApplication> app=
new Ipopt::IpoptApplication;
427 app->Options()->SetNumericValue(
"tol",1e-8);
428 app->Options()->SetIntegerValue(
"acceptable_iter",0);
429 app->Options()->SetStringValue(
"mu_strategy",
"adaptive");
430 app->Options()->SetIntegerValue(
"max_iter",300);
431 app->Options()->SetStringValue(
"nlp_scaling_method",
"gradient-based");
432 app->Options()->SetStringValue(
"hessian_approximation",
"limited-memory");
433 app->Options()->SetIntegerValue(
"print_level",0);
434 app->Options()->SetStringValue(
"derivative_test",
"none");
437 Ipopt::SmartPtr<FindToolTipNLP> nlp=
new FindToolTipNLP(p,H,min,max);
440 Ipopt::ApplicationReturnStatus status=app->OptimizeTNLP(GetRawPtr(nlp));
445 return (status==Ipopt::Solve_Succeeded);
455 class FinderModule:
public RFModule,
public PortReader
461 ICartesianControl *iarm;
473 BufferedPort<ImageOf<PixelBgr> > imgInPort;
474 BufferedPort<ImageOf<PixelBgr> > imgOutPort;
476 BufferedPort<Vector> logPort;
479 bool read(ConnectionReader &connection)
482 data.read(connection);
483 if ((data.size()>=2) && enabled)
486 iarm->getPose(xa,oa);
490 igaze->getLeftEyePose(xe,oe);
492 igaze->getRightEyePose(xe,oe);
494 Matrix Ha=axis2dcm(oa);
495 Ha.setSubcol(xa,0,3);
497 Matrix He=axis2dcm(oe);
498 He.setSubcol(xe,0,3);
500 Matrix H=Prj*SE3inv(He)*Ha;
502 p[0]=data.get(0).asDouble();
503 p[1]=data.get(1).asDouble();
505 if (logPort.getOutputCount()>0)
507 Vector &log=logPort.prepare();
510 for (
int i=0; i<H.rows(); i++)
511 log=cat(log,H.getRow(i));
512 for (
int i=0; i<Prj.rows(); i++)
513 log=cat(log,Prj.getRow(i));
514 for (
int i=0; i<Ha.rows(); i++)
515 log=cat(log,Ha.getRow(i));
516 for (
int i=0; i<He.rows(); i++)
517 log=cat(log,He.getRow(i));
532 bool configure(ResourceFinder &rf)
534 string robot=rf.check(
"robot",Value(
"icub")).asString();
535 string name=rf.check(
"name",Value(
"karmaToolFinder")).asString();
536 arm=rf.check(
"arm",Value(
"right")).asString();
537 eye=rf.check(
"eye",Value(
"left")).asString();
539 if ((arm!=
"left") && (arm!=
"right"))
541 printf(
"Invalid arm requested!\n");
545 if ((eye!=
"left") && (eye!=
"right"))
547 printf(
"Invalid eye requested!\n");
551 Property optionArmL(
"(device cartesiancontrollerclient)");
552 optionArmL.put(
"remote",
"/"+robot+
"/cartesianController/left_arm");
553 optionArmL.put(
"local",
"/"+name+
"/left_arm");
554 if (!drvArmL.open(optionArmL))
556 printf(
"Cartesian left_arm controller not available!\n");
561 Property optionArmR(
"(device cartesiancontrollerclient)");
562 optionArmR.put(
"remote",
"/"+robot+
"/cartesianController/right_arm");
563 optionArmR.put(
"local",
"/"+name+
"/right_arm");
564 if (!drvArmR.open(optionArmR))
566 printf(
"Cartesian right_arm controller not available!\n");
576 Property optionGaze(
"(device gazecontrollerclient)");
577 optionGaze.put(
"remote",
"/iKinGazeCtrl");
578 optionGaze.put(
"local",
"/"+name+
"/gaze");
579 if (drvGaze.open(optionGaze))
583 printf(
"Gaze controller not available!\n");
589 igaze->getInfo(info);
590 if (Bottle *pB=info.find(
"camera_intrinsics_"+eye).asList())
594 for (
int r=0; r<Prj.rows(); r++)
595 for (
int c=0; c<Prj.cols(); c++)
596 Prj(r,c)=pB->get(cnt++).asDouble();
600 printf(
"Camera intrinsic parameters not available!\n");
605 imgInPort.open(
"/"+name+
"/img:i");
606 imgOutPort.open(
"/"+name+
"/img:o");
607 dataInPort.open(
"/"+name+
"/in");
608 logPort.open(
"/"+name+
"/log:o");
609 rpcPort.open(
"/"+name+
"/rpc");
612 Vector min(3),max(3);
613 min[0]=-1.0; max[0]=1.0;
614 min[1]=-1.0; max[1]=1.0;
615 min[2]=-1.0; max[2]=1.0;
616 solver.setBounds(min,max);
617 solution.resize(3,0.0);
620 dataInPort.setReader(*
this);
626 bool respond(
const Bottle &command, Bottle &reply)
628 int ack=Vocab::encode(
"ack");
629 int nack=Vocab::encode(
"nack");
631 if (command.size()>0)
633 switch (command.get(0).asVocab())
636 case createVocab(
'c',
'l',
'e',
'a'):
638 lock_guard<mutex> lg(mtx);
646 case createVocab(
's',
'e',
'l',
'e'):
648 if (command.size()>=3)
650 string arm=command.get(1).asString();
651 string eye=command.get(2).asString();
653 if ((arm==
"left") || (arm==
"right"))
656 if ((eye==
"left") || (eye==
"right"))
659 if (this->arm==
"left")
667 reply.addVocab(nack);
673 case createVocab(
'n',
'u',
'm'):
677 lock_guard<mutex> lg(mtx);
678 reply.addInt((
int)solver.getNumItems());
683 case createVocab(
'f',
'i',
'n',
'd'):
688 bool ok=solver.solve(solution,error);
694 for (
size_t i=0; i<solution.length(); i++)
695 reply.addDouble(solution[i]);
698 reply.addVocab(nack);
704 case createVocab(
's',
'h',
'o',
'w'):
706 if (command.size()>=4)
708 solution[0]=command.get(1).asDouble();
709 solution[1]=command.get(2).asDouble();
710 solution[2]=command.get(3).asDouble();
715 reply.addVocab(nack);
721 case createVocab(
't',
'i',
'p'):
729 reply.addVocab(nack);
735 case createVocab(
'e',
'n',
'a',
'b'):
743 case createVocab(
'd',
'i',
's',
'a'):
752 return RFModule::respond(command,reply);
756 reply.addVocab(nack);
769 if (imgOutPort.getOutputCount()>0)
771 if (ImageOf<PixelBgr> *pImgBgrIn=imgInPort.read(
false))
774 iarm->getPose(xa,oa);
776 Matrix Ha=axis2dcm(oa);
777 Ha.setSubcol(xa,0,3);
779 Vector v(4,0.0); v[3]=1.0;
782 v=0.0; v[0]=0.05; v[3]=1.0;
785 v=0.0; v[1]=0.05; v[3]=1.0;
788 v=0.0; v[2]=0.05; v[3]=1.0;
791 v=solution; v.push_back(1.0);
794 Vector pc,px,py,pz,pt;
795 int camSel=(eye==
"left")?0:1;
796 igaze->get2DPixel(camSel,c,pc);
797 igaze->get2DPixel(camSel,x,px);
798 igaze->get2DPixel(camSel,y,py);
799 igaze->get2DPixel(camSel,z,pz);
800 igaze->get2DPixel(camSel,t,pt);
802 cv::Point point_c((
int)pc[0],(
int)pc[1]);
803 cv::Point point_x((
int)px[0],(
int)px[1]);
804 cv::Point point_y((
int)py[0],(
int)py[1]);
805 cv::Point point_z((
int)pz[0],(
int)pz[1]);
806 cv::Point point_t((
int)pt[0],(
int)pt[1]);
808 cv::Mat imgMat=toCvMat(*pImgBgrIn);
810 cv::circle(imgMat,point_c,4,cv::Scalar(0,255,0),4);
811 cv::circle(imgMat,point_t,4,cv::Scalar(255,0,0),4);
813 cv::line(imgMat,point_c,point_x,cv::Scalar(0,0,255),2);
814 cv::line(imgMat,point_c,point_y,cv::Scalar(0,255,0),2);
815 cv::line(imgMat,point_c,point_z,cv::Scalar(255,0,0),2);
816 cv::line(imgMat,point_c,point_t,cv::Scalar(255,255,255),2);
819 tip.addInt(point_t.x);
820 tip.addInt(point_t.y);
822 imgOutPort.prepare()=*pImgBgrIn;
840 if (drvArmL.isValid())
843 if (drvArmR.isValid())
846 if (drvGaze.isValid())
861 int main(
int argc,
char *argv[])
864 if (!yarp.checkNetwork())
866 printf(
"YARP server not available!\n");
871 rf.configure(argc,argv);
874 return mod.runModule(rf);