mirror of
https://github.com/andreili/klipper.git
synced 2025-08-23 11:24:06 +02:00
motion_queuing: Add new module to help with motion queues and flushing
Create a new module to assist with host management of motion queues. Register all MCU_stepper objects with this module and use the module for step generation. All steppers will now automatically generate steps whenever toolhead._advance_flush_time() is invoked. It is no longer necessary for callers to individually call stepper.generate_steps(). Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
126275d1f4
commit
9399e738bc
@ -85,14 +85,13 @@ class ForceMove:
|
||||
self.trapq_append(self.trapq, print_time, accel_t, cruise_t, accel_t,
|
||||
0., 0., 0., axis_r, 0., 0., 0., cruise_v, accel)
|
||||
print_time = print_time + accel_t + cruise_t + accel_t
|
||||
stepper.generate_steps(print_time)
|
||||
self.trapq_finalize_moves(self.trapq, print_time + 99999.9,
|
||||
print_time + 99999.9)
|
||||
stepper.set_trapq(prev_trapq)
|
||||
stepper.set_stepper_kinematics(prev_sk)
|
||||
toolhead.note_mcu_movequeue_activity(print_time)
|
||||
toolhead.dwell(accel_t + cruise_t + accel_t)
|
||||
toolhead.flush_step_generation()
|
||||
stepper.set_trapq(prev_trapq)
|
||||
stepper.set_stepper_kinematics(prev_sk)
|
||||
self.trapq_finalize_moves(self.trapq, print_time + 99999.9,
|
||||
print_time + 99999.9)
|
||||
def _lookup_stepper(self, gcmd):
|
||||
name = gcmd.get('STEPPER')
|
||||
if name not in self.steppers:
|
||||
|
@ -76,7 +76,6 @@ class ManualStepper:
|
||||
self.sync_print_time()
|
||||
self.next_cmd_time = self._submit_move(self.next_cmd_time, movepos,
|
||||
speed, accel)
|
||||
self.rail.generate_steps(self.next_cmd_time)
|
||||
self.trapq_finalize_moves(self.trapq, self.next_cmd_time + 99999.9,
|
||||
self.next_cmd_time + 99999.9)
|
||||
toolhead = self.printer.lookup_object('toolhead')
|
||||
@ -138,7 +137,6 @@ class ManualStepper:
|
||||
raise gcmd.error("Must unregister axis first")
|
||||
# Unregister
|
||||
toolhead.remove_extra_axis(self)
|
||||
toolhead.unregister_step_generator(self.rail.generate_steps)
|
||||
self.axis_gcode_id = None
|
||||
return
|
||||
if (len(gcode_axis) != 1 or not gcode_axis.isupper()
|
||||
@ -155,7 +153,6 @@ class ManualStepper:
|
||||
self.gaxis_limit_velocity = limit_velocity
|
||||
self.gaxis_limit_accel = limit_accel
|
||||
toolhead.add_extra_axis(self, self.get_position()[0])
|
||||
toolhead.register_step_generator(self.rail.generate_steps)
|
||||
def process_move(self, print_time, move, ea_index):
|
||||
axis_r = move.axes_r[ea_index]
|
||||
start_pos = move.start_pos[ea_index]
|
||||
@ -208,7 +205,7 @@ class ManualStepper:
|
||||
speed, self.homing_accel)
|
||||
# Drip updates to motors
|
||||
toolhead = self.printer.lookup_object('toolhead')
|
||||
toolhead.drip_update_time(maxtime, drip_completion, self.steppers)
|
||||
toolhead.drip_update_time(maxtime, drip_completion)
|
||||
# Clear trapq of any remaining parts of movement
|
||||
reactor = self.printer.get_reactor()
|
||||
self.trapq_finalize_moves(self.trapq, reactor.NEVER, 0)
|
||||
|
19
klippy/extras/motion_queuing.py
Normal file
19
klippy/extras/motion_queuing.py
Normal file
@ -0,0 +1,19 @@
|
||||
# Helper code for low-level motion queuing and flushing
|
||||
#
|
||||
# Copyright (C) 2025 Kevin O'Connor <kevin@koconnor.net>
|
||||
#
|
||||
# This file may be distributed under the terms of the GNU GPLv3 license.
|
||||
import logging
|
||||
|
||||
class PrinterMotionQueuing:
|
||||
def __init__(self, config):
|
||||
self.printer = config.get_printer()
|
||||
self.steppers = []
|
||||
def register_stepper(self, config, stepper):
|
||||
self.steppers.append(stepper)
|
||||
def flush_motion_queues(self, must_flush_time, max_step_gen_time):
|
||||
for stepper in self.steppers:
|
||||
stepper.generate_steps(max_step_gen_time)
|
||||
|
||||
def load_config(config):
|
||||
return PrinterMotionQueuing(config)
|
@ -36,7 +36,6 @@ class CartKinematics:
|
||||
'safe_distance', None, minval=0.))
|
||||
for s in self.get_steppers():
|
||||
s.set_trapq(toolhead.get_trapq())
|
||||
toolhead.register_step_generator(s.generate_steps)
|
||||
# Setup boundary checks
|
||||
max_velocity, max_accel = toolhead.get_max_velocity()
|
||||
self.max_z_velocity = config.getfloat('max_z_velocity', max_velocity,
|
||||
|
@ -20,7 +20,6 @@ class CoreXYKinematics:
|
||||
self.rails[2].setup_itersolve('cartesian_stepper_alloc', b'z')
|
||||
for s in self.get_steppers():
|
||||
s.set_trapq(toolhead.get_trapq())
|
||||
toolhead.register_step_generator(s.generate_steps)
|
||||
# Setup boundary checks
|
||||
max_velocity, max_accel = toolhead.get_max_velocity()
|
||||
self.max_z_velocity = config.getfloat(
|
||||
|
@ -20,7 +20,6 @@ class CoreXZKinematics:
|
||||
self.rails[2].setup_itersolve('corexz_stepper_alloc', b'-')
|
||||
for s in self.get_steppers():
|
||||
s.set_trapq(toolhead.get_trapq())
|
||||
toolhead.register_step_generator(s.generate_steps)
|
||||
# Setup boundary checks
|
||||
max_velocity, max_accel = toolhead.get_max_velocity()
|
||||
self.max_z_velocity = config.getfloat(
|
||||
|
@ -52,7 +52,6 @@ class DeltaKinematics:
|
||||
r.setup_itersolve('delta_stepper_alloc', a, t[0], t[1])
|
||||
for s in self.get_steppers():
|
||||
s.set_trapq(toolhead.get_trapq())
|
||||
toolhead.register_step_generator(s.generate_steps)
|
||||
# Setup boundary checks
|
||||
self.need_home = True
|
||||
self.limit_xy2 = -1.
|
||||
|
@ -40,7 +40,6 @@ class DeltesianKinematics:
|
||||
self.rails[2].setup_itersolve('cartesian_stepper_alloc', b'y')
|
||||
for s in self.get_steppers():
|
||||
s.set_trapq(toolhead.get_trapq())
|
||||
toolhead.register_step_generator(s.generate_steps)
|
||||
self.limits = [(1.0, -1.0)] * 3
|
||||
# X axis limits
|
||||
min_angle = config.getfloat('min_angle', MIN_ANGLE,
|
||||
|
@ -39,8 +39,6 @@ class ExtruderStepper:
|
||||
self.name, self.cmd_SYNC_EXTRUDER_MOTION,
|
||||
desc=self.cmd_SYNC_EXTRUDER_MOTION_help)
|
||||
def _handle_connect(self):
|
||||
toolhead = self.printer.lookup_object('toolhead')
|
||||
toolhead.register_step_generator(self.stepper.generate_steps)
|
||||
self._set_pressure_advance(self.config_pa, self.config_smooth_time)
|
||||
def get_status(self, eventtime):
|
||||
return {'pressure_advance': self.pressure_advance,
|
||||
|
@ -108,7 +108,6 @@ class GenericCartesianKinematics:
|
||||
self._load_kinematics(config)
|
||||
for s in self.get_steppers():
|
||||
s.set_trapq(toolhead.get_trapq())
|
||||
toolhead.register_step_generator(s.generate_steps)
|
||||
self.dc_module = None
|
||||
if self.dc_carriages:
|
||||
pcs = [dc.get_dual_carriage() for dc in self.dc_carriages]
|
||||
|
@ -39,7 +39,6 @@ class HybridCoreXYKinematics:
|
||||
'safe_distance', None, minval=0.))
|
||||
for s in self.get_steppers():
|
||||
s.set_trapq(toolhead.get_trapq())
|
||||
toolhead.register_step_generator(s.generate_steps)
|
||||
# Setup boundary checks
|
||||
max_velocity, max_accel = toolhead.get_max_velocity()
|
||||
self.max_z_velocity = config.getfloat(
|
||||
|
@ -39,7 +39,6 @@ class HybridCoreXZKinematics:
|
||||
'safe_distance', None, minval=0.))
|
||||
for s in self.get_steppers():
|
||||
s.set_trapq(toolhead.get_trapq())
|
||||
toolhead.register_step_generator(s.generate_steps)
|
||||
# Setup boundary checks
|
||||
max_velocity, max_accel = toolhead.get_max_velocity()
|
||||
self.max_z_velocity = config.getfloat(
|
||||
|
@ -21,7 +21,6 @@ class PolarKinematics:
|
||||
for s in r.get_steppers() ]
|
||||
for s in self.get_steppers():
|
||||
s.set_trapq(toolhead.get_trapq())
|
||||
toolhead.register_step_generator(s.generate_steps)
|
||||
# Setup boundary checks
|
||||
max_velocity, max_accel = toolhead.get_max_velocity()
|
||||
self.max_z_velocity = config.getfloat(
|
||||
|
@ -52,7 +52,6 @@ class RotaryDeltaKinematics:
|
||||
math.radians(a), ua, la)
|
||||
for s in self.get_steppers():
|
||||
s.set_trapq(toolhead.get_trapq())
|
||||
toolhead.register_step_generator(s.generate_steps)
|
||||
# Setup boundary checks
|
||||
self.need_home = True
|
||||
self.limit_xy2 = -1.
|
||||
|
@ -21,7 +21,6 @@ class WinchKinematics:
|
||||
self.anchors.append(a)
|
||||
s.setup_itersolve('winch_stepper_alloc', *a)
|
||||
s.set_trapq(toolhead.get_trapq())
|
||||
toolhead.register_step_generator(s.generate_steps)
|
||||
# Setup boundary checks
|
||||
acoords = list(zip(*self.anchors))
|
||||
self.axes_min = toolhead.Coord(*[min(a) for a in acoords], e=0.)
|
||||
|
@ -273,7 +273,8 @@ def PrinterStepper(config, units_in_radians=False):
|
||||
rotation_dist, steps_per_rotation,
|
||||
step_pulse_duration, units_in_radians)
|
||||
# Register with helper modules
|
||||
for mname in ['stepper_enable', 'force_move', 'motion_report']:
|
||||
mods = ['stepper_enable', 'force_move', 'motion_report', 'motion_queuing']
|
||||
for mname in mods:
|
||||
m = printer.load_object(config, mname)
|
||||
m.register_stepper(config, mcu_stepper)
|
||||
return mcu_stepper
|
||||
@ -442,9 +443,6 @@ class GenericPrinterRail:
|
||||
def setup_itersolve(self, alloc_func, *params):
|
||||
for stepper in self.steppers:
|
||||
stepper.setup_itersolve(alloc_func, *params)
|
||||
def generate_steps(self, flush_time):
|
||||
for stepper in self.steppers:
|
||||
stepper.generate_steps(flush_time)
|
||||
def set_trapq(self, trapq):
|
||||
for stepper in self.steppers:
|
||||
stepper.set_trapq(trapq)
|
||||
|
@ -251,7 +251,7 @@ class ToolHead:
|
||||
self.trapq_append = ffi_lib.trapq_append
|
||||
self.trapq_finalize_moves = ffi_lib.trapq_finalize_moves
|
||||
# Motion flushing
|
||||
self.step_generators = []
|
||||
self.motion_queuing = self.printer.load_object(config, 'motion_queuing')
|
||||
self.flush_trapqs = [self.trapq]
|
||||
# Create kinematics class
|
||||
gcode = self.printer.lookup_object('gcode')
|
||||
@ -280,8 +280,7 @@ class ToolHead:
|
||||
sg_flush_want = min(flush_time + STEPCOMPRESS_FLUSH_TIME,
|
||||
self.print_time - self.kin_flush_delay)
|
||||
sg_flush_time = max(sg_flush_want, flush_time)
|
||||
for sg in self.step_generators:
|
||||
sg(sg_flush_time)
|
||||
self.motion_queuing.flush_motion_queues(flush_time, sg_flush_time)
|
||||
self.min_restart_time = max(self.min_restart_time, sg_flush_time)
|
||||
# Free trapq entries that are no longer needed
|
||||
clear_history_time = self.clear_history_time
|
||||
@ -517,7 +516,7 @@ class ToolHead:
|
||||
def get_extra_axes(self):
|
||||
return [None, None, None] + self.extra_axes
|
||||
# Homing "drip move" handling
|
||||
def drip_update_time(self, next_print_time, drip_completion, addstepper=()):
|
||||
def drip_update_time(self, next_print_time, drip_completion):
|
||||
# Transition from "NeedPrime"/"Priming"/main state to "Drip" state
|
||||
self.special_queuing_state = "Drip"
|
||||
self.need_check_pause = self.reactor.NEVER
|
||||
@ -539,8 +538,6 @@ class ToolHead:
|
||||
continue
|
||||
npt = min(self.print_time + DRIP_SEGMENT_TIME, next_print_time)
|
||||
self.note_mcu_movequeue_activity(npt + self.kin_flush_delay)
|
||||
for stepper in addstepper:
|
||||
stepper.generate_steps(npt)
|
||||
self._advance_move_time(npt)
|
||||
# Exit "Drip" state
|
||||
self.reactor.update_timer(self.flush_timer, self.reactor.NOW)
|
||||
@ -617,11 +614,6 @@ class ToolHead:
|
||||
return self.kin
|
||||
def get_trapq(self):
|
||||
return self.trapq
|
||||
def register_step_generator(self, handler):
|
||||
self.step_generators.append(handler)
|
||||
def unregister_step_generator(self, handler):
|
||||
if handler in self.step_generators:
|
||||
self.step_generators.remove(handler)
|
||||
def note_step_generation_scan_time(self, delay, old_delay=0.):
|
||||
self.flush_step_generation()
|
||||
if old_delay:
|
||||
|
Loading…
x
Reference in New Issue
Block a user