From 60a344bdcb00349f7583ef465c3d8a3930658304 Mon Sep 17 00:00:00 2001 From: Neelix Date: Fri, 23 Jan 2026 18:54:42 +0100 Subject: [PATCH 1/4] polar kinemcatics: adds velocity scaling Print near the origin lead in to fast motor movements, therefore the movement needs to be scaled down. The start of the scaling is done via a critical radius variable from the config Signed-off-by: Nils Hensch nils.hensch@gmx.de --- klippy/kinematics/polar.py | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/klippy/kinematics/polar.py b/klippy/kinematics/polar.py index 422c9981f..cdaa1d436 100644 --- a/klippy/kinematics/polar.py +++ b/klippy/kinematics/polar.py @@ -6,6 +6,25 @@ import logging, math import stepper + +def distance_line_to_point(p1, p2): + ab_x = p2[0]-p1[0] + ab_y = p2[1]-p1[1] + ap_x = -p1[0] + ap_y = -p1[1] + + ab_ap_dot_product = ab_x * ap_x + ab_y * ap_y + ab_length = math.sqrt(ab_x ** 2 + ab_y ** 2) + + # Check if the projected point lies on the bounded line segment + if ab_ap_dot_product <= -0.1: + dist = math.sqrt(ap_x ** 2 + ap_y ** 2) + elif ab_ap_dot_product >= ab_length ** 2: + dist = math.sqrt(p2[0] ** 2 + p2[1] ** 2) + else: + dist = abs(ab_x * ap_y - ab_y * ap_x) / ab_length + return dist + class PolarKinematics: def __init__(self, toolhead, config): # Setup axis steppers @@ -22,11 +41,13 @@ class PolarKinematics: for s in self.get_steppers(): s.set_trapq(toolhead.get_trapq()) # Setup boundary checks - max_velocity, max_accel = toolhead.get_max_velocity() + self.max_velocity, self.max_accel = toolhead.get_max_velocity() self.max_z_velocity = config.getfloat( - 'max_z_velocity', max_velocity, above=0., maxval=max_velocity) + 'max_z_velocity', self.max_velocity, above=0., maxval=self.max_velocity) self.max_z_accel = config.getfloat( - 'max_z_accel', max_accel, above=0., maxval=max_accel) + 'max_z_accel', self.max_accel, above=0., maxval=self.max_accel) + self.critical_radius = config.getfloat( + 'critical_radius', above=0., default=0) self.limit_z = (1.0, -1.0) self.limit_xy2 = -1. max_xy = self.rails[0].get_range()[1] @@ -101,6 +122,15 @@ class PolarKinematics: z_ratio = move.move_d / abs(move.axes_d[2]) move.limit_speed(self.max_z_velocity * z_ratio, self.max_z_accel * z_ratio) + # Slow down near center + if move.axes_d[0] or move.axes_d[1]: + if self.critical_radius != 0: + min_dist = distance_line_to_point(move.start_pos[0:2], move.end_pos[0:2]) + if min_dist <= self.critical_radius: + if min_dist != 0: + scale_radius = min_dist/self.critical_radius + move.limit_speed(self.max_velocity * scale_radius, self.max_accel * scale_radius) + def get_status(self, eventtime): xy_home = "xy" if self.limit_xy2 >= 0. else "" z_home = "z" if self.limit_z[0] <= self.limit_z[1] else "" @@ -111,4 +141,4 @@ class PolarKinematics: } def load_kinematics(toolhead, config): - return PolarKinematics(toolhead, config) + return PolarKinematics(toolhead, config) \ No newline at end of file From f0ef9036d544229f598a6d27b6be4fc689460603 Mon Sep 17 00:00:00 2001 From: Neelix Date: Fri, 23 Jan 2026 22:15:17 +0100 Subject: [PATCH 2/4] Removes building errors Signed-off-by: Nils Hensch nils.hensch@gmx.de --- klippy/kinematics/polar.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/klippy/kinematics/polar.py b/klippy/kinematics/polar.py index cdaa1d436..dde3137f0 100644 --- a/klippy/kinematics/polar.py +++ b/klippy/kinematics/polar.py @@ -43,7 +43,8 @@ class PolarKinematics: # Setup boundary checks self.max_velocity, self.max_accel = toolhead.get_max_velocity() self.max_z_velocity = config.getfloat( - 'max_z_velocity', self.max_velocity, above=0., maxval=self.max_velocity) + 'max_z_velocity', self.max_velocity, above=0., + maxval=self.max_velocity) self.max_z_accel = config.getfloat( 'max_z_accel', self.max_accel, above=0., maxval=self.max_accel) self.critical_radius = config.getfloat( @@ -125,11 +126,13 @@ class PolarKinematics: # Slow down near center if move.axes_d[0] or move.axes_d[1]: if self.critical_radius != 0: - min_dist = distance_line_to_point(move.start_pos[0:2], move.end_pos[0:2]) + min_dist = distance_line_to_point(move.start_pos[0:2], + move.end_pos[0:2]) if min_dist <= self.critical_radius: if min_dist != 0: scale_radius = min_dist/self.critical_radius - move.limit_speed(self.max_velocity * scale_radius, self.max_accel * scale_radius) + move.limit_speed(self.max_velocity * scale_radius, + self.max_accel * scale_radius) def get_status(self, eventtime): xy_home = "xy" if self.limit_xy2 >= 0. else "" @@ -141,4 +144,4 @@ class PolarKinematics: } def load_kinematics(toolhead, config): - return PolarKinematics(toolhead, config) \ No newline at end of file + return PolarKinematics(toolhead, config) From 1ecd6f01384adff721cd66ec9d2896ba48cc1dc6 Mon Sep 17 00:00:00 2001 From: Neelix Date: Sun, 1 Feb 2026 17:17:04 +0100 Subject: [PATCH 3/4] Velocity limit in radians Changes the speed limit from a radius based variable to a rotation velocity limit. Signed-off-by: Nils Hensch nils.hensch@gmx.de --- klippy/kinematics/polar.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/klippy/kinematics/polar.py b/klippy/kinematics/polar.py index dde3137f0..dff6a1f2b 100644 --- a/klippy/kinematics/polar.py +++ b/klippy/kinematics/polar.py @@ -25,6 +25,7 @@ def distance_line_to_point(p1, p2): dist = abs(ab_x * ap_y - ab_y * ap_x) / ab_length return dist + class PolarKinematics: def __init__(self, toolhead, config): # Setup axis steppers @@ -47,8 +48,8 @@ class PolarKinematics: maxval=self.max_velocity) self.max_z_accel = config.getfloat( 'max_z_accel', self.max_accel, above=0., maxval=self.max_accel) - self.critical_radius = config.getfloat( - 'critical_radius', above=0., default=0) + self.v_rad_max = config.getfloat( + 'max_rad_velocity', above=0., default=0) self.limit_z = (1.0, -1.0) self.limit_xy2 = -1. max_xy = self.rails[0].get_range()[1] @@ -125,12 +126,13 @@ class PolarKinematics: self.max_z_accel * z_ratio) # Slow down near center if move.axes_d[0] or move.axes_d[1]: - if self.critical_radius != 0: + if self.v_rad_max != 0: min_dist = distance_line_to_point(move.start_pos[0:2], move.end_pos[0:2]) - if min_dist <= self.critical_radius: - if min_dist != 0: - scale_radius = min_dist/self.critical_radius + if min_dist != 0: + v_rot = math.sqrt(move.max_cruise_v2) / min_dist + if self.v_rad_max < v_rot: + scale_radius = self.v_rad_max/v_rot move.limit_speed(self.max_velocity * scale_radius, self.max_accel * scale_radius) From 0fbe6ae2106e39cd881ae005bf25e64a59c0797b Mon Sep 17 00:00:00 2001 From: Neelix Date: Sun, 1 Feb 2026 18:50:29 +0100 Subject: [PATCH 4/4] Config Reference: Add max_rad_velocity to polar kinematics Adds max_rad_velocity for reducing rotational velocity as variable to config reference Signed-off-by: Nils Hensch nils.hensch@gmx.de --- docs/Config_Reference.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/Config_Reference.md b/docs/Config_Reference.md index b01360adf..ae88ec66c 100644 --- a/docs/Config_Reference.md +++ b/docs/Config_Reference.md @@ -531,6 +531,11 @@ max_z_velocity: max_z_accel: # This sets the maximum acceleration (in mm/s^2) of movement along # the z axis. The default is to use max_accel for max_z_accel. +max_rad_velocity: +# This limits the maximum rotational velocity (in rad/s) of a move. +# Lower values will result in longer print times, but prevents too +# fast motions near the center. A value of 0 deactivates the +# scaling. The default is 0. # The stepper_x section is used to describe the X axis as well as the # stepper controlling the X-Z movement.