From 04f051ff61eefaaa42ecb4f08f3beec856d0cbf2 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 19 Sep 2019 14:58:04 +0200 Subject: [PATCH 1/4] Wipe tower now doesn't print sparse layers, it is instead lower than the object --- src/libslic3r/GCode.cpp | 46 +++++++++++++++++++++++++++++++---------- src/libslic3r/GCode.hpp | 3 ++- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 0ccc3ddf5..3ebf75c2e 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -274,7 +274,7 @@ static inline Point wipe_tower_point_to_object_point(GCode &gcodegen, const Vec2 return Point(scale_(wipe_tower_pt.x() - gcodegen.origin()(0)), scale_(wipe_tower_pt.y() - gcodegen.origin()(1))); } -std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id) const +std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id, double z) const { if (new_extruder_id != -1 && new_extruder_id != tcr.new_tool) throw std::invalid_argument("Error: WipeTowerIntegration::append_tcr was asked to do a toolchange it didn't expect."); @@ -310,6 +310,12 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T gcode += gcodegen.unretract(); } + double current_z = gcodegen.writer().get_position().z(); + if (z == -1.) // in case no specific z was provided, print at current_z pos + z = current_z; + if (! is_approx(z, current_z)) + gcode += gcodegen.writer().travel_to_z(z, "Travel down to the last wipe tower layer."); + // Process the end filament gcode. std::string end_filament_gcode_str; @@ -376,16 +382,23 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T // A phony move to the end position at the wipe tower. gcodegen.writer().travel_to_xy(end_pos.cast()); gcodegen.set_last_pos(wipe_tower_point_to_object_point(gcodegen, end_pos)); + if (! is_approx(z, current_z)) { + gcode += gcodegen.writer().retract(); + gcode += gcodegen.writer().travel_to_z(current_z, "Travel back up to the topmost object layer."); + gcode += gcodegen.writer().unretract(); + } - // Prepare a future wipe. - gcodegen.m_wipe.path.points.clear(); - if (new_extruder_id >= 0) { - // Start the wipe at the current position. - gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen, end_pos)); - // Wipe end point: Wipe direction away from the closer tower edge to the further tower edge. - gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen, - Vec2f((std::abs(m_left - end_pos.x()) < std::abs(m_right - end_pos.x())) ? m_right : m_left, - end_pos.y()))); + else { + // Prepare a future wipe. + gcodegen.m_wipe.path.points.clear(); + if (new_extruder_id >= 0) { + // Start the wipe at the current position. + gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen, end_pos)); + // Wipe end point: Wipe direction away from the closer tower edge to the further tower edge. + gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen, + Vec2f((std::abs(m_left - end_pos.x()) < std::abs(m_right - end_pos.x())) ? m_right : m_left, + end_pos.y()))); + } } // Let the planner know we are traveling between objects. @@ -511,7 +524,18 @@ std::string WipeTowerIntegration::tool_change(GCode &gcodegen, int extruder_id, if (m_layer_idx < (int)m_tool_changes.size()) { if (! (size_t(m_tool_change_idx) < m_tool_changes[m_layer_idx].size())) throw std::runtime_error("Wipe tower generation failed, possibly due to empty first layer."); - gcode += append_tcr(gcodegen, m_tool_changes[m_layer_idx][m_tool_change_idx++], extruder_id); + + + double wipe_tower_z = m_last_wipe_tower_print_z; + bool is_sparse_layer = (m_brim_done && m_tool_changes[m_layer_idx].size() == 1 && m_tool_changes[m_layer_idx].front().initial_tool == m_tool_changes[m_layer_idx].front().new_tool); + + if (m_tool_change_idx == 0 && ! is_sparse_layer) + wipe_tower_z = m_last_wipe_tower_print_z + m_tool_changes[m_layer_idx].front().layer_height; + + if (! is_sparse_layer) { + gcode += append_tcr(gcodegen, m_tool_changes[m_layer_idx][m_tool_change_idx++], extruder_id, wipe_tower_z); + m_last_wipe_tower_print_z = wipe_tower_z; + } } m_brim_done = true; } diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 72813810b..16fd20faa 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -110,7 +110,7 @@ public: private: WipeTowerIntegration& operator=(const WipeTowerIntegration&); - std::string append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id) const; + std::string append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id, double z = -1.) const; // Postprocesses gcode: rotates and moves G1 extrusions and returns result std::string post_process_wipe_tower_moves(const WipeTower::ToolChangeResult& tcr, const Vec2f& translation, float angle) const; @@ -131,6 +131,7 @@ private: int m_tool_change_idx; bool m_brim_done; bool i_have_brim = false; + double m_last_wipe_tower_print_z = 0.f; }; class GCode { From abaebb489a33403e5d1fbca530691d2a29ce5252 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 19 Sep 2019 16:30:01 +0200 Subject: [PATCH 2/4] Added a config option to not print sparse layers on the wipe tower --- src/libslic3r/GCode.cpp | 22 +++++++++++++++------- src/libslic3r/Print.cpp | 1 + src/libslic3r/PrintConfig.cpp | 8 ++++++++ src/libslic3r/PrintConfig.hpp | 2 ++ src/slic3r/GUI/Preset.cpp | 2 +- src/slic3r/GUI/Tab.cpp | 1 + 6 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 3ebf75c2e..2210e40b2 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -313,8 +313,11 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T double current_z = gcodegen.writer().get_position().z(); if (z == -1.) // in case no specific z was provided, print at current_z pos z = current_z; - if (! is_approx(z, current_z)) + if (! is_approx(z, current_z)) { + gcode += gcodegen.writer().retract(); gcode += gcodegen.writer().travel_to_z(z, "Travel down to the last wipe tower layer."); + gcode += gcodegen.writer().unretract(); + } // Process the end filament gcode. @@ -526,13 +529,18 @@ std::string WipeTowerIntegration::tool_change(GCode &gcodegen, int extruder_id, throw std::runtime_error("Wipe tower generation failed, possibly due to empty first layer."); - double wipe_tower_z = m_last_wipe_tower_print_z; - bool is_sparse_layer = (m_brim_done && m_tool_changes[m_layer_idx].size() == 1 && m_tool_changes[m_layer_idx].front().initial_tool == m_tool_changes[m_layer_idx].front().new_tool); + // Calculate where the wipe tower layer will be printed. -1 means that print z will not change, + // resulting in a wipe tower with sparse layers. + double wipe_tower_z = -1; + bool ignore_sparse = false; + if (gcodegen.config().wipe_tower_no_sparse_layers.value) { + wipe_tower_z = m_last_wipe_tower_print_z; + ignore_sparse = (m_brim_done && m_tool_changes[m_layer_idx].size() == 1 && m_tool_changes[m_layer_idx].front().initial_tool == m_tool_changes[m_layer_idx].front().new_tool); + if (m_tool_change_idx == 0 && ! ignore_sparse) + wipe_tower_z = m_last_wipe_tower_print_z + m_tool_changes[m_layer_idx].front().layer_height; + } - if (m_tool_change_idx == 0 && ! is_sparse_layer) - wipe_tower_z = m_last_wipe_tower_print_z + m_tool_changes[m_layer_idx].front().layer_height; - - if (! is_sparse_layer) { + if (! ignore_sparse) { gcode += append_tcr(gcodegen, m_tool_changes[m_layer_idx][m_tool_change_idx++], extruder_id, wipe_tower_z); m_last_wipe_tower_print_z = wipe_tower_z; } diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 4d8482743..8a5282b4b 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -143,6 +143,7 @@ bool Print::invalidate_state_by_config_options(const std::vectormode = comAdvanced; def->set_default_value(new ConfigOptionBool(true)); + def = this->add("wipe_tower_no_sparse_layers", coBool); + def->label = L("No sparse layers"); + def->tooltip = L("If enabled, the wipe tower will not be printed on layers with no toolchanges. " + "On layers with a toolchange, extruder will travel downward to print the wipe tower. " + "User is responsible for ensuring there is no collision with the print."); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionBool(false)); + def = this->add("support_material", coBool); def->label = L("Generate support material"); def->category = L("Support material"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 6a19edf84..20ab60e9a 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -648,6 +648,7 @@ public: ConfigOptionStrings start_filament_gcode; ConfigOptionBool single_extruder_multi_material; ConfigOptionBool single_extruder_multi_material_priming; + ConfigOptionBool wipe_tower_no_sparse_layers; ConfigOptionString toolchange_gcode; ConfigOptionFloat travel_speed; ConfigOptionBool use_firmware_retraction; @@ -718,6 +719,7 @@ protected: OPT_PTR(retract_speed); OPT_PTR(single_extruder_multi_material); OPT_PTR(single_extruder_multi_material_priming); + OPT_PTR(wipe_tower_no_sparse_layers); OPT_PTR(start_gcode); OPT_PTR(start_filament_gcode); OPT_PTR(toolchange_gcode); diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index d2503d349..853a803b7 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -385,7 +385,7 @@ const std::vector& Preset::print_options() "top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "bridge_flow_ratio", "clip_multipart_objects", "elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging", "single_extruder_multi_material_priming", - "compatible_printers", "compatible_printers_condition", "inherits" + "wipe_tower_no_sparse_layers", "compatible_printers", "compatible_printers_condition", "inherits" }; return s_opts; } diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index c87626a48..5ecfb9a77 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1170,6 +1170,7 @@ void TabPrint::build() optgroup->append_single_option_line("wipe_tower_width"); optgroup->append_single_option_line("wipe_tower_rotation_angle"); optgroup->append_single_option_line("wipe_tower_bridging"); + optgroup->append_single_option_line("wipe_tower_no_sparse_layers"); optgroup->append_single_option_line("single_extruder_multi_material_priming"); optgroup = page->new_optgroup(_(L("Advanced"))); From b5e3899267b3ed2e2432048f804013bf21a2e54b Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 1 Oct 2019 11:41:37 +0200 Subject: [PATCH 3/4] Wipe tower: Sparse layers are not included in filament consumption in case that the 'no sparse layers' option is set --- src/libslic3r/GCode/WipeTower.cpp | 13 +++++++++---- src/libslic3r/GCode/WipeTower.hpp | 1 + src/libslic3r/Print.cpp | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/libslic3r/GCode/WipeTower.cpp b/src/libslic3r/GCode/WipeTower.cpp index b35761b5f..fff03786f 100644 --- a/src/libslic3r/GCode/WipeTower.cpp +++ b/src/libslic3r/GCode/WipeTower.cpp @@ -471,6 +471,7 @@ WipeTower::WipeTower(const PrintConfig& config, const std::vectortoolchanges_depth() > WT_EPSILON; box_coordinates box = fill_box; for (int i=0;i<2;++i) { - if (m_layer_info->toolchanges_depth() < WT_EPSILON) { // there were no toolchanges on this layer + if (! toolchanges_on_layer) { if (i==0) box.expand(m_perimeter_width); else box.expand(-m_perimeter_width); } @@ -1192,9 +1194,12 @@ WipeTower::ToolChangeResult WipeTower::finish_layer() m_depth_traversed = m_wipe_tower_depth-m_perimeter_width; - // Ask our writer about how much material was consumed: - if (m_current_tool < m_used_filament_length.size()) - m_used_filament_length[m_current_tool] += writer.get_and_reset_used_filament_length(); + + // Ask our writer about how much material was consumed. + // Skip this in case the layer is sparse and config option to not print sparse layers is enabled. + if (! m_no_sparse_layers || toolchanges_on_layer) + if (m_current_tool < m_used_filament_length.size()) + m_used_filament_length[m_current_tool] += writer.get_and_reset_used_filament_length(); ToolChangeResult result; result.priming = false; diff --git a/src/libslic3r/GCode/WipeTower.hpp b/src/libslic3r/GCode/WipeTower.hpp index 5477aa609..ff3ec46e5 100644 --- a/src/libslic3r/GCode/WipeTower.hpp +++ b/src/libslic3r/GCode/WipeTower.hpp @@ -218,6 +218,7 @@ private: float m_parking_pos_retraction = 0.f; float m_extra_loading_move = 0.f; float m_bridging = 0.f; + bool m_no_sparse_layers = false; bool m_set_extruder_trimpot = false; bool m_adhesion = true; GCodeFlavor m_gcode_flavor; diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 8a5282b4b..fcda80a67 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -143,7 +143,6 @@ bool Print::invalidate_state_by_config_options(const std::vector Date: Thu, 14 Nov 2019 10:05:02 +0100 Subject: [PATCH 4/4] No sparse layers option marked as EXPERIMENTAL --- src/libslic3r/PrintConfig.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index f082e13b3..6fa6ae3a2 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1826,7 +1826,7 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionBool(true)); def = this->add("wipe_tower_no_sparse_layers", coBool); - def->label = L("No sparse layers"); + def->label = L("No sparse layers (EXPERIMENTAL)"); def->tooltip = L("If enabled, the wipe tower will not be printed on layers with no toolchanges. " "On layers with a toolchange, extruder will travel downward to print the wipe tower. " "User is responsible for ensuring there is no collision with the print.");