diff --git a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp index a0a12ea62..fa82cccda 100644 --- a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp +++ b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp @@ -1249,7 +1249,7 @@ if (isnan(z_values[i][j])) { // Invalid mesh point? // Skip points the probe can't reach - if (!position_is_reachable_by_probe(mesh_index_to_xpos(i), mesh_index_to_ypos(j))) + if (!probe.can_reach(mesh_index_to_xpos(i), mesh_index_to_ypos(j))) continue; found_a_NAN = true; @@ -1316,7 +1316,7 @@ // Also for round beds, there are grid points outside the bed the nozzle can't reach. // Prune them from the list and ignore them till the next Phase (manual nozzle probing). - if (probe_relative ? !position_is_reachable_by_probe(mpos) : !position_is_reachable(mpos)) + if (!(probe_relative ? probe.can_reach(mpos) : position_is_reachable(mpos))) continue; // Reachable. Check if it's the best_so_far location to the nozzle. diff --git a/Marlin/src/gcode/bedlevel/abl/G29.cpp b/Marlin/src/gcode/bedlevel/abl/G29.cpp index 517350516..c81e5f0a8 100644 --- a/Marlin/src/gcode/bedlevel/abl/G29.cpp +++ b/Marlin/src/gcode/bedlevel/abl/G29.cpp @@ -417,17 +417,7 @@ G29_TYPE GcodeSuite::G29() { ); } - if ( - #if IS_SCARA || ENABLED(DELTA) - !position_is_reachable_by_probe(probe_position_lf.x, 0) - || !position_is_reachable_by_probe(probe_position_rb.x, 0) - || !position_is_reachable_by_probe(0, probe_position_lf.y) - || !position_is_reachable_by_probe(0, probe_position_rb.y) - #else - !position_is_reachable_by_probe(probe_position_lf) - || !position_is_reachable_by_probe(probe_position_rb) - #endif - ) { + if (!probe.good_bounds(probe_position_lf, probe_position_rb)) { SERIAL_ECHOLNPGM("? (L,R,F,B) out of bounds."); G29_RETURN(false); } @@ -704,7 +694,7 @@ G29_TYPE GcodeSuite::G29() { #if IS_KINEMATIC // Avoid probing outside the round or hexagonal area - if (!position_is_reachable_by_probe(probePos)) continue; + if (!probe.can_reach(probePos)) continue; #endif if (verbose_level) SERIAL_ECHOLNPAIR("Probing mesh point ", int(pt_index), "/", int(GRID_MAX_POINTS), "."); diff --git a/Marlin/src/gcode/calibrate/G34_M422.cpp b/Marlin/src/gcode/calibrate/G34_M422.cpp index e7bc63828..7144038eb 100644 --- a/Marlin/src/gcode/calibrate/G34_M422.cpp +++ b/Marlin/src/gcode/calibrate/G34_M422.cpp @@ -432,11 +432,11 @@ void GcodeSuite::M422() { }; if (is_probe_point) { - if (!position_is_reachable_by_probe(pos.x, Y_CENTER)) { + if (!probe.can_reach(pos.x, Y_CENTER)) { SERIAL_ECHOLNPGM("?(X) out of bounds."); return; } - if (!position_is_reachable_by_probe(pos)) { + if (!probe.can_reach(pos)) { SERIAL_ECHOLNPGM("?(Y) out of bounds."); return; } diff --git a/Marlin/src/gcode/calibrate/G76_M871.cpp b/Marlin/src/gcode/calibrate/G76_M871.cpp index 4340084ec..8cd9c8a0c 100644 --- a/Marlin/src/gcode/calibrate/G76_M871.cpp +++ b/Marlin/src/gcode/calibrate/G76_M871.cpp @@ -116,7 +116,7 @@ void GcodeSuite::G76() { temp_comp.measure_point_x - probe.offset_xy.x, temp_comp.measure_point_y - probe.offset_xy.y ); - if (!position_is_reachable_by_probe(destination)) { + if (!probe.can_reach(destination)) { SERIAL_ECHOLNPGM("!Probe position unreachable - aborting."); return; } diff --git a/Marlin/src/gcode/calibrate/M48.cpp b/Marlin/src/gcode/calibrate/M48.cpp index 8fba7a646..fb8651779 100644 --- a/Marlin/src/gcode/calibrate/M48.cpp +++ b/Marlin/src/gcode/calibrate/M48.cpp @@ -80,11 +80,11 @@ void GcodeSuite::M48() { xy_float_t next_pos = current_position; const xy_pos_t probe_pos = { - parser.linearval('X', next_pos.x + probe.offset_xy.x), - parser.linearval('Y', next_pos.y + probe.offset_xy.y) + parser.linearval('X', next_pos.x + probe.offset_xy.x), // If no X use the probe's current X position + parser.linearval('Y', next_pos.y + probe.offset_xy.y) // If no Y, ditto }; - if (!position_is_reachable_by_probe(probe_pos)) { + if (!probe.can_reach(probe_pos)) { SERIAL_ECHOLNPGM("? (X,Y) out of bounds."); return; } @@ -179,7 +179,7 @@ void GcodeSuite::M48() { #else // If we have gone out too far, we can do a simple fix and scale the numbers // back in closer to the origin. - while (!position_is_reachable_by_probe(next_pos)) { + while (!probe.can_reach(next_pos)) { next_pos *= 0.8f; if (verbose_level > 3) SERIAL_ECHOLNPAIR_P(PSTR("Moving inward: X"), next_pos.x, SP_Y_STR, next_pos.y); diff --git a/Marlin/src/gcode/probe/G30.cpp b/Marlin/src/gcode/probe/G30.cpp index 8b2ada9ce..21d56b3fd 100644 --- a/Marlin/src/gcode/probe/G30.cpp +++ b/Marlin/src/gcode/probe/G30.cpp @@ -43,7 +43,7 @@ void GcodeSuite::G30() { const xy_pos_t pos = { parser.linearval('X', current_position.x + probe.offset_xy.x), parser.linearval('Y', current_position.y + probe.offset_xy.y) }; - if (!position_is_reachable_by_probe(pos)) return; + if (!probe.can_reach(pos)) return; // Disable leveling so the planner won't mess with us #if HAS_LEVELING diff --git a/Marlin/src/module/motion.h b/Marlin/src/module/motion.h index c50da25a3..f1c2dc069 100644 --- a/Marlin/src/module/motion.h +++ b/Marlin/src/module/motion.h @@ -30,10 +30,6 @@ #include "../inc/MarlinConfig.h" -#if HAS_BED_PROBE - #include "probe.h" -#endif - #if IS_SCARA #include "scara.h" #endif @@ -58,7 +54,7 @@ FORCE_INLINE bool homing_needed() { } // Error margin to work around float imprecision -constexpr float slop = 0.0001; +constexpr float fslop = 0.0001; extern bool relative_mode; @@ -306,7 +302,7 @@ void homeaxis(const AxisEnum axis); // Return true if the given point is within the printable area inline bool position_is_reachable(const float &rx, const float &ry, const float inset=0) { #if ENABLED(DELTA) - return HYPOT2(rx, ry) <= sq(DELTA_PRINTABLE_RADIUS - inset + slop); + return HYPOT2(rx, ry) <= sq(DELTA_PRINTABLE_RADIUS - inset + fslop); #elif IS_SCARA const float R2 = HYPOT2(rx - SCARA_OFFSET_X, ry - SCARA_OFFSET_Y); return ( @@ -322,67 +318,24 @@ void homeaxis(const AxisEnum axis); return position_is_reachable(pos.x, pos.y, inset); } - #if HAS_BED_PROBE - - #if HAS_PROBE_XY_OFFSET - - // Return true if the both nozzle and the probe can reach the given point. - // Note: This won't work on SCARA since the probe offset rotates with the arm. - inline bool position_is_reachable_by_probe(const float &rx, const float &ry) { - return position_is_reachable(rx - probe.offset_xy.x, ry - probe.offset_xy.y) - && position_is_reachable(rx, ry, ABS(MIN_PROBE_EDGE)); - } - - #else - - FORCE_INLINE bool position_is_reachable_by_probe(const float &rx, const float &ry) { - return position_is_reachable(rx, ry, MIN_PROBE_EDGE); - } - - #endif - - #endif // HAS_BED_PROBE - #else // CARTESIAN // Return true if the given position is within the machine bounds. inline bool position_is_reachable(const float &rx, const float &ry) { - if (!WITHIN(ry, Y_MIN_POS - slop, Y_MAX_POS + slop)) return false; + if (!WITHIN(ry, Y_MIN_POS - fslop, Y_MAX_POS + fslop)) return false; #if ENABLED(DUAL_X_CARRIAGE) if (active_extruder) - return WITHIN(rx, X2_MIN_POS - slop, X2_MAX_POS + slop); + return WITHIN(rx, X2_MIN_POS - fslop, X2_MAX_POS + fslop); else - return WITHIN(rx, X1_MIN_POS - slop, X1_MAX_POS + slop); + return WITHIN(rx, X1_MIN_POS - fslop, X1_MAX_POS + fslop); #else - return WITHIN(rx, X_MIN_POS - slop, X_MAX_POS + slop); + return WITHIN(rx, X_MIN_POS - fslop, X_MAX_POS + fslop); #endif } inline bool position_is_reachable(const xy_pos_t &pos) { return position_is_reachable(pos.x, pos.y); } - #if HAS_BED_PROBE - - /** - * Return whether the given position is within the bed, and whether the nozzle - * can reach the position required to put the probe at the given position. - * - * Example: For a probe offset of -10,+10, then for the probe to reach 0,0 the - * nozzle must be be able to reach +10,-10. - */ - inline bool position_is_reachable_by_probe(const float &rx, const float &ry) { - return position_is_reachable(rx - probe.offset_xy.x, ry - probe.offset_xy.y) - && WITHIN(rx, probe.min_x() - slop, probe.max_x() + slop) - && WITHIN(ry, probe.min_y() - slop, probe.max_y() + slop); - } - - #endif // HAS_BED_PROBE - #endif // CARTESIAN -#if !HAS_BED_PROBE - FORCE_INLINE bool position_is_reachable_by_probe(const float &rx, const float &ry) { return position_is_reachable(rx, ry); } -#endif -FORCE_INLINE bool position_is_reachable_by_probe(const xy_pos_t &pos) { return position_is_reachable_by_probe(pos.x, pos.y); } - /** * Duplication mode */ diff --git a/Marlin/src/module/probe.cpp b/Marlin/src/module/probe.cpp index 858dcae74..67c165537 100644 --- a/Marlin/src/module/probe.cpp +++ b/Marlin/src/module/probe.cpp @@ -89,7 +89,7 @@ Probe probe; xyz_pos_t Probe::offset; // Initialized by settings.load() #if HAS_PROBE_XY_OFFSET - const xyz_pos_t &Probe::offset_xy = probe.offset; + const xyz_pos_t &Probe::offset_xy = Probe::offset; #endif #if ENABLED(Z_PROBE_SLED) @@ -727,7 +727,7 @@ float Probe::probe_at_point(const float &rx, const float &ry, const ProbePtRaise // TODO: Adapt for SCARA, where the offset rotates xyz_pos_t npos = { rx, ry }; if (probe_relative) { // The given position is in terms of the probe - if (!position_is_reachable_by_probe(npos)) { + if (!can_reach(npos)) { if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Position Not Reachable"); return NAN; } diff --git a/Marlin/src/module/probe.h b/Marlin/src/module/probe.h index 6f17090e6..84a8f953c 100644 --- a/Marlin/src/module/probe.h +++ b/Marlin/src/module/probe.h @@ -27,6 +27,8 @@ #include "../inc/MarlinConfig.h" +#include "motion.h" + #if HAS_BED_PROBE enum ProbePtRaise : uint8_t { PROBE_PT_NONE, // No raise or stow after run_z_probe @@ -45,6 +47,39 @@ public: static bool set_deployed(const bool deploy); + + #if IS_KINEMATIC + + #if HAS_PROBE_XY_OFFSET + // Return true if the both nozzle and the probe can reach the given point. + // Note: This won't work on SCARA since the probe offset rotates with the arm. + static inline bool can_reach(const float &rx, const float &ry) { + return position_is_reachable(rx - offset_xy.x, ry - offset_xy.y) // The nozzle can go where it needs to go? + && position_is_reachable(rx, ry, ABS(MIN_PROBE_EDGE)); // Can the nozzle also go near there? + } + #else + FORCE_INLINE static bool can_reach(const float &rx, const float &ry) { + return position_is_reachable(rx, ry, MIN_PROBE_EDGE); + } + #endif + + #else + + /** + * Return whether the given position is within the bed, and whether the nozzle + * can reach the position required to put the probe at the given position. + * + * Example: For a probe offset of -10,+10, then for the probe to reach 0,0 the + * nozzle must be be able to reach +10,-10. + */ + static inline bool can_reach(const float &rx, const float &ry) { + return position_is_reachable(rx - offset_xy.x, ry - offset_xy.y) + && WITHIN(rx, min_x() - fslop, max_x() + fslop) + && WITHIN(ry, min_y() - fslop, max_y() + fslop); + } + + #endif + #ifdef Z_AFTER_PROBING static void move_z_after_probing(); #endif @@ -62,8 +97,22 @@ public: static bool set_deployed(const bool) { return false; } + FORCE_INLINE static bool can_reach(const float &rx, const float &ry) { return position_is_reachable(rx, ry); } + #endif + FORCE_INLINE static bool can_reach(const xy_pos_t &pos) { return can_reach(pos.x, pos.y); } + + FORCE_INLINE static bool good_bounds(const xy_pos_t &lf, const xy_pos_t &rb) { + return ( + #if IS_KINEMATIC + can_reach(lf.x, 0) && can_reach(rb.x, 0) && can_reach(0, lf.y) && can_reach(0, rb.y) + #else + can_reach(lf) && can_reach(rb) + #endif + ); + } + // Use offset_xy for read only access // More optimal the XY offset is known to always be zero. #if HAS_PROBE_XY_OFFSET