From 5c56b43166ab32b09da31b7046efbbcbe3cbc9c8 Mon Sep 17 00:00:00 2001 From: "zhimin.zeng" Date: Tue, 11 Feb 2025 16:30:02 +0800 Subject: [PATCH] FIX: fix some wipe tower issue 1. the nozzle change gcode use double perimeter width 2. fix the error layer height for adaptive layer height 3. limit the nozzle change speed to 50 when a bridge is detected 4. fix the error extrusion flow for filament change gcode when a bridge is detected jira: STUDIO-10269 Change-Id: I580c618555fe19d000a56e2510a42004722c1b8b --- src/libslic3r/GCode/WipeTower.cpp | 99 ++++++++++++++++++++----------- src/libslic3r/GCode/WipeTower.hpp | 3 + 2 files changed, 68 insertions(+), 34 deletions(-) diff --git a/src/libslic3r/GCode/WipeTower.cpp b/src/libslic3r/GCode/WipeTower.cpp index e31ca038e..6f854cbb8 100644 --- a/src/libslic3r/GCode/WipeTower.cpp +++ b/src/libslic3r/GCode/WipeTower.cpp @@ -1441,6 +1441,7 @@ void WipeTower::set_extruder(size_t idx, const PrintConfig& config) m_filpar[idx].max_e_speed = (max_vol_speed / filament_area()); m_perimeter_width = nozzle_diameter * Width_To_Nozzle_Ratio; // all extruders are now assumed to have the same diameter + m_nozzle_change_perimeter_width = 2 * m_perimeter_width; // BBS: remove useless config #if 0 if (m_semm) { @@ -1588,7 +1589,7 @@ WipeTower::ToolChangeResult WipeTower::tool_change(size_t tool, bool extrude_per Vec2f start_pos = m_nozzle_change_result.start_pos + Vec2f(0, m_perimeter_width); bool left_to_right = true; double tpu_travel_length = 5; - double e_flow = extrusion_flow(0.2); + double e_flow = extrusion_flow(m_layer_height); double length = tpu_travel_length / e_flow; int tpu_line_count = length / (m_wipe_tower_width - 2 * m_perimeter_width) + 1; @@ -1682,9 +1683,9 @@ WipeTower::NozzleChangeResult WipeTower::nozzle_change(int old_filament_id, int wipe_depth = b.required_depth; purge_volume = b.purge_volume; if (has_tpu_filament()) - nozzle_change_line_count = ((b.nozzle_change_depth + WT_EPSILON) / m_perimeter_width) / 2; + nozzle_change_line_count = ((b.nozzle_change_depth + WT_EPSILON) / m_nozzle_change_perimeter_width) / 2; else - nozzle_change_line_count = (b.nozzle_change_depth + WT_EPSILON) / m_perimeter_width; + nozzle_change_line_count = (b.nozzle_change_depth + WT_EPSILON) / m_nozzle_change_perimeter_width; break; } } else { @@ -1757,7 +1758,7 @@ WipeTower::NozzleChangeResult WipeTower::nozzle_change(int old_filament_id, int { bool left_to_right = !m_left_to_right; double tpu_travel_length = 5; - double e_flow = extrusion_flow(0.2); + double e_flow = extrusion_flow(m_layer_height); double length = tpu_travel_length / e_flow; int tpu_line_count = length / (m_wipe_tower_width - 2 * m_perimeter_width) + 1; @@ -2351,13 +2352,13 @@ void WipeTower::plan_toolchange(float z_par, float layer_height_par, unsigned in float nozzle_change_depth = 0; if (!m_filament_map.empty() && m_filament_map[old_tool] != m_filament_map[new_tool]) { - double e_flow = extrusion_flow(0.2); + double e_flow = extrusion_flow(layer_height_par); double length = m_filaments_change_length[old_tool] / e_flow; int nozzle_change_line_count = length / (m_wipe_tower_width - 2*m_perimeter_width) + 1; if (has_tpu_filament()) - nozzle_change_depth = m_tpu_fixed_spacing * nozzle_change_line_count * m_perimeter_width; + nozzle_change_depth = m_tpu_fixed_spacing * nozzle_change_line_count * m_nozzle_change_perimeter_width; else - nozzle_change_depth = nozzle_change_line_count * m_perimeter_width; + nozzle_change_depth = nozzle_change_line_count * m_nozzle_change_perimeter_width; depth += nozzle_change_depth; } WipeTowerInfo::ToolChange tool_change = WipeTowerInfo::ToolChange(old_tool, new_tool, depth, 0.f, 0.f, wipe_volume, length_to_extrude, purge_volume); @@ -2620,6 +2621,7 @@ WipeTower::ToolChangeResult WipeTower::tool_change_new(size_t new_tool) } WipeTowerBlock &block = get_block_by_category(m_filpar[new_tool].category); + m_cur_block = █ box_coordinates cleaning_box(Vec2f(m_perimeter_width, block.cur_depth), m_wipe_tower_width - 2 * m_perimeter_width, block.depth); WipeTowerWriter writer(m_layer_height, m_perimeter_width, m_gcode_flavor, m_filpar); @@ -2664,7 +2666,7 @@ WipeTower::ToolChangeResult WipeTower::tool_change_new(size_t new_tool) Vec2f start_pos = m_nozzle_change_result.origin_start_pos + Vec2f(0, m_perimeter_width); bool left_to_right = true; double tpu_travel_length = 5; - double e_flow = extrusion_flow(0.2); + double e_flow = extrusion_flow(m_layer_height); double length = tpu_travel_length / e_flow; int tpu_line_count = length / (m_wipe_tower_width - 2 * m_perimeter_width) + 1; @@ -2717,9 +2719,9 @@ WipeTower::NozzleChangeResult WipeTower::nozzle_change_new(int old_filament_id, for (const auto &b : m_layer_info->tool_changes) if (b.new_tool == new_filament_id) { if (has_tpu_filament()) - nozzle_change_line_count = ((b.nozzle_change_depth + WT_EPSILON) / m_perimeter_width) / 2; + nozzle_change_line_count = ((b.nozzle_change_depth + WT_EPSILON) / m_nozzle_change_perimeter_width) / 2; else - nozzle_change_line_count = (b.nozzle_change_depth + WT_EPSILON) / m_perimeter_width; + nozzle_change_line_count = (b.nozzle_change_depth + WT_EPSILON) / m_nozzle_change_perimeter_width; break; } } @@ -2731,22 +2733,31 @@ WipeTower::NozzleChangeResult WipeTower::nozzle_change_new(int old_filament_id, return std::string(buff); }; - float nozzle_change_speed = 60.0f * m_filpar[m_current_tool].max_e_speed / m_extrusion_flow; + auto nozzle_change_extrusion_flow = [this](float layer_height) -> float { + return layer_height * (m_nozzle_change_perimeter_width - layer_height * (1.f - float(M_PI) / 4.f)) / filament_area(); + }; + + float nz_extrusion_flow = nozzle_change_extrusion_flow(m_layer_height); + float nozzle_change_speed = 60.0f * m_filpar[m_current_tool].max_e_speed / nz_extrusion_flow; + + float bridge_speed = 60.f * 50; // limit the bridge speed to 50 for nozzle change //float nozzle_change_speed = is_first_layer() ? std::min(m_first_layer_speed * 60.f, 4800.f) : 4800.f; if (is_tpu_filament(m_current_tool)) { nozzle_change_speed *= 0.25; } + bridge_speed = std::min(bridge_speed, nozzle_change_speed); - WipeTowerWriter writer(m_layer_height, m_perimeter_width, m_gcode_flavor, m_filpar); - writer.set_extrusion_flow(m_extrusion_flow) + WipeTowerWriter writer(m_layer_height, m_nozzle_change_perimeter_width, m_gcode_flavor, m_filpar); + writer.set_extrusion_flow(nz_extrusion_flow) .set_z(m_z_pos) .set_initial_tool(m_current_tool) - .set_extrusion_flow(m_extrusion_flow) .set_y_shift(m_y_shift + (new_filament_id != (unsigned int) (-1) && (m_current_shape == SHAPE_REVERSED) ? m_layer_info->depth - m_layer_info->toolchanges_depth() : 0.f)) .append(format_nozzle_change_line(true, old_filament_id, new_filament_id)); WipeTowerBlock & block = get_block_by_category(m_filpar[old_filament_id].category); - box_coordinates cleaning_box(Vec2f(m_perimeter_width, block.cur_depth), m_wipe_tower_width - 2 * m_perimeter_width, std::min(block.depth, m_wipe_tower_depth - block.cur_depth) - m_perimeter_width); + m_cur_block = █ + box_coordinates cleaning_box(Vec2f(m_perimeter_width, block.cur_depth + (m_nozzle_change_perimeter_width - m_perimeter_width) / 2), + m_wipe_tower_width - 2 * m_perimeter_width, std::min(block.depth, m_wipe_tower_depth - block.cur_depth) - m_perimeter_width); Vec2f initial_position = cleaning_box.ld; writer.set_initial_position(initial_position, m_wipe_tower_width, m_wipe_tower_depth, m_internal_rotation); @@ -2754,25 +2765,26 @@ WipeTower::NozzleChangeResult WipeTower::nozzle_change_new(int old_filament_id, const float &xl = cleaning_box.ld.x(); const float &xr = cleaning_box.rd.x(); - float dy = m_layer_info->extra_spacing * m_perimeter_width; + float dy = m_layer_info->extra_spacing * m_nozzle_change_perimeter_width; if (has_tpu_filament() && m_extra_spacing < m_tpu_fixed_spacing) - dy = m_tpu_fixed_spacing * m_perimeter_width; + dy = m_tpu_fixed_spacing * m_nozzle_change_perimeter_width; m_left_to_right = true; for (int i = 0; true; ++i) { + bool need_change_flow = need_thick_bridge_flow(writer.y()); if (m_left_to_right) - writer.extrude(xr + wipe_tower_wall_infill_overlap * m_perimeter_width, writer.y(), nozzle_change_speed); + writer.extrude(xr + wipe_tower_wall_infill_overlap * m_perimeter_width, writer.y(), need_change_flow ? bridge_speed : nozzle_change_speed); else - writer.extrude(xl - wipe_tower_wall_infill_overlap * m_perimeter_width, writer.y(), nozzle_change_speed); + writer.extrude(xl - wipe_tower_wall_infill_overlap * m_perimeter_width, writer.y(), need_change_flow ? bridge_speed : nozzle_change_speed); if (i == nozzle_change_line_count - 1) break; - writer.extrude(writer.x(), writer.y() + dy); + writer.travel(writer.x(), writer.y() + dy, nozzle_change_speed); m_left_to_right = !m_left_to_right; } - writer.set_extrusion_flow(m_extrusion_flow); // Reset the extrusion flow. + writer.set_extrusion_flow(nz_extrusion_flow); // Reset the extrusion flow. block.cur_depth += nozzle_change_line_count * dy; block.last_nozzle_change_id = old_filament_id; @@ -2780,11 +2792,11 @@ WipeTower::NozzleChangeResult WipeTower::nozzle_change_new(int old_filament_id, if (is_tpu_filament(m_current_tool)) { bool left_to_right = !m_left_to_right; double tpu_travel_length = 5; - double e_flow = extrusion_flow(0.2); + double e_flow = extrusion_flow(m_layer_height); double length = tpu_travel_length / e_flow; - int tpu_line_count = length / (m_wipe_tower_width - 2 * m_perimeter_width) + 1; + int tpu_line_count = length / (m_wipe_tower_width - 2 * m_nozzle_change_perimeter_width) + 1; - writer.travel(writer.x(), writer.y() - m_perimeter_width); + writer.travel(writer.x(), writer.y() - m_nozzle_change_perimeter_width); for (int i = 0; true; ++i) { if (left_to_right) @@ -3112,8 +3124,15 @@ WipeTower::ToolChangeResult WipeTower::finish_block(const WipeTowerBlock &block, WipeTower::ToolChangeResult WipeTower::finish_block_solid(const WipeTowerBlock &block, int filament_id, bool extrude_fill) { - WipeTowerWriter writer(m_layer_height, m_perimeter_width, m_gcode_flavor, m_filpar); - writer.set_extrusion_flow(m_extrusion_flow) + float layer_height = m_layer_height; + float e_flow = m_extrusion_flow; + if (m_cur_layer_id > 1 && !block.solid_infill[m_cur_layer_id - 1] && m_extrusion_flow < extrusion_flow(0.2)) { + layer_height = 0.2; + e_flow = extrusion_flow(0.2); + } + + WipeTowerWriter writer(layer_height, m_perimeter_width, m_gcode_flavor, m_filpar); + writer.set_extrusion_flow(e_flow) .set_z(m_z_pos) .set_initial_tool(filament_id) .set_y_shift(m_y_shift - (m_current_shape == SHAPE_REVERSED ? m_layer_info->toolchanges_depth() : 0.f)); @@ -3177,6 +3196,9 @@ void WipeTower::toolchange_wipe_new(WipeTowerWriter &writer, const box_coordinat { writer.set_extrusion_flow(m_extrusion_flow * (is_first_layer() ? 1.15f : 1.f)).append("; CP TOOLCHANGE WIPE\n"); + if (!m_nozzle_change_result.gcode.empty()) + writer.change_analyzer_line_width(m_perimeter_width); + // BBS: add the note for gcode-check, when the flow changed, the width should follow the change if (is_first_layer()) { writer.append(";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Width) + std::to_string(1.15 * m_perimeter_width) + "\n"); @@ -3196,7 +3218,6 @@ void WipeTower::toolchange_wipe_new(WipeTowerWriter &writer, const box_coordinat m_left_to_right = ((m_cur_layer_id + 3) % 4 >= 2); bool is_from_up = (m_cur_layer_id % 2 == 1); - bool need_change_flow = false; // now the wiping itself: for (int i = 0; true; ++i) { if (i != 0) { @@ -3210,11 +3231,11 @@ void WipeTower::toolchange_wipe_new(WipeTowerWriter &writer, const box_coordinat wipe_speed = std::min(target_speed, wipe_speed + 50.f); } + bool need_change_flow = need_thick_bridge_flow(writer.y()); // BBS: check the bridging area and use the bridge flow - if (need_change_flow || need_thick_bridge_flow(writer.y())) { + if (need_change_flow) { writer.set_extrusion_flow(extrusion_flow(0.2)); writer.append(";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height) + std::to_string(0.2) + "\n"); - need_change_flow = true; } float ironing_length = 3.; @@ -3430,6 +3451,7 @@ void WipeTower::generate_wipe_tower_blocks() if (block.layer_depths.empty()) { block.layer_depths.resize(all_layer_category_to_depth.size(), 0); block.solid_infill.resize(all_layer_category_to_depth.size(), false); + block.finish_depth.resize(all_layer_category_to_depth.size(), 0); } block.depth = std::max(block.depth, iter->second); block.layer_depths[layer_id] = iter->second; @@ -3489,9 +3511,9 @@ void WipeTower::plan_tower_new() double length = m_filaments_change_length[toolchange.old_tool] / e_flow; int nozzle_change_line_count = length / (m_wipe_tower_width - 2*m_perimeter_width) + 1; if (has_tpu_filament()) - nozzle_change_depth = m_tpu_fixed_spacing * nozzle_change_line_count * m_perimeter_width; + nozzle_change_depth = m_tpu_fixed_spacing * nozzle_change_line_count * m_nozzle_change_perimeter_width; else - nozzle_change_depth = nozzle_change_line_count * m_perimeter_width; + nozzle_change_depth = nozzle_change_line_count * m_nozzle_change_perimeter_width; depth += nozzle_change_depth; } toolchange.nozzle_change_depth = nozzle_change_depth; @@ -3725,7 +3747,7 @@ void WipeTower::generate_new(std::vector= block.start_depth + block.layer_depths[m_cur_layer_id]) { continue; } @@ -3740,8 +3762,10 @@ void WipeTower::generate_new(std::vectorstart_depth + m_cur_block->depth - m_perimeter_width; + start_pos_y = m_cur_block->finish_depth[m_cur_layer_id - 1]; + +#if 0 float last_layer_fill_box_y = (m_layer_info - 1)->toolchanges_depth() + m_perimeter_width; float last_layer_wipe_depth = (m_layer_info - 1)->depth; if (last_layer_wipe_depth - last_layer_fill_box_y <= 2 * m_perimeter_width) @@ -4153,7 +4184,7 @@ bool WipeTower::get_floating_area(float &start_pos_y, float &end_pos_y) const { start_pos_y = last_layer_fill_box_y + m_perimeter_width; end_pos_y = last_layer_wipe_depth - m_perimeter_width; - +#endif return true; } diff --git a/src/libslic3r/GCode/WipeTower.hpp b/src/libslic3r/GCode/WipeTower.hpp index a063fe5a5..98bd3409e 100644 --- a/src/libslic3r/GCode/WipeTower.hpp +++ b/src/libslic3r/GCode/WipeTower.hpp @@ -334,6 +334,7 @@ public: int filament_adhesiveness_category{0}; std::vector layer_depths; std::vector solid_infill; + std::vector finish_depth{0}; // the start pos of finish frame for every layer float depth{0}; float start_depth{0}; float cur_depth{0}; @@ -351,6 +352,7 @@ public: std::vector> m_all_layers_depth; std::vector m_wipe_tower_blocks; int m_last_block_id; + WipeTowerBlock* m_cur_block{nullptr}; // help function WipeTowerBlock& get_block_by_category(int filament_adhesiveness_category); @@ -444,6 +446,7 @@ private: Vec2f m_bed_bottom_left; // bottom-left corner coordinates (for rectangular beds) float m_perimeter_width = 0.4f * Width_To_Nozzle_Ratio; // Width of an extrusion line, also a perimeter spacing for 100% infill. + float m_nozzle_change_perimeter_width = 2 * 0.4f * Width_To_Nozzle_Ratio; float m_extrusion_flow = 0.038f; //0.029f;// Extrusion flow is derived from m_perimeter_width, layer height and filament diameter. // Extruder specific parameters.