GCOP  1.0
gndoep.h
Go to the documentation of this file.
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