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