Source code for pypot.utils.trajectory
from __future__ import division
import numpy
import collections
import pypot.utils.pypot_time as time
from ..utils.stoppablethread import StoppableLoopThread
[docs]class MinimumJerkTrajectory(object):
def __init__(self, initial, final, duration, init_vel=0.0, init_acc=0.0, final_vel=0.0, final_acc=0.0):
self.initial = initial
self.final = final
self.duration = duration
self.init_vel = init_vel
self.init_acc = init_acc
self.final_vel = final_vel
self.final_acc = final_acc
self.durations = [0, duration]
self.finals = [final]
self.compute()
[docs] def compute(self): # N'Guyen's magic
a0 = self.initial
a1 = self.init_vel
a2 = self.init_acc / 2.0
d = lambda x: self.duration ** x
A = numpy.array([[d(3), d(4), d(5)], [3 * d(2), 4 * d(3), 5 * d(4)], [6 * d(1), 12 * d(2), 20 * d(3)]])
B = numpy.array([self.final - a0 - (a1 * d(1)) - (a2 * d(2)), self.final_vel - a1 - (2 * a2 * d(1)), self.final_acc - (2 * a2)])
X = numpy.linalg.solve(A, B)
self.other_gen = None
self._mylambda = lambda x: a0 + a1 * x + a2 * x ** 2 + X[0] * x ** 3 + X[1] * x ** 4 + X[2] * x ** 5
self._generators = [self._mylambda]
[docs] def get_value(self, t):
return self._mygenerator[-1](t)
[docs] def domain(self, x):
if not isinstance(x, collections.Iterable):
x = numpy.array([x])
return numpy.array([
self.durations[0] <= xi < self.durations[1]
for xi in x
])
[docs] def test_domain(self, x):
return [((numpy.array(x) >= self.durations[i])) for i in range(len(self.durations) - 1)]
[docs] def get_generator(self):
return lambda x: numpy.piecewise(x, self.domain(x), [self._generators[j] for j in range(len(self._generators))] + [self.finals[-1]])
[docs]class GotoMinJerk(StoppableLoopThread):
def __init__(self, motor, position, duration, frequency=50):
StoppableLoopThread.__init__(self, frequency)
self.motor = motor
self.goal = position # dict { 'motor1_name': x1, 'motor2_name': x2 }
self.duration = duration # seconds
[docs] def setup(self):
if self.duration < numpy.finfo(float).eps:
self.motor.goal_position = self.goal
self.stop()
else:
self.trajs = MinimumJerkTrajectory(self.motor.present_position, self.goal, self.duration).get_generator()
self.t0 = time.time()
[docs] def update(self):
if numpy.finfo(float).eps < self.duration > self.elapsed_time:
self.motor.goal_position = self.trajs(self.elapsed_time)
else:
self.stop(wait=False)
@property
def elapsed_time(self):
return time.time() - self.t0
[docs]class GotoLinear(StoppableLoopThread):
def __init__(self, motor, position, duration, frequency=50):
StoppableLoopThread.__init__(self, frequency)
self.motor = motor
nb_step = round(duration * frequency)
start = motor.goal_position
end = position
self.positions = numpy.linspace(start, end, nb_step + 1)[1:]
self.positions = iter(self.positions)
[docs] def update(self):
try:
p = next(self.positions)
self.motor.goal_position = p
except StopIteration:
self.stop(wait=False)