From c4d78ae7d3bf49931efb64e5f547a6194d7d5eb8 Mon Sep 17 00:00:00 2001 From: Jorge Apaza Merma Date: Fri, 17 Jan 2025 16:41:49 -0300 Subject: [PATCH 1/3] This commit implements support for the Y-axis in the axis_twist_compensation module. This update enables the module to handle corrections for printers with a twisted Y rail. Co-authored-by: Adelino Penedo --- docs/Axis_Twist_Compensation.md | 52 +++-- docs/Config_Reference.md | 29 ++- docs/G-Codes.md | 14 +- klippy/extras/axis_twist_compensation.py | 284 +++++++++++++++++------ 4 files changed, 290 insertions(+), 89 deletions(-) diff --git a/docs/Axis_Twist_Compensation.md b/docs/Axis_Twist_Compensation.md index 5aeef9de4..3d8750497 100644 --- a/docs/Axis_Twist_Compensation.md +++ b/docs/Axis_Twist_Compensation.md @@ -14,7 +14,9 @@ representations of the bed. This module uses manual measurements by the user to correct the probe's results. Note that if your axis is significantly twisted it is strongly recommended to -first use mechanical means to fix it prior to applying software corrections. +first use mechanical means to fix it prior to applying software corrections, +as the calibration could be affected by issues with probe accuracy, +bed flatness, Z axis alignment, etc. **Warning**: This module is not compatible with dockable probes yet and will try to probe the bed without attaching the probe if you use it. @@ -24,18 +26,42 @@ try to probe the bed without attaching the probe if you use it. > **Tip:** Make sure the [probe X and Y offsets](Config_Reference.md#probe) are > correctly set as they greatly influence calibration. -1. After setting up the [axis_twist_compensation] module, -perform `AXIS_TWIST_COMPENSATION_CALIBRATE` -* The calibration wizard will prompt you to measure the probe Z offset at a few -points along the bed -* The calibration defaults to 3 points but you can use the option -`SAMPLE_COUNT=` to use a different number. -2. [Adjust your Z offset](Probe_Calibrate.md#calibrating-probe-z-offset) -3. Perform automatic/probe-based bed tramming operations, such as -[Screws Tilt Adjust](G-Codes.md#screws_tilt_adjust), -[Z Tilt Adjust](G-Codes.md#z_tilt_adjust) etc -4. Home all axis, then perform a [Bed Mesh](Bed_Mesh.md) if required -5. Perform a test print, followed by any fine-tuning as desired +### Basic Usage: X-Axis Calibration +1. After setting up the ```[axis_twist_compensation]``` module, run: +``` +AXIS_TWIST_COMPENSATION_CALIBRATE +``` +This command will calibrate the X-axis by default. + - The calibration wizard will prompt you to measure the probe Z offset at + several points along the bed. + - By default, the calibration uses 3 points, but you can specify a different + number with the option: +`` +SAMPLE_COUNT= +`` + +2. **Adjust Your Z Offset:** +After completing the calibration, be sure to [adjust your Z offset] +(Probe_Calibrate.md#calibrating-probe-z-offset). + +3. **Perform Bed Leveling Operations:** +Use probe-based operations as needed, such as: + - [Screws Tilt Adjust](G-Codes.md#screws_tilt_adjust) + - [Z Tilt Adjust](G-Codes.md#z_tilt_adjust) + +4. **Finalize the Setup:** + - Home all axes, and perform a [Bed Mesh](Bed_Mesh.md) if necessary. + - Run a test print, followed by any + [fine-tuning](Axis_Twist_Compensation.md#fine-tuning) + if needed. + +### For Y-Axis Calibration +The calibration process for the Y-axis is similar to the X-axis. To calibrate +the Y-axis, use: +``` +AXIS_TWIST_COMPENSATION_CALIBRATE AXIS=Y +``` +This will guide you through the same measuring process as for the X-axis. > **Tip:** Bed temperature and nozzle temperature and size do not seem to have > an influence to the calibration process. diff --git a/docs/Config_Reference.md b/docs/Config_Reference.md index 0bea6ec2c..3585489f2 100644 --- a/docs/Config_Reference.md +++ b/docs/Config_Reference.md @@ -2608,9 +2608,9 @@ sensor_type: ldc1612 ### [axis_twist_compensation] -A tool to compensate for inaccurate probe readings due to twist in X gantry. See -the [Axis Twist Compensation Guide](Axis_Twist_Compensation.md) for more -detailed information regarding symptoms, configuration and setup. +A tool to compensate for inaccurate probe readings due to twist in X or Y +gantry. See the [Axis Twist Compensation Guide](Axis_Twist_Compensation.md) +for more detailed information regarding symptoms, configuration and setup. ``` [axis_twist_compensation] @@ -2623,16 +2623,33 @@ detailed information regarding symptoms, configuration and setup. calibrate_start_x: 20 # Defines the minimum X coordinate of the calibration # This should be the X coordinate that positions the nozzle at the starting -# calibration position. This parameter must be provided. +# calibration position. calibrate_end_x: 200 # Defines the maximum X coordinate of the calibration # This should be the X coordinate that positions the nozzle at the ending -# calibration position. This parameter must be provided. +# calibration position. calibrate_y: 112.5 # Defines the Y coordinate of the calibration # This should be the Y coordinate that positions the nozzle during the -# calibration process. This parameter must be provided and is recommended to +# calibration process. This parameter is recommended to # be near the center of the bed + +# For Y-axis twist compensation, specify the following parameters: +calibrate_start_y: ... +# Defines the minimum Y coordinate of the calibration +# This should be the Y coordinate that positions the nozzle at the starting +# calibration position for the Y axis. This parameter must be provided if +# compensating for Y axis twist. +calibrate_end_y: ... +# Defines the maximum Y coordinate of the calibration +# This should be the Y coordinate that positions the nozzle at the ending +# calibration position for the Y axis. This parameter must be provided if +# compensating for Y axis twist. +calibrate_x: ... +# Defines the X coordinate of the calibration for Y axis twist compensation +# This should be the X coordinate that positions the nozzle during the +# calibration process for Y axis twist compensation. This parameter must be +# provided and is recommended to be near the center of the bed. ``` ### ⚠️ [z_calibration] diff --git a/docs/G-Codes.md b/docs/G-Codes.md index 55128ce97..55b165824 100644 --- a/docs/G-Codes.md +++ b/docs/G-Codes.md @@ -155,9 +155,17 @@ The following commands are available when the section](Config_Reference.md#axis_twist_compensation) is enabled. #### AXIS_TWIST_COMPENSATION_CALIBRATE -`AXIS_TWIST_COMPENSATION_CALIBRATE [SAMPLE_COUNT=]`: Initiates the X -twist calibration wizard. `SAMPLE_COUNT` specifies the number of points along -the X axis to calibrate at and defaults to 3. +`AXIS_TWIST_COMPENSATION_CALIBRATE [AXIS=] +[SAMPLE_COUNT=] [=]`: + +Calibrates axis twist compensation by specifying the target axis or +enabling automatic calibration. + +- **SAMPLE_COUNT:** Number of points tested during the calibration. +If not specified, it defaults to 3. + +- **AXIS:** Define the axis (`X` or `Y`) for which the twist compensation +will be calibrated. If not specified, the axis defaults to `'X'`. ### [bed_mesh] diff --git a/klippy/extras/axis_twist_compensation.py b/klippy/extras/axis_twist_compensation.py index 4418462c1..77dd28256 100644 --- a/klippy/extras/axis_twist_compensation.py +++ b/klippy/extras/axis_twist_compensation.py @@ -5,7 +5,7 @@ # This file may be distributed under the terms of the GNU GPLv3 license. import math -from . import manual_probe as ManualProbe, bed_mesh as BedMesh +from . import manual_probe, bed_mesh, probe DEFAULT_SAMPLE_COUNT = 3 @@ -34,41 +34,73 @@ def __init__(self, config): "compensation_start_x", default=None ) self.compensation_end_x = config.getfloat( - "compensation_start_y", default=None + "compensation_end_x", default=None ) - self.m = None - self.b = None + self.calibrate_start_y = config.getfloat( + "calibrate_start_y", default=None + ) + self.calibrate_end_y = config.getfloat("calibrate_end_y", default=None) + self.calibrate_x = config.getfloat("calibrate_x", default=None) + self.compensation_start_y = config.getfloat( + "compensation_start_y", default=None + ) + self.compensation_end_y = config.getfloat( + "compensation_end_y", default=None + ) + self.zy_compensations = config.getlists( + "zy_compensations", default=[], parser=float + ) # setup calibrater self.calibrater = Calibrater(self, config) - def get_z_compensation_value(self, pos): - if not self.z_compensations: - return 0 + def get_z_compensation_value(self, pos): + total_interpolated_z_compensation = 0 + + if self.z_compensations: + total_interpolated_z_compensation += self._get_interpolated_z_compensation( + pos[0], self.z_compensations, + self.compensation_start_x, + self.compensation_end_x + ) + + if self.zy_compensations: + total_interpolated_z_compensation += self._get_interpolated_z_compensation( + pos[1], self.zy_compensations, + self.compensation_start_y, + self.compensation_end_y + ) + + return total_interpolated_z_compensation + + def _get_interpolated_z_compensation( + self, coord, z_compensations, + comp_start, + comp_end + ): - x_coord = pos[0] - z_compensations = self.z_compensations sample_count = len(z_compensations) - spacing = (self.calibrate_end_x - self.calibrate_start_x) / ( - sample_count - 1 - ) - interpolate_t = (x_coord - self.calibrate_start_x) / spacing + spacing = ((comp_end - comp_start) + / (sample_count - 1)) + interpolate_t = (coord - comp_start) / spacing interpolate_i = int(math.floor(interpolate_t)) - interpolate_i = BedMesh.constrain(interpolate_i, 0, sample_count - 2) + interpolate_i = bed_mesh.constrain(interpolate_i, 0, sample_count - 2) interpolate_t -= interpolate_i - interpolated_z_compensation = BedMesh.lerp( - interpolate_t, - z_compensations[interpolate_i], - z_compensations[interpolate_i + 1], + interpolated_z_compensation = bed_mesh.lerp( + interpolate_t, z_compensations[interpolate_i], + z_compensations[interpolate_i + 1] ) return interpolated_z_compensation - def clear_compensations(self): - self.z_compensations = [] - self.m = None - self.b = None - + def clear_compensations(self, axis=None): + if axis is None: + self.z_compensations = [] + self.zy_compensations = [] + elif axis == "X": + self.z_compensations = [] + elif axis == "Y": + self.zy_compensations = [] class Calibrater: def __init__(self, compensation, config): @@ -89,14 +121,22 @@ def __init__(self, compensation, config): ) self.speed = compensation.speed self.horizontal_move_z = compensation.horizontal_move_z - self.start_point = ( + self.x_start_point = ( compensation.calibrate_start_x, compensation.calibrate_y, ) - self.end_point = ( + self.x_end_point = ( compensation.calibrate_end_x, compensation.calibrate_y, ) + self.y_start_point = ( + compensation.calibrate_x, + compensation.calibrate_start_y, + ) + self.y_end_point = ( + compensation.calibrate_x, + compensation.calibrate_end_y, + ) self.results = None self.current_point_index = None self.gcmd = None @@ -133,40 +173,127 @@ def _register_gcode_handlers(self): def cmd_AXIS_TWIST_COMPENSATION_CALIBRATE(self, gcmd): self.gcmd = gcmd sample_count = gcmd.get_int("SAMPLE_COUNT", DEFAULT_SAMPLE_COUNT) + axis = gcmd.get("AXIS", "X") + axis = axis.upper() # check for valid sample_count - if sample_count is None or sample_count < 2: - raise self.gcmd.error("SAMPLE_COUNT to probe must be at least 2") + if sample_count < 2: + raise gcmd.error("SAMPLE_COUNT to probe must be at least 2") + + # calculate the points to put the probe at, returned as a list of tuples + nozzle_points = [] - # clear the current config - self.compensation.clear_compensations() + if axis == "X": + + self.compensation.clear_compensations("X") + + if not all([ + self.x_start_point[0], + self.x_end_point[0], + self.x_start_point[1] + ]): + raise gcmd.error( + """AXIS_TWIST_COMPENSATION for X axis requires + calibrate_start_x, calibrate_end_x and calibrate_y + to be defined + """ + ) + + start_point = self.x_start_point + end_point = self.x_end_point + + x_axis_range = end_point[0] - start_point[0] + interval_dist = x_axis_range / (sample_count - 1) + + for i in range(sample_count): + x = start_point[0] + i * interval_dist + y = start_point[1] + nozzle_points.append((x, y)) + + elif axis == "Y": + + self.compensation.clear_compensations("Y") + + if not all([ + self.y_start_point[0], + self.y_end_point[0], + self.y_start_point[1] + ]): + raise gcmd.error( + """AXIS_TWIST_COMPENSATION for Y axis requires + calibrate_start_y, calibrate_end_y and calibrate_x + to be defined + """ + ) + + start_point = self.y_start_point + end_point = self.y_end_point + + y_axis_range = end_point[1] - start_point[1] + interval_dist = y_axis_range / (sample_count - 1) + + for i in range(sample_count): + x = start_point[0] + y = start_point[1] + i * interval_dist + nozzle_points.append((x, y)) + + else: + raise gcmd.error( + "AXIS_TWIST_COMPENSATION_CALIBRATE: " + "Invalid axis." + ) - # calculate some values - x_range = self.end_point[0] - self.start_point[0] - interval_dist = x_range / (sample_count - 1) - nozzle_points = self._calculate_nozzle_points( - sample_count, interval_dist - ) probe_points = self._calculate_probe_points( nozzle_points, self.probe_x_offset, self.probe_y_offset ) # verify no other manual probe is in progress - ManualProbe.verify_no_manual_probe(self.printer) + manual_probe.verify_no_manual_probe(self.printer) # begin calibration self.current_point_index = 0 self.results = [] - self._calibration(probe_points, nozzle_points, interval_dist) - - def _calculate_nozzle_points(self, sample_count, interval_dist): - # calculate the points to put the probe at, returned as a list of tuples - nozzle_points = [] - for i in range(sample_count): - x = self.start_point[0] + i * interval_dist - y = self.start_point[1] - nozzle_points.append((x, y)) - return nozzle_points + self.current_axis = axis + self._calibration(gcmd, probe_points, nozzle_points, interval_dist) + + def _calculate_corrections(self, coordinates): + # Extracting x, y, and z values from coordinates + x_coords = [coord[0] for coord in coordinates] + y_coords = [coord[1] for coord in coordinates] + z_coords = [coord[2] for coord in coordinates] + + # Calculate the desired point (average of all corner points in z) + # For a general case, we should extract the unique + # combinations of corner points + z_corners = [z_coords[i] for i, coord in enumerate(coordinates) + if (coord[0] in [x_coords[0], x_coords[-1]]) + and (coord[1] in [y_coords[0], y_coords[-1]])] + z_desired = sum(z_corners) / len(z_corners) + + + # Calculate average deformation per axis + unique_x_coords = sorted(set(x_coords)) + unique_y_coords = sorted(set(y_coords)) + + avg_z_x = [] + for x in unique_x_coords: + indices = [i for i, coord in enumerate(coordinates) + if coord[0] == x] + avg_z = sum(z_coords[i] for i in indices) / len(indices) + avg_z_x.append(avg_z) + + avg_z_y = [] + for y in unique_y_coords: + indices = [i for i, coord in enumerate(coordinates) + if coord[1] == y] + avg_z = sum(z_coords[i] for i in indices) / len(indices) + avg_z_y.append(avg_z) + + # Calculate corrections to reach the desired point + x_corrections = [z_desired - avg for avg in avg_z_x] + y_corrections = [z_desired - avg for avg in avg_z_y] + + return x_corrections, y_corrections def _calculate_probe_points( self, nozzle_points, probe_x_offset, probe_y_offset @@ -192,9 +319,9 @@ def _move_helper(self, target_coordinates, override_speed=None): speed = override_speed if override_speed is not None else speed toolhead.manual_move(target_coordinates, speed) - def _calibration(self, probe_points, nozzle_points, interval): + def _calibration(self, gcmd, probe_points, nozzle_points, interval): # begin the calibration process - self.gcmd.respond_info( + gcmd.respond_info( "AXIS_TWIST_COMPENSATION_CALIBRATE: " "Probing point %d of %d" % (self.current_point_index + 1, len(probe_points)) @@ -213,7 +340,8 @@ def _calibration(self, probe_points, nozzle_points, interval): ) # probe the point - self.current_measured_z = self.probe.run_probe(self.gcmd)[2] + pos = self.probe.run_probe(gcmd) + self.current_measured_z = pos[2] # horizontal_move_z (to prevent probe trigger or hitting bed) self._move_helper((None, None, self.horizontal_move_z)) @@ -222,16 +350,16 @@ def _calibration(self, probe_points, nozzle_points, interval): self._move_helper((nozzle_points[self.current_point_index])) # start the manual (nozzle) probe - ManualProbe.ManualProbeHelper( + manual_probe.ManualProbeHelper( self.printer, - self.gcmd, + gcmd, self._manual_probe_callback_factory( - probe_points, nozzle_points, interval + gcmd, probe_points, nozzle_points, interval ), ) def _manual_probe_callback_factory( - self, probe_points, nozzle_points, interval + self, gcmd, probe_points, nozzle_points, interval ): # returns a callback function for the manual probe is_end = self.current_point_index == len(probe_points) - 1 @@ -239,7 +367,7 @@ def _manual_probe_callback_factory( def callback(kin_pos): if kin_pos is None: # probe was cancelled - self.gcmd.respond_info( + gcmd.respond_info( "AXIS_TWIST_COMPENSATION_CALIBRATE: Probe cancelled, " "calibration aborted" ) @@ -248,15 +376,15 @@ def callback(kin_pos): self.results.append(z_offset) if is_end: # end of calibration - self._finalize_calibration() + self._finalize_calibration(gcmd) else: # move to next point self.current_point_index += 1 - self._calibration(probe_points, nozzle_points, interval) + self._calibration(gcmd, probe_points, nozzle_points, interval) return callback - def _finalize_calibration(self): + def _finalize_calibration(self, gcmd): # finalize the calibration process # calculate average of results avg = sum(self.results) / len(self.results) @@ -266,23 +394,45 @@ def _finalize_calibration(self): # save the config configfile = self.printer.lookup_object("configfile") values_as_str = ", ".join(["{:.6f}".format(x) for x in self.results]) - configfile.set(self.configname, "z_compensations", values_as_str) - configfile.set( - self.configname, "compensation_start_x", self.start_point[0] - ) - configfile.set(self.configname, "compensation_end_x", self.end_point[0]) - self.compensation.z_compensations = self.results - self.compensation.compensation_start_x = self.start_point[0] - self.compensation.compensation_end_x = self.end_point[0] + + if(self.current_axis == "X"): + + configfile.set(self.configname, "z_compensations", values_as_str) + configfile.set( + self.configname, "compensation_start_x", self.x_start_point[0] + ) + configfile.set( + self.configname, "compensation_end_x", self.x_end_point[0] + ) + + self.compensation.z_compensations = self.results + self.compensation.compensation_start_x = self.x_start_point[0] + self.compensation.compensation_end_x = self.x_end_point[0] + + elif(self.current_axis == "Y"): + + configfile.set(self.configname, "zy_compensations", values_as_str) + configfile.set( + self.configname, "compensation_start_y", self.y_start_point[1] + ) + configfile.set( + self.configname, "compensation_end_y", self.y_end_point[1] + ) + + self.compensation.zy_compensations = self.results + self.compensation.compensation_start_y = self.y_start_point[1] + self.compensation.compensation_end_y = self.y_end_point[1] + self.gcode.respond_info( "AXIS_TWIST_COMPENSATION state has been saved " "for the current session. The SAVE_CONFIG command will " "update the printer config file and restart the printer." ) # output result - self.gcmd.respond_info( + gcmd.respond_info( "AXIS_TWIST_COMPENSATION_CALIBRATE: Calibration complete, " - "offsets: %s, mean z_offset: %f" % (self.results, avg) + "offsets: %s, mean z_offset: %f" + % (self.results, avg) ) From 4cef6837f2ca3f98e2dec6f184e30d5583c679ea Mon Sep 17 00:00:00 2001 From: Adelino Penedo Date: Fri, 17 Jan 2025 17:42:05 -0300 Subject: [PATCH 2/3] Docs fix, Removes unused import --- docs/Axis_Twist_Compensation.md | 4 +--- klippy/extras/axis_twist_compensation.py | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/Axis_Twist_Compensation.md b/docs/Axis_Twist_Compensation.md index 3d8750497..235b9231c 100644 --- a/docs/Axis_Twist_Compensation.md +++ b/docs/Axis_Twist_Compensation.md @@ -51,9 +51,7 @@ Use probe-based operations as needed, such as: 4. **Finalize the Setup:** - Home all axes, and perform a [Bed Mesh](Bed_Mesh.md) if necessary. - - Run a test print, followed by any - [fine-tuning](Axis_Twist_Compensation.md#fine-tuning) - if needed. + - Run a test print, followed by any fine-tuning if needed. ### For Y-Axis Calibration The calibration process for the Y-axis is similar to the X-axis. To calibrate diff --git a/klippy/extras/axis_twist_compensation.py b/klippy/extras/axis_twist_compensation.py index 77dd28256..26ee602a4 100644 --- a/klippy/extras/axis_twist_compensation.py +++ b/klippy/extras/axis_twist_compensation.py @@ -5,7 +5,7 @@ # This file may be distributed under the terms of the GNU GPLv3 license. import math -from . import manual_probe, bed_mesh, probe +from . import manual_probe, bed_mesh DEFAULT_SAMPLE_COUNT = 3 From 733de0032ae24f7b3c0c68fa194dda6463323706 Mon Sep 17 00:00:00 2001 From: Rogerio Goncalves Date: Fri, 17 Jan 2025 21:03:25 -0300 Subject: [PATCH 3/3] ruff: format axis_twist_compensation.py --- klippy/extras/axis_twist_compensation.py | 102 ++++++++++++----------- 1 file changed, 53 insertions(+), 49 deletions(-) diff --git a/klippy/extras/axis_twist_compensation.py b/klippy/extras/axis_twist_compensation.py index 26ee602a4..c55766cad 100644 --- a/klippy/extras/axis_twist_compensation.py +++ b/klippy/extras/axis_twist_compensation.py @@ -55,41 +55,44 @@ def __init__(self, config): # setup calibrater self.calibrater = Calibrater(self, config) - def get_z_compensation_value(self, pos): + def get_z_compensation_value(self, pos): total_interpolated_z_compensation = 0 - + if self.z_compensations: - total_interpolated_z_compensation += self._get_interpolated_z_compensation( - pos[0], self.z_compensations, - self.compensation_start_x, - self.compensation_end_x + total_interpolated_z_compensation += ( + self._get_interpolated_z_compensation( + pos[0], + self.z_compensations, + self.compensation_start_x, + self.compensation_end_x, + ) ) if self.zy_compensations: - total_interpolated_z_compensation += self._get_interpolated_z_compensation( - pos[1], self.zy_compensations, - self.compensation_start_y, - self.compensation_end_y + total_interpolated_z_compensation += ( + self._get_interpolated_z_compensation( + pos[1], + self.zy_compensations, + self.compensation_start_y, + self.compensation_end_y, + ) ) - + return total_interpolated_z_compensation def _get_interpolated_z_compensation( - self, coord, z_compensations, - comp_start, - comp_end + self, coord, z_compensations, comp_start, comp_end ): - sample_count = len(z_compensations) - spacing = ((comp_end - comp_start) - / (sample_count - 1)) + spacing = (comp_end - comp_start) / (sample_count - 1) interpolate_t = (coord - comp_start) / spacing interpolate_i = int(math.floor(interpolate_t)) interpolate_i = bed_mesh.constrain(interpolate_i, 0, sample_count - 2) interpolate_t -= interpolate_i interpolated_z_compensation = bed_mesh.lerp( - interpolate_t, z_compensations[interpolate_i], - z_compensations[interpolate_i + 1] + interpolate_t, + z_compensations[interpolate_i], + z_compensations[interpolate_i + 1], ) return interpolated_z_compensation @@ -102,6 +105,7 @@ def clear_compensations(self, axis=None): elif axis == "Y": self.zy_compensations = [] + class Calibrater: def __init__(self, compensation, config): # setup self attributes @@ -184,14 +188,15 @@ def cmd_AXIS_TWIST_COMPENSATION_CALIBRATE(self, gcmd): nozzle_points = [] if axis == "X": - self.compensation.clear_compensations("X") - if not all([ - self.x_start_point[0], - self.x_end_point[0], - self.x_start_point[1] - ]): + if not all( + [ + self.x_start_point[0], + self.x_end_point[0], + self.x_start_point[1], + ] + ): raise gcmd.error( """AXIS_TWIST_COMPENSATION for X axis requires calibrate_start_x, calibrate_end_x and calibrate_y @@ -211,14 +216,15 @@ def cmd_AXIS_TWIST_COMPENSATION_CALIBRATE(self, gcmd): nozzle_points.append((x, y)) elif axis == "Y": - self.compensation.clear_compensations("Y") - if not all([ - self.y_start_point[0], - self.y_end_point[0], - self.y_start_point[1] - ]): + if not all( + [ + self.y_start_point[0], + self.y_end_point[0], + self.y_start_point[1], + ] + ): raise gcmd.error( """AXIS_TWIST_COMPENSATION for Y axis requires calibrate_start_y, calibrate_end_y and calibrate_x @@ -238,10 +244,7 @@ def cmd_AXIS_TWIST_COMPENSATION_CALIBRATE(self, gcmd): nozzle_points.append((x, y)) else: - raise gcmd.error( - "AXIS_TWIST_COMPENSATION_CALIBRATE: " - "Invalid axis." - ) + raise gcmd.error("AXIS_TWIST_COMPENSATION_CALIBRATE: Invalid axis.") probe_points = self._calculate_probe_points( nozzle_points, self.probe_x_offset, self.probe_y_offset @@ -265,27 +268,31 @@ def _calculate_corrections(self, coordinates): # Calculate the desired point (average of all corner points in z) # For a general case, we should extract the unique # combinations of corner points - z_corners = [z_coords[i] for i, coord in enumerate(coordinates) - if (coord[0] in [x_coords[0], x_coords[-1]]) - and (coord[1] in [y_coords[0], y_coords[-1]])] + z_corners = [ + z_coords[i] + for i, coord in enumerate(coordinates) + if (coord[0] in [x_coords[0], x_coords[-1]]) + and (coord[1] in [y_coords[0], y_coords[-1]]) + ] z_desired = sum(z_corners) / len(z_corners) - # Calculate average deformation per axis unique_x_coords = sorted(set(x_coords)) unique_y_coords = sorted(set(y_coords)) avg_z_x = [] for x in unique_x_coords: - indices = [i for i, coord in enumerate(coordinates) - if coord[0] == x] + indices = [ + i for i, coord in enumerate(coordinates) if coord[0] == x + ] avg_z = sum(z_coords[i] for i in indices) / len(indices) avg_z_x.append(avg_z) avg_z_y = [] for y in unique_y_coords: - indices = [i for i, coord in enumerate(coordinates) - if coord[1] == y] + indices = [ + i for i, coord in enumerate(coordinates) if coord[1] == y + ] avg_z = sum(z_coords[i] for i in indices) / len(indices) avg_z_y.append(avg_z) @@ -395,8 +402,7 @@ def _finalize_calibration(self, gcmd): configfile = self.printer.lookup_object("configfile") values_as_str = ", ".join(["{:.6f}".format(x) for x in self.results]) - if(self.current_axis == "X"): - + if self.current_axis == "X": configfile.set(self.configname, "z_compensations", values_as_str) configfile.set( self.configname, "compensation_start_x", self.x_start_point[0] @@ -409,8 +415,7 @@ def _finalize_calibration(self, gcmd): self.compensation.compensation_start_x = self.x_start_point[0] self.compensation.compensation_end_x = self.x_end_point[0] - elif(self.current_axis == "Y"): - + elif self.current_axis == "Y": configfile.set(self.configname, "zy_compensations", values_as_str) configfile.set( self.configname, "compensation_start_y", self.y_start_point[1] @@ -431,8 +436,7 @@ def _finalize_calibration(self, gcmd): # output result gcmd.respond_info( "AXIS_TWIST_COMPENSATION_CALIBRATE: Calibration complete, " - "offsets: %s, mean z_offset: %f" - % (self.results, avg) + "offsets: %s, mean z_offset: %f" % (self.results, avg) )