diff options
Diffstat (limited to 'klippy/extras/input_shaper.py')
-rw-r--r-- | klippy/extras/input_shaper.py | 137 |
1 files changed, 89 insertions, 48 deletions
diff --git a/klippy/extras/input_shaper.py b/klippy/extras/input_shaper.py index 67a287cd..11218d55 100644 --- a/klippy/extras/input_shaper.py +++ b/klippy/extras/input_shaper.py @@ -8,44 +8,54 @@ import collections import chelper from . import shaper_defs + class InputShaperParams: def __init__(self, axis, config): self.axis = axis - self.shapers = {s.name : s.init_func for s in shaper_defs.INPUT_SHAPERS} - shaper_type = config.get('shaper_type', 'mzv') - self.shaper_type = config.get('shaper_type_' + axis, shaper_type) + self.shapers = {s.name: s.init_func for s in shaper_defs.INPUT_SHAPERS} + shaper_type = config.get("shaper_type", "mzv") + self.shaper_type = config.get("shaper_type_" + axis, shaper_type) if self.shaper_type not in self.shapers: - raise config.error( - 'Unsupported shaper type: %s' % (self.shaper_type,)) - self.damping_ratio = config.getfloat('damping_ratio_' + axis, - shaper_defs.DEFAULT_DAMPING_RATIO, - minval=0., maxval=1.) - self.shaper_freq = config.getfloat('shaper_freq_' + axis, 0., minval=0.) + raise config.error("Unsupported shaper type: %s" % (self.shaper_type,)) + self.damping_ratio = config.getfloat( + "damping_ratio_" + axis, + shaper_defs.DEFAULT_DAMPING_RATIO, + minval=0.0, + maxval=1.0, + ) + self.shaper_freq = config.getfloat("shaper_freq_" + axis, 0.0, minval=0.0) + def update(self, gcmd): axis = self.axis.upper() - self.damping_ratio = gcmd.get_float('DAMPING_RATIO_' + axis, - self.damping_ratio, - minval=0., maxval=1.) - self.shaper_freq = gcmd.get_float('SHAPER_FREQ_' + axis, - self.shaper_freq, minval=0.) - shaper_type = gcmd.get('SHAPER_TYPE', None) + self.damping_ratio = gcmd.get_float( + "DAMPING_RATIO_" + axis, self.damping_ratio, minval=0.0, maxval=1.0 + ) + self.shaper_freq = gcmd.get_float( + "SHAPER_FREQ_" + axis, self.shaper_freq, minval=0.0 + ) + shaper_type = gcmd.get("SHAPER_TYPE", None) if shaper_type is None: - shaper_type = gcmd.get('SHAPER_TYPE_' + axis, self.shaper_type) + shaper_type = gcmd.get("SHAPER_TYPE_" + axis, self.shaper_type) if shaper_type.lower() not in self.shapers: - raise gcmd.error('Unsupported shaper type: %s' % (shaper_type,)) + raise gcmd.error("Unsupported shaper type: %s" % (shaper_type,)) self.shaper_type = shaper_type.lower() + def get_shaper(self): if not self.shaper_freq: A, T = shaper_defs.get_none_shaper() else: - A, T = self.shapers[self.shaper_type]( - self.shaper_freq, self.damping_ratio) + A, T = self.shapers[self.shaper_type](self.shaper_freq, self.damping_ratio) return len(A), A, T + def get_status(self): - return collections.OrderedDict([ - ('shaper_type', self.shaper_type), - ('shaper_freq', '%.3f' % (self.shaper_freq,)), - ('damping_ratio', '%.6f' % (self.damping_ratio,))]) + return collections.OrderedDict( + [ + ("shaper_type", self.shaper_type), + ("shaper_freq", "%.3f" % (self.shaper_freq,)), + ("damping_ratio", "%.6f" % (self.damping_ratio,)), + ] + ) + class AxisInputShaper: def __init__(self, axis, config): @@ -53,72 +63,96 @@ class AxisInputShaper: self.params = InputShaperParams(axis, config) self.n, self.A, self.T = self.params.get_shaper() self.saved = None + def get_name(self): - return 'shaper_' + self.axis + return "shaper_" + self.axis + def get_shaper(self): return self.n, self.A, self.T + def update(self, gcmd): self.params.update(gcmd) self.n, self.A, self.T = self.params.get_shaper() + def set_shaper_kinematics(self, sk): ffi_main, ffi_lib = chelper.get_ffi() - success = ffi_lib.input_shaper_set_shaper_params( - sk, self.axis.encode(), self.n, self.A, self.T) == 0 + success = ( + ffi_lib.input_shaper_set_shaper_params( + sk, self.axis.encode(), self.n, self.A, self.T + ) + == 0 + ) if not success: self.disable_shaping() ffi_lib.input_shaper_set_shaper_params( - sk, self.axis.encode(), self.n, self.A, self.T) + sk, self.axis.encode(), self.n, self.A, self.T + ) return success + def is_enabled(self): return self.n > 0 + def disable_shaping(self): if self.saved is None and self.n: self.saved = (self.n, self.A, self.T) A, T = shaper_defs.get_none_shaper() self.n, self.A, self.T = len(A), A, T + def enable_shaping(self): if self.saved is None: # Input shaper was not disabled return self.n, self.A, self.T = self.saved self.saved = None + def report(self, gcmd): - info = ' '.join(["%s_%s:%s" % (key, self.axis, value) - for (key, value) in self.params.get_status().items()]) + info = " ".join( + [ + "%s_%s:%s" % (key, self.axis, value) + for (key, value) in self.params.get_status().items() + ] + ) gcmd.respond_info(info) + class InputShaper: def __init__(self, config): self.printer = config.get_printer() self.printer.register_event_handler("klippy:connect", self.connect) - self.printer.register_event_handler("dual_carriage:update_kinematics", - self._update_kinematics) + self.printer.register_event_handler( + "dual_carriage:update_kinematics", self._update_kinematics + ) self.toolhead = None - self.shapers = [AxisInputShaper('x', config), - AxisInputShaper('y', config)] + self.shapers = [AxisInputShaper("x", config), AxisInputShaper("y", config)] self.input_shaper_stepper_kinematics = [] self.orig_stepper_kinematics = [] # Register gcode commands - gcode = self.printer.lookup_object('gcode') - gcode.register_command("SET_INPUT_SHAPER", - self.cmd_SET_INPUT_SHAPER, - desc=self.cmd_SET_INPUT_SHAPER_help) + gcode = self.printer.lookup_object("gcode") + gcode.register_command( + "SET_INPUT_SHAPER", + self.cmd_SET_INPUT_SHAPER, + desc=self.cmd_SET_INPUT_SHAPER_help, + ) + def get_shapers(self): return self.shapers + def connect(self): self.toolhead = self.printer.lookup_object("toolhead") - dual_carriage = self.printer.lookup_object('dual_carriage', None) + dual_carriage = self.printer.lookup_object("dual_carriage", None) if dual_carriage is not None: for shaper in self.shapers: if shaper.is_enabled(): raise self.printer.config_error( - 'Input shaper parameters cannot be configured via' - ' [input_shaper] section with dual_carriage(s) ' - ' enabled. Refer to Klipper documentation on how ' - ' to configure input shaper for dual_carriage(s).') + "Input shaper parameters cannot be configured via" + " [input_shaper] section with dual_carriage(s) " + " enabled. Refer to Klipper documentation on how " + " to configure input shaper for dual_carriage(s)." + ) return # Configure initial values self._update_input_shaping(error=self.printer.config_error) + def _get_input_shaper_stepper_kinematics(self, stepper): # Lookup stepper kinematics sk = stepper.get_stepper_kinematics() @@ -134,6 +168,7 @@ class InputShaper: self.orig_stepper_kinematics.append(sk) self.input_shaper_stepper_kinematics.append(is_sk) return is_sk + def _update_kinematics(self): if self.toolhead is None: # Klipper initialization is not yet completed @@ -150,8 +185,8 @@ class InputShaper: ffi_lib.input_shaper_update_sk(is_sk) new_delay = ffi_lib.input_shaper_get_step_generation_window(is_sk) if old_delay != new_delay: - self.toolhead.note_step_generation_scan_time(new_delay, - old_delay) + self.toolhead.note_step_generation_scan_time(new_delay, old_delay) + def _update_input_shaping(self, error=None): self.toolhead.flush_step_generation() ffi_main, ffi_lib = chelper.get_ffi() @@ -171,21 +206,26 @@ class InputShaper: failed_shapers.append(shaper) new_delay = ffi_lib.input_shaper_get_step_generation_window(is_sk) if old_delay != new_delay: - self.toolhead.note_step_generation_scan_time(new_delay, - old_delay) + self.toolhead.note_step_generation_scan_time(new_delay, old_delay) if failed_shapers: error = error or self.printer.command_error - raise error("Failed to configure shaper(s) %s with given parameters" - % (', '.join([s.get_name() for s in failed_shapers]))) + raise error( + "Failed to configure shaper(s) %s with given parameters" + % (", ".join([s.get_name() for s in failed_shapers])) + ) + def disable_shaping(self): for shaper in self.shapers: shaper.disable_shaping() self._update_input_shaping() + def enable_shaping(self): for shaper in self.shapers: shaper.enable_shaping() self._update_input_shaping() + cmd_SET_INPUT_SHAPER_help = "Set cartesian parameters for input shaper" + def cmd_SET_INPUT_SHAPER(self, gcmd): if gcmd.get_command_parameters(): for shaper in self.shapers: @@ -194,5 +234,6 @@ class InputShaper: for shaper in self.shapers: shaper.report(gcmd) + def load_config(config): return InputShaper(config) |