performance optimization

This commit is contained in:
Nikolay Khabarov
2017-06-11 02:19:21 +03:00
parent 65695fe53d
commit 0fe98f4cca
2 changed files with 48 additions and 44 deletions
+5 -2
View File
@@ -145,8 +145,11 @@ def move(generator):
dma.add_set_clear(pins_to_set, pins_to_clear) dma.add_set_clear(pins_to_set, pins_to_clear)
continue continue
pins = 0 pins = 0
k = int(round(min(x for x in (tx, ty, tz, te) if x is not None) m = None
* US_IN_SECONDS)) for i in (tx, ty, tz, te):
if i is not None and (m is None or i < m):
m = i
k = int(round(m * US_IN_SECONDS))
if tx is not None: if tx is not None:
pins |= STEP_PIN_MASK_X pins |= STEP_PIN_MASK_X
if ty is not None: if ty is not None:
+43 -42
View File
@@ -28,10 +28,8 @@ class PulseGenerator(object):
brake will take and recalculate time for them. Linear part will be as brake will take and recalculate time for them. Linear part will be as
is. Since maximum velocity and acceleration is always the same, there is. Since maximum velocity and acceleration is always the same, there
is the ACCELERATION_FACTOR_PER_SEC variable. is the ACCELERATION_FACTOR_PER_SEC variable.
In the same way round or other interpolation can be implemented based on In the same way circular or other interpolation can be implemented
this class. based this class.
Note: round interpolation would require direction change during movement.
It's not implemented yet.
""" """
def __init__(self, delta): def __init__(self, delta):
@@ -162,7 +160,10 @@ class PulseGenerator(object):
raise StopIteration raise StopIteration
# convert to real time # convert to real time
m = min(x for x in (tx, ty, tz, te) if x is not None) m = None
for i in (tx, ty, tz, te):
if i is not None and (m is None or i < m):
m = i
am = self._to_accelerated_time(m) am = self._to_accelerated_time(m)
# sort pulses in time # sort pulses in time
if tx is not None: if tx is not None:
@@ -326,13 +327,15 @@ class PulseGeneratorCircular(PulseGenerator):
apm = STEPPER_PULSES_PER_MM_Z apm = STEPPER_PULSES_PER_MM_Z
bpm = STEPPER_PULSES_PER_MM_X bpm = STEPPER_PULSES_PER_MM_X
# adjust radius to fit into axises step. # adjust radius to fit into axises step.
self._radius = round(math.sqrt(sa * sa + sb * sb) * min(apm, bpm)) \ radius = round(math.sqrt(sa * sa + sb * sb) * min(apm, bpm)) \
/ min(apm, bpm) / min(apm, bpm)
self._radius2 = self._radius * self._radius self._radius2 = radius * radius
self._start_a = sa self._radius_a_pulses = int(radius * apm)
self._start_b = sb self._radius_b_pulses = int(radius * bpm)
self._start_a_pulses = int(sa * apm)
self._start_b_pulses = int(sb * bpm)
assert round(math.sqrt(ea * ea + eb * eb) * min(apm, bpm)) \ assert round(math.sqrt(ea * ea + eb * eb) * min(apm, bpm)) \
/ min(apm, bpm) == self._radius, "Wrong end point" / min(apm, bpm) == radius, "Wrong end point"
# Calculate angles and directions. # Calculate angles and directions.
start_angle = self.__angle(sa, sb) start_angle = self.__angle(sa, sb)
@@ -360,8 +363,8 @@ class PulseGeneratorCircular(PulseGenerator):
self._dir_a = -1 self._dir_a = -1
else: else:
self._dir_a = 1 self._dir_a = 1
self._side_a = self._start_b < 0 or (self._start_b == 0 and self._dir_b < 0) self._side_a = self._start_b_pulses < 0 or (self._start_b_pulses == 0 and self._dir_b < 0)
self._side_b = self._start_a < 0 or (self._start_a == 0 and self._dir_a < 0) self._side_b = self._start_a_pulses < 0 or (self._start_a_pulses == 0 and self._dir_a < 0)
self._start_angle = start_angle self._start_angle = start_angle
logging.debug("start angle {}, end angle {}, delta {}".format( logging.debug("start angle {}, end angle {}, delta {}".format(
start_angle * 180.0 / math.pi, start_angle * 180.0 / math.pi,
@@ -381,8 +384,8 @@ class PulseGeneratorCircular(PulseGenerator):
rstart = int(start_angle / (math.pi / 2.0)) rstart = int(start_angle / (math.pi / 2.0))
rend = int(end_angle_m / (math.pi / 2.0)) rend = int(end_angle_m / (math.pi / 2.0))
if rend - rstart >= 4: if rend - rstart >= 4:
self._iterations_a = 4 * int(self._radius * apm) self._iterations_a = 4 * int(radius * apm)
self._iterations_b = 4 * int(self._radius * apm) self._iterations_b = 4 * int(radius * apm)
else: else:
if rstart == rend: if rstart == rend:
self._iterations_a = int(abs(sa - ea) * apm) self._iterations_a = int(abs(sa - ea) * apm)
@@ -394,30 +397,30 @@ class PulseGeneratorCircular(PulseGenerator):
i -= 4 i -= 4
if r == rstart: if r == rstart:
if i == 0 or i == 2: if i == 0 or i == 2:
self._iterations_a += int(self._radius * apm) - int(abs(sa) * apm) self._iterations_a += int(radius * apm) - int(abs(sa) * apm)
else: else:
self._iterations_a += int(abs(sa) * apm) self._iterations_a += int(abs(sa) * apm)
if i == 1 or i == 3: if i == 1 or i == 3:
self._iterations_b += int(self._radius * bpm) - int(abs(sb) * bpm) self._iterations_b += int(radius * bpm) - int(abs(sb) * bpm)
else: else:
self._iterations_b += int(abs(sb) * bpm) self._iterations_b += int(abs(sb) * bpm)
elif r == rend: elif r == rend:
if i == 0 or i == 2: if i == 0 or i == 2:
self._iterations_a += int(abs(ea) * apm) self._iterations_a += int(abs(ea) * apm)
else: else:
self._iterations_a += int(self._radius * apm) - int(abs(ea) * apm) self._iterations_a += int(radius * apm) - int(abs(ea) * apm)
if i == 1 or i == 3: if i == 1 or i == 3:
self._iterations_b += int(abs(eb) * bpm) self._iterations_b += int(abs(eb) * bpm)
else: else:
self._iterations_b += int(self._radius * bpm) - int(abs(eb) * bpm) self._iterations_b += int(radius * bpm) - int(abs(eb) * bpm)
else: else:
self._iterations_a += int(self._radius * apm) self._iterations_a += int(radius * apm)
self._iterations_b += int(self._radius * bpm) self._iterations_b += int(radius * bpm)
if direction == CCW: if direction == CCW:
self._iterations_a = 4 * int(self._radius * apm) - self._iterations_a self._iterations_a = 4 * int(radius * apm) - self._iterations_a
self._iterations_b = 4 * int(self._radius * bpm) - self._iterations_b self._iterations_b = 4 * int(radius * bpm) - self._iterations_b
arc = delta_angle * self._radius arc = delta_angle * radius
e2 = delta.e * delta.e e2 = delta.e * delta.e
if self._plane == PLANE_XY: if self._plane == PLANE_XY:
self._iterations_3rd = abs(delta.z) * STEPPER_PULSES_PER_MM_Z self._iterations_3rd = abs(delta.z) * STEPPER_PULSES_PER_MM_Z
@@ -437,7 +440,7 @@ class PulseGeneratorCircular(PulseGenerator):
self._iterations_e = abs(delta.e) * STEPPER_PULSES_PER_MM_E self._iterations_e = abs(delta.e) * STEPPER_PULSES_PER_MM_E
# Velocity splits with corresponding distance. # Velocity splits with corresponding distance.
cV = arc / l * velocity cV = arc / l * velocity
self._RdivV = self._radius / cV self._RdivV = radius / cV
self._e_velocity = abs(delta.e) / l * velocity self._e_velocity = abs(delta.e) / l * velocity
self._e_dir = math.copysign(1, delta.e) self._e_dir = math.copysign(1, delta.e)
self.max_velocity_mm_per_sec = max(cV, self._velocity_3rd, self.max_velocity_mm_per_sec = max(cV, self._velocity_3rd,
@@ -469,22 +472,18 @@ class PulseGeneratorCircular(PulseGenerator):
self.linear_time_s, \ self.linear_time_s, \
self.max_velocity_mm_per_sec self.max_velocity_mm_per_sec
def __circularHelper(self, start, i, pulses_per_mm, side, dir): def __circularHelper(self, start, i, radius, side, dir):
np = start + dir * i / pulses_per_mm np = start + dir * i
np = round(np, 10) if np > radius:
if np > self._radius: np -= 2 * (np - radius)
np -= 2 * (np - self._radius)
np = round(np, 10)
dir = -dir dir = -dir
side = not side side = not side
if np < -self._radius: if np < -radius:
np -= 2 * (np + self._radius) np -= 2 * (np + radius)
np = round(np, 10)
dir = -dir dir = -dir
side = not side side = not side
if np > self._radius: if np > radius:
np -= 2 * (np - self._radius) np -= 2 * (np - radius)
np = round(np, 10)
dir = -dir dir = -dir
side = not side side = not side
return np, dir, side return np, dir, side
@@ -502,9 +501,10 @@ class PulseGeneratorCircular(PulseGenerator):
def __circularA(self, i, pulses_per_mm): def __circularA(self, i, pulses_per_mm):
if i >= self._iterations_a: if i >= self._iterations_a:
return self._dir_a, None return self._dir_a, None
a, dir, side = self.__circularHelper(self._start_a, i + 1, a, dir, side = self.__circularHelper(self._start_a_pulses, i + 1,
pulses_per_mm, self._side_a, self._radius_a_pulses,
self._dir_a) self._side_a, self._dir_a)
a /= pulses_per_mm
# last item can be slightly more then end angle due to float precision # last item can be slightly more then end angle due to float precision
if i + 1 == self._iterations_a: if i + 1 == self._iterations_a:
return dir, self._RdivV * self._delta_angle return dir, self._RdivV * self._delta_angle
@@ -516,9 +516,10 @@ class PulseGeneratorCircular(PulseGenerator):
def __circularB(self, i, pulses_per_mm): def __circularB(self, i, pulses_per_mm):
if i >= self._iterations_b: if i >= self._iterations_b:
return self._dir_b, None return self._dir_b, None
b, dir, side = self.__circularHelper(self._start_b, i + 1, b, dir, side = self.__circularHelper(self._start_b_pulses, i + 1,
pulses_per_mm, self._side_b, self._radius_b_pulses,
self._dir_b) self._side_b, self._dir_b)
b /= pulses_per_mm
# last item can be slightly more then end angle due to float precision # last item can be slightly more then end angle due to float precision
if i + 1 == self._iterations_b: if i + 1 == self._iterations_b:
return dir, self._RdivV * self._delta_angle return dir, self._RdivV * self._delta_angle