diff --git a/docs/Config_Reference.md b/docs/Config_Reference.md index b36c47a96a42..d72b51b8d0b6 100644 --- a/docs/Config_Reference.md +++ b/docs/Config_Reference.md @@ -1484,8 +1484,8 @@ using this feature may place the printer in an invalid state - see the ``` [force_move] #enable_force_move: False -# Set to true to enable FORCE_MOVE and SET_KINEMATIC_POSITION -# extended G-Code commands. The default is false. +# Set to true to enable FORCE_MOVE, SET_KINEMATIC_POSITION, and +# CLEAR_KINEMATIC_POSITION extended G-Code commands. The default is false. ``` ### [pause_resume] diff --git a/docs/G-Codes.md b/docs/G-Codes.md index a6d056bf2e56..4d442d8197cc 100644 --- a/docs/G-Codes.md +++ b/docs/G-Codes.md @@ -526,6 +526,14 @@ may lead to internal software errors. This command may invalidate future boundary checks; issue a G28 afterwards to reset the kinematics. +#### CLEAR_KINEMATIC_POSITION +`CLEAR_KINEMATIC_POSITION [KEEP=<[X][Y][Z]>]`: Force the low-level +kinematic code to forget the current position of the toolhead. This +only clears the homing status of the axes, which allows the position +to be restored with SET_KINEMATIC_POSITION. Use the KEEP parameter to +avoid clearing the position of given axes. By default, clears all axes. +Issue a G28 afterwards to reset the kinematics. + ### [gcode] The gcode module is automatically loaded. diff --git a/klippy/extras/force_move.py b/klippy/extras/force_move.py index 3c05843b23bd..3ca5ece0bf32 100644 --- a/klippy/extras/force_move.py +++ b/klippy/extras/force_move.py @@ -49,6 +49,9 @@ def __init__(self, config): gcode.register_command('SET_KINEMATIC_POSITION', self.cmd_SET_KINEMATIC_POSITION, desc=self.cmd_SET_KINEMATIC_POSITION_help) + gcode.register_command('CLEAR_KINEMATIC_POSITION', + self.cmd_CLEAR_KINEMATIC_POSITION, + desc=self.cmd_CLEAR_KINEMATIC_POSITION_help) def register_stepper(self, config, mcu_stepper): self.steppers[mcu_stepper.get_name()] = mcu_stepper def lookup_stepper(self, name): @@ -131,6 +134,15 @@ def cmd_SET_KINEMATIC_POSITION(self, gcmd): z = gcmd.get_float('Z', curpos[2]) logging.info("SET_KINEMATIC_POSITION pos=%.3f,%.3f,%.3f", x, y, z) toolhead.set_position([x, y, z, curpos[3]], homing_axes=(0, 1, 2)) + cmd_CLEAR_KINEMATIC_POSITION_help = "Clear the current kinematic position" + def cmd_CLEAR_KINEMATIC_POSITION(self, gcmd): + keep = gcmd.get('KEEP', '').upper() + axes = [0, 1, 2] + for pos, axis in enumerate('XYZ'): + if axis in keep: + axes.remove(pos) + toolhead = self.printer.lookup_object('toolhead') + toolhead.clear_position(axes) def load_config(config): return ForceMove(config) diff --git a/klippy/extras/safe_z_home.py b/klippy/extras/safe_z_home.py index ca9b8eb59ea3..ead787df4b81 100644 --- a/klippy/extras/safe_z_home.py +++ b/klippy/extras/safe_z_home.py @@ -40,8 +40,8 @@ def cmd_G28(self, gcmd): toolhead.set_position(pos, homing_axes=[2]) toolhead.manual_move([None, None, self.z_hop], self.z_hop_speed) - if hasattr(toolhead.get_kinematics(), "note_z_not_homed"): - toolhead.get_kinematics().note_z_not_homed() + if hasattr(toolhead.get_kinematics(), "clear_position"): + toolhead.get_kinematics().clear_position((2,)) elif pos[2] < self.z_hop: # If the Z axis is homed, and below z_hop, lift it to z_hop toolhead.manual_move([None, None, self.z_hop], diff --git a/klippy/kinematics/cartesian.py b/klippy/kinematics/cartesian.py index 0cd7849a1896..52d238c4794c 100644 --- a/klippy/kinematics/cartesian.py +++ b/klippy/kinematics/cartesian.py @@ -58,9 +58,11 @@ def set_position(self, newpos, homing_axes): rail.set_position(newpos) if i in homing_axes: self.limits[i] = rail.get_range() - def note_z_not_homed(self): - # Helper for Safe Z Home - self.limits[2] = (1.0, -1.0) + def clear_position(self, axes=None): + axes = axes if axes is not None else (0, 1, 2) + for i, _ in enumerate(self.limits): + if i in axes: + self.limits[i] = (1.0, -1.0) def _home_axis(self, homing_state, axis, rail): # Determine movement position_min, position_max = rail.get_range() @@ -88,7 +90,7 @@ def home(self, homing_state): else: self._home_axis(homing_state, axis, self.rails[axis]) def _motor_off(self, print_time): - self.limits = [(1.0, -1.0)] * 3 + self.clear_position() def _check_endstops(self, move): end_pos = move.end_pos for i in (0, 1, 2): diff --git a/klippy/kinematics/corexy.py b/klippy/kinematics/corexy.py index d3b755001916..6378f7c75f62 100644 --- a/klippy/kinematics/corexy.py +++ b/klippy/kinematics/corexy.py @@ -43,9 +43,11 @@ def set_position(self, newpos, homing_axes): rail.set_position(newpos) if i in homing_axes: self.limits[i] = rail.get_range() - def note_z_not_homed(self): - # Helper for Safe Z Home - self.limits[2] = (1.0, -1.0) + def clear_position(self, axes=None): + axes = axes if axes is not None else (0, 1, 2) + for i, _ in enumerate(self.limits): + if i in axes: + self.limits[i] = (1.0, -1.0) def home(self, homing_state): # Each axis is homed independently and in order for axis in homing_state.get_axes(): @@ -63,7 +65,7 @@ def home(self, homing_state): # Perform homing homing_state.home_rails([rail], forcepos, homepos) def _motor_off(self, print_time): - self.limits = [(1.0, -1.0)] * 3 + self.clear_position() def _check_endstops(self, move): end_pos = move.end_pos for i in (0, 1, 2): diff --git a/klippy/kinematics/corexz.py b/klippy/kinematics/corexz.py index 72134c32741b..ef11f1eabf07 100644 --- a/klippy/kinematics/corexz.py +++ b/klippy/kinematics/corexz.py @@ -43,9 +43,11 @@ def set_position(self, newpos, homing_axes): rail.set_position(newpos) if i in homing_axes: self.limits[i] = rail.get_range() - def note_z_not_homed(self): - # Helper for Safe Z Home - self.limits[2] = (1.0, -1.0) + def clear_position(self, axes=None): + axes = axes if axes is not None else (0, 1, 2) + for i, _ in enumerate(self.limits): + if i in axes: + self.limits[i] = (1.0, -1.0) def home(self, homing_state): # Each axis is homed independently and in order for axis in homing_state.get_axes(): @@ -63,7 +65,7 @@ def home(self, homing_state): # Perform homing homing_state.home_rails([rail], forcepos, homepos) def _motor_off(self, print_time): - self.limits = [(1.0, -1.0)] * 3 + self.clear_position() def _check_endstops(self, move): end_pos = move.end_pos for i in (0, 1, 2): diff --git a/klippy/kinematics/hybrid_corexy.py b/klippy/kinematics/hybrid_corexy.py index 62dccc266193..7bedc3ac7ff3 100644 --- a/klippy/kinematics/hybrid_corexy.py +++ b/klippy/kinematics/hybrid_corexy.py @@ -78,9 +78,11 @@ def set_position(self, newpos, homing_axes): rail.set_position(newpos) if i in homing_axes: self.limits[i] = rail.get_range() - def note_z_not_homed(self): - # Helper for Safe Z Home - self.limits[2] = (1.0, -1.0) + def clear_position(self, axes=None): + axes = axes if axes is not None else (0, 1, 2) + for i, _ in enumerate(self.limits): + if i in axes: + self.limits[i] = (1.0, -1.0) def _home_axis(self, homing_state, axis, rail): position_min, position_max = rail.get_range() hi = rail.get_homing_info() @@ -104,7 +106,7 @@ def home(self, homing_state): else: self._home_axis(homing_state, axis, self.rails[axis]) def _motor_off(self, print_time): - self.limits = [(1.0, -1.0)] * 3 + self.clear_position() def _check_endstops(self, move): end_pos = move.end_pos for i in (0, 1, 2): diff --git a/klippy/kinematics/hybrid_corexz.py b/klippy/kinematics/hybrid_corexz.py index a92a21948ba9..e8a0784fa211 100644 --- a/klippy/kinematics/hybrid_corexz.py +++ b/klippy/kinematics/hybrid_corexz.py @@ -78,9 +78,11 @@ def set_position(self, newpos, homing_axes): rail.set_position(newpos) if i in homing_axes: self.limits[i] = rail.get_range() - def note_z_not_homed(self): - # Helper for Safe Z Home - self.limits[2] = (1.0, -1.0) + def clear_position(self, axes=None): + axes = axes if axes is not None else (0, 1, 2) + for i, _ in enumerate(self.limits): + if i in axes: + self.limits[i] = (1.0, -1.0) def _home_axis(self, homing_state, axis, rail): position_min, position_max = rail.get_range() hi = rail.get_homing_info() @@ -104,7 +106,7 @@ def home(self, homing_state): else: self._home_axis(homing_state, axis, self.rails[axis]) def _motor_off(self, print_time): - self.limits = [(1.0, -1.0)] * 3 + self.clear_position() def _check_endstops(self, move): end_pos = move.end_pos for i in (0, 1, 2): diff --git a/klippy/kinematics/polar.py b/klippy/kinematics/polar.py index deed26d06009..cac2b8d39a12 100644 --- a/klippy/kinematics/polar.py +++ b/klippy/kinematics/polar.py @@ -51,9 +51,13 @@ def set_position(self, newpos, homing_axes): self.limit_z = self.rails[1].get_range() if 0 in homing_axes and 1 in homing_axes: self.limit_xy2 = self.rails[0].get_range()[1]**2 - def note_z_not_homed(self): - # Helper for Safe Z Home - self.limit_z = (1.0, -1.0) + def clear_position(self, axes=None): + axes = axes if axes is not None else (0, 1, 2) + if 0 in axes or 1 in axes: + # X and Y cannot be cleared separately + self.limit_xy2 = -1. + if 2 in axes: + self.limit_z = (1.0, -1.0) def _home_axis(self, homing_state, axis, rail): # Determine movement position_min, position_max = rail.get_range() @@ -86,8 +90,7 @@ def home(self, homing_state): if home_z: self._home_axis(homing_state, 2, self.rails[1]) def _motor_off(self, print_time): - self.limit_z = (1.0, -1.0) - self.limit_xy2 = -1. + self.clear_position() def check_move(self, move): end_pos = move.end_pos xy2 = end_pos[0]**2 + end_pos[1]**2 diff --git a/klippy/toolhead.py b/klippy/toolhead.py index d8b9382570b6..4c9365b4edce 100644 --- a/klippy/toolhead.py +++ b/klippy/toolhead.py @@ -414,6 +414,10 @@ def set_position(self, newpos, homing_axes=()): self.commanded_pos[:] = newpos self.kin.set_position(newpos, homing_axes) self.printer.send_event("toolhead:set_position") + def clear_position(self, axes): + self.flush_step_generation() + self.kin.clear_position(axes) + self.printer.send_event("toolhead:set_position") def move(self, newpos, speed): move = Move(self, self.commanded_pos, newpos, speed) if not move.move_d: