MAGIKS  1.1
Manipulator General Inverse Kinematic Solver
 All Classes Namespaces Files Functions Variables Pages
polynomials.py
Go to the documentation of this file.
1 ## @file polynomials.py
2 # @brief This module provides everything you need to work with polynomials
3 # including tools by which you can fit a curve through a set of points.
4 # @author Nima Ramezani Taghiabadi
5 #
6 # PhD Researcher
7 # Faculty of Engineering and Information Technology
8 # University of Technology Sydney (UTS)
9 # Broadway, Ultimo, NSW 2007, Australia
10 # Phone No. : 04 5027 4611
11 # Email(1) : nima.ramezani@gmail.com
12 # Email(2) : Nima.RamezaniTaghiabadi@uts.edu.au
13 # @version 4.0
14 #
15 # start date: February 2011
16 # Last Revision: 03 January 2015
17 
18 silent = True
19 
20 import math, numpy, sys
21 import general_python as genpy
22 
23 class Point(object):
24  def __init__(self, t = 0.0, x = 0.0, v = None, a = None):
25  self.t = t
26  self.x = x
27  self.v = v
28  self.a = a
29 
30  def __str__( self ):
31  s = "Scalar point:" + '\n'
32  s += "t = " + str(self.t) + '\n'
33  s += "x = " + str(self.x) + '\n'
34  s += "v = " + str(self.v) + '\n'
35  s += "a = " + str(self.a) + '\n'
36  return s
37 
38  def count_constraints(self):
39  nc = 0
40  if self.x != None:
41  nc = nc + 1
42  if self.v != None:
43  nc = nc + 1
44  if self.a !=None:
45  nc = nc + 1
46  return nc
47 
48 class Polynomial(object):
49  '''
50  '''
51  def __init__(self, degree = 0):
52  self.degree = degree
53  self.coeff = numpy.zeros(self.degree + 1)
54 
55  def interpolate_smart(self, points):
56  n = len(points)
57  m = 0
58  for p in points:
59  m = m + p.count_constraints()
60 
61  self.degree = m - 1
62  A = numpy.zeros((m,m))
63  i = 0
64  u = numpy.array([])
65  for p in points:
66  if p.x != None:
67  A[i, 0] = 1
68  for j in range(1, m):
69  A[i, j] = A[i, j-1]*p.t
70  i = i + 1
71  u = numpy.append(u, p.x)
72 
73  if p.v != None:
74  A[i, 0] = 0.0
75  A[i, 1] = 1.0
76  for j in range(2, m):
77  A[i, j] = j*(p.t**(j-1))
78  i = i + 1
79  u = numpy.append(u, p.v)
80 
81  if p.a != None:
82  A[i, 0:2] = 0.0
83  A[i, 2] = 2.0
84  for j in range(3, m):
85  A[i, j] = j*(j-1)*(p.t**(j-2))
86  i = i + 1
87  u = numpy.append(u, p.a)
88 
89  try:
90  self.coeff = numpy.dot(numpy.linalg.inv(A), u)
91  except:
92  print genpy.err_str(__name__, self.__class__.__name__, sys._getframe().f_code.co_name, 'The matrix of coefficients is singular')
93  print "Matrix of coefficients:"
94  print A
95  print
96  print "Determinent = ", numpy.linalg.det(A)
97  print
98  assert False
99 
100  def interpolate(self, t, u, v = []):
101  '''
102  Generates the coefficients of a spline passing through key positions and velocities specified by u and v at corresponding t
103  t, u, v must have the same length
104  if v is not specified (keep the default), only positions are considered
105  '''
106  n = len(t)
107  nu = len(u)
108  nv = len(v)
109  assert n == nu
110 
111  if (nv == 0):
112  self.degree = n - 1
113  A = numpy.zeros((n,n))
114  for i in range(n):
115  A[i, 0] = 1.0
116  for j in range(1, n):
117  A[i, j] = A[i, j-1]*t[i]
118 
119  self.coeff = numpy.dot(numpy.linalg.inv(A), u)
120  elif (nv == n):
121  self.degree = 2*n - 1
122  A = numpy.zeros((2*n, 2*n))
123  for i in range(n):
124  A[i, 0] = 1.0
125  A[n+i, 0] = 0.0
126  A[n+i, 1] = 1.0
127  for j in range(1, 2*n):
128  A[i, j] = A[i, j-1]*t[i]
129  A[n + i, j] = j*(t[i]**(j-1))
130 
131  self.coeff = numpy.dot(numpy.linalg.inv(A), numpy.append(u, v))
132  else:
133  print "Error: Size of input vector v is different from t and u"
134 
135  def position(self, t):
136  '''
137  Returns the value of the polynomial at time t
138  '''
139  n = self.degree + 1
140  s = self.coeff[0]
141  for i in range(1,n):
142  s = s + self.coeff[i]*(t**i)
143 
144  return(s)
145 
146  def velocity(self, t):
147  '''
148  Returns the derivative of the polynomial at time t
149  '''
150  n = self.degree
151  if n < 1:
152  v = 0.0
153  else:
154  v = self.coeff[1]
155  for i in range(1, n):
156  v = v + (i+1)*self.coeff[i+1]*(t**i)
157  return(v)
158 
159  def acceleration(self, t):
160  '''
161  Returns the derivative of the polynomial at time t
162  '''
163  n = self.degree - 1
164  if n < 2:
165  a = 0.0
166  else:
167  a = 2*self.coeff[2]
168  for i in range(1, n):
169  a = a + (i+1)*(i+2)*self.coeff[i+2]*(t**i)
170  return(a)
171 
173  '''
174  A polynomial of degree three in the form:
175 
176  f(t) = a * t + b
177 
178  the coefficients are: a, b
179 
180  each coefficient can be n-element vector or matrix (or a multi-dimensional numpy array)
181 
182  '''
183 
184  def __init__(self):
185  self.a = 0.0
186  self.b = 0.0
187 
188  def find_coefficients(self, total_time, start_position, end_position,start_velocity, end_velocity):
189  '''
190  returns two coefficients of a linear polynomial which generates position as a function of time according to the given boundary conditions as
191  the coefficients are: a, b
192  property "total_time" indicates the total time of motion
193  each coefficient is a n-element vector (numpy array)
194 
195  f(t) = a * t + b
196 
197  the output of the polynomial has the same structure of the coefficients
198 
199  '''
200 
201  n = len(start_position)
202 
203  B = numpy.zeros(2)
204 
205  assert len(end_position) == n
206 
207  self.b = start_position
208  self.a = (end_position - start_position) / total_time
209 
210  def interpolated_position(self, t):
211  '''
212  return "f(t)" at time: "t"
213  where:
214 
215  f(t) = a * t + b
216 
217  coefficients a, b can be any vector or multi-dimensional numpy array
218  the output has the same structure of the coefficients
219 
220  '''
221 
222  pos = self.a*t + self.b
223 
224  return pos
225 
227  '''
228  A polynomial of degree three in the form:
229 
230  f(t) = a * t^2 + b * t + c
231 
232  the coefficients are: a, b, c
233 
234  each coefficient can be n-element vector or matrix (or a multi-dimensional numpy array)
235 
236  '''
237 
238  def __init__(self):
239  self.a = 0.0
240  self.b = 0.0
241  self.c = 0.0
242 
243  def find_coefficients(self, total_time, start_position, end_position,start_velocity, end_velocity):
244  '''
245  returns two coefficients of a linear polynomial which generates position as a function of time according to the given boundary conditions as
246  the coefficients are: a, b, c
247  property "total_time" indicates the total time of motion
248  each coefficient is a n-element vector (numpy array)
249 
250  f(t) = a * t^2 + b * t + c
251 
252  the output of the polynomial has the same structure of the coefficients
253 
254  '''
255 
256  n = len(start_position)
257 
258  B = numpy.zeros(2)
259 
260  assert len(end_position) == n
261 
262  self.c = numpy.copy(start_position)
263  self.b = numpy.copy(start_velocity)
264  self.a = (end_position - self.c - self.b*total_time)/(total_time**2)
265 
266  def interpolated_position(self, t):
267  '''
268  return "f(t)" at time: "t"
269  where:
270 
271  f(t) = a * t^2 + b * t + c
272 
273  coefficients a, b can be any vector or multi-dimensional numpy array
274  the output has the same structure of the coefficients
275 
276  '''
277 
278  pos = self.a*(t**2) + self.b*t + self.c
279 
280  return pos
281 
282 
284  '''
285  A polynomial of degree three in the form:
286 
287  f(t) = a * t^3 + b * t^2 + c * t + d
288 
289  the coefficients are: a, b, c, d
290 
291  each coefficient can be n-element vector or matrix (or a multi-dimensional numpy array)
292 
293  '''
294 
295  def __init__(self):
296  self.a = 0.0
297  self.b = 0.0
298  self.c = 0.0
299  self.d = 0.0
300 
301  def find_coefficients(self, total_time, start_position, end_position, start_velocity, end_velocity):
302  '''
303  returns four coefficients of a polynomial of third degree which generates position as a function of time according to the given boundary conditions as
304  the coefficients are: a, b, c, d
305  property "total_time" indicates the total time of motion
306  each coefficient is a n-element vector (numpy array)
307 
308  f(t) = a * t^3 + b * t^2 + c * t + d
309 
310  the output of the polynomial has the same structure of the coefficients
311 
312  '''
313 
314  n = len(start_position)
315 
316  B = numpy.zeros(2)
317 
318  assert len(end_position) == n
319  assert len(start_velocity) == n
320  assert len(end_velocity) == n
321 
322  self.d = start_position
323  self.c = start_velocity
324 
325  self.a = numpy.zeros(n)
326  self.b = numpy.zeros(n)
327 
328  t2 = total_time ** 2
329 
330  T = numpy.array([[total_time*t2, t2],[3*t2, 2*total_time]])
331  Tinv = numpy.linalg.inv(T)
332 
333  for j in range(0,n):
334 
335  B[0] = end_position[j] - self.c[j]*total_time - self.d[j]
336  B[1] = end_velocity[j] - self.c[j]
337 
338  X = numpy.dot(Tinv,B)
339 
340  self.a[j] = X[0]
341  self.b[j] = X[1]
342 
343 
344  def interpolated_position(self, t):
345  '''
346  return "f(t)" at time: "t"
347  where:
348 
349  f(t) = a * t^3 + b * t^2 + c * t + d
350 
351  coefficients a, b, c, d are given via "coeff" and can be any vector or multi-dimensional numpy array
352  the output has the same structure of the coefficients
353 
354  '''
355  t2 = t*t
356  pos = self.a*t*t2 + self.b*t2 + self.c*t + self.d
357 
358  return pos
359 
361  '''
362  return the derivateve of "f(t)" at time: "t"
363  where:
364 
365  f(t) = a * t^3 + b * t^2 + c * t + d
366  f'(t) = 3 * a * t^2 + 2 * b * t + c
367 
368  coefficients a, b, c, d are given via "coeff" and can be any vector or multi-dimensional numpy array
369  the output has the same structure of the coefficients. (Obviously coefficient "d" is not used)
370  '''
371 
372  vel = 3*self.a*t*t + 2*self.b*t + self.c
373 
374  return vel
375 
376 """
377 def interpolate_polynomial(A,X,Y):
378 
379  '''
380  #This function is not complete#
381 
382  A : numpy array of n+1 elements
383  X : numpy array of m elements
384  Y : numpy array of m elements
385 
386 
387  This function assigns coefficients a_0 to a_n so that polynomial defined as:
388 
389  f(x) = a_0 + a_1*x + a_2*x^2 + a_3*x^3 + ... + a_n*x^n
390 
391  fits through points (x_1,y_1) , (x_2,y_2) , ... , (x_m,y_m)
392 
393  The procedures follows three different algorythms in three different possible states:
394 
395  1) m > n :
396 
397  It is not possible to define n degree polynomial to exactly pass through m points,
398  but it is possible to calculate coefficients of n degree polynomial with a minimum
399  sum of squares of distances between the function and the given points.
400 
401  Cost function:
402 
403  J = Sigma_{i=0}^{m}{(y_i-f(x_i))^2}
404 
405  For example:
406 
407  A very special case is n=1 when this function returns coefficients of regression line
408 
409  2) m = n :
410 
411  The problem has only one solution. Only one n degree polynomial can be defined passing exactly through
412  the given points. This function returns the coefficients of this function.
413 
414  3) m < n :
415 
416  Unlimited number of functions can be found to pass exactly through the given points. This
417  function selects only one of these solutions so that sum of squares of its coefficients is minimized.
418 
419  Cost function :
420 
421  J = Sigma_{i=0}^{n}{a_i^2}
422 
423 
424  '''
425  m = X.size
426  n = A.size
427 
428  print "m = ", m
429  print "n = ", n
430 
431 """