From add866cadc60dcca62d92915c87d4922b76129ed Mon Sep 17 00:00:00 2001 From: stevenrwood <50087820+stevenrwood@users.noreply.github.com> Date: Wed, 1 Jul 2026 03:36:43 -0700 Subject: [PATCH] gcode: G53 must ignore the active WCS rotation/offset (when ROTATION_ENABLE=1) Only affects builds with ROTATION_ENABLE defined; the offending code is inside #ifdef ROTATION_ENABLE, so default builds are unaffected. The rotation-transform block was entered for any axis-word motion without excluding NonModal_AbsoluteOverride, so G53 (absolute machine override) moves had the active WCS offset added to the plane axes (and were rotated). Per RS274/NGC a G53 target is in machine coordinates and must ignore all offsets and rotation. Symptom: with a non-zero WCS rotation active (e.g. set by G10 L2 R / G68), G53 drives to the rotated work origin instead of the machine target, false- triggering a soft-limit alarm when that lands outside the machine envelope. Guard the transform with `non_modal_command != NonModal_AbsoluteOverride`, and initialise r_axes.mask = 0 so it stays defined when the block is bypassed. --- gcode.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/gcode.c b/gcode.c index bda6249..846a997 100644 --- a/gcode.c +++ b/gcode.c @@ -3053,7 +3053,12 @@ status_code_t gc_execute_block (char *block) #ifdef ROTATION_ENABLE axes_signals_t r_axes, r_around; uint_fast8_t idx_0, idx_1; - if(!gc_parser_flags.jog_motion && (r_axes.mask = (gc_block.modal.g5x_offset.data.rotation == 0.0f ? 0 : (axis_words.mask & (r_around.mask = rotate_axes[gc_block.modal.plane_select].mask))))) { + r_axes.mask = 0; // keep defined when the transform is bypassed (jog / G53) + // G53 (absolute machine override) must ignore the active WCS entirely - rotation AND offset. Without + // the AbsoluteOverride guard this block adds the g5x offset to the plane axes, so e.g. "G53 G0 X0 Y0" + // goes to the work origin instead of machine 0,0 (and false soft-limits when that lands out of travel). + // A near-zero garbage rotation (stale NVS after enabling ROTATION_ENABLE) is enough to arm it. + if(!gc_parser_flags.jog_motion && gc_block.non_modal_command != NonModal_AbsoluteOverride && (r_axes.mask = (gc_block.modal.g5x_offset.data.rotation == 0.0f ? 0 : (axis_words.mask & (r_around.mask = rotate_axes[gc_block.modal.plane_select].mask))))) { if(r_axes.mask != r_around.mask) { point_3d_t pos;