diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 9907dd70d6..f9cb263672 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -295,7 +295,65 @@ static std::vector get_path_of_change_filament(const Print& print) : gcodegen.config().nozzle_temperature.get_at(gcodegen.writer().extruder()->id()); } - std::string Wipe::wipe(GCode& gcodegen, bool toolchange, bool is_last) + // Ioannis Giannakas: + // Function to calculate the excess retraction length that should be retracted either before or after wiping + // in order for the wipe operation to respect the filament retraction speed + Wipe::RetractionValues Wipe::calculateWipeRetractionLengths(GCode& gcodegen, bool toolchange) { + auto& writer = gcodegen.writer(); + auto& config = gcodegen.config(); + auto extruder = writer.extruder(); + auto extruder_id = extruder->id(); + auto last_pos = gcodegen.last_pos(); + + // Declare & initialize retraction lengths + double retraction_length_remaining = 0, + retractionBeforeWipe = 0, + retractionDuringWipe = 0; + + // initialise the remaining retraction amount with the full retraction amount. + retraction_length_remaining = toolchange ? extruder->retract_length_toolchange() : extruder->retraction_length(); + + // nothing to retract - return early + if(retraction_length_remaining <=EPSILON) return {0.f,0.f}; + + // calculate retraction before wipe distance from the user setting. Keep adding to this variable any excess retraction needed + // to be performed before the wipe. + retractionBeforeWipe = retraction_length_remaining * extruder->retract_before_wipe(); + retraction_length_remaining -= retractionBeforeWipe; // subtract it from the remaining retraction length + + // all of the retraction is to be done before the wipe + if(retraction_length_remaining <=EPSILON) return {retractionBeforeWipe,0.f}; + + // Calculate wipe speed + double wipe_speed = config.role_based_wipe_speed ? writer.get_current_speed() / 60.0 : config.get_abs_value("wipe_speed"); + wipe_speed = std::max(wipe_speed, 10.0); + + // Process wipe path & calculate wipe path length + double wipe_dist = scale_(config.wipe_distance.get_at(extruder_id)); + Polyline wipe_path = {last_pos}; + wipe_path.append(this->path.points.begin() + 1, this->path.points.end()); + double wipe_path_length = std::min(wipe_path.length(), wipe_dist); + + // Calculate the maximum retraction amount during wipe + retractionDuringWipe = config.retraction_speed.get_at(extruder_id) * unscale_(wipe_path_length) / wipe_speed; + // If the maximum retraction amount during wipe is too small, return 0 and retract everything prior to the wipe. + if(retractionDuringWipe <= EPSILON) return {retractionBeforeWipe,0.f}; + + // If the maximum retraction amount during wipe is greater than any remaining retraction length + // return the remaining retraction length to be retracted during the wipe + if (retractionDuringWipe - retraction_length_remaining > EPSILON) return {retractionBeforeWipe,retraction_length_remaining}; + + // If the user has requested any retract before wipe, proceed with incrementing the retraction amount before wiping with the difference + // and return the maximum allowed wipe amount to be retracted during the wipe move + // If the user has not requested any retract before wipe, the retraction amount before wiping should not be incremented and left to the parent + // function to retract after wipe is done. + if(gcodegen.config().retract_before_wipe.get_at(gcodegen.writer().extruder()->id()) > EPSILON){ + retractionBeforeWipe += retraction_length_remaining - retractionDuringWipe; + } + return {retractionBeforeWipe, retractionDuringWipe}; + } + + std::string Wipe::wipe(GCode& gcodegen,double length, bool toolchange, bool is_last) { std::string gcode; @@ -307,12 +365,6 @@ static std::vector get_path_of_change_filament(const Print& print) if(_wipe_speed < 10) _wipe_speed = 10; - // get the retraction length - double length = toolchange - ? gcodegen.writer().extruder()->retract_length_toolchange() - : gcodegen.writer().extruder()->retraction_length(); - // Shorten the retraction length by the amount already retracted before wipe. - length *= (1. - gcodegen.writer().extruder()->retract_before_wipe()); //SoftFever: allow 100% retract before wipe if (length >= 0) @@ -322,7 +374,7 @@ static std::vector get_path_of_change_filament(const Print& print) for the time needed to consume retraction_length at retraction_speed? */ // BBS double wipe_dist = scale_(gcodegen.config().wipe_distance.get_at(gcodegen.writer().extruder()->id())); - + /* Take the stored wipe path and replace first point with the current actual position (they might be different, for example, in case of loop clipping). */ Polyline wipe_path; @@ -346,7 +398,7 @@ static std::vector get_path_of_change_filament(const Print& print) // add tag for processor gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Wipe_Start) + "\n"; //BBS: don't need to enable cooling makers when this is the last wipe. Because no more cooling layer will clean this "_WIPE" - //Softfever: + //Softfever: std::string cooling_mark = ""; if (gcodegen.enable_cooling_markers() && !is_last) cooling_mark = /*gcodegen.config().role_based_wipe_speed ? ";_EXTERNAL_PERIMETER" : */";_WIPE"; @@ -5463,8 +5515,9 @@ std::string GCode::retract(bool toolchange, bool is_last_retraction, LiftType li // wipe (if it's enabled for this extruder and we have a stored wipe path and no-zero wipe distance) if (EXTRUDER_CONFIG(wipe) && m_wipe.has_path() && scale_(EXTRUDER_CONFIG(wipe_distance)) > SCALED_EPSILON) { - gcode += toolchange ? m_writer.retract_for_toolchange(true) : m_writer.retract(true); - gcode += m_wipe.wipe(*this, toolchange, is_last_retraction); + Wipe::RetractionValues wipeRetractions = m_wipe.calculateWipeRetractionLengths(*this, toolchange); + gcode += toolchange ? m_writer.retract_for_toolchange(true,wipeRetractions.retractLengthBeforeWipe) : m_writer.retract(true, wipeRetractions.retractLengthBeforeWipe); + gcode += m_wipe.wipe(*this,wipeRetractions.retractLengthDuringWipe, toolchange, is_last_retraction); } /* The parent class will decide whether we need to perform an actual retraction diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 708df1c5f1..481a005d55 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -55,11 +55,16 @@ class Wipe { public: bool enable; Polyline path; + struct RetractionValues{ + double retractLengthBeforeWipe; + double retractLengthDuringWipe; + }; Wipe() : enable(false) {} bool has_path() const { return !this->path.points.empty(); } void reset_path() { this->path = Polyline(); } - std::string wipe(GCode &gcodegen, bool toolchange = false, bool is_last = false); + std::string wipe(GCode &gcodegen, double length, bool toolchange = false, bool is_last = false); + RetractionValues calculateWipeRetractionLengths(GCode& gcodegen, bool toolchange); }; class WipeTowerIntegration { diff --git a/src/libslic3r/GCodeWriter.cpp b/src/libslic3r/GCodeWriter.cpp index 5fc57307f0..39fba8747f 100644 --- a/src/libslic3r/GCodeWriter.cpp +++ b/src/libslic3r/GCodeWriter.cpp @@ -682,23 +682,23 @@ std::string GCodeWriter::extrude_to_xyz(const Vec3d &point, double dE, const std return w.string(); } -std::string GCodeWriter::retract(bool before_wipe) +std::string GCodeWriter::retract(bool before_wipe, double retract_length) { double factor = before_wipe ? m_extruder->retract_before_wipe() : 1.; assert(factor >= 0. && factor <= 1. + EPSILON); return this->_retract( - factor * m_extruder->retraction_length(), + retract_length > EPSILON ? retract_length : factor * m_extruder->retraction_length(), factor * m_extruder->retract_restart_extra(), "retract" ); } -std::string GCodeWriter::retract_for_toolchange(bool before_wipe) +std::string GCodeWriter::retract_for_toolchange(bool before_wipe, double retract_length) { double factor = before_wipe ? m_extruder->retract_before_wipe() : 1.; assert(factor >= 0. && factor <= 1. + EPSILON); return this->_retract( - factor * m_extruder->retract_length_toolchange(), + retract_length > EPSILON ? retract_length : factor * m_extruder->retract_length_toolchange(), factor * m_extruder->retract_restart_extra_toolchange(), "retract for toolchange" ); diff --git a/src/libslic3r/GCodeWriter.hpp b/src/libslic3r/GCodeWriter.hpp index bbaa069da0..27c58a0702 100644 --- a/src/libslic3r/GCodeWriter.hpp +++ b/src/libslic3r/GCodeWriter.hpp @@ -74,8 +74,8 @@ public: //BBS: generate G2 or G3 extrude which moves by arc std::string extrude_arc_to_xy(const Vec2d &point, const Vec2d ¢er_offset, double dE, const bool is_ccw, const std::string &comment = std::string(), bool force_no_extrusion = false); std::string extrude_to_xyz(const Vec3d &point, double dE, const std::string &comment = std::string(), bool force_no_extrusion = false); - std::string retract(bool before_wipe = false); - std::string retract_for_toolchange(bool before_wipe = false); + 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); std::string unlift(); diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index beab114f32..edd152488e 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -4183,7 +4183,7 @@ def = this->add("filament_loading_speed", coFloats); def = this->add("wipe_distance", coFloats); def->label = L("Wipe Distance"); - def->tooltip = L("Discribe how long the nozzle will move along the last path when retracting"); + def->tooltip = L("Discribe how long the nozzle will move along the last path when retracting. \n\nDepending on how long the wipe operation lasts, how fast and long the extruder/filament retraction settings are, a retraction move may be needed to retract the remaining filament. \n\nSetting a value in the retract amount before wipe setting below will perform any excess retraction before the wipe, else it will be performed after."); def->sidetext = L("mm"); def->min = 0; def->mode = comAdvanced;