GCOP  1.0
gndocp.h
Go to the documentation of this file.
00001 #ifndef GCOP_GNDOCP_H
00002 #define GCOP_GNDOCP_H
00003 
00004 #include "docp.h"
00005 #include "lqcost.h"
00006 #include "tparam.h"
00007 
00008 #include <unsupported/Eigen/NonLinearOptimization>
00009 
00010 #ifdef GCOP_GNDOCP_CERES
00011 #include "ceres/ceres.h"
00012 #include "glog/logging.h"
00013 #endif
00014 
00015 //#define USE_SAMPLE_NUMERICAL_DIFF
00016 /*#ifdef USE_SAMPLE_NUMERICAL_DIFF
00017 #include "samplenumericaldiff.h"
00018 #endif
00019 */
00020 
00021 namespace gcop {
00022 
00023 #ifdef GCOP_GNDOCP_CERES
00024 using ceres::DynamicNumericDiffCostFunction;
00025 using ceres::CENTRAL;
00026 using ceres::CostFunction;
00027 using ceres::Problem;
00028 using ceres::Solver;
00029 using ceres::Solve;
00030 #endif
00031   
00032   using namespace std;
00033   using namespace Eigen;
00034 
00035  
00036   template <typename T, 
00037     int _nx, 
00038     int _nu,
00039     int _np,
00040     int _ng,
00041     int _ntp> class GnCost;
00042   
00043   template <typename T, 
00044     int _nx = Dynamic, 
00045     int _nu = Dynamic,
00046     int _np = Dynamic,
00047     int _ng = Dynamic,
00048     int _ntp = Dynamic> class GnDocp : 
00049     public Docp<T, _nx, _nu, _np> {
00050     
00051     typedef Matrix<double, _ng, 1> Vectorgd;
00052     typedef Matrix<double, _ng, _nx> Matrixgxd;
00053     typedef Matrix<double, _ng, _nu> Matrixgud;
00054     typedef Matrix<double, _ng, _np> Matrixgpd;
00055     
00056     typedef Matrix<double, _nx, 1> Vectornd;
00057     typedef Matrix<double, _nu, 1> Vectorcd;
00058 
00059     typedef Matrix<double, _nx, _nx> Matrixnd;
00060     typedef Matrix<double, _nx, _nu> Matrixncd;
00061     typedef Matrix<double, _nu, _nx> Matrixcnd;
00062     typedef Matrix<double, _nu, _nu> Matrixcd;
00063     
00064     typedef Matrix<double, _np, 1> Vectormd;
00065     
00066     typedef Matrix<double, _np, _np> Matrixmd;
00067     typedef Matrix<double, _nx, _np> Matrixnmd;
00068     typedef Matrix<double, _np, _nx> Matrixmnd;    
00069   public:
00091     GnDocp(System<T, _nx, _nu, _np> &sys, 
00092            LqCost<T, _nx, _nu, _np, _ng> &cost, Tparam<T, _nx, _nu, _np, _ntp> &tparam,
00093            vector<double> &ts, vector<T> &xs, vector<Vectorcd> &us, 
00094            Vectormd *p = 0, bool update = true);
00095     
00096     virtual ~GnDocp();
00097 
00102     void Iterate();
00103     Tparam<T, _nx, _nu, _np, _ntp> &tparam;
00104 
00105     int info;
00106     double fnorm, covfac;
00107 
00108     int inputs;
00109     int values;
00110 
00111     double numdiff_stepsize;   
00112      
00113     VectorXd s;  
00114     
00115     GnCost<T, _nx, _nu, _np, _ng, _ntp> *functor;
00116 //#ifndef USE_SAMPLE_NUMERICAL_DIFF
00117     NumericalDiff<GnCost<T, _nx, _nu, _np, _ng, _ntp>, NumericalDiffMode::Central> *numDiff;
00118     LevenbergMarquardt<NumericalDiff<GnCost<T, _nx, _nu, _np, _ng, _ntp>, NumericalDiffMode::Central> > *lm;
00119 /*#else 
00120     SampleNumericalDiff<GnCost<T, _nx, _nu, _np, _ng, _ntp> > *numDiff;
00121     LevenbergMarquardt<SampleNumericalDiff<GnCost<T, _nx, _nu, _np, _ng, _ntp> > > *lm;
00122 #endif
00123     */
00124   };
00125 
00126   
00127 // Generic functor
00128 template<typename _Scalar, int NX=Dynamic, int NY=Dynamic>
00129 struct Functor
00130 {
00131   typedef _Scalar Scalar;
00132   enum {
00133     InputsAtCompileTime = NX,
00134     ValuesAtCompileTime = NY
00135   };
00136   typedef Matrix<Scalar,InputsAtCompileTime,1> InputType;
00137   typedef Matrix<Scalar,ValuesAtCompileTime,1> ValueType;
00138   typedef Matrix<Scalar,ValuesAtCompileTime,InputsAtCompileTime> JacobianType;
00139 
00140   const int m_inputs, m_values;
00141 
00142   Functor() : m_inputs(InputsAtCompileTime), m_values(ValuesAtCompileTime) {}
00143   Functor(int inputs, int values) : m_inputs(inputs), m_values(values) {}
00144 
00145   int inputs() const { return m_inputs; }
00146   int values() const { return m_values; }
00147 
00148   // you should define that in the subclass :
00149 //  void operator() (const InputType& x, ValueType* v, JacobianType* _j=0) const;
00150 };
00151 
00152 
00153  template <typename T, 
00154    int _nx = Dynamic,
00155    int _nu = Dynamic,
00156    int _np = Dynamic,
00157    int _ng = Dynamic,
00158    int _ntp = Dynamic>
00159    struct GnCost : Functor<double> {  
00160 
00161    GnDocp<T, _nx, _nu, _np, _ng, _ntp> *docp;
00162 
00163    GnCost<T, _nx, _nu, _np, _ng, _ntp>(int inputs, int values) : Functor<double>(inputs, values), docp(0) {};
00164    
00165    typedef Matrix<double, _nx, 1> Vectornd;
00166    typedef Matrix<double, _nu, 1> Vectorcd;
00167    typedef Matrix<double, _ng, 1> Vectorgd;
00168    
00169    int operator()(const VectorXd &s, VectorXd &fvec) const
00170    {
00171      assert(docp);
00172      docp->tparam.From(docp->ts, docp->xs, docp->us, s, docp->p);
00173 
00174      //#DEBUG Number of function evaluations:
00175      //cout<<++(docp->nofevaluations)<<endl;
00176      ++(docp->nofevaluations);
00177 
00178      //cout<<"Docp->Xsback: "<<(docp->xs).back().transpose()<<endl;//what is this back doing?
00179      if(docp->p)
00180      {
00181        cout<<"docp->p: "<<(docp->p)->transpose()<<endl;
00182      }
00183      //cout<<"Xf: "<<docp->xs[(docp->xs).size()-1].transpose()<<endl;
00184      /*
00185        for (int i = 0, k = 0; k < docp.us.size(); ++k) {
00186        memcpy(docp.us[k].data(), s.data() + i, docp.sys.U.n*sizeof(double));
00187        i += docp.sys.U.n;
00188       }
00189       docp.Update(false);
00190       */
00191      
00192      Vectorgd &g = ((LsCost<T, _nx, _nu, _np, _ng>&)docp->cost).g;
00193      
00194      int i = 0;
00195       for (int k = 0; k < docp->us.size(); ++k) {
00196         const double &t = docp->ts[k];
00197         double h = docp->ts[k+1] - t;
00198         const T& x = docp->xs[k];
00199         const Vectorcd& u = docp->us[k];
00200         
00201         ((LqCost<T, _nx, _nu, _np, _ng>&)docp->cost).Res(g, t, x, u, h, docp->p);
00202         //double cost_debug = ((LqCost<T, _nx, _nu, _np, _ng>&)docp->cost).L(t, x, u, h, docp->p);
00203         memcpy(fvec.data() + i, g.data(), g.size()*sizeof(double));
00204         i += g.size();
00205         /*cout<<"docp->us["<<k<<"]: "<<(docp->us[k].transpose())<<endl;
00206         cout<<"g["<<k<<"]: "<<g.transpose()<<endl;
00207         cout<<"gcost["<<k<<"]: "<<0.5*(g.transpose()*g)<<endl;
00208         cout<<"Lcost["<<k<<"]: "<<cost_debug<<endl;
00209         // 
00210         ((LqCost<T, _nx, _nu>&)docp->cost).ResX(rx, t, x, h);
00211         memcpy(fvec.data() + i, rx.data(), rx.size()*sizeof(double));
00212         i += rx.size();
00213 
00214         ((LqCost<T, _nx, _nu>&)docp->cost).ResU(ru, t, u, h);
00215         memcpy(fvec.data() + i, ru.data(), ru.size()*sizeof(double));
00216         i += ru.size();
00217         */
00218       }
00219       
00220       ((LqCost<T, _nx, _nu, _np, _ng>&)docp->cost).Res(g, 
00221                                                        docp->ts.back(), 
00222                                                        docp->xs.back(), 
00223                                                        docp->us.back(), 0);
00224       //cout<<"g[end]: "<<g.transpose()<<endl;
00225       memcpy(fvec.data() + i, g.data(), g.size()*sizeof(double));
00226       docp->J = 0.5*(fvec.transpose()*fvec)(0);
00227       //cout<<"s: "<<s.transpose()<<endl;
00228       //cout<<"fvec: "<<fvec.transpose()<<endl;
00229       //cout<<"Cost: "<<(docp->J)<<endl;
00230       //getchar(); // #DEBUG
00231       return 0;
00232     }
00233   };
00234 
00235 
00236 
00237 #ifdef GCOP_GNDOCP_CERES
00238 
00239   // A cost functor that implements the residual r = 10 - x.
00240   template <typename T, int _nx = Dynamic, int _nu = Dynamic>
00241     struct GnCost {  
00242       GnCost<T, _nx, _nu>(GnDocp<T, _nx, _nu> &docp) : docp(docp) {};
00243 
00244       GnDocp<T, _nx, _nu> &docp;
00245 
00246     typedef Matrix<double, _nx, 1> Vectornd;
00247     typedef Matrix<double, _nu, 1> Vectorcd;
00248 
00249     
00250     //   bool operator()(const double* const s, double* residual) const {
00251     bool operator()(double const* const* parameters, double* residuals) const {
00252 
00253       const double *s = parameters[0];
00254       for (int i = 0, k = 0; k < docp.us.size(); ++k) {
00255         memcpy(docp.us[k].data(), s + i, docp.sys.U.n*sizeof(double));
00256         i += docp.sys.U.n;
00257       }
00258       docp.Update(false);
00259 
00260       Vectorcd ru;
00261       Vectornd rx;
00262       int i = 0;
00263       for (int k = 0; k < docp.us.size(); ++k) {
00264         const double &t = docp.ts[k];
00265         double h = docp.ts[k+1] - t;
00266         const T& x = docp.xs[k];
00267         const Vectorcd& u = docp.us[k];
00268 
00269         ((LqCost<T, _nx, _nu>&)docp.cost).ResX(rx, t, x, h);
00270         memcpy(residuals + i, rx.data(), rx.size()*sizeof(double));
00271         i += rx.size();
00272 
00273         ((LqCost<T, _nx, _nu>&)docp.cost).ResU(ru, t, u, h);
00274         memcpy(residuals + i, ru.data(), ru.size()*sizeof(double));
00275         i += ru.size();
00276       }
00277       if (docp.ts.size() > 1) {
00278         double h = docp.ts.back() - docp.ts[docp.ts.size() - 2];
00279         ((LqCost<T, _nx, _nu>&)docp.cost).ResX(rx, docp.ts.back(), docp.xs.back(), h);
00280         memcpy(residuals + i, rx.data(), rx.size()*sizeof(double));
00281       }
00282       return true;
00283     }
00284   };
00285 #endif
00286 
00287   using namespace std;
00288   using namespace Eigen;
00289   
00290   template <typename T, int _nx, int _nu, int _np, int _ng, int _ntp> 
00291     GnDocp<T, _nx, _nu, _np, _ng, _ntp>::GnDocp(System<T, _nx, _nu, _np> &sys, 
00292                                                 LqCost<T, _nx, _nu, _np, _ng> &cost,
00293                                                 Tparam<T, _nx, _nu, _np, _ntp> &tparam,
00294                                                 vector<double> &ts, 
00295                                                 vector<T> &xs, 
00296                                                 vector<Matrix<double, _nu, 1> > &us,
00297                                                 Matrix<double, _np, 1> *p,
00298                                                 bool update) : 
00299     Docp<T, _nx, _nu, _np>(sys, cost, ts, xs, us, p, false), tparam(tparam),
00300     inputs(tparam.ntp),
00301     values(cost.ng*xs.size()), s(inputs), 
00302     functor(0), numDiff(0), lm(0), 
00303 #ifndef USE_SAMPLE_NUMERICAL_DIFF
00304     numdiff_stepsize(1e-8)
00305 #else
00306     numdiff_stepsize(1e-4)
00307 #endif
00308     {
00309       if(update)
00310         this->Update(false);//No need of derivatives
00311 
00312       ++(this->nofevaluations);
00313 
00314       tparam.To(s, this->ts, this->xs, this->us, this->p);
00315 
00316       cout <<"ntp=" <<tparam.ntp << endl;
00317     }
00318   
00319   template <typename T, int _nx, int _nu, int _np, int _ng, int _ntp> 
00320     GnDocp<T, _nx, _nu, _np, _ng, _ntp>::~GnDocp()
00321     {
00322       delete lm;
00323       delete numDiff;
00324       delete functor;
00325     }  
00326   
00327   template <typename T, int _nx, int _nu, int _np, int _ng, int _ntp> 
00328     void GnDocp<T, _nx, _nu, _np, _ng, _ntp>::Iterate() {
00329 
00330     if (!lm) {
00331       functor = new GnCost<T, _nx, _nu, _np, _ng, _ntp>(inputs, values);
00332       functor->docp = this;
00333 //#ifndef USE_SAMPLE_NUMERICAL_DIFF
00334       numDiff = new NumericalDiff<GnCost<T, _nx, _nu, _np, _ng, _ntp>, NumericalDiffMode::Central>(*functor,numdiff_stepsize);
00335       lm = new LevenbergMarquardt<NumericalDiff<GnCost<T, _nx, _nu, _np, _ng, _ntp>, NumericalDiffMode::Central> >(*numDiff);
00336 /*#else 
00337       numDiff = new SampleNumericalDiff<GnCost<T, _nx, _nu, _np, _ng, _ntp> >(*functor,numdiff_stepsize);
00338       lm = new LevenbergMarquardt<SampleNumericalDiff<GnCost<T, _nx, _nu, _np, _ng, _ntp> > >(*numDiff);
00339 #endif
00340       */
00341       lm->parameters.maxfev = 1e6;//Maximum nof evaluations is very high
00342       info = lm->minimizeInit(s);
00343       cout <<"info="<<info <<endl;
00344     }
00345 
00346     /*
00347     for (int i = 0, k = 0; k < this->us.size(); ++k) {
00348       memcpy(s.data() + i, this->us[k].data(), this->sys.U.n*sizeof(double));
00349       i += this->sys.U.n;
00350     }
00351     */
00352 
00353     //    lm.parameters.maxfev=10000;
00354     info = lm->minimizeOneStep(s);
00355     
00356     cout <<"info="<<info <<endl;
00357     // check return values
00358     // VERIFY_IS_EQUAL(info, 1);
00359     //   VERIFY_IS_EQUAL(lm.nfev(), 26);
00360     
00361 #ifdef GCOP_GNDOCP_CERES
00362 
00363     //  google::InitGoogleLogging(argv[0]);
00364 
00365   int npar = this->sys.U.n*this->us.size();
00366   int nres = ((LqCost<T, _nx, _nu, _np, _ng>&)cost).gn*this->xs.size();
00367 
00368   // The variable to solve for with its initial value. It will be
00369   // mutated in place by the solver.
00370   double s[npar];
00371   for (int i = 0, k = 0; k < this->us.size(); ++k) {
00372     memcpy(s + i, this->us[k].data(), this->sys.U.n*sizeof(double));
00373     i += this->sys.U.n;
00374   }
00375 
00376   //  const double initial_x = x;
00377 
00378   // Build the problem.
00379   Problem problem;
00380 
00381   //  CostFunction* cost_function =
00382   //    new NumericDiffCostFunction<CostFunctor, CENTRAL, nres, _npar> (new CostFunctor);
00383   //  problem.AddResidualBlock(cost_function, NULL, &x);
00384   
00385   DynamicNumericDiffCostFunction<GnCost<T,n,c> > *cost_function = new DynamicNumericDiffCostFunction<GnCost<T,n,c> >(new GnCost<T,n,c>(*this));
00386   cost_function->AddParameterBlock(npar);
00387   cost_function->SetNumResiduals(nres);
00388 
00389   problem.AddResidualBlock(cost_function, NULL, s);
00390 
00391   // Run the solver!
00392   Solver::Options options;
00393 
00394   options.linear_solver_type = ceres::DENSE_QR;
00395   //  options.num_threads = 8;
00396   options.minimizer_progress_to_stdout = true;
00397   options.max_num_iterations = 1;
00398   Solver::Summary summary;
00399   Solve(options, &problem, &summary);
00400 
00401   std::cout << summary.BriefReport() << "\n";
00402   //  std::cout << "x : " << initial_x
00403   #endif
00404     
00405   }
00406 }
00407 
00408 #endif