23 Changes from previous version:
25 2- smoothed add_point feature added based on finite difference coefficients
26 3- add_point respecs limits for position, velocity, acceleration and jerk
27 4- function draw_points() added.
28 5- function plot_list() added
31 import copy, math, sys, numpy
as np
33 import general_python
as genpy
34 from math_tools
import general_math
as gen
38 all_figures = [
'Position',
'Velocity',
'Acceleration',
'Jerk']
39 all_ltypes = [
'-',
'r--',
'bs',
'g^',
'bo',
'k']
40 all_colors = [
'black',
'blue',
'cyan',
'green',
'red',
'purple',
'orange',
'gray',
'yellow',
'magenta',
42 '#F0E442',
'#8A2BE2',
'#bcbcbc',
'#8b8b8b',
'#b3de69',
'#0072B2',
'#eeeeee',
43 '#6ACC65',
'#ffed6f',
'#FF9F9A',
'#6d904f',
'#FFFEA3',
'0.70'
44 '#FFB5B8',
'#bc82bd',
'#ccebc4',
'#77BEDB',
'#009E73',
'#97F0AA',
'#D65F5F',
45 '.8' ,
'#003FFF',
'#92C6FF',
'#fdb462',
'#FBC15E',
'#8172B2',
'#B47CC7',
46 '#E5E5E5',
'#CC79A7',
'#E24A33',
'#006374',
'#EEEEEE',
'#8EBA42',
'0.40',
47 'w' ,
'#fa8174',
'#55A868',
'#B0E0E6',
'#C44E52',
'#64B5CD',
'#4C72B0',
48 '#D0BBFF',
'#f0f0f0',
'#cbcbcb',
'#C4AD66',
'#03ED3A',
'#467821',
'#00FFCC',
49 '#FFC400',
'#30a2da',
'#988ED5',
'#e5ae38',
'darkgoldenrod',
'#CCB974',
50 '#348ABD',
'0.8' ,
'#feffb3',
'#bfbbd9',
'#555555',
'#8dd3c7',
'#777777',
51 '0.6' ,
'#D55E00',
'#fc4f30',
'#7600A1',
'#00D7FF',
'#4878CF',
'#017517',
52 '#001C7F',
'#B8860B',
'#EAEAF2',
'#E8000B',
'#afeeee',
'#81b1d2',
'#7A68A6',
53 '#8C0900',
'.15' ,
'#A60628',
'#56B4E9']
62 FDC_v = {1:[1.0, - 1.0],
64 3:[11.0/6, - 3.0, 1.5, - 1.0/3],
65 4:[25.0/12, - 4.0, 3.0, - 4.0/3, 0.25 ],
66 5:[137.0/60, - 5.0, 5.0, - 10.0/3, 1.25, - 0.2 ],
67 6:[49.0/20, - 6.0, 7.5, - 20.0/3, 3.75, - 1.2, 1.0/6 ]}
69 FDC_a = {1:[1.0, - 2.0, 1.0],
70 2:[2.0, - 5.0, 4.0, - 1.0 ],
71 3:[35.0/12, - 26.0/3, 9.5, - 14.0/3, 11.0/12],
72 4:[15.0/4, - 77.0/6, 107.0/6, - 13.0, 61.0/12, - 5.0/6 ],
73 5:[203.0/45, - 87.0/5, 117.0/4, - 254.0/9, 33.0/2, - 27.0/5 , 137.0/180],
74 6:[469.0/90, - 22.3, 879.0/20, - 949.0/18, 41.0, - 20.1, 1019.0/180.0, -0.7]}
79 v_max = v_max*math.sqrt(dim)
80 a_max = a_max*math.sqrt(dim)
83 v0 = np.linalg.norm(V0)
84 assert v0 < v_max + r ,
"Inconsistent "
96 if v0*v0 + v*v - 2*vv0 > r*r:
97 theta = trig.arccos(vv0/(v*v0))
98 O = geo2d.Point_2D([- v0, 0.0])
99 cir = geo2d.Circle_2D(R = r)
100 line_V = geo2d.Line_2D(O, theta, representation =
'point-angle')
101 sol = cir.intersection(line_V)
104 a = np.linalg.norm(A)
105 while (v > v_max)
or (a > a_max):
110 v = np.linalg.norm(V)
115 a = np.linalg.norm(A)
118 assert np.linalg.norm(A) < a_max + 0.001
119 assert np.linalg.norm(V) < v_max + 0.001
123 CH = cir.center.perpend_to(line_V)
124 H = line_V.intersection(CH)
129 v_opt = O.dist(sol[0])
150 if gen.equal(o1*o1 + v0*v0 - 2*o1*v0*math.cos(theta) - r*r, 0.0):
158 V = V*min(1.0, vm.feasible_stepsize(direction = V*dt, x = X0, x_min = X_min, x_max = X_max))
164 assert sum(X > X_max) == 0
165 assert sum(X < X_min) == 0
167 assert np.linalg.norm(A) < a_max + 0.001
168 assert np.linalg.norm(V) < v_max + 0.001
174 def feasible_position(Xd, X0, V0, X_min, X_max, v_max, a_max, dt):
176 v0 = np.linalg.norm(V0)
177 assert v0 < v_max + r , "Inconsistent "
181 v = np.linalg.norm(V)
188 if v0*v0 + v*v - 2*vv0 > r*r: # end of vector V is not inside the circle: desired velocity is not feasible
189 print "****************"
191 theta = trig.arccos(vv0/(v*v0))
192 O = geo2d.Point_2D([- v0, 0.0])
193 cir = geo2d.Circle_2D(R = r)
194 line_V = geo2d.Line_2D(O, theta, representation = 'point-angle')
195 sol = cir.intersection(line_V)
197 print "No Intersection: "
198 CH = cir.center.perpend_to(line_V)
199 H = line_V.intersection(CH)
206 print "Two Intersections: "
207 if O.dist(cir.center) > r:
208 print "O outside circle"
210 print "same direction"
211 d1 = abs(O.dist(sol[0]) - v)
212 d2 = abs(O.dist(sol[1]) - v)
214 print 'O.dist(sol[0]) = ', O.dist(sol[0])
215 print 'O.dist(sol[1]) = ', O.dist(sol[1])
217 print "opposite direction"
221 print "I must be zero: ", d1*d1 + v0*v0 + 2*d1*v0*math.cos(theta) - r*r
222 print "I must be zero: ", d2*d2 + v0*v0 + 2*d2*v0*math.cos(theta) - r*r
232 print "O inside circle"
236 if gen.equal(d1*d1 + v0*v0 - 2*d1*v0*math.cos(theta) - r*r, 0.0):
239 print "I must be zero: ", d2*d2 + v0*v0 + 2*d2*v0*math.cos(theta) - r*r
240 print "I must be amax: ", np.linalg.norm( (V*d1/v - V0) /dt)
244 print "I must be zero: ", d1*d1 + v0*v0 + 2*d1*v0*math.cos(theta) - r*r
245 print "I must be amax: ", np.linalg.norm( (V*d2/v - V0) /dt)
248 print "same direction"
250 print "opposite direction"
252 assert cir.possess(sol[0])
253 assert cir.possess(sol[1])
261 a = np.linalg.norm(A)
267 v = np.linalg.norm(V)
270 print "v_max = ", v_max
272 a = np.linalg.norm(A)
275 print "a_max = ", a_max
277 # kh = min(1.0, vm.feasible_stepsize(direction = Xd - X0, x = X0, x_min = X_min, x_max = X_max))
285 if np.dot(V, Xd - X0) > 0.0:
286 print "Belakhare hamjahat shodand: sgn = ", sgn
288 print "Akharesh hamjahat nashodand dadash: sgn = ", sgn
292 def feasible_position(xd, x0, v0, x_min, x_max, v_max, a_max, dt):
294 Ld = np.linalg.norm(d)
295 if gen.equal(Ld, 0.0):
296 return (xd, d, - v0/dt)
300 kh = min(ss, vm.feasible_stepsize(direction = u, x = x0, x_min = x_min, x_max = x_max))
307 delta = betta*betta + a_max*a_max*dt*dt - gamma
312 sqrt_delta = math.sqrt(delta)
313 al = betta - sqrt_delta
314 ah = betta + sqrt_delta
332 La = np.linalg.norm(a)
333 Lv = np.linalg.norm(v)
335 if La > a_max + 0.0001:
336 print La, a_max, 'al: ', al, 'ah: ', ah,'sl: ', sl,'sh: ', sh, 'vh: ', vh, 'delta: ', delta
337 if Lv > v_max + 0.0001:
340 assert Lv <= v_max + 0.0001
343 def feasible_position(xd, x0, v0, x_min, x_max, v_max, a_max, dt):
349 xh = np.minimum(x_max, xh)
350 xl = np.maximum(x_min, xl)
354 if sum(xl > xh) != 0:
355 print "THIS SHOULD NOT HAPPEN *************************************************************************"
359 kh = min(1.0, vm.feasible_stepsize(direction = dr, x = x0, x_min = xl, x_max = xh))
383 Lj = np.linalg.norm(j)
387 j = j*j_max*(1.0 + math.log(Lj/j_max))/Lj
402 Lv = np.linalg.norm(v)
403 La = np.linalg.norm(a)
405 a = a*a_max*(1.0 + math.log(La/a_max))/La
417 Lv = np.linalg.norm(v)
421 v = v*v_max*(1.0 + math.log(Lv/v_max))/Lv
432 genpy.check_type(x, [np.ndarray, list, tuple], __name__,
'', sys._getframe().f_code.co_name,
'x', array_length = [2,3,4,5,6,7,8], shape_length = 2)
448 v0 = np.dot(FDC_v[n - 2], x[1:n])/dt
451 gain = (1.0/math.sqrt(x.shape[1]))
455 a_t = np.dot(ca, x)/dt2
456 v_t = np.dot(cv, x)/dt
457 kh = min(1.0, vm.feasible_stepsize(direction = x[0] - x[1], x = x[1], x_min = x_min, x_max = x_max))
459 La = np.linalg.norm(a_t)*gain
460 Lv = np.linalg.norm(v_t)*gain
461 sa = - np.dot(ca[1:n], x[1:n])
462 sv = - np.dot(cv[1:n], x[1:n])
466 a_t = a_t*a_max*(1.0 + math.log(La/a_max))/La
467 x[0] = (sa + dt2*a_t)/ca[0]
468 v_t = np.dot(cv, x)/dt
469 Lv = np.linalg.norm(v_t)*gain
470 La = np.linalg.norm(a_t)*gain
471 kh = min(1.0, vm.feasible_stepsize(direction = x[0] - x[1], x = x[1], x_min = x_min, x_max = x_max))
472 print "acc changed: ", La, Lv, kh
475 if Lv > v_max: # clamping the vector if higher than maximum
476 v_t = v_t*v_max*(1.0 + math.log(Lv/v_max))/Lv
477 x[0] = (sv + dt*v_t)/cv[0]
478 a_t = np.dot(ca, x)/dt2
479 La = np.linalg.norm(a_t)*gain
480 Lv = np.linalg.norm(v_t)*gain
481 kh = min(1.0, vm.feasible_stepsize(direction = x[0] - x[1], x = x[1], x_min = x_min, x_max = x_max))
483 print "vel changed: ", La, Lv, kh
486 x[0] = x[1] + kh*(x[0] - x[1])
487 v_t = np.dot(cv, x)/dt
488 a_t = np.dot(ca, x)/dt2
489 La = np.linalg.norm(a_t)*gain
494 for j
in range(x.shape[1]):
495 assert (x_t[j] < x_max[j] + 0.0001)
and (x_t[j] > x_min[j] - 0.0001),
"j = " + str(j)
497 return (x_t, v_t, a_t)
500 def plot_list(pathlist, ncol = 1, show_limits = False, show_plot = True):
501 if len(pathlist) == 0:
503 dim = pathlist[0].dim
504 for path
in pathlist:
505 assert dim == path.dim,
"\n Error: All paths must have the same dimensions \n"
507 import matplotlib.pyplot
as plt
512 for i
in range(nrow):
513 for j
in range(ncol):
515 plt.subplot(nrow,ncol,cn + 1)
516 for path
in pathlist:
517 path.draw_points(plt, axis = cn)
519 if path.plot_settings.figure ==
'Position':
520 path.axhline(y = path.pos_max[cn])
521 path.axhline(y = path.pos_min[cn])
522 elif path.plot_settings.figure ==
'Velocity':
523 path.axhline(y = path.vel_max)
524 path.axhline(y = path.vel_min)
525 elif path.plot_settings.figure ==
'Acceleration':
526 path.axhline(y = path.acc_max)
527 path.axhline(y = path.acc_min)
529 assert False, genpy.err_str(__name__, self.__class__.__name__, sys._getframe().f_code.co_name, path.plot_settings.figure +
" is not a valid value for argument figure")
532 plt.ylabel(path.plot_settings.ylabel(cn))
552 assert axis < len(self.
axis_label), genpy.err_str(__name__, self.__class__.__name__, sys._getframe().f_code.co_name, str(axis) +
" is not a valid value for argument axis: Must be lower than dimension")
577 def __init__(self, phi, pos, vel = None, acc = None):
599 s =
"Point Dimension: " + str(self.
dim) +
'\n'
600 s +=
"Phase : " + str(self.
phi) +
'\n'
601 s +=
"Position : " + str(self.
pos) +
'\n'
602 s +=
"Velocity : " + str(self.
vel) +
'\n'
603 s +=
"Acceleration: " + str(self.
acc) +
'\n'
613 def value(self, field_name = 'Position', axis = 0):
614 assert (axis <= self.
dim), genpy.err_str(__name__, self.__class__.__name__, sys._getframe().f_code.co_name,
"Argument axis must not esxeed the space dimension")
615 assert (axis >= 0), genpy.err_str(__name__, self.__class__.__name__, sys._getframe().f_code.co_name,
"Argument axis can not have a negative value")
617 if field_name ==
'Position':
618 return self.
pos[axis]
619 elif field_name ==
'Velocity':
620 return self.
vel[axis]
621 elif field_name ==
'Acceleration':
622 return self.
acc[axis]
624 assert False, genpy.err_str(__name__, self.__class__.__name__, sys._getframe().f_code.co_name, field_name +
" is not not a valid value for argument field_name")
658 s =
"Phase Length : " + str(self.
phi_end) +
'\n'
659 s +=
"Number of Points : " + str(len(self.
point)) +
'\n'
660 s +=
"Segment Starting Point: " +
'\n'
661 s += str(self.
point[0]) +
'\n'
662 s +=
"Segment End Point: " +
'\n'
663 s += str(self.
point[len(self.
point) - 1]) +
'\n'
674 assert n < self.
capacity, genpy.err_str(__name__, self.__class__.__name__, sys._getframe().f_code.co_name,
"The path capacity is full! Can not take more points than its capacity")
677 assert phi >= self.
point[n-1].phi, genpy.err_str(__name__, self.__class__.__name__, sys._getframe().f_code.co_name,
"Given phi is less than the last point's phase")
679 nn = np.array([
None for j
in range(self.
dim)])
680 pos = genpy.check_type(pos, [np.ndarray], __name__, self.__class__.__name__, sys._getframe().f_code.co_name,
'pos', array_length = self.
dim, default = np.copy(nn))
681 vel = genpy.check_type(vel, [np.ndarray], __name__, self.__class__.__name__, sys._getframe().f_code.co_name,
'vel', array_length = self.
dim, default = np.copy(nn))
682 acc = genpy.check_type(acc, [np.ndarray], __name__, self.__class__.__name__, sys._getframe().f_code.co_name,
'acc', array_length = self.
dim, default = np.copy(nn))
684 self.point.append(
Key_Point(phi, pos, vel, acc))
693 n_pnt = len(self.
point)
695 dist = np.zeros(n_pnt - 1)
696 for i
in range(n_pnt - 1):
697 dist[i] = np.linalg.norm(self.
point[i+1].pos - self.
point[i].pos)
700 assert False, genpy.err_str(__name__, self.__class__.__name__,
'points_dist',
'The segment must have at least two key points')
705 npnt = len(self.
point)
712 assert point_number < self.
npoint,
"Argument point_number must be smaller than self.npoint"
713 return self.
point[point_number]
719 assert phi <= self.
phi_end, genpy.err_str(__name__, self.__class__.__name__,
'set_phi',
'Given phi (' + str(phi) +
') is greater than the phase of the last key point (' + str(self.
phi_end) +
')')
720 assert len(self.
point) > 1, genpy.err_str(__name__, self.__class__.__name__,
'value',
'Can not change the phase when there are less than two key points!')
724 for j
in range(self.
dim):
725 if (self.
point[i].pos[j] !=
None)
and (self.
point[i-1].pos[j] !=
None):
730 if (self.
point[i].vel[j] !=
None)
and (self.
point[i-1].vel[j] !=
None):
733 if (self.
point[i].pos[j] !=
None)
and (self.
point[i-1].pos[j] !=
None):
738 if (self.
point[i].acc[j] !=
None)
and (self.
point[i-1].acc[j] !=
None):
741 if (self.
point[i].vel[j] !=
None)
and (self.
point[i-1].vel[j] !=
None):
748 genpy.check_range(phi, 0.0, self.
phi_end, __name__, self.__class__.__name__, sys._getframe().f_code.co_name,
'phi')
757 check phi to be valid. Many changes must be delivered.
758 1- current_position must be a function returning property pos
762 def map_phi(self, phi_start = 0, phi_end = 1.0):
764 Maps the current trajectory phase interval to the given interval (phi_start, phi_end)
765 and adjusts all keypoint phases, velocities and accelerations accordingly
766 The segment will be interpolated after that
767 Also the current_phi will be changed to the mapped value
771 delta_the = phi_end - phi_start
772 r = delta_the/delta_phi
773 for pnt
in self.
point:
775 the = phi_start + x*delta_the
777 for j
in range(self.
dim):
778 if pnt.vel[j] !=
None:
779 pnt.vel[j] = pnt.vel[j]/r
780 if pnt.acc[j] !=
None:
781 pnt.acc[j] = pnt.acc[j]/(r*r)
791 if field_name ==
'Position':
793 elif field_name ==
'Velocity':
795 elif field_name ==
'Acceleration':
798 assert False, genpy.err_str(__name__, self.__class__.__name__, sys._getframe().f_code.co_name, field_name +
" is not a valid value for field_name")
800 def plot(self, axis = 0, n = 100, show_points = False):
801 import matplotlib.pyplot
as plt
803 s = self.plot_settings.ylabel(axis)
808 y.append(self.
current_value(field_name = self.plot_settings.figure, axis = axis))
812 for pnt
in self.
point:
814 py.append(pnt.value(field_name = self.plot_settings.figure, axis = axis))
816 plt.plot(x, y, px, py,
'o')
825 def plot_all(self, axis = [0,1], n = 100, y_text = "", figure = 'Position', show_points = False):
827 s = figure + " of Axis " + str(axis)
829 s = figure + " of " + y_text
831 x = np.append(np.arange(0.0, self.phi_end, self.phi_end/n), self.phi_end)
836 y.append(self.current_value(field_name = figure, axis = axis))
840 for pnt in self.point:
842 py.append(pnt.value(field_name = figure, axis = axis))
844 plt.plot(x, y, px, py, 'o')
853 def scatter_plot(self, figure = 'Position', axis_x = 0, axis_y = 1, n = 100, y_text = "", show_points = False):
860 x.append(self.
current_value(field_name = figure, axis = axis_x))
861 y.append(self.
current_value(field_name = figure, axis = axis_y))
866 for pnt
in self.
point:
867 px.append(pnt.value(field_name = figure, axis = axis_x))
868 py.append(pnt.value(field_name = figure, axis = axis_y))
870 plt.plot(x, y, px, py,
'o')
881 super(Path_Polynomial, self).
__init__(dimension = dimension, capacity = capacity)
882 self.
traj = [pl.Polynomial()
for j
in range(self.
dim)]
886 specifies the coefficients of the trajectory_tbc_path which passes through a number of poses
887 At least one position and one phi is required.
892 pnt = [[]
for j
in range(self.
dim)]
895 for j
in range(self.
dim):
896 pnt[j].append(pl.Point(t = self.
point[i].phi, x = self.
point[i].pos[j], v = self.
point[i].vel[j], a = self.
point[i].acc[j]))
897 for j
in range(self.
dim):
898 self.
traj[j].interpolate_smart(pnt[j])
903 assert False, genpy.err_str(__name__, self.__class__.__name__, sys._getframe().f_code.co_name,
"No key points defined")
905 def map_phi(self, phi_start = 0, phi_end = 1.0):
906 super(Path_Polynomial, self).
map_phi(phi_start = phi_start, phi_end = phi_end)
914 check phi to be valid. Many changes must be delivered.
915 1- current_position must be a function returning property pos
919 assert len(self.
point) > 1, genpy.err_str(__name__, self.__class__.__name__,
'value',
'Can not change the phase when there are less than two key points!')
925 for j
in range(self.
dim):
931 def __init__(self, representation = 'vector', parametrization = 'identity', capacity = 2):
932 super(Orientation_Path, self).
__init__(dimension = 3, capacity = capacity)
936 super(Orientation_Path, self).
set_phi(phi = phi)
942 rpn = self.current_orientation.representation
943 ori.parametrization = self.current_orientation.parametrization
945 vel = ori[rpn +
'_velocity']
946 acc = ori[rpn +
'_acceleration']
947 super(Orientation_Path, self).
add_point(phi, pos, vel, acc)
950 def __init__(self, representation = 'vector', parametrization = 'identity'):
951 super(Orientation_Path_Polynomial, self).
__init__(representation = representation, parametrization = parametrization)
983 s =
"Trajectory Phase Length : " + str(self.
phi_end) +
'\n'
984 s +=
"Number of Segments : " + str(len(self.
segment)) +
'\n'
985 for i
in range(len(self.
segment)):
986 s +=
"Segment Number " + str(i) +
" starting at phi = " + str(self.
seg_start[i]) +
': \n'
988 s +=
"****************************************** \n"
992 assert point_number < self.
npoints,
"point number must be smaller than total number of points"
995 while (self.
seg_start_pntn[i] <= point_number)
and (i < nseg - 1):
1008 return self.
segment[sn].point[pn]
1012 if field_name ==
'Position':
1014 elif field_name ==
'Velocity':
1016 elif field_name ==
'Acceleration':
1019 assert False, genpy.err_str(__name__, self.__class__.__name__, sys._getframe().f_code.co_name, field_name +
" is not a valid value for field_name")
1023 assert len(new_seg.point) > 0
1025 self.
npoints = len(new_seg.point)
1027 self.
npoints += len(new_seg.point) - 1
1030 self.segment.append(new_seg)
1031 self.seg_start.append(self.
phi_end)
1032 self.
phi_end += new_seg.phi_end
1034 self.seg_start_pntn.append(self.
npoints - 1)
1037 capacity = genpy.check_type(capacity, [int], __name__, self.__class__.__name__, sys._getframe().f_code.co_name,
'capacity', default = self.
capacity)
1040 seg =
Path(dimension = self.
dim, capacity = capacity)
1041 assert len(self.
segment[lsi].point) > 1, genpy.err_str(__name__, self.__class__.__name__, sys._getframe().f_code.co_name,
'Can not create a new segment. The last segment needs at least two points.')
1043 seg.add_point(0.0, lslp.pos, lslp.vel, lslp.acc)
1049 dist = np.append(dist, seg.points_dist())
1056 for i
in range(n_seg - 1):
1094 genpy.check_range(phi, 0.0, self.
phi_end, __name__, self.__class__.__name__, sys._getframe().f_code.co_name,
'phi')
1099 P = np.zeros((n, self.
dim))
1106 if gen.equal(self.
phi_end, 0.0):
1107 self.
add_point(phi, pos, vel = np.zeros(self.
dim), acc = np.zeros(self.
dim))
1113 lpi = len(self.
segment[lsi].point) - 1
1114 p0 = self.
segment[lsi].point[lpi].pos
1115 v0 = self.
segment[lsi].point[lpi].vel
1116 a0 = self.
segment[lsi].point[lpi].acc
1119 (P, V, A) =
feasible_position(pos, p0, v0, self.
pos_min, self.
pos_max, self.
vel_max, self.
acc_max, dt, smooth = smooth)
1121 self.
add_point(phi, pos = P, vel = V, acc = A)
1124 assert not self.
npoints == 0,
"An initial position must exist"
1129 lpi = len(self.
segment[lsi].point) - 1
1130 p0 = self.
segment[lsi].point[lpi].pos
1131 v0 = self.
segment[lsi].point[lpi].vel
1132 a0 = self.
segment[lsi].point[lpi].acc
1137 self.
add_point(phi, pos = P, vel = V, acc = A)
1141 assert lsi >= 0,
"Empty Trajectory!"
1142 lpi = len(self.
segment[lsi].point) - 1
1143 return self.
segment[lsi].point[lpi].pos
1147 assert lsi >= 0,
"Empty Trajectory!"
1148 lpi = len(self.
segment[lsi].point) - 1
1149 return self.
segment[lsi].point[lpi].vel
1152 def add_position(self, phi, pos):
1153 if gen.equal(self.phi_end, 0.0):
1154 self.add_point(phi, pos, vel = np.zeros(self.dim), acc = np.zeros(self.dim))
1157 assert phi > self.phi_end
1158 dt = phi - self.phi_end
1159 al = self.accuracy_level
1160 # if accuracy_level is m we need m+1 position points to compute velocity, m+2 points to compute acceleration
1163 while (j < al) and (self.phi_end < (al - j)*dt):
1168 x = self.positions(phi = self.phi_end - al*dt, n = al + 1, d_phi = dt)
1169 x = np.append([pos], x, axis = 0)
1170 (P, V, A) = finite_difference_estimate(x, self.pos_min, self.pos_max, self.vel_max, self.acc_max, dt)
1171 self.add_point(phi, pos = P, vel = V, acc = A)
1185 genpy.check_type(phi, [float, np.float64], __name__, self.__class__.__name__,sys._getframe().f_code.co_name,
'phi', default =
None)
1190 assert gen.equal(phi, 0.0), genpy.err_str(__name__, self.__class__.__name__,sys._getframe().f_code.co_name,
"Given phi is " + str(phi) +
" which should be zero for the first point")
1191 seg =
Path(dimension = self.
dim)
1192 seg.add_point(0.0, pos, vel, acc)
1195 assert (phi > self.
phi_end)
and (
not gen.equal(phi, self.
phi_end)), genpy.err_str(__name__, self.__class__.__name__,sys._getframe().f_code.co_name,
"Given phi is " + str(phi) +
" which should be greater than the last point's phase " + str(self.
phi_end))
1209 nn = np.array([
None for i
in range(self.
dim)])
1211 for pnt
in seg.point:
1212 pnt.vel = np.copy(nn)
1215 nn = np.array([
None for i
in range(self.
dim)])
1217 for pnt
in seg.point:
1218 pnt.acc = np.copy(nn)
1221 def add_vector(self, delta_phi, delta_pos, vel = None, acc = None):
1222 assert delta_phi > 0
1223 phi = self.
phi_end + delta_phi
1227 pos = lslp.pos + delta_pos
1232 Maps the current trajectory phase interval to the given interval (phi_start, phi_end)
1233 and adjusts all keypoint phases, velocities and accelerations accordingly
1234 All the segments will be interpolated after that
1235 Also the current_phi will be changed to the mapped value
1240 delta_the = phi_end - phi_start
1241 r = delta_the/delta_phi
1242 for i
in range(n_seg):
1244 the = phi_start + x*delta_the
1255 if figure ==
'Position':
1258 elif figure ==
'Velocity':
1261 elif figure ==
'Acceleration':
1265 assert False,
"Unknown figure"
1269 def get_plot(self, plt = None, axis = 0, figure = 'Position'):
1271 import matplotlib.pyplot
as plt
1273 s = self.plot_settings.ylabel(axis)
1275 fig, ax = plt.subplots()
1278 if self.plot_settings.show_range:
1279 (miny, maxy) = self.
get_range(axis, figure)
1280 ax.annotate(
'Upper Bound: ' +
'{:04.3f}'.format(maxy),
1281 xy = (self.
phi_end, maxy), xycoords =
'data',
1282 xytext = (- 150, -17), textcoords =
'offset points',
1283 horizontalalignment=
'left', verticalalignment=
'bottom',
1284 color = self.plot_settings.plot_color[axis])
1285 ax.annotate(
'Lower Bound: ' +
'{:04.3f}'.format(miny),
1286 xy = (0.0, miny), xycoords =
'data',
1287 xytext = (150, 17), textcoords =
'offset points',
1288 horizontalalignment=
'right', verticalalignment=
'top',
1290 color = self.plot_settings.plot_color[axis])
1292 plt.axhline(linewidth = 4, color = self.plot_settings.plot_color[axis], y = miny)
1293 plt.axhline(linewidth = 4, color = self.plot_settings.plot_color[axis], y = maxy)
1294 plt.axhspan(miny, maxy, facecolor = self.plot_settings.plot_color[axis], alpha = 0.2)
1300 def plot(self, axis = 0, figure = 'Position'):
1301 plt = self.
get_plot(axis = axis, figure = figure)
1305 import matplotlib.pyplot
as plt
1307 s = self.plot_settings.ylabel(axis =
None)
1309 fig, ax = plt.subplots()
1310 for j
in range(self.
dim):
1313 if self.plot_settings.grid:
1320 ax.legend([self.plot_settings.axis_label[i]
for i
in range(self.
dim)], loc=
'upper right')
1327 assert axis < self.
dim, genpy.err_str(__name__, self.__class__.__name__, sys._getframe().f_code.co_name, str(axis) +
" is not a valid value for argument axis: Must be lower than dimension")
1330 for i
in range(len(self.
segment)):
1331 for pnt
in self.
segment[i].point:
1334 for i
in range(len(self.
segment)):
1335 for pnt
in self.
segment[i].point:
1336 px.append(pnt.value(field_name = self.plot_settings.figure, axis = axis))
1342 ax.plot(self[-1], self[axis], ltype, color = self.plot_settings.plot_color[axis])
1348 dic = {
'Position':
'x',
'Velocity':
'v',
'Acceleration':
'a'}
1350 for i
in range(self.
dim):
1351 s +=
',' + dic[self.plot_settings.figure] + str(i)
1358 for j
in range(self.
dim):
1359 if self.plot_settings.figure ==
'Position':
1361 elif self.plot_settings.figure ==
'Velocity':
1363 elif self.plot_settings.figure ==
'Acceleration':
1369 def write_csv(self, filename, n = 100, path = '', header = True):
1370 FILE_HANDLE = open(filename,
"w")
1371 FILE_HANDLE.write(self.
csv_str(n = n , header = header))
1373 def matrix(self, n = 100, figures = ['Position']):
1378 M = np.zeros((nrow, nfig*self.
dim + 1))
1387 if 'Position' in figures:
1390 if 'Velocity' in figures:
1393 if 'Acceleration' in figures:
1399 def plot2d(self, figure = 'Position', axis_x = 0, axis_y = 1, n = 100, show_points = False):
1406 x.append(self.
current_value(field_name = self.plot_settings.figure, axis = axis_x))
1407 y.append(self.
current_value(field_name = self.plot_settings.figure, axis = axis_y))
1412 for i
in range(len(self.
segment)):
1413 for pnt
in self.
segment[i].point:
1414 px.append(pnt.value(field_name = self.plot_settings.figure, axis = axis_x))
1415 py.append(pnt.value(field_name = self.plot_settings.figure, axis = axis_y))
1417 plt.plot(x, y, px, py,
'o')
1425 def plot3d(self, figure = 'Position', axis_x = 0, axis_y = 1, axis_z = 2, n = 100, label = "", show_points = False):
1426 import matplotlib
as mpl
1427 from mpl_toolkits.mplot3d
import Axes3D
1430 mpl.rcParams[
'legend.fontsize'] = 10
1432 ax = fig.gca(projection=
'3d')
1439 x.append(self.
current_value(field_name = self.plot_settings.figure, axis = axis_x))
1440 y.append(self.
current_value(field_name = self.plot_settings.figure, axis = axis_y))
1441 z.append(self.
current_value(field_name = self.plot_settings.figure, axis = axis_z))
1443 ax.plot(x, y, z, label = label)
1448 def __init__(self, representation = 'vector', parametrization = 'identity'):
1449 super(Orientation_Trajectory, self).
__init__()
1453 super(Orientation_Trajectory, self).
set_phi(phi = phi)
1459 rpn = self.current_orientation.representation
1460 ori.parametrization = self.current_orientation.parametrization
1462 vel = ori[rpn +
'_velocity']
1463 acc = ori[rpn +
'_acceleration']
1464 super(Orientation_Trajectory, self).
add_point(phi, pos, vel, acc)
1468 super(Trajectory_Polynomial, self).
__init__(dimension = dimension, capacity = capacity)
1471 capacity = genpy.check_type(capacity, [int], __name__, self.__class__.__name__, sys._getframe().f_code.co_name,
'capacity', default = self.
capacity)
1474 assert len(self.
segment[lsi].point) > 1, genpy.err_str(__name__, self.__class__.__name__, sys._getframe().f_code.co_name,
'Can not create a new segment. The last segment needs at least two points.')
1477 seg.add_point(0.0, lslp.pos, lslp.vel, lslp.acc)
1485 genpy.check_type(phi, [float, np.float64], __name__, self.__class__.__name__,sys._getframe().f_code.co_name,
'phi', default =
None)
1490 assert gen.equal(phi, 0.0), genpy.err_str(__name__, self.__class__.__name__,sys._getframe().f_code.co_name,
"Given phi is " + str(phi) +
" which should be zero for the first point")
1492 seg.add_point(0.0, pos, vel, acc)
1495 assert (phi > self.
phi_end)
and (
not gen.equal(phi, self.
phi_end)), genpy.err_str(__name__, self.__class__.__name__,sys._getframe().f_code.co_name,
"Given phi is " + str(phi) +
" which should be greater than the last point's phase " + str(self.
phi_end))
1510 figure = self.plot_settings.figure
1515 y.append(self.
current_value(field_name = figure, axis = axis))
1517 ax.plot(x, y, ltype)
1519 def plot(self, axis = 0, figure = None, n = 100, show_points = False):
1521 figure = self.plot_settings.figure
1522 import matplotlib.pyplot
as plt
1523 s = self.plot_settings.ylabel(axis)
1524 fig, ax = plt.subplots()
1530 if self.plot_settings.show_range:
1532 (miny, maxy) = self.
get_range(axis, figure)
1534 ax.annotate(
'Upper Bound: ' +
'{:04.3f}'.format(maxy),
1535 xy = (self.
phi_end, maxy), xycoords =
'data',
1536 xytext = (- 150, -17), textcoords =
'offset points',
1537 horizontalalignment=
'left', verticalalignment=
'bottom',
1538 color = self.plot_settings.plot_color[axis])
1539 ax.annotate(
'Lower Bound: ' +
'{:04.3f}'.format(miny),
1540 xy = (0.0, miny), xycoords =
'data',
1541 xytext = (150, 17), textcoords =
'offset points',
1542 horizontalalignment=
'right', verticalalignment=
'top',
1544 color = self.plot_settings.plot_color[axis])
1546 plt.axhline(linewidth = 4, color = self.plot_settings.plot_color[axis], y = miny)
1547 plt.axhline(linewidth = 4, color = self.plot_settings.plot_color[axis], y = maxy)
1548 plt.axhspan(miny, maxy, facecolor = self.plot_settings.plot_color[axis], alpha = 0.2)
1558 for i
in range(lsi + 1):
1563 for j
in range(self.
dim):
1566 if lp.vel[j] ==
None:
1567 if self.
segment[ip1].point[0].vel[j] ==
None:
1568 v = 0.5*(self.
segment[i].current_velocity[j] + self.
segment[ip1].current_velocity[j])
1570 self.
segment[ip1].point[0].vel[j] = v
1572 lp.vel[j] = self.
segment[ip1].point[0].vel[j]
1573 elif self.
segment[ip1].point[0].vel[j] ==
None:
1574 self.
segment[ip1].point[0].vel[j] = lp.vel[j]
1575 elif not gen.equal(lp.vel[j], self.
segment[ip1].point[0].vel[j]):
1576 v = 0.5*(lp.vel[j] + self.
segment[ip1].point[0].vel[j])
1578 self.
segment[ip1].point[0].vel[j] = v
1588 self.
segment[0].point[0].acc = np.zeros(self.
dim)
1589 for i
in range(lsi + 1):
1594 for j
in range(self.
dim):
1597 if lp.acc[j] ==
None:
1598 if self.
segment[ip1].point[0].acc[j] ==
None:
1599 a = 0.5*(self.
segment[i].current_acceleration[j] + self.
segment[ip1].current_acceleration[j])
1601 self.
segment[ip1].point[0].acc[j] = a
1603 lp.acc[j] = self.
segment[ip1].point[0].acc[j]
1604 elif self.
segment[ip1].point[0].acc[j] ==
None:
1605 self.
segment[ip1].point[0].acc[j] = lp.acc[j]
1606 elif not gen.equal(lp.acc[j], self.
segment[ip1].point[0].acc[j]):
1607 a = 0.5*(lp.acc[j] + self.
segment[ip1].point[0].acc[j])
1609 self.
segment[ip1].point[0].acc[j] = a
1617 def __init__(self, representation = 'vector', parametrization = 'identity'):
1618 super(Orientation_Trajectory_Polynomial, self).
__init__(representation = representation, parametrization = parametrization)