toolhead: Support calculation of cornering minimum and maximum
Calculate the next "cornering" minimum and maximum for each move. The "cornering minimum" is the lowest speed the head will reach immediately after this move (with no interleaving acceleration or cruising). The "cornering maximum" is the maximum speed the head will reach after the cornering minimum (with no interleaving deceleration or cruising). These cornering calculations will be helpful in the extruder "pressure advance" code. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
6285cc6f66
commit
9d7aa1e155
|
@ -70,10 +70,9 @@ class Move:
|
||||||
self.junction_start_max = min(
|
self.junction_start_max = min(
|
||||||
R * self.accel, self.junction_max, prev_move.junction_max
|
R * self.accel, self.junction_max, prev_move.junction_max
|
||||||
, prev_move.junction_start_max + prev_move.junction_delta)
|
, prev_move.junction_start_max + prev_move.junction_delta)
|
||||||
def process(self, junction_start, junction_end):
|
def process(self, junction_start, junction_cruise, junction_end
|
||||||
|
, cornering_min, cornering_max):
|
||||||
# Determine accel, cruise, and decel portions of the move distance
|
# Determine accel, cruise, and decel portions of the move distance
|
||||||
junction_cruise = min((junction_start + junction_end
|
|
||||||
+ self.junction_delta) * .5, self.junction_max)
|
|
||||||
inv_junction_delta = 1. / self.junction_delta
|
inv_junction_delta = 1. / self.junction_delta
|
||||||
accel_r = (junction_cruise-junction_start) * inv_junction_delta
|
accel_r = (junction_cruise-junction_start) * inv_junction_delta
|
||||||
decel_r = (junction_cruise-junction_end) * inv_junction_delta
|
decel_r = (junction_cruise-junction_end) * inv_junction_delta
|
||||||
|
@ -84,6 +83,8 @@ class Move:
|
||||||
cruise_v = math.sqrt(junction_cruise)
|
cruise_v = math.sqrt(junction_cruise)
|
||||||
end_v = math.sqrt(junction_end)
|
end_v = math.sqrt(junction_end)
|
||||||
self.start_v, self.cruise_v, self.end_v = start_v, cruise_v, end_v
|
self.start_v, self.cruise_v, self.end_v = start_v, cruise_v, end_v
|
||||||
|
self.corner_min = math.sqrt(cornering_min)
|
||||||
|
self.corner_max = math.sqrt(cornering_max)
|
||||||
# Determine time spent in each portion of move (time is the
|
# Determine time spent in each portion of move (time is the
|
||||||
# distance divided by average velocity)
|
# distance divided by average velocity)
|
||||||
accel_t = accel_r * self.move_d / ((start_v + cruise_v) * 0.5)
|
accel_t = accel_r * self.move_d / ((start_v + cruise_v) * 0.5)
|
||||||
|
@ -102,42 +103,45 @@ class Move:
|
||||||
class MoveQueue:
|
class MoveQueue:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.queue = []
|
self.queue = []
|
||||||
self.prev_junction_max = 0.
|
|
||||||
self.junction_flush = 0.
|
self.junction_flush = 0.
|
||||||
def reset(self):
|
def reset(self):
|
||||||
del self.queue[:]
|
del self.queue[:]
|
||||||
self.prev_junction_max = self.junction_flush = 0.
|
|
||||||
def flush(self, lazy=False):
|
def flush(self, lazy=False):
|
||||||
flush_count = len(self.queue)
|
flush_count = len(self.queue)
|
||||||
junction_end = [None] * flush_count
|
move_info = [None] * flush_count
|
||||||
# Traverse queue from last to first move and determine maximum
|
# Traverse queue from last to first move and determine maximum
|
||||||
# junction speed assuming the robot comes to a complete stop
|
# junction speed assuming the robot comes to a complete stop
|
||||||
# after the last move.
|
# after the last move.
|
||||||
next_junction_max = 0.
|
next_junction_end = cornering_min = cornering_max = 0.
|
||||||
for i in range(flush_count-1, -1, -1):
|
for i in range(flush_count-1, -1, -1):
|
||||||
move = self.queue[i]
|
move = self.queue[i]
|
||||||
junction_end[i] = next_junction_max
|
reachable_start = next_junction_end + move.junction_delta
|
||||||
next_junction_max = next_junction_max + move.junction_delta
|
junction_start = min(move.junction_start_max, reachable_start)
|
||||||
if next_junction_max >= move.junction_start_max:
|
junction_cruise = min((junction_start + reachable_start) * .5
|
||||||
next_junction_max = move.junction_start_max
|
, move.junction_max)
|
||||||
if lazy:
|
move_info[i] = (junction_start, junction_cruise, next_junction_end
|
||||||
flush_count = i
|
, cornering_min, cornering_max)
|
||||||
lazy = False
|
if reachable_start > junction_start:
|
||||||
|
cornering_min = junction_start
|
||||||
|
if junction_start + move.junction_delta > next_junction_end:
|
||||||
|
cornering_max = junction_cruise
|
||||||
|
if lazy:
|
||||||
|
flush_count = i
|
||||||
|
lazy = False
|
||||||
|
next_junction_end = junction_start
|
||||||
|
if lazy:
|
||||||
|
flush_count = 0
|
||||||
# Generate step times for all moves ready to be flushed
|
# Generate step times for all moves ready to be flushed
|
||||||
prev_junction_max = self.prev_junction_max
|
|
||||||
for i in range(flush_count):
|
for i in range(flush_count):
|
||||||
move = self.queue[i]
|
self.queue[i].process(*move_info[i])
|
||||||
move.process(prev_junction_max, junction_end[i])
|
|
||||||
prev_junction_max = junction_end[i]
|
|
||||||
self.prev_junction_max = prev_junction_max
|
|
||||||
# Remove processed moves from the queue
|
# Remove processed moves from the queue
|
||||||
del self.queue[:flush_count]
|
del self.queue[:flush_count]
|
||||||
if self.queue:
|
if self.queue:
|
||||||
self.junction_flush = self.queue[-1].junction_max
|
self.junction_flush = 2. * self.queue[-1].junction_max
|
||||||
def add_move(self, move):
|
def add_move(self, move):
|
||||||
self.queue.append(move)
|
self.queue.append(move)
|
||||||
if len(self.queue) == 1:
|
if len(self.queue) == 1:
|
||||||
self.junction_flush = move.junction_max
|
self.junction_flush = 2. * move.junction_max
|
||||||
return
|
return
|
||||||
move.calc_junction(self.queue[-2])
|
move.calc_junction(self.queue[-2])
|
||||||
self.junction_flush -= move.junction_delta
|
self.junction_flush -= move.junction_delta
|
||||||
|
|
Loading…
Reference in New Issue