GCOP
1.0
|
00001 #ifndef GCOP_SPLINETPARAM_H 00002 #define GCOP_SPLINETPARAM_H 00003 00004 #include "tparam.h" 00005 #include <unsupported/Eigen/Splines> 00006 00007 namespace gcop { 00008 00009 using namespace std; 00010 using namespace Eigen; 00011 00018 template <typename T, 00019 int nx, 00020 int nu, 00021 int np = Dynamic, 00022 int _ntp = Dynamic> class SplineTparam : public Tparam<T, nx, nu, np, _ntp> { 00023 00024 typedef Matrix<double, nx, 1> Vectornd; 00025 typedef Matrix<double, nu, 1> Vectorcd; 00026 typedef Matrix<double, nx, nx> Matrixnd; 00027 typedef Matrix<double, nx, nu> Matrixncd; 00028 typedef Matrix<double, nu, nx> Matrixcnd; 00029 typedef Matrix<double, nu, nu> Matrixcd; 00030 00031 typedef Matrix<double, np, 1> Vectormd; 00032 00033 typedef Matrix<double, _ntp, 1> Vectorntpd; 00034 00035 typedef Spline<double, nu> ControlSpline; 00036 00037 public: 00043 SplineTparam(System<T, nx, nu, np> &sys, const VectorXd tks, int degree = 2);//By default use quadratic spline 00044 00045 bool To(Vectorntpd &s, 00046 const vector<double> &ts, 00047 const vector<T> &xs, 00048 const vector<Vectorcd> &us, 00049 const Vectormd *p = 0); 00050 00051 bool From(vector<double> &ts, 00052 vector<T> &xs, 00053 vector<Vectorcd> &us, 00054 const Vectorntpd &s, 00055 Vectormd *p = 0); 00056 00057 VectorXd tks; 00058 double tf; 00059 int degree; 00060 }; 00061 00062 template <typename T, int nx, int nu, int np, int _ntp> 00063 SplineTparam<T, nx, nu, np, _ntp>::SplineTparam(System<T, nx, nu, np> &sys, const VectorXd tks, int degree) : Tparam<T, nx, nu, np, _ntp>(sys, tks.size()*sys.U.n), tks(tks), degree(degree) { 00064 //normalize tks from 0 to 1 00065 assert(tks.size() > degree+1);//Make sure there are enough points 00066 tf = this->tks(tks.size()-1);//Last element 00067 //Assuming increasing order normalize so that last element is 1.0: 00068 (this->tks) /= tf; 00069 this->tks(tks.size()-1) = 1.0;//Redundancy 00070 cout<<"tks: "<<tks.transpose()<<endl; 00071 } 00072 00073 template <typename T, int nx, int nu, int np, int _ntp> 00074 bool SplineTparam<T, nx, nu, np, _ntp>::To(Vectorntpd &s, 00075 const vector<double> &ts, 00076 const vector<T> &xs, 00077 const vector<Vectorcd> &us, 00078 const Vectormd *p) { 00079 //Find control points(uks) given us 00080 int m = degree + 1 + tks.size();//Number of knots 00081 int nofsegments = m - 2*(degree+1)+1; 00082 assert(nofsegments > 0); 00083 //Create knot vector: 00084 VectorXd knotVector(m); 00085 KnotAveraging(tks, degree, knotVector); 00086 //cout<<"knotvector: "<<knotVector.transpose()<<endl; 00087 //cout<<"tks: "<<tks.transpose()<<endl; 00088 00089 //Initialize variables for least square fit; Fitting each control dimension separately 00090 MatrixXd A(us.size(), tks.size());//Basis Matrix 00091 MatrixXd Asquare(tks.size(), tks.size());//Basis Matrix 00092 VectorXd c(us.size());//RHS 00093 A.setZero();//Initialize A 00094 //VectorXd b(tks.size());//control points 00095 00096 //Find Basis Matrix to find the control points: 00097 double tdiff = ts.back() - ts.front(); 00098 for(int ind = 0;ind < us.size(); ind++) 00099 { 00100 double ts_normalized = (ts[ind] - ts[0])/tdiff; 00101 int index = ControlSpline::Span(ts_normalized, degree, knotVector); 00102 VectorXd basisFcns = ControlSpline::BasisFunctions(ts_normalized, degree, knotVector); 00103 // cout<<"Index: "<<index<<endl; 00104 //cout<<"BasisFcns: "<<basisFcns.transpose()<<endl; 00105 A.block(ind, index-degree, 1, degree+1) = basisFcns.transpose();//Create Basis Matrix 00106 } 00107 Asquare = (A.transpose()*A); 00108 //cout<<"A: "<<endl<<A<<endl; 00109 //cout<<"Asquare: "<<endl<<Asquare<<endl; 00110 //getchar(); 00111 for(int ind = 0; ind < nu; ind++) 00112 { 00113 for(int uind = 0; uind < us.size(); uind++) 00114 { 00115 c(uind) = us[uind](ind); 00116 } 00117 VectorXd b = Asquare.ldlt().solve(A.transpose()*c); 00118 cout<<"Error: "<<(A*b - c).squaredNorm()<<endl; 00119 // cout<<"c: "<<c.transpose()<<endl; 00120 //cout<<"b: "<<b.transpose()<<endl; 00121 //Copy the elements back into vector s: 00122 for(int sind = 0; sind < tks.size(); sind++) 00123 { 00124 s(sind*nu + ind) = b(sind); 00125 } 00126 } 00127 cout<<"s: "<<s.transpose()<<endl; 00128 //Verify if this s is good: 00129 /*{ 00130 MatrixXd controlMatrix(this->sys.U.n, tks.size()); 00131 for(int cs = 0; cs < tks.size(); cs++) 00132 { 00133 controlMatrix.col(cs) = s.segment(cs*nu, nu);//Fill Control Matrix 00134 } 00135 ControlSpline cspline = SplineFitting<ControlSpline>::Interpolate(controlMatrix, degree, tks); 00136 for (int i = 0; i < us.size(); ++i) { 00137 Vectorcd usbar = cspline((ts[i] - ts[0])/tdiff); 00138 cout<<"us_pred["<<i<<"]: "<<usbar.transpose()<<"ts: "<<ts[i]<<endl; 00139 cout<<"us_actual["<<i<<"]: "<<us[i].transpose()<<"ts: "<<ts[i]<<endl; 00140 } 00141 getchar(); 00142 } 00143 */ 00144 00145 //s.setZero(); 00146 return true; 00147 } 00148 00149 template <typename T, int nx, int nu, int np, int _ntp> 00150 bool SplineTparam<T, nx, nu, np, _ntp>::From(vector<double> &ts, 00151 vector<T> &xs, 00152 vector<Vectorcd> &us, 00153 const Vectorntpd &s, 00154 Vectormd *p) { 00155 00156 00157 assert(this->ntp == tks.size()*this->sys.U.n); 00158 00159 //Create knot matrix: 00160 MatrixXd controlMatrix(this->sys.U.n, tks.size()); 00161 for(int cs = 0; cs < tks.size(); cs++) 00162 { 00163 controlMatrix.col(cs) = s.segment(cs*nu, nu);//Fill Control Matrix 00164 } 00165 //cout<<"s: "<<s.transpose()<<endl;//Input control points 00166 //cout<<"Control Matrix: "<<endl<<controlMatrix<<endl; 00167 ControlSpline cspline = SplineFitting<ControlSpline>::Interpolate(controlMatrix, degree, tks); 00168 double tdiff = ts.back() - ts.front(); 00169 00170 this->sys.Reset(xs[0],ts[0]); 00171 for (int i = 0; i < us.size(); ++i) { 00172 us[i] = cspline((ts[i] - ts[0])/tdiff); 00173 //cout<<"ts["<<i<<"]: "<<ts[i]<<endl; 00174 //cout<<"us["<<i<<"]: "<<us[i].transpose()<<"ts: "<<ts[i]<<endl; 00175 this->sys.Step(xs[i+1], us[i], ts[i+1] - ts[i], p); 00176 //cout<<"Xs["<<(i+1)<<"]"<<xs[i+1].transpose()<<endl; #DEBUG 00177 //cout<<"us["<<i<<"]"<<us[i].transpose()<<endl; 00178 } 00179 //getchar(); 00180 return true; 00181 } 00182 } 00183 00184 #endif