23#include <yarp/sig/all.h>
24#include <yarp/dev/all.h>
25#include <yarp/math/Math.h>
33using namespace yarp::os;
34using namespace yarp::sig;
35using namespace yarp::math;
42 Matrix
H=rpy2dcm(
x.subVector(3,5));
43 H(0,3)=
x[0];
H(1,3)=
x[1];
H(2,3)=
x[2];
53 for (
size_t i=0; i<_x.length(); i++)
64 const deque<Vector> &
p2d;
65 const deque<Vector> &
p3d;
76 const deque<Vector> &_p3d,
77 const Vector &_min,
const Vector &_max,
89 size_t len=std::min(this->x0.length(),
x0.length());
90 for (
size_t i=0; i<len; i++)
101 bool get_nlp_info(Ipopt::Index &
n, Ipopt::Index &m, Ipopt::Index &nnz_jac_g,
102 Ipopt::Index &nnz_h_lag, IndexStyleEnum &index_style)
105 m=nnz_jac_g=nnz_h_lag=0;
106 index_style=TNLP::C_STYLE;
113 Ipopt::Index m, Ipopt::Number *g_l, Ipopt::Number *g_u)
115 for (Ipopt::Index i=0; i<
n; i++)
126 bool init_z, Ipopt::Number *z_L, Ipopt::Number *z_U,
127 Ipopt::Index m,
bool init_lambda, Ipopt::Number *lambda)
129 for (Ipopt::Index i=0; i<
n; i++)
136 bool eval_f(Ipopt::Index
n,
const Ipopt::Number *
x,
bool new_x,
137 Ipopt::Number &obj_value)
144 for (
size_t i=0; i<
p2d.size(); i++)
146 Vector p2di=PrjH*
p3d[i];
153 obj_value/=
p2d.size();
161 Ipopt::Number *grad_f)
163 double roll=
x[3];
double cr=cos(roll);
double sr=sin(roll);
164 double pitch=
x[4];
double cp=cos(pitch);
double sp=sin(pitch);
165 double yaw=
x[5];
double cy=cos(yaw);
double sy=sin(yaw);
168 Rz(0,0)=cy; Rz(1,1)=cy; Rz(0,1)=-sy; Rz(1,0)=sy;
169 Matrix dRz=
zeros(4,4);
170 dRz(0,0)=-sy; dRz(1,1)=-sy; dRz(0,1)=-cy; dRz(1,0)=cy;
173 Ry(0,0)=cp; Ry(2,2)=cp; Ry(0,2)=sp; Ry(2,0)=-sp;
174 Matrix dRy=
zeros(4,4);
175 dRy(0,0)=-sp; dRy(2,2)=-sp; dRy(0,2)=cp; dRy(2,0)=-cp;
178 Rx(1,1)=cr; Rx(2,2)=cr; Rx(1,2)=-sr; Rx(2,1)=sr;
179 Matrix dRx=
zeros(4,4);
180 dRx(1,1)=-sr; dRx(2,2)=-sr; dRx(1,2)=-cr; dRx(2,1)=cr;
182 Matrix invRz=Rz.transposed();
183 Matrix invRy=Ry.transposed();
184 Matrix invRx=Rx.transposed();
186 Matrix invR=(-1.0)*invRx*invRy*invRz;
187 Vector
p(4,-1.0);
p[0]=-
x[0];
p[1]=-
x[1];
p[2]=-
x[2];
189 Matrix dHdx0=
zeros(4,4); dHdx0.setCol(3,invR.getCol(0));
190 Matrix dHdx1=
zeros(4,4); dHdx1.setCol(3,invR.getCol(1));
191 Matrix dHdx2=
zeros(4,4); dHdx2.setCol(3,invR.getCol(2));
192 Matrix dHdx3=dRx.transposed()*invRy*invRz; dHdx3.setCol(3,dHdx3*
p);
193 Matrix dHdx4=invRx*dRy.transposed()*invRz; dHdx4.setCol(3,dHdx4*
p);
194 Matrix dHdx5=invRx*invRy*dRz.transposed(); dHdx5.setCol(3,dHdx5*
p);
196 Matrix dPrjHdx0=
Prj*dHdx0;
197 Matrix dPrjHdx1=
Prj*dHdx1;
198 Matrix dPrjHdx2=
Prj*dHdx2;
199 Matrix dPrjHdx3=
Prj*dHdx3;
200 Matrix dPrjHdx4=
Prj*dHdx4;
201 Matrix dPrjHdx5=
Prj*dHdx5;
205 grad_f[0]=grad_f[1]=grad_f[2]=0.0;
206 grad_f[3]=grad_f[4]=grad_f[5]=0.0;
209 for (
size_t i=0; i<
p2d.size(); i++)
211 Vector p2di=PrjH*
p3d[i];
215 Vector d=
p2d[i]-p2di;
217 double u_num=
dot(PrjH.getRow(0),
p3d[i]);
218 double v_num=
dot(PrjH.getRow(1),
p3d[i]);
219 double lambda=
dot(PrjH.getRow(2),
p3d[i]);
220 double lambda2=lambda*lambda;
224 tmp_dot=
dot(dPrjHdx0.getRow(2),
p3d[i]);
225 dp2d_dx0[0]=(
dot(dPrjHdx0.getRow(0),
p3d[i])*lambda-tmp_dot*u_num)/lambda2;
226 dp2d_dx0[1]=(
dot(dPrjHdx0.getRow(1),
p3d[i])*lambda-tmp_dot*v_num)/lambda2;
229 tmp_dot=
dot(dPrjHdx1.getRow(2),
p3d[i]);
230 dp2d_dx1[0]=(
dot(dPrjHdx1.getRow(0),
p3d[i])*lambda-tmp_dot*u_num)/lambda2;
231 dp2d_dx1[1]=(
dot(dPrjHdx1.getRow(1),
p3d[i])*lambda-tmp_dot*v_num)/lambda2;
234 tmp_dot=
dot(dPrjHdx2.getRow(2),
p3d[i]);
235 dp2d_dx2[0]=(
dot(dPrjHdx2.getRow(0),
p3d[i])*lambda-tmp_dot*u_num)/lambda2;
236 dp2d_dx2[1]=(
dot(dPrjHdx2.getRow(1),
p3d[i])*lambda-tmp_dot*v_num)/lambda2;
239 tmp_dot=
dot(dPrjHdx3.getRow(2),
p3d[i]);
240 dp2d_dx3[0]=(
dot(dPrjHdx3.getRow(0),
p3d[i])*lambda-tmp_dot*u_num)/lambda2;
241 dp2d_dx3[1]=(
dot(dPrjHdx3.getRow(1),
p3d[i])*lambda-tmp_dot*v_num)/lambda2;
244 tmp_dot=
dot(dPrjHdx4.getRow(2),
p3d[i]);
245 dp2d_dx4[0]=(
dot(dPrjHdx4.getRow(0),
p3d[i])*lambda-tmp_dot*u_num)/lambda2;
246 dp2d_dx4[1]=(
dot(dPrjHdx4.getRow(1),
p3d[i])*lambda-tmp_dot*v_num)/lambda2;
249 tmp_dot=
dot(dPrjHdx5.getRow(2),
p3d[i]);
250 dp2d_dx5[0]=(
dot(dPrjHdx5.getRow(0),
p3d[i])*lambda-tmp_dot*u_num)/lambda2;
251 dp2d_dx5[1]=(
dot(dPrjHdx5.getRow(1),
p3d[i])*lambda-tmp_dot*v_num)/lambda2;
253 grad_f[0]-=2.0*
dot(d,dp2d_dx0);
254 grad_f[1]-=2.0*
dot(d,dp2d_dx1);
255 grad_f[2]-=2.0*
dot(d,dp2d_dx2);
256 grad_f[3]-=2.0*
dot(d,dp2d_dx3);
257 grad_f[4]-=2.0*
dot(d,dp2d_dx4);
258 grad_f[5]-=2.0*
dot(d,dp2d_dx5);
261 for (Ipopt::Index i=0; i<
n; i++)
262 grad_f[i]/=
p2d.size();
269 bool eval_g(Ipopt::Index
n,
const Ipopt::Number *
x,
bool new_x,
270 Ipopt::Index m, Ipopt::Number *g)
277 Ipopt::Index m, Ipopt::Index nele_jac, Ipopt::Index *iRow,
278 Ipopt::Index *jCol, Ipopt::Number *values)
285 bool eval_h(Ipopt::Index
n,
const Ipopt::Number *
x,
bool new_x,
286 Ipopt::Number obj_factor, Ipopt::Index m,
const Ipopt::Number *lambda,
287 bool new_lambda, Ipopt::Index nele_hess, Ipopt::Index *iRow,
288 Ipopt::Index *jCol, Ipopt::Number *values)
296 const Ipopt::Number *
x,
const Ipopt::Number *z_L,
297 const Ipopt::Number *z_U, Ipopt::Index m,
298 const Ipopt::Number *g,
const Ipopt::Number *lambda,
299 Ipopt::Number obj_value,
const Ipopt::IpoptData *ip_data,
300 Ipopt::IpoptCalculatedQuantities *ip_cq)
303 for (Ipopt::Index i=0; i<
n; i++)
313 min.resize(6);
max.resize(6);
322 Prj.resize(3,4);
Prj.zero();
329 Matrix PrjH=
Prj*SE3inv(
H);
334 for (
size_t i=0; i<
p2d.size(); i++)
336 Vector p2di=PrjH*
p3d[i];
353 if ((
Prj.rows()>=3) && (
Prj.cols()>=4))
355 this->Prj=
Prj.submatrix(0,2,0,3);
373 size_t len_min=std::min(this->min.length(),
min.length());
374 size_t len_max=std::min(this->max.length(),
max.length());
376 for (
size_t i=0; i<len_min; i++)
379 for (
size_t i=0; i<len_max; i++)
387 if ((p2di.length()>=2) && (p3di.length()>=4))
389 p2d.push_back(p2di.subVector(0,1));
390 p3d.push_back(p3di.subVector(0,3));
417 if ((
H.rows()>=4) && (
H.cols()>=4))
419 Vector rpy=dcm2rpy(
H);
420 x0[0]=
H(0,3);
x0[1]=
H(1,3);
x0[2]=
H(2,3);
421 x0[3]=rpy[0];
x0[4]=rpy[1];
x0[5]=rpy[2];
423 for (
size_t i=0; i<
min.length(); i++)
424 x0[i]=std::min(std::max(
x0[i],
min[i]),
max[i]);
435 const int print_level,
const string &derivative_test)
439 Ipopt::SmartPtr<Ipopt::IpoptApplication> app=
new Ipopt::IpoptApplication;
440 app->Options()->SetNumericValue(
"tol",1
e-8);
441 app->Options()->SetIntegerValue(
"acceptable_iter",0);
442 app->Options()->SetStringValue(
"mu_strategy",
"adaptive");
443 app->Options()->SetIntegerValue(
"max_iter",max_iter);
444 app->Options()->SetStringValue(
"nlp_scaling_method",
"gradient-based");
445 app->Options()->SetStringValue(
"hessian_approximation",
"limited-memory");
446 app->Options()->SetIntegerValue(
"print_level",print_level);
447 app->Options()->SetStringValue(
"derivative_test",derivative_test.c_str());
448 app->Options()->SetStringValue(
"derivative_test_print_all",
"yes");
454 Ipopt::ApplicationReturnStatus status=app->OptimizeTNLP(GetRawPtr(nlp));
456 Vector
x=nlp->get_result();
460 return (status==Ipopt::Solve_Succeeded);
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)
const deque< Vector > & p3d
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)
bool eval_g(Ipopt::Index n, const Ipopt::Number *x, bool new_x, Ipopt::Index m, Ipopt::Number *g)
const deque< Vector > & p2d
bool eval_f(Ipopt::Index n, const Ipopt::Number *x, bool new_x, Ipopt::Number &obj_value)
bool eval_grad_f(Ipopt::Index n, const Ipopt::Number *x, bool new_x, Ipopt::Number *grad_f)
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)
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 set_x0(const Vector &x0)
bool get_nlp_info(Ipopt::Index &n, Ipopt::Index &m, Ipopt::Index &nnz_jac_g, Ipopt::Index &nnz_h_lag, IndexStyleEnum &index_style)
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)
Vector get_result() const
EyeAlignerNLP(const deque< Vector > &_p2d, const deque< Vector > &_p3d, const Vector &_min, const Vector &_max, const Matrix &_Prj)
bool setInitialGuess(const yarp::sig::Matrix &H)
std::deque< yarp::sig::Vector > p3d
size_t getNumPoints() const
void setBounds(const yarp::sig::Vector &min, const yarp::sig::Vector &max)
double evalError(const yarp::sig::Matrix &H)
bool calibrate(yarp::sig::Matrix &H, double &error, const int max_iter=ALIGN_IPOPT_MAX_ITER, const int print_level=0, const std::string &derivative_test="none")
bool addPoints(const yarp::sig::Vector &p2di, const yarp::sig::Vector &p3di)
bool setProjection(const yarp::sig::Matrix &Prj)
std::deque< yarp::sig::Vector > p2d
yarp::sig::Matrix getProjection() const
double dot(const yarp::sig::Matrix &A, int colA, const yarp::sig::Matrix &B, int colB)
Returns the dot product between two vectors given in the form: matrix(:,col).
double norm2(const yarp::sig::Matrix &M, int col)
Returns the squared norm of the vector given in the form: matrix(:,col).
double norm(const yarp::sig::Matrix &M, int col)
Returns the norm of the vector given in the form: matrix(:,col).
Matrix computeH(const Vector &x)
yarp::sig::Matrix computeH(const yarp::sig::Vector &x)