Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00042 #include "dmp/radial_approx.h"
00043 #include<stdio.h>
00044 using namespace Eigen;
00045 using namespace std;
00046 
00047 namespace dmp{
00048 
00049 RadialApprox::RadialApprox(int num_bases, double base_width, double alpha)
00050 {
00051         n_bases = num_bases;
00052         features = new double[n_bases];
00053         centers = new double[n_bases];
00054         widths = new double[n_bases];
00055         weights.resize(n_bases);
00056         for(int i=0; i<n_bases; i++){
00057                 features[i] = 0;
00058                 centers[i] = exp((-alpha*i)/n_bases);
00059                 widths[i] = base_width * (1/exp((-alpha*i)/n_bases));
00060         }
00061 }
00062 
00063 
00064 RadialApprox::RadialApprox(const vector<double> &w, double base_width, double alpha)
00065 {
00066         weights = w;
00067         n_bases = w.size();
00068         features = new double[n_bases];
00069                 centers = new double[n_bases];
00070                 widths = new double[n_bases];
00071                 for(int i=0; i<n_bases; i++){
00072                         features[i] = 0;
00073                         centers[i] = ((double)i)/((double)n_bases);  
00074                         widths[i] = base_width; 
00075                 }
00076 }
00077 
00078 
00079 RadialApprox::~RadialApprox()
00080 {
00081         delete[] features;
00082         delete[] centers;
00083         delete[] widths;
00084 }
00085 
00086 
00087 double RadialApprox::evalAt(double x)
00088 {
00089         calcFeatures(x);
00090 
00091         double wsum = 0;
00092         for(int i=0; i<n_bases; i++){
00093                 wsum += features[i] * weights[i];
00094         }
00095         return wsum;
00096 }
00097 
00098 
00099 void RadialApprox::leastSquaresWeights(double *X, double *Y, int n_pts)
00100 {
00101         MatrixXd D_mat = MatrixXd(n_pts,n_bases);
00102         MatrixXd Y_mat = MatrixXd(n_pts,1);
00103 
00104         
00105         for(int i=0; i<n_pts; i++){
00106                 Y_mat(i,0) = Y[i];
00107                 calcFeatures(X[i]);
00108                 for(int j=0; j<n_bases; j++){
00109                         D_mat(i,j) = features[j];
00110                 }
00111         }
00112 
00113         
00114         MatrixXd w = pseudoinverse(D_mat.transpose() * D_mat) * D_mat.transpose() * Y_mat;
00115         for(int i=0; i<n_bases; i++){
00116                 weights[i] = w(i,0);
00117         }
00118 }
00119 
00120 
00121 void RadialApprox::calcFeatures(double x)
00122 {
00123         double sum = 0;
00124         for(int i=0; i<n_bases; i++){
00125                 features[i] = exp(-widths[i]*(x-centers[i])*(x-centers[i]));
00126                 sum += features[i];
00127         }
00128         for(int i=0; i<n_bases; i++){
00129                 features[i] /= sum;
00130         }
00131 }
00132 
00133 
00134 MatrixXd RadialApprox::pseudoinverse(MatrixXd mat){
00135         
00136         double precisionCutoff = 1e-10;
00137 
00138         
00139         JacobiSVD<MatrixXd> svd(mat, ComputeThinU | ComputeThinV);
00140         MatrixXd U = svd.matrixU();
00141         MatrixXd V = svd.matrixV();
00142         MatrixXd S = svd.singularValues();
00143 
00144         
00145         MatrixXd S_plus = MatrixXd::Zero(n_bases, n_bases);
00146         for(int i=0; i<n_bases; i++){
00147                 if(S(i) > precisionCutoff){  
00148                         S_plus(i,i) = 1.0/S(i);
00149                 }
00150         }
00151 
00152         
00153         return V * S_plus * U.transpose();
00154 }
00155 
00156 }
00157 
00158