GCOP
1.0
|
00001 #ifndef GCOP_GNDOEP_H 00002 #define GCOP_GNDOEP_H 00003 00004 #include "doep.h" 00005 #include "lqsensorcost.h" 00006 00007 #include <unsupported/Eigen/NonLinearOptimization> 00008 00009 namespace gcop { 00010 00011 00012 using namespace std; 00013 using namespace Eigen; 00014 00015 00016 template <typename T, 00017 int _nx, 00018 int _nu, 00019 int _np, 00020 int _ng, 00021 typename Tz, 00022 int _nz, 00023 typename T1, 00024 int _nx1> class GnCost; 00025 00026 template <typename T = VectorXd, 00027 int _nx = Dynamic, 00028 int _nu = Dynamic, 00029 int _np = Dynamic, 00030 int _ng = Dynamic, 00031 typename Tz = VectorXd, 00032 int _nz = Dynamic, 00033 typename T1 = T, 00034 int _nx1 = _nx> 00035 class GnDoep : public Doep<T, _nx, _nu, _np, Tz, _nz, T1, _nx1> { 00036 00037 typedef Matrix<double, _ng, 1> Vectorgd; 00038 typedef Matrix<double, _ng, _nx> Matrixgxd; 00039 typedef Matrix<double, _ng, _nu> Matrixgud; 00040 typedef Matrix<double, _ng, _np> Matrixgpd; 00041 00042 typedef Matrix<double, _nx, 1> Vectornd; 00043 typedef Matrix<double, _nu, 1> Vectorcd; 00044 00045 typedef Matrix<double, _nx, _nx> Matrixnd; 00046 typedef Matrix<double, _nx, _nu> Matrixncd; 00047 typedef Matrix<double, _nu, _nx> Matrixcnd; 00048 typedef Matrix<double, _nu, _nu> Matrixcd; 00049 00050 typedef Matrix<double, _np, 1> Vectormd; 00051 00052 typedef Matrix<double, _np, _np> Matrixmd; 00053 typedef Matrix<double, _nx, _np> Matrixnmd; 00054 typedef Matrix<double, _np, _nx> Matrixmnd; 00055 00056 typedef Matrix<double, _nz, 1> Vectorrd; 00057 typedef Matrix<double, _nz, _nz> Matrixrd; 00058 typedef Matrix<double, _nz, _nx> Matrixrnd; 00059 typedef Matrix<double, _nz, _nu> Matrixrcd; 00060 typedef Matrix<double, _nz, _np> Matrixrmd; 00061 00062 typedef void(*Func_type)(const T &, T1 &); 00063 00064 public: 00093 GnDoep(System<T, _nx, _nu, _np> &sys, Sensor<T1, _nx1, _nu, _np, Tz, _nz> &sensor, 00094 LqSensorCost<T, _nx, _nu, _np, _ng, Tz, _nz> &cost, 00095 vector<double> &ts, vector<T> &xs, vector<Vectorcd> &us, Vectormd &p, 00096 vector<double> &ts1, Func_type _project=NULL, bool update = true); 00097 00098 virtual ~GnDoep(); 00099 00104 void Iterate(); 00105 00106 int info; 00107 double fnorm, covfac; 00108 00109 int inputs; 00110 int values; 00111 00112 VectorXd s; 00113 00114 GnCost<T, _nx, _nu, _np, _ng, Tz, _nz, T1, _nx1> *functor; 00115 NumericalDiff<GnCost<T, _nx, _nu, _np, _ng, Tz, _nz, T1, _nx1> > *numDiff; 00116 LevenbergMarquardt<NumericalDiff<GnCost<T, _nx, _nu, _np, _ng, Tz, _nz, T1, _nx1> > > *lm; 00117 }; 00118 00119 00120 // Generic functor 00121 template<typename _Scalar, int NX=Dynamic, int NY=Dynamic> 00122 struct Functor 00123 { 00124 typedef _Scalar Scalar; 00125 enum { 00126 InputsAtCompileTime = NX, 00127 ValuesAtCompileTime = NY 00128 }; 00129 typedef Matrix<Scalar,InputsAtCompileTime,1> InputType; 00130 typedef Matrix<Scalar,ValuesAtCompileTime,1> ValueType; 00131 typedef Matrix<Scalar,ValuesAtCompileTime,InputsAtCompileTime> JacobianType; 00132 00133 const int m_inputs, m_values; 00134 00135 Functor() : m_inputs(InputsAtCompileTime), m_values(ValuesAtCompileTime) {} 00136 Functor(int inputs, int values) : m_inputs(inputs), m_values(values) {} 00137 00138 int inputs() const { return m_inputs; } 00139 int values() const { return m_values; } 00140 00141 // you should define that in the subclass : 00142 // void operator() (const InputType& x, ValueType* v, JacobianType* _j=0) const; 00143 }; 00144 00145 00146 template <typename T, 00147 int _nx = Dynamic, 00148 int _nu = Dynamic, 00149 int _np = Dynamic, 00150 int _ng = Dynamic, 00151 typename Tz=VectorXd, 00152 int _nz = Dynamic, 00153 typename T1 = T, 00154 int _nx1 = _nx> 00155 struct GnCost : Functor<double> { 00156 GnCost<T, _nx, _nu, _np, _ng, Tz, _nz, T1, _nx1>(int inputs, int values) : Functor<double>(inputs, values) {}; 00157 00158 GnDoep<T, _nx, _nu, _np, _ng, Tz, _nz, T1, _nx1> *doep; 00159 00160 typedef Matrix<double, _nx, 1> Vectornd; 00161 typedef Matrix<double, _np, 1> Vectormd; 00162 typedef Matrix<double, _nu, 1> Vectorcd; 00163 typedef Matrix<double, _ng, 1> Vectorgd; 00164 typedef Matrix<double, _nz, 1> Vectorrd; 00165 00166 int operator()(const VectorXd &s, VectorXd &fvec) const 00167 { 00168 assert(doep); 00169 00170 const int &np = doep->sys.P.n; 00171 const int &nz = doep->sensor.Z.n; 00172 const int &nw = doep->sys.X.n; 00173 const int N = doep->us.size(); 00174 00175 //Update inputs: process noise ws[i], p: 00176 doep->p = s.tail(np); 00177 for(int i = 0; i < N; i++) 00178 { 00179 doep->ws[i] = s.segment(i*nw,nw); 00180 } 00181 //Update sensor measurements using the input parameters and noise ws: 00182 doep->Update(false); 00183 00184 Vectorgd &g = ((LsSensorCost<T, _nx, _nu, _np, _ng, Tz, _nz>&)doep->cost).g; 00185 Vectormd &gp = ((LsSensorCost<T, _nx, _nu, _np, _ng, Tz, _nz>&)doep->cost).gp; 00186 fvec.tail(np).setZero(); 00187 00188 //Compute and set residuals 00189 int i = 0; 00190 int sensor_index = 0; 00191 for(int k = 0; k< N; ++k) 00192 { 00193 double h = doep->ts[k+1] - doep->ts[k]; 00194 //cout<<"Res: "<<g.transpose()<<endl; 00195 //cout<<"i: "<<i<<endl; 00196 //cout<<"More Time debug Info: "<<doep->ts1[sensor_index]<<"\t"<<doep->ts[k]<<"\t"<<doep->ts[k+1]<<"\t"<<k<<"\t"<<sensor_index<<endl; 00197 00198 if((doep->ts1[sensor_index] - doep->ts[k])>= 0 && (doep->ts1[sensor_index] - doep->ts[k+1]) < 0) 00199 { 00200 while((doep->ts1[sensor_index] - doep->ts[k])>= 0 && (doep->ts1[sensor_index] - doep->ts[k+1]) < 0)//Nearest state to find the sensor measurement 00201 { 00202 ((LqSensorCost<T, _nx, _nu, _np, _ng, Tz, _nz>&)doep->cost).Res(g, doep->ts[k], doep->zs[sensor_index], doep->ws[k], doep->p, h, sensor_index); 00203 fvec.segment(i,nz) = g.segment(nw,nz); 00204 i += nz; 00205 sensor_index = sensor_index < (doep->ts1.size()-1)?sensor_index+1:sensor_index; 00206 if(sensor_index == (doep->ts1.size()-1)) 00207 break; 00208 fvec.tail(np) += g.tail(np);//The tail is a constant residual for parameters 00209 } 00210 fvec.segment(i,nw) = g.head(nw); 00211 i += nw; 00212 } 00213 else 00214 { 00215 ((LqSensorCost<T, _nx, _nu, _np, _ng, Tz, _nz>&)doep->cost).Res(g, doep->ts[k], doep->zs[sensor_index], doep->ws[k], doep->p, h, sensor_index); 00216 memcpy(fvec.data() + i, g.data(), nw*sizeof(double)); 00217 i += nw; 00218 } 00219 } 00220 assert(sensor_index == (doep->ts1.size()-1));//Assert that we collected all the sensor data 00221 ((LqSensorCost<T, _nx, _nu, _np, _ng, Tz, _nz>&)doep->cost).Resp(gp, doep->p); 00222 fvec.tail(np) += gp; 00223 //cout<<"Gp: "<<gp<<endl;//#DEBUG 00224 00225 if(doep->debug) 00226 { 00227 std::cout<<"Input: "<<s.transpose()<<endl; 00228 std::cout<<"Fvec: "<<fvec.transpose()<<endl; 00229 //std::cout<<"Resp: "<<fvec.tail(np).transpose()<<"\t"<<doep->p<<endl; 00230 } 00231 std::cout<<"Cost: "<<0.5*(fvec.transpose()*fvec)<<endl; 00232 //getchar(); 00233 return 0; 00234 } 00235 }; 00236 00237 using namespace std; 00238 using namespace Eigen; 00239 00240 template <typename T, int _nx, int _nu, int _np, int _ng, typename Tz, int _nz, typename T1, int _nx1> 00241 GnDoep<T, _nx, _nu, _np, _ng, Tz, _nz, T1, _nx1>::GnDoep(System<T, _nx, _nu, _np> &sys, Sensor<T1, _nx1, _nu, _np, Tz, _nz> &sensor, 00242 LqSensorCost<T, _nx, _nu, _np, _ng, Tz, _nz> &cost, 00243 vector<double> &ts, 00244 vector<T> &xs, 00245 vector<Vectorcd > &us, 00246 Vectormd &p, 00247 vector<double> &ts1, 00248 Func_type _project, 00249 bool update) : 00250 Doep<T, _nx, _nu, _np, Tz, _nz, T1, _nx1>(sys, sensor, cost, ts, xs, us, p, ts1, _project, update), 00251 inputs(us.size()*sys.X.n + sys.P.n), 00252 values((sys.X.n)*us.size()+(sensor.Z.n)*ts1.size()+sys.P.n), s(inputs), 00253 functor(0), numDiff(0), lm(0) 00254 { 00255 cout <<"inputs=" <<inputs<<" values= "<<values<< endl; 00256 } 00257 00258 template <typename T, int _nx, int _nu, int _np, int _ng, typename Tz, int _nz, typename T1, int _nx1> 00259 GnDoep<T, _nx, _nu, _np, _ng, Tz, _nz, T1, _nx1>::~GnDoep() 00260 { 00261 delete lm; 00262 delete numDiff; 00263 delete functor; 00264 } 00265 00266 template <typename T, int _nx, int _nu, int _np, int _ng, typename Tz, int _nz, typename T1, int _nx1> 00267 void GnDoep<T, _nx, _nu, _np, _ng, Tz, _nz, T1, _nx1>::Iterate() { 00268 00269 if (!lm) { 00270 functor = new GnCost<T, _nx, _nu, _np, _ng, Tz, _nz, T1, _nx1>(inputs, values); 00271 functor->doep = this; 00272 numDiff = new NumericalDiff<GnCost<T, _nx, _nu, _np, _ng, Tz, _nz, T1, _nx1> >(*functor); 00273 lm = new LevenbergMarquardt<NumericalDiff<GnCost<T, _nx, _nu, _np, _ng, Tz, _nz, T1, _nx1> > >(*numDiff); 00274 00275 s.setZero();//Set the initial noise ws to zero 00276 const int &np = this->sys.P.n; 00277 s.tail(np) = this->p;//Set the system parameters to initial guess 00278 } 00279 00280 /* 00281 for (int i = 0, k = 0; k < this->us.size(); ++k) { 00282 memcpy(s.data() + i, this->us[k].data(), this->sys.U.n*sizeof(double)); 00283 i += this->sys.U.n; 00284 } 00285 */ 00286 00287 // lm.parameters.maxfev=10000; 00288 info = lm->minimize(s); 00289 00290 cout <<"info="<<info <<endl; 00291 // check return values 00292 // VERIFY_IS_EQUAL(info, 1); 00293 // VERIFY_IS_EQUAL(lm.nfev(), 26); 00294 } 00295 } 00296 00297 #endif