shaper_calibrate: Ignore vibrations below max_psd / 20 threshold

The input shaper can only reduce vibrations by 20x. Therefore,
the best-case achievable vibrations level is max(psd) / 20.
Any vibrations below that level can be ignored for the prupose
of input shaper scoring. This allows tuning script to ignore
wide tails of resonances, because it is not helpful to try to
reduce them with input shaping.

Signed-off-by: Dmitry Butyugin <dmbutyugin@google.com>
This commit is contained in:
Dmitry Butyugin 2021-03-13 23:28:16 +01:00 committed by KevinOConnor
parent db4a254ece
commit 57494458f3
1 changed files with 16 additions and 8 deletions

View File

@ -10,6 +10,7 @@ MAX_FREQ = 200.
WINDOW_T_SEC = 0.5 WINDOW_T_SEC = 0.5
MAX_SHAPER_FREQ = 150. MAX_SHAPER_FREQ = 150.
SHAPER_VIBRATION_REDUCTION=20.
TEST_DAMPING_RATIOS=[0.075, 0.1, 0.15] TEST_DAMPING_RATIOS=[0.075, 0.1, 0.15]
SHAPER_DAMPING_RATIO = 0.1 SHAPER_DAMPING_RATIO = 0.1
@ -50,7 +51,7 @@ def get_mzv_shaper(shaper_freq, damping_ratio):
return (A, T) return (A, T)
def get_ei_shaper(shaper_freq, damping_ratio): def get_ei_shaper(shaper_freq, damping_ratio):
v_tol = 0.05 # vibration tolerance v_tol = 1. / SHAPER_VIBRATION_REDUCTION # vibration tolerance
df = math.sqrt(1. - damping_ratio**2) df = math.sqrt(1. - damping_ratio**2)
K = math.exp(-damping_ratio * math.pi / df) K = math.exp(-damping_ratio * math.pi / df)
t_d = 1. / (shaper_freq * df) t_d = 1. / (shaper_freq * df)
@ -64,7 +65,7 @@ def get_ei_shaper(shaper_freq, damping_ratio):
return (A, T) return (A, T)
def get_2hump_ei_shaper(shaper_freq, damping_ratio): def get_2hump_ei_shaper(shaper_freq, damping_ratio):
v_tol = 0.05 # vibration tolerance v_tol = 1. / SHAPER_VIBRATION_REDUCTION # vibration tolerance
df = math.sqrt(1. - damping_ratio**2) df = math.sqrt(1. - damping_ratio**2)
K = math.exp(-damping_ratio * math.pi / df) K = math.exp(-damping_ratio * math.pi / df)
t_d = 1. / (shaper_freq * df) t_d = 1. / (shaper_freq * df)
@ -81,7 +82,7 @@ def get_2hump_ei_shaper(shaper_freq, damping_ratio):
return (A, T) return (A, T)
def get_3hump_ei_shaper(shaper_freq, damping_ratio): def get_3hump_ei_shaper(shaper_freq, damping_ratio):
v_tol = 0.05 # vibration tolerance v_tol = 1. / SHAPER_VIBRATION_REDUCTION # vibration tolerance
df = math.sqrt(1. - damping_ratio**2) df = math.sqrt(1. - damping_ratio**2)
K = math.exp(-damping_ratio * math.pi / df) K = math.exp(-damping_ratio * math.pi / df)
t_d = 1. / (shaper_freq * df) t_d = 1. / (shaper_freq * df)
@ -302,8 +303,14 @@ class ShaperCalibrate:
def _estimate_remaining_vibrations(self, shaper, test_damping_ratio, def _estimate_remaining_vibrations(self, shaper, test_damping_ratio,
freq_bins, psd): freq_bins, psd):
vals = self._estimate_shaper(shaper, test_damping_ratio, freq_bins) vals = self._estimate_shaper(shaper, test_damping_ratio, freq_bins)
remaining_vibrations = (vals * psd).sum() / psd.sum() # The input shaper can only reduce the amplitude of vibrations by
return (remaining_vibrations, vals) # SHAPER_VIBRATION_REDUCTION times, so all vibrations below that
# threshold can be igonred
vibrations_threshold = psd.max() / SHAPER_VIBRATION_REDUCTION
remaining_vibrations = self.numpy.maximum(
vals * psd - vibrations_threshold, 0).sum()
all_vibrations = self.numpy.maximum(psd - vibrations_threshold, 0).sum()
return (remaining_vibrations / all_vibrations, vals)
def fit_shaper(self, shaper_cfg, calibration_data, max_smoothing): def fit_shaper(self, shaper_cfg, calibration_data, max_smoothing):
np = self.numpy np = self.numpy
@ -335,7 +342,8 @@ class ShaperCalibrate:
# The score trying to minimize vibrations, but also accounting # The score trying to minimize vibrations, but also accounting
# the growth of smoothing. The formula itself does not have any # the growth of smoothing. The formula itself does not have any
# special meaning, it simply shows good results on real user data # special meaning, it simply shows good results on real user data
shaper_score = shaper_vibrations**1.5 * shaper_smoothing shaper_score = shaper_smoothing * (shaper_vibrations**1.5 +
shaper_vibrations * .2 + .01)
results.append( results.append(
CalibrationResult( CalibrationResult(
name=shaper_cfg.name, freq=test_freq, vals=shaper_vals, name=shaper_cfg.name, freq=test_freq, vals=shaper_vals,
@ -392,10 +400,10 @@ class ShaperCalibrate:
shaper.name, round(shaper.max_accel / 100.) * 100.)) shaper.name, round(shaper.max_accel / 100.) * 100.))
all_shapers.append(shaper) all_shapers.append(shaper)
if (best_shaper is None or shaper.score * 1.2 < best_shaper.score or if (best_shaper is None or shaper.score * 1.2 < best_shaper.score or
(shaper.score * 1.1 < best_shaper.score and (shaper.score * 1.05 < best_shaper.score and
shaper.smoothing * 1.1 < best_shaper.smoothing)): shaper.smoothing * 1.1 < best_shaper.smoothing)):
# Either the shaper significantly improves the score (by 20%), # Either the shaper significantly improves the score (by 20%),
# or it improves both the score and smoothing (by 10%) # or it improves the score and smoothing (by 5% and 10% resp.)
best_shaper = shaper best_shaper = shaper
return best_shaper, all_shapers return best_shaper, all_shapers