From 21399999f1ef5359e124568422cea80595562e98 Mon Sep 17 00:00:00 2001 From: "xun.zhang" Date: Fri, 24 Jan 2025 15:56:53 +0800 Subject: [PATCH] ENH: add eager lift function 1.Immediate do lift in eager_lift function jira:NONE Signed-off-by: xun.zhang Change-Id: I931d22e901e2123bb886c31d8d1a5788fddeed42 (cherry picked from commit 6cea772d4f3b2f7e2a43c35a2271e4bdbba9eadd) --- src/libslic3r/GCode.cpp | 37 +++++++------ src/libslic3r/GCode.hpp | 2 +- src/libslic3r/GCodeWriter.cpp | 97 ++++++++++++++++++++++++----------- src/libslic3r/GCodeWriter.hpp | 5 +- src/libslic3r/PrintConfig.hpp | 2 +- 5 files changed, 93 insertions(+), 50 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index b3cd9222e3..2ec1718e6b 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -789,7 +789,7 @@ static std::vector get_path_of_change_filament(const Print& print) auto_lift_type = LiftType::SpiralLift; // BBS: should be placed before toolchange parsing - std::string toolchange_retract_str = gcodegen.retract(tcr.is_tool_change && !is_nozzle_change, false, auto_lift_type); + std::string toolchange_retract_str = gcodegen.retract(tcr.is_tool_change && !is_nozzle_change, false, auto_lift_type, true); check_add_eol(toolchange_retract_str); //BBS: if needed, write the gcode_label_objects_end then priming tower, if the retract, didn't did it. @@ -817,7 +817,7 @@ static std::vector get_path_of_change_filament(const Print& print) gcodegen.m_wipe.reset_path(); for (const Vec2f& wipe_pt : tcr.nozzle_change_result.wipe_path) gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen, transform_wt_pt(wipe_pt) + plate_origin_2d)); - nozzle_change_gcode_trans += gcodegen.retract(tcr.is_tool_change, false, auto_lift_type); + nozzle_change_gcode_trans += gcodegen.retract(tcr.is_tool_change, false, auto_lift_type, true); end_filament_gcode_str = nozzle_change_gcode_trans + end_filament_gcode_str; } @@ -1064,7 +1064,7 @@ static std::vector get_path_of_change_filament(const Print& print) gcodegen.m_wipe.reset_path(); for (const Vec2f &wipe_pt : tcr.wipe_path) gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen, transform_wt_pt(wipe_pt))); - gcode += gcodegen.retract(false, false, auto_lift_type); + gcode += gcodegen.retract(false, false, auto_lift_type, true); } // Let the planner know we are traveling between objects. @@ -4776,7 +4776,7 @@ LayerResult GCode::process_layer( if (!need_insert_timelapse_gcode_for_traditional) { // Equivalent to the timelapse gcode placed in layer_change_gcode if (FILAMENT_CONFIG(retract_when_changing_layer)) { - gcode += this->retract(false, false, auto_lift_type); + gcode += this->retract(false, false, auto_lift_type, true); } gcode += insert_timelapse_gcode(); } @@ -4833,7 +4833,7 @@ LayerResult GCode::process_layer( } if (should_insert) { - gcode += this->retract(false, false, auto_lift_type); + gcode += this->retract(false, false, auto_lift_type, true); m_writer.add_object_change_labels(gcode); gcode += insert_timelapse_gcode(); @@ -4842,7 +4842,7 @@ LayerResult GCode::process_layer( } if (print.config().enable_wrapping_detection && !has_insert_wrapping_detection_gcode) { - gcode += this->retract(false, false, auto_lift_type); + gcode += this->retract(false, false, auto_lift_type, true); gcode += insert_wrapping_detection_gcode(); has_insert_wrapping_detection_gcode = true; } @@ -4855,7 +4855,7 @@ LayerResult GCode::process_layer( m_config.nozzle_diameter.values.size() == 2 && writer().filament() && (get_extruder_id(writer().filament()->id()) == most_used_extruder)) { - gcode += this->retract(false, false, auto_lift_type); + gcode += this->retract(false, false, auto_lift_type, true); m_writer.add_object_change_labels(gcode); gcode += insert_timelapse_gcode(); @@ -4863,7 +4863,7 @@ LayerResult GCode::process_layer( } if (print.config().enable_wrapping_detection && !has_insert_wrapping_detection_gcode) { - gcode += this->retract(false, false, auto_lift_type); + gcode += this->retract(false, false, auto_lift_type, true); gcode += insert_wrapping_detection_gcode(); has_insert_wrapping_detection_gcode = true; } @@ -5068,7 +5068,7 @@ LayerResult GCode::process_layer( gcode += this->extrude_perimeters(print, by_region_specific, first_layer, false); if (!has_wipe_tower && need_insert_timelapse_gcode_for_traditional && printer_structure == PrinterStructure::psI3 && !has_insert_timelapse_gcode && has_infill(by_region_specific)) { - gcode += this->retract(false, false, auto_lift_type); + gcode += this->retract(false, false, auto_lift_type, true); gcode += insert_timelapse_gcode(); has_insert_timelapse_gcode = true; @@ -5153,7 +5153,7 @@ LayerResult GCode::process_layer( m_support_traditional_timelapse = false; } if (FILAMENT_CONFIG(retract_when_changing_layer)) { - gcode += this->retract(false, false, auto_lift_type); + gcode += this->retract(false, false, auto_lift_type, true); } m_writer.add_object_change_labels(gcode); @@ -6890,7 +6890,7 @@ std::string GCode::travel_to(const Point& point, ExtrusionRole role, std::string m_wipe.reset_path();*/ Point last_post_before_retract = this->last_pos(); - gcode += this->retract(false, false, lift_type, role); + gcode += this->retract(false, false, lift_type, false, role); // When "Wipe while retracting" is enabled, then extruder moves to another position, and travel from this position can cross perimeters. // Because of it, it is necessary to call avoid crossing perimeters again with new starting point after calling retraction() // FIXME Lukas H.: Try to predict if this second calling of avoid crossing perimeters will be needed or not. It could save computations. @@ -6969,7 +6969,7 @@ LiftType GCode::to_lift_type(ZHopType z_hop_types) { case ZHopType::zhtNormal: return LiftType::NormalLift; case ZHopType::zhtSlope: - return LiftType::LazyLift; + return LiftType::SlopeLift; case ZHopType::zhtSpiral: return LiftType::SpiralLift; default: @@ -7060,7 +7060,7 @@ bool GCode::needs_retraction(const Polyline &travel, ExtrusionRole role, LiftTyp //Better way is judging whether the travel move direction is same with last extrusion move. if (is_perimeter(m_last_processor_extrusion_role) && m_last_processor_extrusion_role != erPerimeter) { if (ZHopType(FILAMENT_CONFIG(z_hop_types)) == ZHopType::zhtAuto) { - lift_type = is_through_overhang(clipped_travel) ? LiftType::SpiralLift : LiftType::LazyLift; + lift_type = is_through_overhang(clipped_travel) ? LiftType::SpiralLift : LiftType::SlopeLift; } else { lift_type = to_lift_type(ZHopType(FILAMENT_CONFIG(z_hop_types))); @@ -7094,7 +7094,7 @@ bool GCode::needs_retraction(const Polyline &travel, ExtrusionRole role, LiftTyp // retract if reduce_infill_retraction is disabled or doesn't apply when role is perimeter if (ZHopType(FILAMENT_CONFIG(z_hop_types)) == ZHopType::zhtAuto) { - lift_type = is_through_overhang(clipped_travel) ? LiftType::SpiralLift : LiftType::LazyLift; + lift_type = is_through_overhang(clipped_travel) ? LiftType::SpiralLift : LiftType::SlopeLift; } else { lift_type = to_lift_type(ZHopType(FILAMENT_CONFIG(z_hop_types))); @@ -7102,7 +7102,7 @@ bool GCode::needs_retraction(const Polyline &travel, ExtrusionRole role, LiftTyp return true; } -std::string GCode::retract(bool toolchange, bool is_last_retraction, LiftType lift_type, ExtrusionRole role) +std::string GCode::retract(bool toolchange, bool is_last_retraction, LiftType lift_type, bool apply_instantly, ExtrusionRole role) { std::string gcode; @@ -7151,7 +7151,10 @@ std::string GCode::retract(bool toolchange, bool is_last_retraction, LiftType li } if (needs_lift && can_lift) { - gcode += m_writer.lift(lift_type, m_spiral_vase != nullptr); + if (apply_instantly) + gcode += m_writer.eager_lift(lift_type); + else + gcode += m_writer.lazy_lift(lift_type, m_spiral_vase != nullptr); } return gcode; @@ -7371,7 +7374,7 @@ std::string GCode::set_extruder(unsigned int new_filament_id, double print_z, bo std::string change_filament_gcode = m_config.change_filament_gcode.value; // Move the lift gcode here which is in the change_filament_gcode originally - change_filament_gcode = this->retract(false, false, LiftType::SpiralLift) + change_filament_gcode; + change_filament_gcode = this->retract(false, false, LiftType::SpiralLift, true) + change_filament_gcode; std::string toolchange_gcode_parsed; //Orca: Ignore change_filament_gcode if is the first call for a tool change and manual_filament_change is enabled diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 0106670a24..2bf29aa002 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -246,7 +246,7 @@ public: std::string travel_to(const Point& point, ExtrusionRole role, std::string comment, double z = DBL_MAX); bool needs_retraction(const Polyline& travel, ExtrusionRole role, LiftType& lift_type); - std::string retract(bool toolchange = false, bool is_last_retraction = false, LiftType lift_type = LiftType::NormalLift, ExtrusionRole role = erNone); + std::string retract(bool toolchange = false, bool is_last_retraction = false, LiftType lift_type = LiftType::NormalLift, bool apply_instantly = false, ExtrusionRole role = erNone); std::string unretract() { return m_writer.unlift() + m_writer.unretract(); } std::string set_extruder(unsigned int extruder_id, double print_z, bool by_object=false); bool is_BBL_Printer(); diff --git a/src/libslic3r/GCodeWriter.cpp b/src/libslic3r/GCodeWriter.cpp index c53d3a0f9a..1cabed0066 100644 --- a/src/libslic3r/GCodeWriter.cpp +++ b/src/libslic3r/GCodeWriter.cpp @@ -528,6 +528,71 @@ std::string GCodeWriter::travel_to_xy(const Vec2d &point, const std::string &com return w.string(); } +/* If this method is called more than once before calling unlift(), +it will not perform subsequent lifts, even if Z was raised manually +(i.e. with travel_to_z()) and thus _lifted was reduced. */ +std::string GCodeWriter::lazy_lift(LiftType lift_type, bool spiral_vase) +{ + // check whether the above/below conditions are met + double target_lift = 0; + { + //BBS + int extruder_id = filament()->extruder_id(); + int filament_id = filament()->id(); + double above = this->config.retract_lift_above.get_at(extruder_id); + double below = this->config.retract_lift_below.get_at(extruder_id); + if (m_pos.z() >= above && m_pos.z() <= below) + target_lift = this->config.z_hop.get_at(filament_id); + } + // BBS + if (m_lifted == 0 && m_to_lift == 0 && target_lift > 0) { + if (spiral_vase) { + m_lifted = target_lift; + return this->_travel_to_z(m_pos(2) + target_lift, "lift Z"); + } + else { + m_to_lift = target_lift; + m_to_lift_type = lift_type; + } + } + return ""; +} + +// BBS: immediately execute an undelayed lift move with a spiral lift pattern +// designed specifically for subsequent gcode injection (e.g. timelapse) +std::string GCodeWriter::eager_lift(const LiftType type) { + std::string lift_move; + double target_lift = 0; + { + //BBS + int extruder_id = filament()->extruder_id(); + int filament_id = filament()->id(); + double above = this->config.retract_lift_above.get_at(extruder_id); + double below = this->config.retract_lift_below.get_at(extruder_id); + if (m_pos.z() >= above && m_pos.z() <= below) + target_lift = this->config.z_hop.get_at(filament_id); + } + + // BBS: spiral lift only safe with known position + // TODO: check the arc will move within bed area + if (type == LiftType::SpiralLift && this->is_current_position_clear()) { + double radius = target_lift / (2 * PI * atan(filament()->travel_slope())); + // static spiral alignment when no move in x,y plane. + // spiral centra is a radius distance to the right (y=0) + Vec2d ij_offset = { radius, 0 }; + if (target_lift > 0) { + lift_move = this->_spiral_travel_to_z(m_pos(2) + target_lift, ij_offset, "spiral lift Z"); + } + } + //BBS: if position is unknown use normal lift + else if (target_lift > 0) { + lift_move = _travel_to_z(m_pos(2) + target_lift, "normal lift Z"); + } + m_lifted = target_lift; + m_to_lift = 0; + return lift_move; +} + std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &comment, bool force_z) { // FIXME: This function was not being used when travel_speed_z was separated (bd6badf). @@ -573,8 +638,8 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co ij_offset = { -ij_offset(1), ij_offset(0) }; slop_move = this->_spiral_travel_to_z(target(2), ij_offset, "spiral lift Z"); } - //BBS: LazyLift - else if (m_to_lift_type == LiftType::LazyLift && + //BBS: SlopeLift + else if (m_to_lift_type == LiftType::SlopeLift && this->is_current_position_clear() && atan2(delta(2), delta_no_z.norm()) < this->filament()->travel_slope()) { //BBS: check whether we can make a travel like @@ -871,34 +936,6 @@ std::string GCodeWriter::unretract() return gcode; } -/* If this method is called more than once before calling unlift(), - it will not perform subsequent lifts, even if Z was raised manually - (i.e. with travel_to_z()) and thus _lifted was reduced. */ -std::string GCodeWriter::lift(LiftType lift_type, bool spiral_vase) -{ - // check whether the above/below conditions are met - double target_lift = 0; - { - int extruder_id = filament()->extruder_id(); - int filament_id = filament()->id(); - double above = this->config.retract_lift_above.get_at(extruder_id); - double below = this->config.retract_lift_below.get_at(extruder_id); - if (m_pos(2) >= above && (below == 0 || m_pos(2) <= below)) - target_lift = this->config.z_hop.get_at(filament_id); - } - // BBS - if (m_lifted == 0 && m_to_lift == 0 && target_lift > 0) { - if (spiral_vase) { - m_lifted = target_lift; - return this->_travel_to_z(m_pos(2) + target_lift, "lift Z"); - } - else { - m_to_lift = target_lift; - m_to_lift_type = lift_type; - } - } - return ""; -} std::string GCodeWriter::unlift() { diff --git a/src/libslic3r/GCodeWriter.hpp b/src/libslic3r/GCodeWriter.hpp index 1fbe7623c0..2c68c921d8 100644 --- a/src/libslic3r/GCodeWriter.hpp +++ b/src/libslic3r/GCodeWriter.hpp @@ -83,7 +83,10 @@ public: std::string retract(bool before_wipe = false, double retract_length = 0); std::string retract_for_toolchange(bool before_wipe = false, double retract_length = 0); std::string unretract(); - std::string lift(LiftType lift_type = LiftType::NormalLift, bool spiral_vase = false); + // do lift instantly + std::string eager_lift(const LiftType type); + // record a lift request, do realy lift in next travel + std::string lazy_lift(LiftType lift_type = LiftType::NormalLift, bool spiral_vase = false); std::string unlift(); const Vec3d& get_position() const { return m_pos; } Vec3d& get_position() { return m_pos; } diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 0d9f2c444e..280fbd3680 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -221,7 +221,7 @@ enum GapFillTarget { enum LiftType { NormalLift, SpiralLift, - LazyLift + SlopeLift }; enum SLAMaterial {