GCOP
1.0
|
00001 #ifndef GCOP_UNIFORMSPLINETPARAM_H 00002 #define GCOP_UNIFORMSPLINETPARAM_H 00003 00004 #include "tparam.h" 00005 00006 namespace gcop { 00007 00008 using namespace std; 00009 using namespace Eigen; 00010 00023 template <typename T, 00024 int nx, 00025 int nu, 00026 int np = Dynamic> class UniformSplineTparam : public Tparam<T, nx, nu, np> { 00027 00028 typedef Matrix<double, nx, 1> Vectornd; 00029 typedef Matrix<double, nu, 1> Vectorcd; 00030 typedef Matrix<double, nx, nx> Matrixnd; 00031 typedef Matrix<double, nx, nu> Matrixncd; 00032 typedef Matrix<double, nu, nx> Matrixcnd; 00033 typedef Matrix<double, nu, nu> Matrixcd; 00034 00035 typedef Matrix<double, np, 1> Vectormd; 00036 00037 public: 00038 UniformSplineTparam(System<T, nx, nu, np> &sys, const VectorXd &tks, int degree = 2);//By default use quadratic spline 00039 00040 bool To(VectorXd &s, 00041 const vector<double> &ts, 00042 const vector<T> &xs, 00043 const vector<Vectorcd> &us, 00044 const Vectormd *p = 0); 00045 00046 bool From(vector<double> &ts, 00047 vector<T> &xs, 00048 vector<Vectorcd> &us, 00049 const VectorXd &s, 00050 Vectormd *p = 0); 00051 00052 const VectorXd &tks; 00053 int degree; //Degree of the spline // p = (m - n - 1) where m is knot vector size; n is the control vector size (tks size) 00054 00055 //Basis Function: 00056 void FindBasis(VectorXd &basis, double u) 00057 { 00058 assert((u <=1) && (u>=0)); 00059 assert(degree <= 4 && degree>=1);//I only have closed form solution for basis from Wiki http://www.wikiwand.com/en/Irwin%E2%80%93Hall_distribution#/Special_cases 00060 //Can put an assert for basis size not doing right now 00061 //In general it is easy to use deboor algorithm to find the basis for any n. 00062 double x; 00063 switch(degree) 00064 { 00065 case 1: 00066 basis[1] = u; 00067 x = 1+u; 00068 basis[0] = 2-x; 00069 break; 00070 case 2: 00071 basis[2] = 0.5*u*u; 00072 x = 1+u; 00073 basis[1] = 0.5*(-2*x*x + 6*x -3); 00074 x = 2+u; 00075 basis[0] = 0.5*(x*x - 6*x +9); 00076 break; 00077 case 3: 00078 basis[3] = (1.0/6.0)*u*u*u; 00079 x = 1+u; 00080 basis[2] = (1.0/6.0)*(-3*x*x*x + 12*x*x -12*x + 4); 00081 x = 2+u; 00082 basis[1] = (1.0/6.0)*(3*x*x*x - 24*x*x +60*x - 44); 00083 x = 3+u; 00084 basis[0] = (1.0/6.0)*(-1*x*x*x + 12*x*x -48*x +64); 00085 break; 00086 case 4: 00087 basis[4] = (1.0/24.0)*u*u*u*u; 00088 x = 1+u; 00089 basis[3] = (1.0/24.0)*(-4*x*x*x*x +20*x*x*x - 30*x*x + 20*x -5); 00090 x = 2+u; 00091 basis[2] = (1.0/24.0)*(6*x*x*x*x -60*x*x*x + 210*x*x - 300*x +155); 00092 x = 3+u; 00093 basis[1] = (1.0/24.0)*(-4*x*x*x*x +60*x*x*x - 330*x*x + 780*x -655); 00094 x = 4+u; 00095 basis[0] = (1.0/24.0)*(x*x*x*x -20*x*x*x + 150*x*x - 500*x +625); 00096 break; 00098 } 00099 } 00100 }; 00101 00102 template <typename T, int nx, int nu, int np> 00103 UniformSplineTparam<T, nx, nu, np>::UniformSplineTparam(System<T, nx, nu, np> &sys, const VectorXd &tks, int degree) : Tparam<T, nx, nu, np>(sys, (tks.size()+degree-1)*(sys.U.n)),degree(degree), tks(tks) { 00104 00105 assert(tks.size() >=2);//atleast 1 segments for which above constructor size is valid 00106 cout<<"Degree: "<<degree<<endl; 00107 00108 cout<<"tks: "<<tks.transpose()<<endl; 00109 } 00110 00111 template <typename T, int nx, int nu, int np> 00112 bool UniformSplineTparam<T, nx, nu, np>::To(VectorXd &s, 00113 const vector<double> &ts, 00114 const vector<T> &xs, 00115 const vector<Vectorcd> &us, 00116 const Vectormd *p) { 00117 //Find control points(uks) given us 00118 int nofcontrolpoints = (degree + this->tks.size() - 1); 00119 int tks_index = 0; 00120 00121 //Initialize variables for least square fit; Fitting each control dimension separately 00122 MatrixXd A(us.size(), nofcontrolpoints);//Basis Matrix 00123 MatrixXd Asquare(nofcontrolpoints, nofcontrolpoints);//Basis Matrix 00124 VectorXd c(us.size());//RHS 00125 A.setZero();//Initialize A 00126 VectorXd basis(degree+1); 00127 00128 //Find Basis Matrix to find the control points: 00129 for(int ind = 0;ind < us.size(); ind++) 00130 { 00131 //Find the region in which ts[i] lies: 00132 if(tks_index < (tks.size()-1)) 00133 while((ts[ind] - tks[tks_index+1])>1e-17) 00134 tks_index +=1; 00135 //tks_index = (ts[ind] - tks[tks_index+1])<-1e-17?tks_index:(tks_index+1);//1e-17 so that it considers numerical accuracy 00136 //Find the Basis for the normalized coordinate: 00137 //cout<<"index: "<<tks_index<<endl; 00138 double u = (ts[ind] - tks[tks_index])/(tks[tks_index+1] - tks[tks_index]); 00139 //cout<<"tks["<<(tks_index)<<"]: "<<tks[tks_index]<<"\t"<<tks[tks_index+1]<<endl; 00140 //cout<<"ts: "<<ts[ind]<<endl; 00141 //cout<<"u: "<<u<<endl; 00142 FindBasis(basis, u); 00143 A.block(ind, tks_index, 1, degree+1) = basis.transpose();//Create Basis Matrix 00144 } 00145 //Asquare = (A.transpose()*A); 00146 //cout<<"A: "<<endl<<A<<endl; 00147 //cout<<"Asquare: "<<endl<<Asquare<<endl; 00148 //getchar(); 00149 for(int ind = 0; ind < nu; ind++) 00150 { 00151 for(int uind = 0; uind < us.size(); uind++) 00152 { 00153 c(uind) = us[uind](ind); 00154 } 00155 Asquare = A.transpose()*A;//Weighted matrix 00156 VectorXd b = Asquare.ldlt().solve(A.transpose()*c); 00157 cout<<"Error: "<<(A*b - c).squaredNorm()<<endl; 00158 // cout<<"c: "<<c.transpose()<<endl; 00159 //cout<<"b: "<<b.transpose()<<endl; 00160 //Copy the elements back into vector s: 00161 for(int sind = 0; sind < nofcontrolpoints; sind++) 00162 { 00163 s(sind*nu + ind) = b(sind); 00164 } 00165 } 00166 cout<<"s: "<<s.transpose()<<endl; 00167 //getchar(); 00168 //Verify if this s is good: 00169 /* 00170 { 00171 tks_index = 0; 00172 Vectorcd usi; 00173 for (int i = 0; i < us.size(); ++i) { 00174 //Find the region in which ts[i] lies: 00175 if(tks_index < (tks.size()-1)) 00176 tks_index = (ts[i] - tks[tks_index+1])<-1e-17?tks_index:(tks_index+1); 00177 //Find the Basis for the normalized coordinate: 00178 double u = (ts[i] - tks[tks_index])/(tks[tks_index+1] - tks[tks_index]); 00179 FindBasis(basis, u); 00180 usi.setZero(); 00181 //Weight the spline using the basis: 00182 for(int degree_count = 0; degree_count <= degree; degree_count++) 00183 { 00184 usi += basis[degree_count]*s.segment((tks_index+degree_count)*nu,nu); 00185 } 00186 cout<<"Basis: "<<basis.transpose()<<endl; 00187 00188 cout<<"us_pred["<<i<<"]: "<<usi.transpose()<<"us_act: "<<us[i].transpose()<<endl; 00189 } 00190 } 00191 getchar(); 00192 */ 00193 00194 //s.setZero(); 00195 return true; 00196 } 00197 00198 template <typename T, int nx, int nu, int np> 00199 bool UniformSplineTparam<T, nx, nu, np>::From(vector<double> &ts, 00200 vector<T> &xs, 00201 vector<Vectorcd> &us, 00202 const VectorXd &s, 00203 Vectormd *p) { 00204 assert(s.size() == (degree + this->tks.size() - 1)*(this->sys.U.n)); 00205 00206 this->sys.Reset(xs[0],ts[0]); 00207 int tks_index = 0; 00208 VectorXd basis(degree+1); 00209 Vectorcd usi; 00210 for (int i = 0; i < us.size(); ++i) { 00211 //Find the region in which ts[i] lies: 00212 if(tks_index < (tks.size()-1)) 00213 while((ts[i] - tks[tks_index+1])>1e-17) 00214 tks_index +=1; 00215 //tks_index = (ts[i] - tks[tks_index+1])<-1e-17?tks_index:(tks_index+1); 00216 //Find the Basis for the normalized coordinate: 00217 double u = (ts[i] - tks[tks_index])/(tks[tks_index+1] - tks[tks_index]); 00218 FindBasis(basis, u); 00219 us[i].setZero(); 00220 //Weight the spline using the basis: 00221 for(int degree_count = 0; degree_count <= degree; degree_count++) 00222 { 00223 //us[i] += basis[degree_count]*s.segment((tks_index+degree_count)*(this->sys.U.n), this->sys.U.n); 00224 us[i] += basis[degree_count]*s.segment((tks_index+degree_count)*nu,nu); 00225 } 00226 00227 // cout<<"ts["<<i<<"]: "<<ts[i]<<endl; 00228 //cout<<"us["<<i<<"]: "<<us[i].transpose()<<"ts: "<<ts[i]<<endl; 00229 this->sys.Step(xs[i+1], us[i], ts[i+1] - ts[i], p); 00230 //cout<<"Xs["<<(i+1)<<"]"<<xs[i+1].transpose()<<endl;//#DEBUG 00231 //cout<<"us["<<i<<"]"<<us[i].transpose()<<endl; 00232 } 00233 return true; 00234 //getchar(); 00235 } 00236 } 00237 00238 #endif