00001 import roslib; roslib.load_manifest('tabletop_pushing')
00002 import rospy
00003 import numpy as np
00004
00005 class RBFController:
00006 '''
00007 Class to implement an RBF network controller based on PILCO learning for use in control of the robot.
00008 '''
00009
00010 def feedbackControl(self, X):
00011 inp = np.zeros((self.N,self.D))
00012 for r in xrange(self.N):
00013 inp[r,:] = self.X_pi.T[r,:]-X.T
00014
00015 k = None
00016
00017 U = np.zeros((self.E,1))
00018 for i in xrange(self.E):
00019 Lambda = self.lambdas[i]
00020 sf2 = self.sf2s[i]
00021 t = np.matrix(inp)*Lambda
00022 tb = np.sum(np.multiply(t,t),1)/2
00023 l = np.exp(-tb)
00024 lb = np.reshape(np.multiply(l.squeeze(),self.beta[:,i]),(self.N,1))
00025 U[i] = sf2*np.sum(lb)
00026 k_i = 2*self.Hyp[i,self.D]-tb;
00027 if k is None:
00028 k = k_i
00029 else:
00030 k = np.hstack([k, k_i])
00031
00032
00033 S = np.zeros((self.E, self.E))
00034 for i in xrange(self.E):
00035 ii = inp/np.exp(2.*self.Hyp[i,:self.D])
00036 for j in xrange(i+1):
00037 R = np.eye(self.D)
00038 ij = inp/np.exp(2.*self.Hyp[j,:self.D])
00039 L = np.asmatrix(np.exp(k[:,i]+k[:,j].T))
00040 S[i,j] = np.asmatrix(self.beta[:,i])*L*np.asmatrix(self.beta[:,j]).T
00041 S[j,i] = S[i,j]
00042 S[i,i] += 1e-6
00043 S = S - U*U.T
00044
00045
00046 if self.max_U is not None:
00047 F = self.D+self.E
00048 j = range(self.D, F)
00049 M = np.vstack([X, U])
00050 V = np.zeros((F,F))
00051 V[np.ix_(j,j)] = S
00052 return self.gaussian_saturate(M, V, j, self.max_U)
00053 return U
00054
00055 def computeBetaPi(self):
00056 '''
00057 Compute the RBF network weights in GP form
00058 '''
00059 self.beta = np.zeros((self.N, self.E))
00060 self.lambdas = []
00061 self.sf2s = []
00062 for i in xrange(self.E):
00063 Lambda = np.diag(np.exp(-1*self.Hyp[i,:self.D]))
00064 sf2 = np.exp(2*self.Hyp[i,self.D])
00065 sigmaBeta2 = np.exp(2*self.Hyp[i,self.D+1])
00066
00067
00068 inp = self.X_pi.T / np.exp(self.Hyp[i,:self.D]).T
00069 KX = np.exp(2*self.Hyp[i,self.D]-self.maha(inp, inp)/2.)
00070
00071 L = np.linalg.cholesky(KX+sigmaBeta2*np.eye(self.N))
00072 betai = np.linalg.solve(L.T, np.linalg.solve(L, self.Y_pi[:,i]))
00073 self.lambdas.append(Lambda)
00074 self.sf2s.append(sf2)
00075 self.beta[:,i] = betai.squeeze()
00076
00077 def squaredExponentialKernelARD(self, x, c, ell, sf2):
00078 '''
00079 Squared exponential with automatic relavence determination pre-computed parameters 'self.ell_diag'
00080 '''
00081 return sf2*np.exp(-self.squaredDist(ell*x, ell*c)/2)
00082
00083 def squaredExponentialKernel(self, x, c, sf2):
00084 '''
00085 Squared exponential without the length scale hyperparemeters
00086 '''
00087 return sf2*np.exp(-self.squaredDist(x,c)/2)
00088
00089 def squaredDist(self, x1, x2):
00090 '''
00091 Get the squared distance between two vectors
00092 TODO: Make this work for full matrices
00093 '''
00094 xx = x1-x2
00095 xx = np.multiply(xx,xx)
00096 xx = np.sum(xx)
00097 return xx
00098
00099 def maha(self, a, b):
00100 A = np.sum(np.multiply(a,a),1)
00101 B = np.sum(np.multiply(b,b),1)
00102 C = -2*a*b.T
00103 return A + B.T + C
00104
00105 def gaussian_saturate(self, m, v, i, e):
00106 m = np.asmatrix(m)
00107 d = len(m)
00108 I = len(i)
00109 i = np.hstack([i, np.asarray(i)+d])
00110 P = np.asmatrix(np.vstack([np.eye(d), 3.*np.eye(d)]))
00111 m = P*m
00112 e = np.asmatrix(np.hstack([9.*e, e])/8).T
00113 va = P*v*P.T
00114 va = (va+va.T)/2.
00115 vi = va[i][:,i]
00116 vii = np.asmatrix(np.diag(vi)).T
00117 mi = m[i,:]
00118
00119
00120 M2 = np.multiply(np.multiply(e, np.exp(-vii/2)), np.sin(mi));
00121
00122 P = np.asmatrix(np.hstack([np.eye(I), np.eye(I)]))
00123 return P*M2
00124
00125
00126
00127
00128 def loadRBFController(self, controller_path):
00129 '''
00130 Read controller data from disk that was learned by PILCO
00131 '''
00132 M_LINE = 0
00133 N_LINE = 1
00134 E_LINE = 2
00135 D_LINE = 3
00136 MAX_U_LINE = 4
00137 HYP_LINE = 5
00138 TARGET_LINE = 6
00139
00140 rospy.logwarn('controller_path:'+controller_path)
00141 controller_file = file(controller_path,'r')
00142 data_in = controller_file.readlines()
00143 controller_file.close()
00144 M = int(data_in[M_LINE].split()[1])
00145 N = int(data_in[N_LINE].split()[1])
00146 E = int(data_in[E_LINE].split()[1])
00147 D = int(data_in[D_LINE].split()[1])
00148 self.max_U = np.asarray([float(u) for u in data_in[MAX_U_LINE].split()[1:]])
00149 Hyp = np.asarray([float(h) for h in data_in[HYP_LINE].split()])
00150 self.Hyp = np.reshape(Hyp, (E, D+2))
00151 data_in = data_in[TARGET_LINE:]
00152 Y_pi = np.asmatrix([d.split() for d in data_in[:N]],'float')
00153 X_pi = np.asmatrix([d.split() for d in data_in[N:]],'float').T
00154 self.X_pi = X_pi
00155 self.Y_pi = Y_pi
00156 self.N = N
00157 self.D = D
00158 self.E = E
00159
00160 self.computeBetaPi()