diff --git a/Marlin/src/gcode/geometry/G92.cpp b/Marlin/src/gcode/geometry/G92.cpp index 626441f4e2..cfdff51eba 100644 --- a/Marlin/src/gcode/geometry/G92.cpp +++ b/Marlin/src/gcode/geometry/G92.cpp @@ -42,7 +42,7 @@ * G92 : Modify Workspace Offsets so the reported position shows the given X [Y [Z [A [B [C [U [V [W ]]]]]]]] [E]. * G92.1 : Zero XYZ Workspace Offsets (so the reported position = the native position). * - * With POWER_LOSS_RECOVERY: + * With POWER_LOSS_RECOVERY or with AXISn_ROTATES: * G92.9 : Set NATIVE Current Position to the given X [Y [Z [A [B [C [U [V [W ]]]]]]]] [E]. */ void GcodeSuite::G92() { @@ -67,7 +67,7 @@ void GcodeSuite::G92() { break; #endif - #if ENABLED(POWER_LOSS_RECOVERY) + #if ANY(POWER_LOSS_RECOVERY, HAS_ROTATIONAL_AXES) case 9: // G92.9 - Set Current Position directly (like Marlin 1.0) LOOP_LOGICAL_AXES(i) { if (parser.seenval(AXIS_CHAR(i))) { diff --git a/Marlin/src/inc/Conditionals_post.h b/Marlin/src/inc/Conditionals_post.h index c64bde0bc0..2683312976 100644 --- a/Marlin/src/inc/Conditionals_post.h +++ b/Marlin/src/inc/Conditionals_post.h @@ -3279,7 +3279,7 @@ #endif // Add commands that need sub-codes to this list -#if ANY(G38_PROBE_TARGET, CNC_COORDINATE_SYSTEMS, POWER_LOSS_RECOVERY) +#if ANY(G38_PROBE_TARGET, CNC_COORDINATE_SYSTEMS, POWER_LOSS_RECOVERY, HAS_ROTATIONAL_AXES) #define USE_GCODE_SUBCODES 1 #endif diff --git a/Marlin/src/lcd/marlinui.cpp b/Marlin/src/lcd/marlinui.cpp index f66b680bc1..99a5996a2d 100644 --- a/Marlin/src/lcd/marlinui.cpp +++ b/Marlin/src/lcd/marlinui.cpp @@ -23,6 +23,7 @@ #include "../inc/MarlinConfig.h" #include "../MarlinCore.h" // for printingIsPaused +#include "../gcode/parser.h" // for axis_is_rotational, using_inch_units #if LED_POWEROFF_TIMEOUT > 0 || ALL(HAS_WIRED_LCD, PRINTER_EVENT_LEDS) || (HAS_BACKLIGHT_TIMEOUT && defined(NEOPIXEL_BKGD_INDEX_FIRST)) #include "../feature/leds/leds.h" @@ -824,6 +825,13 @@ void MarlinUI::init() { const feedRate_t fr_mm_s = (axis < LOGICAL_AXES) ? manual_feedrate_mm_s[axis] : XY_PROBE_FEEDRATE_MM_S; + /** + * For a rotational axis apply the "inch" to "mm" conversion factor. This mimics behaviour of the G-code G1 + * (see get_destination_from_command). For moves involving only rotational axes, the planner will convert + * back to the feedrate in degrees-per-time unit. + */ + const feedRate_t fr = parser.axis_is_rotational(axis) && parser.using_inch_units() ? IN_TO_MM(fr_mm_s) : fr_mm_s; + #if IS_KINEMATIC #if HAS_MULTI_EXTRUDER @@ -850,13 +858,13 @@ void MarlinUI::init() { // previous invocation is being blocked. Modifications to offset shouldn't be made while // processing is true or the planner will get out of sync. processing = true; - prepare_internal_move_to_destination(fr_mm_s); // will set current_position from destination + prepare_internal_move_to_destination(fr); // will set current_position from destination processing = false; #else // For Cartesian / Core motion simply move to the current_position - planner.buffer_line(current_position, fr_mm_s, + planner.buffer_line(current_position, fr, TERN_(MULTI_E_MANUAL, axis == E_AXIS ? e_index :) active_extruder ); diff --git a/Marlin/src/lcd/menu/menu_motion.cpp b/Marlin/src/lcd/menu/menu_motion.cpp index 239d03d977..ebc809fef8 100644 --- a/Marlin/src/lcd/menu/menu_motion.cpp +++ b/Marlin/src/lcd/menu/menu_motion.cpp @@ -78,8 +78,8 @@ void lcd_move_axis(const AxisEnum axis) { if (ui.should_draw()) { MenuEditItemBase::itemIndex = axis; const float pos = ui.manual_move.axis_value(axis); - if (parser.using_inch_units()) { - const float imp_pos = LINEAR_UNIT(pos); + if (parser.using_inch_units() && !parser.axis_is_rotational(axis)) { + const float imp_pos = parser.per_axis_value(axis, pos); MenuEditItemBase::draw_edit_screen(GET_TEXT_F(MSG_MOVE_N), ftostr63(imp_pos)); } else diff --git a/Marlin/src/module/motion.cpp b/Marlin/src/module/motion.cpp index c6b0936447..862f0c5754 100644 --- a/Marlin/src/module/motion.cpp +++ b/Marlin/src/module/motion.cpp @@ -1153,10 +1153,13 @@ float get_move_distance(const xyze_pos_t &diff OPTARG(HAS_ROTATIONAL_AXES, bool #if HAS_ROTATIONAL_AXES if (UNEAR_ZERO(distance_sqr)) { - // Move involves only rotational axes. Calculate angular distance in accordance with LinuxCNC - is_cartesian_move = false; + // Move involves no linear axes. Calculate angular distance in accordance with LinuxCNC distance_sqr = ROTATIONAL_AXIS_GANG(sq(diff.i), + sq(diff.j), + sq(diff.k), + sq(diff.u), + sq(diff.v), + sq(diff.w)); } + if (!UNEAR_ZERO(distance_sqr)) { + // Move involves rotational axes, not just the extruder + is_cartesian_move = false; + } #endif #endif diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp index 0ace6e32ce..8f7c4ceb72 100644 --- a/Marlin/src/module/planner.cpp +++ b/Marlin/src/module/planner.cpp @@ -2079,11 +2079,11 @@ bool Planner::_populate_block( /** * This part of the code calculates the total length of the movement. - * For cartesian bots, the X_AXIS is the real X movement and same for Y_AXIS. - * But for corexy bots, that is not true. The "X_AXIS" and "Y_AXIS" motors (that should be named to A_AXIS - * and B_AXIS) cannot be used for X and Y length, because A=X+Y and B=X-Y. - * So we need to create other 2 "AXIS", named X_HEAD and Y_HEAD, meaning the real displacement of the Head. - * Having the real displacement of the head, we can calculate the total movement length and apply the desired speed. + * For cartesian bots, the distance along the X axis equals the X_AXIS joint displacement and same holds true for Y_AXIS. + * But for geometries like CORE_XY that is not true. For these machines we need to create 2 additional variables, named X_HEAD and Y_HEAD, to store the displacent of the head along the X and Y axes in a cartesian coordinate system. + * The displacement of the head along the axes of the cartesian coordinate system has to be calculated from "X_AXIS" and "Y_AXIS" (should be renamed to A_JOINT and B_JOINT) + * displacements in joints space using forward kinematics (A=X+Y and B=X-Y in the case of CORE_XY). + * Next we can calculate the total movement length and apply the desired speed. */ struct DistanceMM : abce_float_t { #if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX) @@ -2308,6 +2308,10 @@ bool Planner::_populate_block( // Example 2: At 120°/s a 60° move involving only rotational axes takes 0.5s. So this will give 2.0. float inverse_secs = inverse_millimeters * ( #if ALL(HAS_ROTATIONAL_AXES, INCH_MODE_SUPPORT) + /** + * Workaround for premature feedrate conversion + * from in/s to mm/s by get_distance_from_command. + */ cartesian_move ? fr_mm_s : LINEAR_UNIT(fr_mm_s) #else fr_mm_s