toolhead: Permit look-ahead between Z moves

Extend the look-ahead mechanism to work between moves that contain Z
movement.  This improves Klipper's handling of g-code produced in
"vase mode".

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2017-09-03 14:10:21 -04:00
parent 7a81bfc4a4
commit 8d0ef49e8f
2 changed files with 11 additions and 10 deletions

View File

@ -88,9 +88,9 @@ The junction speeds are determined using "approximated centripetal
acceleration". Best acceleration". Best
[described by the author](https://onehossshay.wordpress.com/2011/09/24/improving_grbl_cornering_algorithm/). [described by the author](https://onehossshay.wordpress.com/2011/09/24/improving_grbl_cornering_algorithm/).
Klipper implements look-ahead between moves contained in the XY plane Klipper implements look-ahead between moves that have similar extruder
that have similar extruder flow rates. Other moves are relatively rare flow rates. Other moves are relatively rare and implementing
and implementing look-ahead between them is unnecessary. look-ahead between them is unnecessary.
Key formula for look-ahead: Key formula for look-ahead:
``` ```

View File

@ -42,18 +42,18 @@ class Move:
self.delta_v2 = 2.0 * self.move_d * self.accel self.delta_v2 = 2.0 * self.move_d * self.accel
self.smooth_delta_v2 = min(self.smooth_delta_v2, self.delta_v2) self.smooth_delta_v2 = min(self.smooth_delta_v2, self.delta_v2)
def calc_junction(self, prev_move): def calc_junction(self, prev_move):
axes_d = self.axes_d if not self.is_kinematic_move or not prev_move.is_kinematic_move:
prev_axes_d = prev_move.axes_d
if (axes_d[2] or prev_axes_d[2] or self.accel != prev_move.accel
or not self.is_kinematic_move or not prev_move.is_kinematic_move):
return return
# Allow extruder to calculate its maximum junction # Allow extruder to calculate its maximum junction
extruder_v2 = self.toolhead.extruder.calc_junction(prev_move, self) extruder_v2 = self.toolhead.extruder.calc_junction(prev_move, self)
# Find max velocity using approximated centripetal velocity as # Find max velocity using approximated centripetal velocity as
# described at: # described at:
# https://onehossshay.wordpress.com/2011/09/24/improving_grbl_cornering_algorithm/ # https://onehossshay.wordpress.com/2011/09/24/improving_grbl_cornering_algorithm/
axes_d = self.axes_d
prev_axes_d = prev_move.axes_d
junction_cos_theta = -((axes_d[0] * prev_axes_d[0] junction_cos_theta = -((axes_d[0] * prev_axes_d[0]
+ axes_d[1] * prev_axes_d[1]) + axes_d[1] * prev_axes_d[1]
+ axes_d[2] * prev_axes_d[2])
/ (self.move_d * prev_move.move_d)) / (self.move_d * prev_move.move_d))
if junction_cos_theta > 0.999999: if junction_cos_theta > 0.999999:
return return
@ -61,8 +61,9 @@ class Move:
sin_theta_d2 = math.sqrt(0.5*(1.0-junction_cos_theta)) sin_theta_d2 = math.sqrt(0.5*(1.0-junction_cos_theta))
R = self.toolhead.junction_deviation * sin_theta_d2 / (1. - sin_theta_d2) R = self.toolhead.junction_deviation * sin_theta_d2 / (1. - sin_theta_d2)
self.max_start_v2 = min( self.max_start_v2 = min(
R * self.accel, self.max_cruise_v2, prev_move.max_cruise_v2 R * self.accel, R * prev_move.accel, extruder_v2
, extruder_v2, prev_move.max_start_v2 + prev_move.delta_v2) , self.max_cruise_v2, prev_move.max_cruise_v2
, prev_move.max_start_v2 + prev_move.delta_v2)
self.max_smoothed_v2 = min( self.max_smoothed_v2 = min(
self.max_start_v2 self.max_start_v2
, prev_move.max_smoothed_v2 + prev_move.smooth_delta_v2) , prev_move.max_smoothed_v2 + prev_move.smooth_delta_v2)