From 04554abae62e0e7f5b77ab74dd9a56385d55a46d Mon Sep 17 00:00:00 2001 From: harrierpigeon Date: Sat, 27 Jun 2026 01:47:20 -0500 Subject: [PATCH] Fix belt printer illegal gantry move at print start MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On a belt printer the first travel of the print emitted a bogus move to the bed corner with the nozzle far up the gantry, e.g. G1 X95 Y168.19 Z237.857 F12000 right after the first "; printing object" line. Y168 (≈ the layer Z) is out of the gantry's range. Root cause: the layer-change z-hop is deferred via lazy_lift and consumed by the first BeltGCodeWriter::travel_to_xyz, whose NormalLift branch does a separate lift-in-place via _travel_to_z(target.z()). On a normal printer _travel_to_z emits a Z-only move, but in belt mode Z is coupled to Y/X, so _travel_to_z re-emits the current m_pos through the belt shear. At print start (and after custom gcode) m_pos.xy is still the uninitialised origin (0,0), which the back-transform + axis-remap shear into machine (X=bed_max, Y=layer_z) — the illegal move. Guard the NormalLift branch on is_current_position_clear(), matching the SlopeLift branch directly above it which already does so. When the position isn't established there is nothing to lift over, and the xy_z_move that follows travels straight to the destination with full XYZ, establishing the correct position. Bookkeeping is unaffected: in this path m_lifted stays 0, so no spurious restore move is produced. Verified by re-slicing the repro project: the start-of-print move is now G1 X44.946 Y.621 Z237.857 (straight to the first object point), no move touches the bed-max X edge, and the max Y over the whole file is 62.8mm (printable_height 100). --- src/libslic3r/BeltGCodeWriter.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/BeltGCodeWriter.cpp b/src/libslic3r/BeltGCodeWriter.cpp index f46b1f2c35..e1dad4177f 100644 --- a/src/libslic3r/BeltGCodeWriter.cpp +++ b/src/libslic3r/BeltGCodeWriter.cpp @@ -217,7 +217,17 @@ std::string BeltGCodeWriter::travel_to_xyz(const Vec3d &point, const std::string w0.emit_comment(GCodeWriter::full_gcode_comment, comment); slop_move = w0.string(); } - else if (m_to_lift_type == LiftType::NormalLift) { + else if (m_to_lift_type == LiftType::NormalLift && this->is_current_position_clear()) { + // Only lift-in-place when the current position is known. On a normal + // printer _travel_to_z emits a Z-only move, but in belt mode Z is coupled + // to Y/X, so _travel_to_z re-emits the current m_pos through the belt + // shear. At print start (and after custom gcode) m_pos.xy is still the + // uninitialised origin (0,0), which shears into a bogus machine point + // (e.g. X=bed_max, Y=layer_z) far up the gantry. Skipping the separate + // lift here is safe: there is nothing to lift over yet, and the + // xy_z_move below travels straight to the destination with full XYZ, + // establishing the correct position. This mirrors the SlopeLift branch + // above, which already guards on is_current_position_clear(). slop_move = _travel_to_z(target.z(), "normal lift Z"); } }