GCOP
1.0
|
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