diff options
Diffstat (limited to 'klippy/extras/shaper_calibrate.py')
-rw-r--r-- | klippy/extras/shaper_calibrate.py | 52 |
1 files changed, 37 insertions, 15 deletions
diff --git a/klippy/extras/shaper_calibrate.py b/klippy/extras/shaper_calibrate.py index af77845c..f3bfd8d2 100644 --- a/klippy/extras/shaper_calibrate.py +++ b/klippy/extras/shaper_calibrate.py @@ -1,6 +1,6 @@ # Automatic calibration of input shapers # -# Copyright (C) 2020 Dmitry Butyugin <dmbutyugin@google.com> +# Copyright (C) 2020-2024 Dmitry Butyugin <dmbutyugin@google.com> # # This file may be distributed under the terms of the GNU GPLv3 license. import collections, importlib, logging, math, multiprocessing, traceback @@ -227,34 +227,49 @@ class ShaperCalibrate: offset_180 *= inv_D return max(offset_90, offset_180) - def fit_shaper(self, shaper_cfg, calibration_data, max_smoothing): + def fit_shaper(self, shaper_cfg, calibration_data, shaper_freqs, + damping_ratio, scv, max_smoothing, test_damping_ratios, + max_freq): np = self.numpy - test_freqs = np.arange(shaper_cfg.min_freq, MAX_SHAPER_FREQ, .2) + damping_ratio = damping_ratio or shaper_defs.DEFAULT_DAMPING_RATIO + test_damping_ratios = test_damping_ratios or TEST_DAMPING_RATIOS + + if not shaper_freqs: + shaper_freqs = (None, None, None) + if isinstance(shaper_freqs, tuple): + freq_end = shaper_freqs[1] or MAX_SHAPER_FREQ + freq_start = min(shaper_freqs[0] or shaper_cfg.min_freq, + freq_end - 1e-7) + freq_step = shaper_freqs[2] or .2 + test_freqs = np.arange(freq_start, freq_end, freq_step) + else: + test_freqs = np.array(shaper_freqs) + + max_freq = max(max_freq or MAX_FREQ, test_freqs.max()) freq_bins = calibration_data.freq_bins - psd = calibration_data.psd_sum[freq_bins <= MAX_FREQ] - freq_bins = freq_bins[freq_bins <= MAX_FREQ] + psd = calibration_data.psd_sum[freq_bins <= max_freq] + freq_bins = freq_bins[freq_bins <= max_freq] best_res = None results = [] for test_freq in test_freqs[::-1]: shaper_vibrations = 0. shaper_vals = np.zeros(shape=freq_bins.shape) - shaper = shaper_cfg.init_func( - test_freq, shaper_defs.DEFAULT_DAMPING_RATIO) - shaper_smoothing = self._get_shaper_smoothing(shaper) + shaper = shaper_cfg.init_func(test_freq, damping_ratio) + shaper_smoothing = self._get_shaper_smoothing(shaper, scv=scv) if max_smoothing and shaper_smoothing > max_smoothing and best_res: return best_res # Exact damping ratio of the printer is unknown, pessimizing # remaining vibrations over possible damping values - for dr in TEST_DAMPING_RATIOS: + for dr in test_damping_ratios: vibrations, vals = self._estimate_remaining_vibrations( shaper, dr, freq_bins, psd) shaper_vals = np.maximum(shaper_vals, vals) if vibrations > shaper_vibrations: shaper_vibrations = vibrations - max_accel = self.find_shaper_max_accel(shaper) + max_accel = self.find_shaper_max_accel(shaper, scv) # The score trying to minimize vibrations, but also accounting # the growth of smoothing. The formula itself does not have any # special meaning, it simply shows good results on real user data @@ -278,6 +293,8 @@ class ShaperCalibrate: def _bisect(self, func): left = right = 1. + if not func(1e-9): + return 0. while not func(left): right = left left *= .5 @@ -292,22 +309,27 @@ class ShaperCalibrate: right = middle return left - def find_shaper_max_accel(self, shaper): + def find_shaper_max_accel(self, shaper, scv): # Just some empirically chosen value which produces good projections # for max_accel without much smoothing TARGET_SMOOTHING = 0.12 max_accel = self._bisect(lambda test_accel: self._get_shaper_smoothing( - shaper, test_accel) <= TARGET_SMOOTHING) + shaper, test_accel, scv) <= TARGET_SMOOTHING) return max_accel - def find_best_shaper(self, calibration_data, max_smoothing, logger=None): + def find_best_shaper(self, calibration_data, shapers=None, + damping_ratio=None, scv=None, shaper_freqs=None, + max_smoothing=None, test_damping_ratios=None, + max_freq=None, logger=None): best_shaper = None all_shapers = [] + shapers = shapers or AUTOTUNE_SHAPERS for shaper_cfg in shaper_defs.INPUT_SHAPERS: - if shaper_cfg.name not in AUTOTUNE_SHAPERS: + if shaper_cfg.name not in shapers: continue shaper = self.background_process_exec(self.fit_shaper, ( - shaper_cfg, calibration_data, max_smoothing)) + shaper_cfg, calibration_data, shaper_freqs, damping_ratio, + scv, max_smoothing, test_damping_ratios, max_freq)) if logger is not None: logger("Fitted shaper '%s' frequency = %.1f Hz " "(vibrations = %.1f%%, smoothing ~= %.3f)" % ( |