iCub-main
Loading...
Searching...
No Matches
pointing_far.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2017 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
18#include <string>
19#include <cmath>
20#include <limits>
21
22#include <IpTNLP.hpp>
23#include <IpIpoptApplication.hpp>
24
25#include <yarp/os/Property.h>
26#include <yarp/os/LogStream.h>
27#include <yarp/dev/CartesianControl.h>
28#include <yarp/sig/Vector.h>
29#include <yarp/sig/Matrix.h>
30#include <yarp/math/Math.h>
31
32#include <iCub/iKin/iKinFwd.h>
33#include <iCub/pointing_far.h>
34
35#define RAD2DEG (180.0/M_PI)
36#define DEG2RAD (M_PI/180.0)
37
38using namespace std;
39using namespace yarp::os;
40using namespace yarp::dev;
41using namespace yarp::sig;
42using namespace yarp::math;
43using namespace iCub::iKin;
44
45
46/*************************************************************************/
47class PointingFarNLP : public Ipopt::TNLP
48{
49 iCubArm *finger_tip;
50 iCubArm *elbow;
51 iCubFinger *finger;
52 Vector point;
53
54public:
55 /*********************************************************************/
56 PointingFarNLP(ICartesianControl *iarm) :
57 point(3,0.0)
58 {
59 Bottle info;
60 iarm->getInfo(info);
61 string hand=info.find("arm_type").asString();
62 finger_tip=new iCubArm(hand);
63 elbow=new iCubArm(hand);
64
65 size_t underscore=hand.find('_');
66 if (underscore!=string::npos)
67 hand=hand.substr(0,underscore);
68
69 // update joints limits
70 for (unsigned int i=0; i<finger_tip->getN(); i++)
71 {
72 double min,max;
73 iarm->getLimits(i,&min,&max);
74 (*finger_tip->asChain())[i].setMin(DEG2RAD*min);
75 (*finger_tip->asChain())[i].setMax(DEG2RAD*max);
76 (*elbow->asChain())[i].setMin(DEG2RAD*min);
77 (*elbow->asChain())[i].setMax(DEG2RAD*max);
78 }
79
80 // finger_tip: block torso
81 finger_tip->blockLink(0,0.0);
82 finger_tip->blockLink(1,0.0);
83 finger_tip->blockLink(2,0.0);
84
85 // finger_tip: block wrist
86 finger_tip->blockLink(8,0.0);
87 finger_tip->blockLink(9,0.0);
88
89 // elbow: block torso
90 elbow->blockLink(0,0.0);
91 elbow->blockLink(1,0.0);
92 elbow->blockLink(2,0.0);
93
94 // elbow: remove forearm
95 for (auto i=0; i<4; i++)
96 elbow->asChain()->rmLink(7);
97
98 // remove all constraints
99 finger_tip->asChain()->setAllConstraints(false);
100 elbow->asChain()->setAllConstraints(false);
101
102 finger=new iCubFinger(hand+"_index");
103 finger->asChain()->setAllConstraints(false);
105 }
106
107 /*********************************************************************/
109 {
110 delete finger_tip;
111 delete elbow;
112 delete finger;
113 }
114
115 /*********************************************************************/
116 void setPoint(const Vector& point)
117 {
118 this->point=point;
119 }
120
121 /*********************************************************************/
122 void setFingerJoints(const Vector& finger_joints)
123 {
124 Vector chain_joints;
125 finger->getChainJoints(finger_joints,chain_joints);
126 finger->setAng(DEG2RAD*chain_joints);
127
128 // add final transformations
129 finger_tip->asChain()->setHN(finger->getH());
130 }
131
132 /*********************************************************************/
133 void getResult(Vector &q, Vector &x) const
134 {
135 q.resize(finger_tip->getN());
136 for (unsigned int i=0; i<q.length(); i++)
137 q[i]=RAD2DEG*finger_tip->getAng(i);
138 x=finger_tip->EndEffPose();
139 }
140
141 /*********************************************************************/
142 bool get_nlp_info(Ipopt::Index& n, Ipopt::Index& m, Ipopt::Index& nnz_jac_g,
143 Ipopt::Index& nnz_h_lag, IndexStyleEnum& index_style)
144 {
145 n=finger_tip->getDOF();
146 m=2;
147 nnz_jac_g=m*n;
148 nnz_h_lag=0;
149 index_style=TNLP::C_STYLE;
150 return true;
151 }
152
153 /*********************************************************************/
154 bool get_bounds_info(Ipopt::Index n, Ipopt::Number* x_l, Ipopt::Number* x_u,
155 Ipopt::Index m, Ipopt::Number* g_l, Ipopt::Number* g_u)
156 {
157 for (Ipopt::Index i=0; i<n; i++)
158 {
159 x_l[i]=(*finger_tip->asChain())(i).getMin();
160 x_u[i]=(*finger_tip->asChain())(i).getMax();
161 }
162
163 g_l[0]=0.9999;
164 g_u[0]=std::numeric_limits<double>::max();
165
166 g_l[1]=-std::numeric_limits<double>::max();
167 g_u[1]=0.0;
168 return true;
169 }
170
171 /*********************************************************************/
172 bool get_starting_point(Ipopt::Index n, bool init_x, Ipopt::Number* x,
173 bool init_z, Ipopt::Number* z_L, Ipopt::Number* z_U,
174 Ipopt::Index m, bool init_lambda, Ipopt::Number* lambda)
175 {
176 for (Ipopt::Index i=0; i<n; i++)
177 x[i]=0.5*((*finger_tip->asChain())(i).getMin()+
178 (*finger_tip->asChain())(i).getMax());
179 return true;
180 }
181
182 /*********************************************************************/
183 void setAng(const Ipopt::Number* x)
184 {
185 Vector q(finger_tip->getDOF());
186 for (size_t i=0; i<q.length(); i++)
187 q[i]=x[i];
188 finger_tip->setAng(q);
189 elbow->asChain()->setAng(q);
190 }
191
192 /*********************************************************************/
193 bool eval_f(Ipopt::Index n, const Ipopt::Number* x, bool new_x,
194 Ipopt::Number& obj_value)
195 {
196 setAng(x);
197 Matrix tip=finger_tip->getH();
198 double e=-1.0-tip(2,2);
199 obj_value=e*e;
200 return true;
201 }
202
203 /*********************************************************************/
204 bool eval_grad_f(Ipopt::Index n, const Ipopt::Number* x, bool new_x,
205 Ipopt::Number* grad_f)
206 {
207 setAng(x);
208 Matrix tip=finger_tip->getH();
209 double e=-1.0-tip(2,2);
210 Matrix dtipZ=finger_tip->AnaJacobian(2);
211 for (Ipopt::Index i=0; i<n; i++)
212 grad_f[i]=-2.0*e*dtipZ(2,i);
213 return true;
214 }
215
216 /*********************************************************************/
217 bool eval_g(Ipopt::Index n, const Ipopt::Number* x, bool new_x,
218 Ipopt::Index m, Ipopt::Number* g)
219 {
220 setAng(x);
221 Vector elbowPos=elbow->asChain()->EndEffPosition();
222 Vector pe_dir=point-elbowPos;
223
224 Matrix tip=finger_tip->getH();
225 Vector te_dir=tip.getCol(3).subVector(0,2)-elbowPos;
226 g[0]=dot(pe_dir,te_dir)/(norm(pe_dir)*norm(te_dir));
227
228 Vector pt_dir=point-tip.getCol(3).subVector(0,2);
229 g[1]=pt_dir[0];
230 return true;
231 }
232
233 /*********************************************************************/
234 bool eval_jac_g(Ipopt::Index n, const Ipopt::Number* x, bool new_x,
235 Ipopt::Index m, Ipopt::Index nele_jac, Ipopt::Index* iRow,
236 Ipopt::Index *jCol, Ipopt::Number* values)
237 {
238 if (!values)
239 {
240 Ipopt::Index idx=0;
241 for (Ipopt::Index i=0; i<n; i++,idx++)
242 {
243 iRow[idx]=0;
244 jCol[idx]=i;
245 }
246 for (Ipopt::Index i=0; i<n; i++,idx++)
247 {
248 iRow[idx]=1;
249 jCol[idx]=i;
250 }
251 }
252 else
253 {
254 setAng(x);
255 Vector elbowPos=elbow->asChain()->EndEffPosition();
256 Vector pe_dir=point-elbowPos;
257
258 Matrix tip=finger_tip->getH();
259 Vector te_dir=tip.getCol(3).subVector(0,2)-elbowPos;
260
261 Matrix dpe_dir=-1.0*elbow->asChain()->AnaJacobian().removeRows(3,3);
262 dpe_dir=cat(dpe_dir,zeros(3,finger_tip->getDOF()-elbow->asChain()->getDOF()));
263 Matrix dte_dir=finger_tip->AnaJacobian().removeRows(3,3)+dpe_dir;
264
265 double npe=norm(pe_dir);
266 double nte=norm(te_dir);
267 double nn=npe*nte;
268
269 for (Ipopt::Index i=0; i<n; i++)
270 values[i]=(dot(dpe_dir.getCol(i),te_dir)+dot(pe_dir,dte_dir.getCol(i)))/nn-
271 dot(pe_dir,te_dir)*(dot(pe_dir,dpe_dir.getCol(i))*nte/npe)/(nn*nn);
272
273 Matrix dtip=-1.0*finger_tip->AnaJacobian();
274 for (Ipopt::Index i=0; i<n; i++)
275 values[n+i]=dtip(0,i);
276 }
277 return true;
278 }
279
280 /*********************************************************************/
281 bool eval_h(Ipopt::Index n, const Ipopt::Number *x, bool new_x,
282 Ipopt::Number obj_factor, Ipopt::Index m,
283 const Ipopt::Number *lambda, bool new_lambda,
284 Ipopt::Index nele_hess, Ipopt::Index *iRow,
285 Ipopt::Index *jCol, Ipopt::Number *values)
286 {
287 return true;
288 }
289
290 /*********************************************************************/
291 void finalize_solution(Ipopt::SolverReturn status, Ipopt::Index n,
292 const Ipopt::Number* x, const Ipopt::Number* z_L,
293 const Ipopt::Number* z_U, Ipopt::Index m,
294 const Ipopt::Number* g, const Ipopt::Number* lambda,
295 Ipopt::Number obj_value, const Ipopt::IpoptData* ip_data,
296 Ipopt::IpoptCalculatedQuantities* ip_cq)
297 {
298 }
299};
300
301
302/*************************************************************************/
303bool PointingFar::compute(ICartesianControl *iarm, const Property& requirements,
304 Vector& q, Vector& x)
305{
306 if (iarm==NULL)
307 {
308 yError()<<"Cartesian controller not configured";
309 return false;
310 }
311
312 Bottle *bPoint=requirements.find("point").asList();
313 if (bPoint==NULL)
314 {
315 yError()<<"Target point not provided";
316 return false;
317 }
318
319 Vector point(3,0.0);
320 for (int i=0; i<bPoint->size(); i++)
321 point[i]=bPoint->get(i).asFloat64();
322
323 Ipopt::SmartPtr<Ipopt::IpoptApplication> app=new Ipopt::IpoptApplication;
324 app->Options()->SetNumericValue("tol",0.01);
325 app->Options()->SetNumericValue("constr_viol_tol",0.01);
326 app->Options()->SetIntegerValue("acceptable_iter",0);
327 app->Options()->SetStringValue("mu_strategy","adaptive");
328 app->Options()->SetIntegerValue("max_iter",200);
329 app->Options()->SetStringValue("nlp_scaling_method","gradient-based");
330 app->Options()->SetStringValue("hessian_approximation","limited-memory");
331 app->Options()->SetStringValue("derivative_test","none");
332 app->Options()->SetIntegerValue("print_level",0);
333 app->Initialize();
334
335 Ipopt::SmartPtr<PointingFarNLP> nlp=new PointingFarNLP(iarm);
336
337 // specify requirements
338 nlp->setPoint(point);
339 if (Bottle *bFingerJoints=requirements.find("finger-joints").asList())
340 {
341 Vector finger_joints(bFingerJoints->size());
342 for (size_t i=0; i<finger_joints.length(); i++)
343 finger_joints[i]=bFingerJoints->get(i).asFloat64();
344 nlp->setFingerJoints(finger_joints);
345 }
346
347 Ipopt::ApplicationReturnStatus status=app->OptimizeTNLP(GetRawPtr(nlp));
348 nlp->getResult(q,x);
349 return true;
350}
351
352
353/*************************************************************************/
354bool PointingFar::point(ICartesianControl *iarm, const Vector& q, const Vector& x)
355{
356 if ((q.length()>=10) && (x.length()>=7))
357 {
358 int context;
359 iarm->storeContext(&context);
360
361 // specify all joints
362 Vector dof(10,1.0);
363 iarm->setDOF(dof,dof);
364 for (unsigned int i=0; i<q.length(); i++)
365 iarm->setLimits(i,q[i],q[i]);
366
367 double traj;
368 iarm->getTrajTime(&traj);
369 iarm->setInTargetTol(0.02);
370 iarm->goToPoseSync(x.subVector(0,2),x.subVector(3,6));
371 iarm->waitMotionDone(0.2,5.0*traj);
372 iarm->stopControl();
373
374 iarm->restoreContext(context);
375 iarm->deleteContext(context);
376 return true;
377 }
378 else
379 return false;
380}
381
382
bool get_starting_point(Ipopt::Index n, bool init_x, Ipopt::Number *x, bool init_z, Ipopt::Number *z_L, Ipopt::Number *z_U, Ipopt::Index m, bool init_lambda, Ipopt::Number *lambda)
PointingFarNLP(ICartesianControl *iarm)
bool eval_f(Ipopt::Index n, const Ipopt::Number *x, bool new_x, Ipopt::Number &obj_value)
virtual ~PointingFarNLP()
bool eval_grad_f(Ipopt::Index n, const Ipopt::Number *x, bool new_x, Ipopt::Number *grad_f)
bool eval_h(Ipopt::Index n, const Ipopt::Number *x, bool new_x, Ipopt::Number obj_factor, Ipopt::Index m, const Ipopt::Number *lambda, bool new_lambda, Ipopt::Index nele_hess, Ipopt::Index *iRow, Ipopt::Index *jCol, Ipopt::Number *values)
bool eval_g(Ipopt::Index n, const Ipopt::Number *x, bool new_x, Ipopt::Index m, Ipopt::Number *g)
void setFingerJoints(const Vector &finger_joints)
void setAng(const Ipopt::Number *x)
void finalize_solution(Ipopt::SolverReturn status, Ipopt::Index n, const Ipopt::Number *x, const Ipopt::Number *z_L, const Ipopt::Number *z_U, Ipopt::Index m, const Ipopt::Number *g, const Ipopt::Number *lambda, Ipopt::Number obj_value, const Ipopt::IpoptData *ip_data, Ipopt::IpoptCalculatedQuantities *ip_cq)
void setPoint(const Vector &point)
bool get_bounds_info(Ipopt::Index n, Ipopt::Number *x_l, Ipopt::Number *x_u, Ipopt::Index m, Ipopt::Number *g_l, Ipopt::Number *g_u)
bool get_nlp_info(Ipopt::Index &n, Ipopt::Index &m, Ipopt::Index &nnz_jac_g, Ipopt::Index &nnz_h_lag, IndexStyleEnum &index_style)
void getResult(Vector &q, Vector &x) const
bool eval_jac_g(Ipopt::Index n, const Ipopt::Number *x, bool new_x, Ipopt::Index m, Ipopt::Index nele_jac, Ipopt::Index *iRow, Ipopt::Index *jCol, Ipopt::Number *values)
A class for defining the iCub Arm.
Definition iKinFwd.h:1193
A class for defining the iCub Finger.
Definition iKinFwd.h:1233
virtual bool getChainJoints(const yarp::sig::Vector &motorEncoders, yarp::sig::Vector &chainJoints)
Retrieves the vector of actual finger's joint values (to be used in conjuction with the iKinLimb meth...
yarp::sig::Matrix getH(const unsigned int i, const bool allLink=false)
Returns the rigid roto-translation matrix from the root reference frame to the ith frame in Denavit-H...
Definition iKinFwd.cpp:732
bool setHN(const yarp::sig::Matrix &_HN)
Sets HN, the rigid roto-translation matrix from the Nth frame to the end-effector.
Definition iKinFwd.cpp:580
yarp::sig::Vector EndEffPosition()
Returns the 3D coordinates of end-effector position.
Definition iKinFwd.cpp:894
yarp::sig::Matrix AnaJacobian(const unsigned int i, unsigned int col)
Returns the analitical Jacobian of the ith link.
Definition iKinFwd.cpp:911
bool rmLink(const unsigned int i)
Removes the ith Link from the Chain.
Definition iKinFwd.cpp:321
yarp::sig::Vector EndEffPose(const bool axisRep=true)
Returns the coordinates of end-effector.
Definition iKinFwd.cpp:850
yarp::sig::Vector getAng()
Returns the current free joint angles values.
Definition iKinFwd.cpp:611
yarp::sig::Vector setAng(const yarp::sig::Vector &q)
Sets the free joint angles to values of q[i].
unsigned int getN() const
Returns the number of Links belonging to the Chain.
Definition iKinFwd.h:549
unsigned int getDOF() const
Returns the current number of Chain's DOF.
Definition iKinFwd.h:556
bool blockLink(const unsigned int i, double Ang)
Blocks the ith Link at the a certain value of its joint angle.
Definition iKinFwd.cpp:394
void setAllConstraints(bool _constrained)
Sets the constraint status of all chain links.
Definition iKinFwd.cpp:498
iKinChain * asChain()
Returns a pointer to the Limb seen as Chain object.
Definition iKinFwd.h:1012
zeros(2, 2) eye(2
int n
static uint32_t idx[BOARD_NUM]
#define RAD2DEG
#define DEG2RAD
static bool compute(yarp::dev::ICartesianControl *iarm, const yarp::os::Property &requirements, yarp::sig::Vector &q, yarp::sig::Vector &x)
static bool point(yarp::dev::ICartesianControl *iarm, const yarp::sig::Vector &q, const yarp::sig::Vector &x)