GCOP  1.0
lqcost.h
Go to the documentation of this file.
00001 #ifndef GCOP_LQCOST_H
00002 #define GCOP_LQCOST_H
00003 
00004 #include <limits>
00005 #include "lscost.h"
00006 #include <iostream>
00007 
00008 namespace gcop {
00009   
00010   using namespace std;
00011   using namespace Eigen;
00012   
00013   template <typename T, 
00014     int _nx = Dynamic, 
00015     int _nu = Dynamic,
00016     int _np = Dynamic,
00017     int _ng = Dynamic> class LqCost : public LsCost<T, _nx, _nu, _np, _ng, T> {
00018     public:
00019 
00020   typedef Matrix<double, _ng, 1> Vectorgd;
00021   typedef Matrix<double, _ng, _nx> Matrixgxd;
00022   typedef Matrix<double, _ng, _nu> Matrixgud;
00023   typedef Matrix<double, _ng, _np> Matrixgpd;
00024 
00025   typedef Matrix<double, _nx, 1> Vectornd;
00026   typedef Matrix<double, _nu, 1> Vectorcd;
00027   typedef Matrix<double, _np, 1> Vectormd;
00028 
00029   typedef Matrix<double, _nx, _nx> Matrixnd;
00030   typedef Matrix<double, _nx, _nu> Matrixncd;
00031   typedef Matrix<double, _nu, _nx> Matrixcnd;
00032   typedef Matrix<double, _nu, _nu> Matrixcd;
00033   
00034   //  typedef Matrix<double, Dynamic, 1> Vectormd;
00035   typedef Matrix<double, _np, _np> Matrixmd;
00036   typedef Matrix<double, _nx, _np> Matrixnmd;
00037   typedef Matrix<double, _np, _nx> Matrixmnd;
00038       
00048     LqCost(System<T, _nx, _nu, _np> &sys, double tf, const T &xf, bool diag = true);
00049 
00054     void UpdateGains(); 
00055     
00056     virtual double L(double t, const T& x, const Vectorcd& u, double h,
00057                      const Vectormd *p = 0,
00058                      Vectornd *Lx = 0, Matrixnd* Lxx = 0,
00059                      Vectorcd *Lu = 0, Matrixcd* Luu = 0,
00060                      Matrixncd *Lxu = 0,
00061                      Vectormd *Lp = 0, Matrixmd *Lpp = 0,
00062                      Matrixmnd *Lpx = 0);
00063 
00064     bool Res(Vectorgd &g, 
00065              double t, const T &x, const Vectorcd &u, double h,
00066              const Vectormd *p = 0,
00067              Matrixgxd *dgdx = 0, Matrixgud *dgdu = 0,
00068              Matrixgpd *dgdp = 0);                 
00069 
00075     void SetReference(const vector<T> *xds, const vector<Vectorcd> *uds);        
00076     
00077     virtual bool SetContext(const T &c);
00078 
00079     const T *xf; 
00080     
00081     bool diag;   
00082     
00083     Matrixnd Q;       
00084     Matrixnd Qf;      
00085     Matrixcd R;       
00086 
00087     Matrixnd Qsqrt;       
00088     Matrixnd Qfsqrt;      
00089     Matrixcd Rsqrt;       
00090 
00091     const vector<T> *xds;         
00092     const vector<Vectorcd> *uds;  
00093 
00094     protected:
00095 
00096     Vectornd dx;      
00097     Vectorcd du;      
00098 
00099     };
00100   
00101   template <typename T, int _nx, int _nu, int _np, int _ng>
00102     LqCost<T, _nx, _nu, _np, _ng>::LqCost(System<T, _nx, _nu, _np> &sys, 
00103                                           double tf, const T &xf, bool diag) : 
00104     LsCost<T, _nx, _nu, _np, _ng, T>(sys, tf, sys.X.n + sys.U.n), xf(&xf), diag(diag) {
00105     
00106     if (_nx == Dynamic || _nu == Dynamic) {
00107       Q.resize(sys.X.n, sys.X.n);
00108       Qf.resize(sys.X.n, sys.X.n);
00109       R.resize(sys.U.n, sys.U.n);
00110       Qsqrt.resize(sys.X.n, sys.X.n);
00111       Qfsqrt.resize(sys.X.n, sys.X.n);
00112       Rsqrt.resize(sys.U.n, sys.U.n);
00113       dx.resize(sys.X.n);
00114       du.resize(sys.U.n);
00115     }
00116 
00117     Q.setZero();
00118     //    Q.setIdentity();
00119     Qf.setIdentity();
00120     R.setIdentity();
00121 
00122     UpdateGains();
00123 
00124     xds = 0;
00125     uds = 0;
00126   }
00127 
00128   template <typename T, int _nx, int _nu, int _np, int _ng>
00129     bool LqCost<T, _nx, _nu, _np, _ng>::SetContext(const T& c) {
00130     this->xf = &c;
00131   }
00132   
00133   template <typename T, int _nx, int _nu, int _np, int _ng>
00134     void LqCost<T, _nx, _nu, _np, _ng>::UpdateGains() {
00135     Qsqrt = Q.array().sqrt();
00136     Qfsqrt = Qf.array().sqrt();
00137     Rsqrt = R.array().sqrt();
00138   }
00139 
00140 
00141   template <typename T, int _nx, int _nu, int _np, int _ng>  
00142     void LqCost<T, _nx, _nu, _np, _ng>::SetReference(const vector<T> *xds, const vector<Vectorcd> *uds) {
00143     this->xds = xds;
00144     this->uds = uds;
00145   }
00146 
00147   template <typename T, int _nx, int _nu, int _np, int _ng> 
00148     bool LqCost<T, _nx, _nu, _np, _ng>::Res(Vectorgd &g, 
00149                                             double t, const T &x, const Vectorcd &u, double h,
00150                                             const Vectormd *p,
00151                                             Matrixgxd *dgdx, Matrixgud *dgdu,
00152                                             Matrixgpd *dgdp) {
00153     assert(g.size() == this->sys.U.n + this->sys.X.n);
00154     
00155     int &nx = this->sys.X.n;
00156     int &nu = this->sys.U.n;
00157     
00158     // check if final state
00159     if (t > this->tf - 1e-10) {
00160       if (xds) {
00161         this->sys.X.Lift(dx, xds->back(), x); // difference (on a vector space we have dx = x - xf)
00162       } else {
00163         this->sys.X.Lift(dx, *xf, x); // difference (on a vector space we have dx = x - xf)     
00164       }
00165       if (std::isnan(dx[0])) {
00166         cout << "[W] LqCost::Res: dx is nan" << endl;
00167         return false;
00168       }
00169 
00170       if (diag)
00171         g.head(nx) = Qfsqrt.diagonal().cwiseProduct(dx);
00172       else
00173         g.head(nx) = Qfsqrt*dx;      
00174 
00175       g.tail(nu).setZero();
00176 
00177     } else {
00178       assert(h > 0);
00179       int k = round(t/h);
00180       if (xds) {
00181         assert(k < xds->size());
00182         this->sys.X.Lift(dx, (*xds)[k], x); // difference (on a vector space we have dx = x - xf)
00183       } else {
00184         this->sys.X.Lift(dx, *xf, x); // difference (on a vector space we have dx = x - xf)     
00185       }
00186       if (std::isnan(dx[0])) {
00187         cout << "[W] LqCost::Res: dx is nan" << endl;
00188         return false;
00189       }
00190 
00191       if (diag)
00192         g.head(nx) = Qsqrt.diagonal().cwiseProduct(sqrt(h)*dx);
00193       else
00194         g.head(nx) = Qsqrt*(sqrt(h)*dx);
00195 
00196       if (uds) {
00197         assert(k < uds->size());
00198         du = sqrt(h)*(u - (*uds)[k]);
00199       } else {
00200         du = sqrt(h)*u;
00201       }
00202       
00203       if (diag)
00204         g.tail(nu) = Rsqrt.diagonal().cwiseProduct(du);
00205       else
00206         g.tail(nu) = Rsqrt*(du);
00207     }
00208     return true;
00209   }
00210   
00211   
00212   template <typename T, int _nx, int _nu, int _np, int _ng> 
00213     double LqCost<T, _nx, _nu, _np, _ng>::L(double t, const T &x, const Matrix<double, _nu, 1> &u,
00214                                             double h,
00215                                             const Matrix<double, _np, 1> *p,
00216                                             Matrix<double, _nx, 1> *Lx, Matrix<double, _nx, _nx> *Lxx,
00217                                             Matrix<double, _nu, 1> *Lu, Matrix<double, _nu, _nu> *Luu,
00218                                             Matrix<double, _nx, _nu> *Lxu,
00219                                             Matrix<double, _np, 1> *Lp, Matrix<double, _np, _np> *Lpp,
00220                                             Matrix<double, _np, _nx> *Lpx) {
00221     
00222     int k = round(t/h);
00223     
00224         // check if final state
00225     if (t > this->tf - 1e-10) {
00226 
00227       if (xds) {
00228         this->sys.X.Lift(dx, xds->back(), x); // difference (on a vector space we have dx = x - xf)
00229       } else {
00230         this->sys.X.Lift(dx, *xf, x); // difference (on a vector space we have dx = x - xf)      
00231       }
00232       if (std::isnan(dx[0])) {
00233         cout << "[W] LqCost::L: dx is nan" << endl;
00234         return std::numeric_limits<double>::max();
00235       }    
00236 
00237       if (Lx)
00238         if (diag)
00239           *Lx = Qf.diagonal().cwiseProduct(dx);
00240         else
00241           *Lx = Qf*dx;
00242       
00243       if (Lxx)
00244         *Lxx = Qf;
00245       
00246       if (Lu)
00247         Lu->setZero();
00248       if (Luu)
00249         Luu->setZero();
00250       if (Lxu)
00251         Lxu->setZero();    
00252       
00253       if (diag)
00254         return dx.dot(Qf.diagonal().cwiseProduct(dx))/2;
00255       else
00256         return dx.dot(Qf*dx)/2;
00257       
00258     } else {
00259 
00260       if (xds) {
00261         assert(k < xds->size());
00262         this->sys.X.Lift(dx, (*xds)[k], x); // difference (on a vector space we have dx = x - xf)
00263       } else {
00264         this->sys.X.Lift(dx, *xf, x); // difference (on a vector space we have dx = x - xf)      
00265       }
00266       if (std::isnan(dx[0])) {
00267         cout << "[W] LqCost::L: dx is nan" << endl;
00268         return std::numeric_limits<double>::max();
00269       }     
00270       
00271       if (uds) {
00272         assert(k < uds->size());
00273         du = u - (*uds)[k];
00274       } else {
00275         du = u;
00276       }
00277 
00278       if (Lx)
00279         if (diag)
00280           *Lx = Q.diagonal().cwiseProduct(h*dx);
00281         else
00282           *Lx = Q*(h*dx);
00283 
00284       if (Lxx) 
00285         *Lxx = h*Q;
00286       
00287       if (Lu)
00288         if (diag)
00289           *Lu = R.diagonal().cwiseProduct(h*du);
00290         else
00291           *Lu = R*(h*du);        
00292 
00293       if (Luu)
00294         *Luu = h*R;
00295 
00296       if (Lxu)
00297         Lxu->setZero();
00298       
00299       if (diag)
00300         return h*(dx.dot(Q.diagonal().cwiseProduct(dx)) + du.dot(R.diagonal().cwiseProduct(du)))/2;
00301       else
00302         return h*(dx.dot(Q*dx) + du.dot(R*du))/2;
00303     }
00304     return 0;
00305   }  
00306 }
00307 
00308 
00309 #endif