small code cleaning and fixes
This commit is contained in:
12
README.md
12
README.md
@@ -33,22 +33,22 @@ Follow these steps to install Shake&Tune on your printer:
|
||||
# The maximum time in seconds to let Shake&Tune process the CSV files and generate the graphs.
|
||||
|
||||
# motor_freq:
|
||||
# /!\ This option is only available in DangerKlipper /!\
|
||||
# /!\ This option has limitations in stock Klipper and is best used with DangerKlipper /!\
|
||||
# Frequencies of X and Y motor resonances to filter them using
|
||||
# composite shapers. This require the `[input_shaper]` config
|
||||
# composite shapers. This requires the `[input_shaper]` config
|
||||
# section to be defined in your printer.cfg file to work.
|
||||
# motor_freq_x:
|
||||
# motor_freq_y:
|
||||
# /!\ This option is only available in DangerKlipper /!\
|
||||
# /!\ This option has limitations in stock Klipper and is best used with DangerKlipper /!\
|
||||
# If motor_freq is not set, these two parameters can be used
|
||||
# to configure different filters for X and Y motors. The same
|
||||
# values are supported as for motor_freq parameter.
|
||||
# motor_damping_ratio: 0.05
|
||||
# /!\ This option is only available in DangerKlipper /!\
|
||||
# Damping ratios of X and Y motor resonances.
|
||||
# /!\ This option has limitations in stock Klipper and is best used with DangerKlipper /!\
|
||||
# Damping ratios for X and Y motor resonances.
|
||||
# motor_damping_ratio_x:
|
||||
# motor_damping_ratio_y:
|
||||
# /!\ This option is only available in DangerKlipper /!\
|
||||
# /!\ This option has limitations in stock Klipper and is best used with DangerKlipper /!\
|
||||
# If motor_damping_ratio is not set, these two parameters can be used
|
||||
# to configure different filters for X and Y motors. The same values
|
||||
# are supported as for motor_damping_ratio parameter.
|
||||
|
||||
@@ -26,7 +26,7 @@ class MotorResonanceFilter:
|
||||
|
||||
self._original_shapers = {}
|
||||
|
||||
# Convolve two Klipper shapers into a new composite shaper
|
||||
# Convolve two Klipper shapers into a new custom composite input shaping filter
|
||||
@staticmethod
|
||||
def convolve_shapers(L, R):
|
||||
As = [a * b for a in L[0] for b in R[0]]
|
||||
@@ -36,6 +36,11 @@ class MotorResonanceFilter:
|
||||
|
||||
def apply_filters(self) -> None:
|
||||
input_shaper = self._printer.lookup_object('input_shaper', None)
|
||||
if input_shaper is None:
|
||||
raise ValueError(
|
||||
'Unable to apply Shake&Tune motor resonance filters: no [input_shaper] config section found!'
|
||||
)
|
||||
|
||||
shapers = input_shaper.get_shapers()
|
||||
for shaper in shapers:
|
||||
axis = shaper.axis
|
||||
@@ -71,7 +76,7 @@ class MotorResonanceFilter:
|
||||
ConsoleOutput.print(
|
||||
(
|
||||
f'Error: the {axis} axis is not a ZV type shaper. Shake&Tune motor resonance filters '
|
||||
'will be ignored for this axis... Thi is due to the size of the pulse train being too '
|
||||
'will be ignored for this axis... This is due to the size of the pulse train being too '
|
||||
'small and not allowing the convolved shapers to be applied... unless this PR is '
|
||||
'merged: https://github.com/Klipper3d/klipper/pull/6460'
|
||||
)
|
||||
@@ -109,6 +114,11 @@ class MotorResonanceFilter:
|
||||
|
||||
def remove_filters(self) -> None:
|
||||
input_shaper = self._printer.lookup_object('input_shaper', None)
|
||||
if input_shaper is None:
|
||||
raise ValueError(
|
||||
'Unable to deactivate Shake&Tune motor resonance filters: no [input_shaper] config section found!'
|
||||
)
|
||||
|
||||
shapers = input_shaper.get_shapers()
|
||||
for shaper in shapers:
|
||||
axis = shaper.axis
|
||||
|
||||
@@ -31,7 +31,6 @@ from .motor_res_filter import MotorResonanceFilter
|
||||
from .shaketune_config import ShakeTuneConfig
|
||||
from .shaketune_process import ShakeTuneProcess
|
||||
|
||||
IN_DANGER = False
|
||||
DEFAULT_MOTOR_DAMPING_RATIO = 0.05
|
||||
ST_COMMANDS = {
|
||||
'EXCITATE_AXIS_AT_FREQ': (
|
||||
@@ -58,33 +57,18 @@ class ShakeTune:
|
||||
def __init__(self, config) -> None:
|
||||
self._config = config
|
||||
self._printer = config.get_printer()
|
||||
|
||||
self._initialize_danger_klipper()
|
||||
self._initialize_console_output()
|
||||
self._validate_resonance_tester()
|
||||
self._initialize_config(config)
|
||||
self._register_commands()
|
||||
self._initialize_motor_resonance_filter()
|
||||
self._printer.register_event_handler('klippy:connect', self._on_klippy_connect)
|
||||
|
||||
# Check if Shake&Tune is running in DangerKlipper
|
||||
def _initialize_danger_klipper(self) -> None:
|
||||
global IN_DANGER
|
||||
if importlib.util.find_spec('extras.danger_options') is not None:
|
||||
IN_DANGER = True
|
||||
self.IN_DANGER = importlib.util.find_spec('extras.danger_options') is not None
|
||||
|
||||
# Register the console print output callback to the corresponding Klipper function
|
||||
def _initialize_console_output(self) -> None:
|
||||
gcode = self._printer.lookup_object('gcode')
|
||||
ConsoleOutput.register_output_callback(gcode.respond_info)
|
||||
|
||||
# Check if the resonance_tester object is available in the printer
|
||||
# configuration as it is required for Shake&Tune to work properly
|
||||
def _validate_resonance_tester(self) -> None:
|
||||
res_tester = self._printer.lookup_object('resonance_tester', None)
|
||||
if res_tester is None:
|
||||
raise self._config.error(
|
||||
'No [resonance_tester] config section found in printer.cfg! Please add one to use Shake&Tune.'
|
||||
)
|
||||
self._initialize_config(config)
|
||||
self._register_commands()
|
||||
self._initialize_motor_resonance_filter()
|
||||
|
||||
# Initialize the ShakeTune object and its configuration
|
||||
def _initialize_config(self, config) -> None:
|
||||
@@ -155,44 +139,63 @@ class ShakeTune:
|
||||
self._printer.load_object(self._config, gcode_macro_name.lower())
|
||||
|
||||
# Register the motor resonance filters if they are defined in the config
|
||||
# DangerKlipper is required for now or a degraded system forcing the ZV filter for
|
||||
# both input shaping and motor resonance filter will be used instead. But this will
|
||||
# DangerKlipper is required for the full feature but a degraded system forcing the ZV filter for
|
||||
# both input shaping and motor resonance filter will be used instead in stock Klipper. But this might
|
||||
# be improved in the future if https://github.com/Klipper3d/klipper/pull/6460 get merged
|
||||
# TODO: To mitigate this issue, add a automated patch to klippy/chelper/kin_shaper.c
|
||||
# TODO: To mitigate this issue, add an automated patch to klippy/chelper/kin_shaper.c
|
||||
# (using a .diff file) to enable the motor filters in stock Klipper as well.
|
||||
# But this will make the Klipper repo dirty to moonraker update manager, so I'm not
|
||||
# sure how to handle this. Maybe with also a command to revert the patch? Or a
|
||||
# manual command to apply the patch with a required user action?
|
||||
def _initialize_motor_resonance_filter(self) -> None:
|
||||
if self._motor_freq_x is not None and self._motor_freq_y is not None:
|
||||
input_shaper = self._printer.lookup_object('input_shaper', None)
|
||||
if input_shaper is None:
|
||||
raise self._config.error(
|
||||
(
|
||||
'Error: motor resonance filters cannot be enabled because the standard '
|
||||
'[input_shaper] Klipper config section is not configured!'
|
||||
)
|
||||
)
|
||||
|
||||
self._printer.register_event_handler('klippy:ready', self._on_klippy_ready)
|
||||
gcode = self._printer.lookup_object('gcode')
|
||||
gcode.register_command(
|
||||
'MOTOR_RESONANCE_FILTER', self.cmd_MOTOR_RESONANCE_FILTER, desc='Enable/disable motor resonance filters'
|
||||
'MOTOR_RESONANCE_FILTER',
|
||||
self.cmd_MOTOR_RESONANCE_FILTER,
|
||||
desc='Enable/disable the motor resonance filters',
|
||||
)
|
||||
|
||||
self.motor_resonance_filter = MotorResonanceFilter(
|
||||
self._printer,
|
||||
self._motor_freq_x,
|
||||
self._motor_freq_y,
|
||||
self._motor_damping_x,
|
||||
self._motor_damping_y,
|
||||
IN_DANGER,
|
||||
self.IN_DANGER,
|
||||
)
|
||||
|
||||
self._printer.register_event_handler('klippy:ready', self.handle_ready)
|
||||
def _on_klippy_connect(self) -> None:
|
||||
# Check if the resonance_tester object is available in the printer
|
||||
# configuration as it is required for Shake&Tune to work properly
|
||||
res_tester = self._printer.lookup_object('resonance_tester', None)
|
||||
if res_tester is None:
|
||||
raise self._config.error(
|
||||
'No [resonance_tester] config section found in printer.cfg! Please add one to use Shake&Tune!'
|
||||
)
|
||||
|
||||
def handle_ready(self) -> None:
|
||||
# In case the user has configured a motor resonance filter, we need to make sure
|
||||
# that the input shaper is configured as well in order to use them. This is because
|
||||
# the input shaper object is the one used to actually applies the additional filters
|
||||
if self._motor_freq_x is not None and self._motor_freq_y is not None:
|
||||
input_shaper = self._printer.lookup_object('input_shaper', None)
|
||||
if input_shaper is None:
|
||||
raise self._config.error(
|
||||
(
|
||||
'No [input_shaper] config section found in printer.cfg! Please add one to use Shake&Tune '
|
||||
'motor resonance filters!'
|
||||
)
|
||||
)
|
||||
|
||||
def _on_klippy_ready(self) -> None:
|
||||
self.motor_resonance_filter.apply_filters()
|
||||
|
||||
# ------------------------------------------------------------------------------------------
|
||||
# ------------------------------------------------------------------------------------------
|
||||
# Following are all the Shake&Tune commands that are registered to the Klipper console
|
||||
# ------------------------------------------------------------------------------------------
|
||||
# ------------------------------------------------------------------------------------------
|
||||
|
||||
def cmd_EXCITATE_AXIS_AT_FREQ(self, gcmd) -> None:
|
||||
ConsoleOutput.print(f'Shake&Tune version: {ShakeTuneConfig.get_git_version()}')
|
||||
static_freq_graph_creator = StaticGraphCreator(self._st_config)
|
||||
|
||||
Reference in New Issue
Block a user