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)