GCOP  1.0
gndoepv2.h
Go to the documentation of this file.
00001 #ifndef GCOP_GNDOEP1_H
00002 #define GCOP_GNDOEP1_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 GnDoep1 : 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     GnDoep1(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 ~GnDoep1();
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    GnDoep1<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;
00177      //Update sensor measurements using the input parameters and noise ws:
00178      doep->Update(false);
00179 
00180      Vectorgd &g = ((LsSensorCost<T, _nx, _nu, _np, _ng, Tz, _nz>&)doep->cost).g;
00181      Vectormd &gp = ((LsSensorCost<T, _nx, _nu, _np, _ng, Tz, _nz>&)doep->cost).gp;
00182      fvec.tail(np).setZero();
00183 
00184      //Compute and set residuals
00185      int i = 0;
00186      int sensor_index = 0;
00187      for(int k = 0; k< N; ++k)
00188      {
00189        double h = doep->ts[k+1] - doep->ts[k];
00190        //getchar();
00191        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
00192        {
00193          ((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);
00194          fvec.segment(i,nz) = g.segment(nw,nz);
00195          i += nz;
00196          sensor_index = sensor_index < (doep->ts1.size()-1)?sensor_index+1:sensor_index;
00197          if(sensor_index == (doep->ts1.size()-1))
00198            break;
00199          fvec.tail(np) += g.tail(np);//The tail is a constant residual for parameters
00200        }
00201        //cout<<"doep->ts: "<<(doep->ts1[sensor_index])<<"\t"<<(doep->ts[k])<<"\t"<<(doep->ts[k+1])<<endl;
00202        //getchar();
00203        //cout<<"Res: "<<g<<endl;
00204        //cout<<"i: "<<i<<endl;
00205      }
00206      assert(sensor_index == (doep->ts1.size()-1));//Assert that we collected all the sensor data
00207      ((LqSensorCost<T, _nx, _nu, _np, _ng, Tz, _nz>&)doep->cost).Resp(gp, doep->p);
00208      fvec.tail(np) += gp;
00209      //cout<<"Gp: "<<gp<<endl;//#DEBUG
00210 
00211      if(doep->debug)
00212      {
00213        std::cout<<"Input: "<<s.transpose()<<endl;
00214        std::cout<<"Fvec: "<<fvec.transpose()<<endl;
00215        //std::cout<<"Resp: "<<fvec.tail(np).transpose()<<"\t"<<doep->p<<endl;
00216      }
00217        std::cout<<"Cost: "<<0.5*(fvec.transpose()*fvec)<<endl;
00218      return 0;
00219    }
00220   };
00221 
00222   using namespace std;
00223   using namespace Eigen;
00224   
00225   template <typename T, int _nx, int _nu, int _np, int _ng, typename Tz, int _nz, typename T1, int _nx1> 
00226     GnDoep1<T, _nx, _nu, _np, _ng, Tz, _nz, T1, _nx1>::GnDoep1(System<T, _nx, _nu, _np> &sys, Sensor<T1, _nx1, _nu, _np, Tz, _nz> &sensor,
00227                                                 LqSensorCost<T, _nx, _nu, _np, _ng, Tz, _nz> &cost,
00228                                                 vector<double> &ts, 
00229                                                 vector<T> &xs, 
00230                                                 vector<Vectorcd > &us,
00231                                                 Vectormd &p,
00232                                                 vector<double> &ts1,
00233                                                 Func_type _project,
00234                                                 bool update) : 
00235     Doep<T, _nx, _nu, _np, Tz, _nz, T1, _nx1>(sys, sensor, cost, ts, xs, us, p, ts1, _project, false),
00236     inputs(sys.P.n),
00237     values((sensor.Z.n)*ts1.size()+sys.P.n), s(inputs), 
00238     functor(0), numDiff(0), lm(0)
00239     {
00240       cout <<"inputs=" <<inputs<<" values= "<<values<< endl;
00241       if(update)
00242       {
00243         this->Update(false);
00244       }
00245     }
00246   
00247   template <typename T, int _nx, int _nu, int _np, int _ng, typename Tz, int _nz, typename T1, int _nx1> 
00248     GnDoep1<T, _nx, _nu, _np, _ng, Tz, _nz, T1, _nx1>::~GnDoep1()
00249     {
00250       delete lm;
00251       delete numDiff;
00252       delete functor;
00253     }  
00254   
00255   template <typename T, int _nx, int _nu, int _np, int _ng, typename Tz, int _nz, typename T1, int _nx1> 
00256     void GnDoep1<T, _nx, _nu, _np, _ng, Tz, _nz, T1, _nx1>::Iterate() {
00257 
00258     if (!lm) {
00259       functor = new GnCost<T, _nx, _nu, _np, _ng, Tz, _nz, T1, _nx1>(inputs, values);
00260       functor->doep = this;
00261       numDiff = new NumericalDiff<GnCost<T, _nx, _nu, _np, _ng, Tz, _nz, T1, _nx1> >(*functor,1e-12);
00262       lm = new LevenbergMarquardt<NumericalDiff<GnCost<T, _nx, _nu, _np, _ng, Tz, _nz, T1, _nx1> > >(*numDiff);
00263 
00264       //Set doep noise to zero redundancy:
00265       for(int i = 0;i<(this->ws.size());i++)
00266         this->ws[i].setZero();
00267 
00268       const int &np = this->sys.P.n;
00269       s = this->p;//Set the system parameters to initial guess
00270     }
00271 
00272     /*
00273     for (int i = 0, k = 0; k < this->us.size(); ++k) {
00274       memcpy(s.data() + i, this->us[k].data(), this->sys.U.n*sizeof(double));
00275       i += this->sys.U.n;
00276     }
00277     */
00278 
00279     //    lm.parameters.maxfev=10000;
00280     info = lm->minimize(s);
00281     
00282     cout <<"info="<<info <<endl;
00283     // check return values
00284     // VERIFY_IS_EQUAL(info, 1);
00285     //   VERIFY_IS_EQUAL(lm.nfev(), 26);
00286   }
00287 }
00288 
00289 #endif