From 913e49c23512207760437b548301736a634c50b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Wed, 28 Aug 2024 09:50:10 +0200 Subject: [PATCH 1/3] SPE-2437: Avoid unnecessary splitting of extrusions by the pressure equalizer. --- src/libslic3r/GCode/PressureEqualizer.cpp | 26 +++++++++++++++++------ 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/libslic3r/GCode/PressureEqualizer.cpp b/src/libslic3r/GCode/PressureEqualizer.cpp index ed131f7162..571146b206 100644 --- a/src/libslic3r/GCode/PressureEqualizer.cpp +++ b/src/libslic3r/GCode/PressureEqualizer.cpp @@ -41,6 +41,11 @@ static constexpr int max_look_back_limit = 128; // Lines where some extruder pressure will remain (so we should equalize between these small travels). static constexpr double max_ignored_gap_between_extruding_segments = 3.; +// Minimum feedrate change that will be emitted into the G-code. +// Changes below this value will not be emitted into the G-code to filter out tiny changes +// of feedrate and reduce the size of the G-code. +static constexpr float min_emitted_feedrate_change = 0.20f * 60.f; + PressureEqualizer::PressureEqualizer(const Slic3r::GCodeConfig &config) : m_use_relative_e_distances(config.use_relative_e_distances.value) { // Preallocate some data, so that output_buffer.data() will return an empty string. @@ -493,21 +498,27 @@ void PressureEqualizer::output_gcode_line(const size_t line_idx) comment = nullptr; // Emit the line with lowered extrusion rates. - float l = line.dist_xyz(); - if (auto nSegments = size_t(ceil(l / max_segment_length)); nSegments == 1) { // Just update this segment. + const float l = line.dist_xyz(); + const float feedrate_start = line.volumetric_extrusion_rate_start * line.feedrate() / line.volumetric_extrusion_rate; + const float feedrate_end = line.volumetric_extrusion_rate_end * line.feedrate() / line.volumetric_extrusion_rate; + const float feedrate_avg = 0.5f * (feedrate_start + feedrate_end); + if (std::abs(feedrate_avg - line.pos_end[4]) <= min_emitted_feedrate_change) { + // The average feedrate is close to the original feedrate, so we emit the line with the original feedrate. + push_line_to_output(line_idx, line.pos_end[4], comment); + } else if (auto nSegments = size_t(ceil(l / max_segment_length)); nSegments == 1) { // Just update this segment. push_line_to_output(line_idx, line.feedrate() * line.volumetric_correction_avg(), comment); } else { bool accelerating = line.volumetric_extrusion_rate_start < line.volumetric_extrusion_rate_end; // Update the initial and final feed rate values. - line.pos_start[4] = line.volumetric_extrusion_rate_start * line.pos_end[4] / line.volumetric_extrusion_rate; - line.pos_end [4] = line.volumetric_extrusion_rate_end * line.pos_end[4] / line.volumetric_extrusion_rate; - float feed_avg = 0.5f * (line.pos_start[4] + line.pos_end[4]); + line.pos_start[4] = feedrate_start; + line.pos_end [4] = feedrate_end; + // Limiting volumetric extrusion rate slope for this segment. float max_volumetric_extrusion_rate_slope = accelerating ? line.max_volumetric_extrusion_rate_slope_positive : line.max_volumetric_extrusion_rate_slope_negative; // Total time for the segment, corrected for the possibly lowered volumetric feed rate, // if accelerating / decelerating over the complete segment. - float t_total = line.dist_xyz() / feed_avg; + float t_total = line.dist_xyz() / feedrate_avg; // Time of the acceleration / deceleration part of the segment, if accelerating / decelerating // with the maximum volumetric extrusion rate slope. float t_acc = 0.5f * (line.volumetric_extrusion_rate_start + line.volumetric_extrusion_rate_end) / max_volumetric_extrusion_rate_slope; @@ -515,7 +526,7 @@ void PressureEqualizer::output_gcode_line(const size_t line_idx) float l_steady = 0.f; if (t_acc < t_total) { // One may achieve higher print speeds if part of the segment is not speed limited. - l_acc = t_acc * feed_avg; + l_acc = t_acc * feedrate_avg; l_steady = l - l_acc; if (l_steady < 0.5f * max_segment_length) { l_acc = l; @@ -523,6 +534,7 @@ void PressureEqualizer::output_gcode_line(const size_t line_idx) } else nSegments = size_t(ceil(l_acc / max_segment_length)); } + float pos_start[5]; float pos_end[5]; float pos_end2[4]; From e8b1d0ad75e8681a50ff9b27592b6fb6947c35cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Wed, 28 Aug 2024 09:51:35 +0200 Subject: [PATCH 2/3] SPE-2437: Separate update of positions inside the pressure equalizer into functions. --- src/libslic3r/GCode/PressureEqualizer.cpp | 54 ++++++++++++++--------- src/libslic3r/GCode/PressureEqualizer.hpp | 4 +- 2 files changed, 35 insertions(+), 23 deletions(-) diff --git a/src/libslic3r/GCode/PressureEqualizer.cpp b/src/libslic3r/GCode/PressureEqualizer.cpp index 571146b206..72c2597e47 100644 --- a/src/libslic3r/GCode/PressureEqualizer.cpp +++ b/src/libslic3r/GCode/PressureEqualizer.cpp @@ -329,8 +329,6 @@ bool PressureEqualizer::process_line(const char *line, const char *line_end, GCo { // G0, G1: A FFF 3D printer does not make a difference between the two. buf.adjustable_flow = this->opened_extrude_set_speed_block; - buf.extrude_set_speed_tag = found_extrude_set_speed_tag; - buf.extrude_end_tag = found_extrude_end_tag; float new_pos[5]; memcpy(new_pos, m_current_pos, sizeof(float)*5); bool changed[5] = { false, false, false, false, false }; @@ -482,6 +480,30 @@ bool PressureEqualizer::process_line(const char *line, const char *line_end, GCo return true; } +void PressureEqualizer::GCodeLine::update_end_position(const float *position_end) +{ + assert(position_end != nullptr); + if (position_end == nullptr) + return; + + for (int i = 0; i < 4; ++i) { + this->pos_end[i] = position_end[i]; + this->pos_provided[i] = true; + } +} + +void PressureEqualizer::GCodeLine::update_end_position(const float *position_start, const float *position_end, const float t) +{ + assert(position_start != nullptr && position_end != nullptr); + if (position_start == nullptr || position_end == nullptr) + return; + + for (size_t i = 0; i < 4; ++i) { + this->pos_end[i] = position_start[i] + (position_end[i] - position_start[i]) * t; + this->pos_provided[i] = true; + } +} + void PressureEqualizer::output_gcode_line(const size_t line_idx) { GCodeLine &line = m_gcode_lines[line_idx]; @@ -548,15 +570,11 @@ void PressureEqualizer::output_gcode_line(const size_t line_idx) float t = l_acc / l; for (int i = 0; i < 4; ++ i) { pos_end[i] = pos_start[i] + (pos_end[i] - pos_start[i]) * t; - line.pos_provided[i] = true; } } else { // Emit the steady feed rate segment. - float t = l_steady / l; - for (int i = 0; i < 4; ++ i) { - line.pos_end[i] = pos_start[i] + (pos_end[i] - pos_start[i]) * t; - line.pos_provided[i] = true; - } + const float t = l_steady / l; + line.update_end_position(pos_start, pos_end, t); push_line_to_output(line_idx, pos_start[4], comment); comment = nullptr; @@ -569,29 +587,23 @@ void PressureEqualizer::output_gcode_line(const size_t line_idx) pos_start[4] = new_pos_start_feedrate; } } + // Split the segment into pieces. for (size_t i = 1; i < nSegments; ++ i) { - float t = float(i) / float(nSegments); - for (size_t j = 0; j < 4; ++ j) { - line.pos_end[j] = pos_start[j] + (pos_end[j] - pos_start[j]) * t; - line.pos_provided[j] = true; - } + const float t = float(i) / float(nSegments); + line.update_end_position(pos_start, pos_end, t); + // Interpolate the feed rate at the center of the segment. push_line_to_output(line_idx, pos_start[4] + (pos_end[4] - pos_start[4]) * (float(i) - 0.5f) / float(nSegments), comment); comment = nullptr; memcpy(line.pos_start, line.pos_end, sizeof(float)*5); } + if (l_steady > 0.f && accelerating) { - for (int i = 0; i < 4; ++ i) { - line.pos_end[i] = pos_end2[i]; - line.pos_provided[i] = true; - } + line.update_end_position(pos_end2); push_line_to_output(line_idx, pos_end[4], comment); } else { - for (int i = 0; i < 4; ++ i) { - line.pos_end[i] = pos_end[i]; - line.pos_provided[i] = true; - } + line.update_end_position(pos_end); push_line_to_output(line_idx, pos_end[4], comment); } } diff --git a/src/libslic3r/GCode/PressureEqualizer.hpp b/src/libslic3r/GCode/PressureEqualizer.hpp index 0480f011e7..1bb71afbc7 100644 --- a/src/libslic3r/GCode/PressureEqualizer.hpp +++ b/src/libslic3r/GCode/PressureEqualizer.hpp @@ -178,8 +178,8 @@ private: bool adjustable_flow = false; - bool extrude_set_speed_tag = false; - bool extrude_end_tag = false; + void update_end_position(const float *position_end); + void update_end_position(const float *position_start, const float *position_end, float t); }; using GCodeLines = std::vector; From c41e0c22ce8d798e2874851221f375929ef6735d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Wed, 28 Aug 2024 09:52:05 +0200 Subject: [PATCH 3/3] SPE-2437: Avoid unnecessary emitting of the Z axis by the pressure equalizer when it doesn't change and isn't provided. --- src/libslic3r/GCode/PressureEqualizer.cpp | 19 +++++++++++-------- src/libslic3r/GCode/PressureEqualizer.hpp | 4 ++-- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/libslic3r/GCode/PressureEqualizer.cpp b/src/libslic3r/GCode/PressureEqualizer.cpp index 72c2597e47..0a6cc37e5f 100644 --- a/src/libslic3r/GCode/PressureEqualizer.cpp +++ b/src/libslic3r/GCode/PressureEqualizer.cpp @@ -480,7 +480,7 @@ bool PressureEqualizer::process_line(const char *line, const char *line_end, GCo return true; } -void PressureEqualizer::GCodeLine::update_end_position(const float *position_end) +void PressureEqualizer::GCodeLine::update_end_position(const float *position_end, const bool *position_provided_original) { assert(position_end != nullptr); if (position_end == nullptr) @@ -488,11 +488,11 @@ void PressureEqualizer::GCodeLine::update_end_position(const float *position_end for (int i = 0; i < 4; ++i) { this->pos_end[i] = position_end[i]; - this->pos_provided[i] = true; + this->pos_provided[i] = position_provided_original[i] || (this->pos_end[i] != this->pos_start[i]); } } -void PressureEqualizer::GCodeLine::update_end_position(const float *position_start, const float *position_end, const float t) +void PressureEqualizer::GCodeLine::update_end_position(const float *position_start, const float *position_end, const float t, const bool *position_provided_original) { assert(position_start != nullptr && position_end != nullptr); if (position_start == nullptr || position_end == nullptr) @@ -500,7 +500,7 @@ void PressureEqualizer::GCodeLine::update_end_position(const float *position_sta for (size_t i = 0; i < 4; ++i) { this->pos_end[i] = position_start[i] + (position_end[i] - position_start[i]) * t; - this->pos_provided[i] = true; + this->pos_provided[i] = position_provided_original[i] || (this->pos_end[i] != this->pos_start[i]); } } @@ -562,6 +562,9 @@ void PressureEqualizer::output_gcode_line(const size_t line_idx) float pos_end2[4]; memcpy(pos_start, line.pos_start, sizeof(float) * 5); memcpy(pos_end, line.pos_end, sizeof(float) * 5); + + bool pos_provided_original[5]; + memcpy(pos_provided_original, line.pos_provided, sizeof(bool) * 5); if (l_steady > 0.f) { // There will be a steady feed segment emitted. if (accelerating) { @@ -574,7 +577,7 @@ void PressureEqualizer::output_gcode_line(const size_t line_idx) } else { // Emit the steady feed rate segment. const float t = l_steady / l; - line.update_end_position(pos_start, pos_end, t); + line.update_end_position(pos_start, pos_end, t, pos_provided_original); push_line_to_output(line_idx, pos_start[4], comment); comment = nullptr; @@ -591,7 +594,7 @@ void PressureEqualizer::output_gcode_line(const size_t line_idx) // Split the segment into pieces. for (size_t i = 1; i < nSegments; ++ i) { const float t = float(i) / float(nSegments); - line.update_end_position(pos_start, pos_end, t); + line.update_end_position(pos_start, pos_end, t, pos_provided_original); // Interpolate the feed rate at the center of the segment. push_line_to_output(line_idx, pos_start[4] + (pos_end[4] - pos_start[4]) * (float(i) - 0.5f) / float(nSegments), comment); @@ -600,10 +603,10 @@ void PressureEqualizer::output_gcode_line(const size_t line_idx) } if (l_steady > 0.f && accelerating) { - line.update_end_position(pos_end2); + line.update_end_position(pos_end2, pos_provided_original); push_line_to_output(line_idx, pos_end[4], comment); } else { - line.update_end_position(pos_end); + line.update_end_position(pos_end, pos_provided_original); push_line_to_output(line_idx, pos_end[4], comment); } } diff --git a/src/libslic3r/GCode/PressureEqualizer.hpp b/src/libslic3r/GCode/PressureEqualizer.hpp index 1bb71afbc7..29d04b7b39 100644 --- a/src/libslic3r/GCode/PressureEqualizer.hpp +++ b/src/libslic3r/GCode/PressureEqualizer.hpp @@ -178,8 +178,8 @@ private: bool adjustable_flow = false; - void update_end_position(const float *position_end); - void update_end_position(const float *position_start, const float *position_end, float t); + void update_end_position(const float *position_end, const bool *position_provided_original); + void update_end_position(const float *position_start, const float *position_end, float t, const bool *position_provided_original); }; using GCodeLines = std::vector;