Skip to content

Commit 131fb94

Browse files
committed
Sync PressureEq with latest PrusaSlicer
1 parent d6a72fa commit 131fb94

File tree

2 files changed

+29
-93
lines changed

2 files changed

+29
-93
lines changed

src/libslic3r/GCode/PressureEqualizer.cpp

Lines changed: 27 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
#include <memory.h>
77
#include <cstring>
88
#include <cfloat>
9-
#include <algorithm>
109

1110
#include "../libslic3r.h"
1211
#include "../PrintConfig.hpp"
@@ -29,12 +28,6 @@ static const std::string EXTERNAL_PERIMETER_TAG = ";_EXTERNAL_PERIMETER";
2928
// affect how distant will be propagated a flow rate adjustment.
3029
static constexpr int max_look_back_limit = 128;
3130

32-
// Max non-extruding XY distance (travel move) in mm between two continous extrusions where we pretend
33-
// its all one continous extruded line. Above this distance we assume extruder pressure hits 0
34-
// This exists because often there's tiny travel moves between stuff like infill
35-
// lines where some extruder pressure will remain (so we should equalize between these small travels)
36-
static constexpr long max_ignored_gap_between_extruding_segments = 3;
37-
3831
PressureEqualizer::PressureEqualizer(const Slic3r::GCodeConfig &config) : m_use_relative_e_distances(config.use_relative_e_distances.value)
3932
{
4033
// Preallocate some data, so that output_buffer.data() will return an empty string.
@@ -48,8 +41,10 @@ PressureEqualizer::PressureEqualizer(const Slic3r::GCodeConfig &config) : m_use_
4841
m_current_extrusion_role = GCodeExtrusionRole::None;
4942
// Expect the first command to fill the nozzle (deretract).
5043
m_retracted = true;
51-
52-
m_max_segment_length = 2.f;
44+
45+
// Maximum segment length to split a long segment if the initial and the final flow rate differ.
46+
// Smaller value means a smoother transition between two different flow rates.
47+
m_max_segment_length = 5.f;
5348

5449
// Calculate filamet crossections for the multiple extruders.
5550
m_filament_crossections.clear();
@@ -64,17 +59,17 @@ PressureEqualizer::PressureEqualizer(const Slic3r::GCodeConfig &config) : m_use_
6459

6560
if(config.max_volumetric_extrusion_rate_slope.value > 0){
6661
m_max_volumetric_extrusion_rate_slope_positive = float(config.max_volumetric_extrusion_rate_slope.value) * 60.f * 60.f;
67-
m_max_volumetric_extrusion_rate_slope_negative = float(config.max_volumetric_extrusion_rate_slope.value) * 60.f * 60.f;
68-
m_max_segment_length = float(config.max_volumetric_extrusion_rate_slope_segment_length.value);
62+
m_max_volumetric_extrusion_rate_slope_negative = float(config.max_volumetric_extrusion_rate_slope.value) * 60.f * 60.f;
63+
m_max_segment_length = float(config.max_volumetric_extrusion_rate_slope_segment_length.value);
6964
}
7065

7166
for (ExtrusionRateSlope &extrusion_rate_slope : m_max_volumetric_extrusion_rate_slopes) {
7267
extrusion_rate_slope.negative = m_max_volumetric_extrusion_rate_slope_negative;
7368
extrusion_rate_slope.positive = m_max_volumetric_extrusion_rate_slope_positive;
7469
}
75-
76-
// Don't regulate the pressure before and after ironing.
77-
for (const GCodeExtrusionRole er : {GCodeExtrusionRole::Ironing}) {
70+
71+
// Don't regulate the pressure before and after gap-fill and ironing.
72+
for (const GCodeExtrusionRole er : {GCodeExtrusionRole::GapFill, GCodeExtrusionRole::Ironing}) {
7873
m_max_volumetric_extrusion_rate_slopes[size_t(er)].negative = 0;
7974
m_max_volumetric_extrusion_rate_slopes[size_t(er)].positive = 0;
8075
}
@@ -111,67 +106,6 @@ void PressureEqualizer::process_layer(const std::string &gcode)
111106
}
112107
assert(!this->opened_extrude_set_speed_block);
113108
}
114-
115-
// at this point, we have an entire layer of gcode lines loaded into m_gcode_lines
116-
// now we will split the mix of travels and extrudes into segments of continous extrusion and process those
117-
// We skip over large travels, and pretend small ones are part of a continous extrusion segment
118-
long idx_end_current_extrusion = 0;
119-
while (idx_end_current_extrusion < m_gcode_lines.size()) {
120-
// find beginning of next extrusion segment from current pos
121-
const long idx_begin_current_extrusion = find_if(m_gcode_lines.begin() + idx_end_current_extrusion, m_gcode_lines.end(),
122-
[](GCodeLine line) { return line.extruding(); }) - m_gcode_lines.begin();
123-
// (extrusion begin idx = extrusion end idx) here because we start with extrusion length of zero
124-
idx_end_current_extrusion = idx_begin_current_extrusion;
125-
126-
// inner loop extends the extrusion segment over small travel moves
127-
while (idx_end_current_extrusion < m_gcode_lines.size()) {
128-
// find end of the current extrusion segment
129-
const auto just_after_end_extrusion = find_if(m_gcode_lines.begin() + idx_end_current_extrusion, m_gcode_lines.end(),
130-
[](GCodeLine line) { return !line.extruding(); });
131-
idx_end_current_extrusion = std::max<long>(0,(just_after_end_extrusion - m_gcode_lines.begin()) - 1);
132-
const long idx_begin_segment_continuation = advance_segment_beyond_small_gap(idx_end_current_extrusion);
133-
if (idx_begin_segment_continuation > idx_end_current_extrusion) {
134-
// extend the continous line over the small gap
135-
idx_end_current_extrusion = idx_begin_segment_continuation;
136-
continue; // keep going, loop again to find new end of extrusion segment
137-
} else {
138-
// gap to next extrude is too big, stop looking forward. We've found end of this segment
139-
break;
140-
}
141-
}
142-
143-
// now run the pressure equalizer across the segment like a streamroller
144-
// it operates on a sliding window that moves forward across gcode line by line
145-
for (int i = idx_begin_current_extrusion; i < idx_end_current_extrusion; ++i) {
146-
// feed pressure equalizer past lines, going back to max_look_back_limit (or start of segment)
147-
const auto start_idx = std::max<long>(idx_begin_current_extrusion, i - max_look_back_limit);
148-
adjust_volumetric_rate(start_idx, i);
149-
}
150-
// current extrusion is all done processing so advance beyond it for next loop
151-
idx_end_current_extrusion++;
152-
}
153-
}
154-
155-
long PressureEqualizer::advance_segment_beyond_small_gap(const long idx_orig)
156-
{
157-
// this should only be run on the last extruding line before a gap
158-
assert(m_gcode_lines[idx_cur_pos].extruding());
159-
double distance_traveled = 0.0;
160-
// start at beginning of gap, advance till extrusion found or gap too big
161-
for (auto idx_cur_pos = idx_orig + 1; idx_cur_pos < m_gcode_lines.size(); idx_cur_pos++) {
162-
// started extruding again! return segment extension
163-
if (m_gcode_lines[idx_cur_pos].extruding()) {
164-
return idx_cur_pos;
165-
}
166-
167-
distance_traveled += m_gcode_lines[idx_cur_pos].dist_xy();
168-
// gap too big, dont extend segment
169-
if (distance_traveled > max_ignored_gap_between_extruding_segments) {
170-
return idx_orig;
171-
}
172-
}
173-
// looped until end of layer and couldn't extend extrusion
174-
return idx_orig;
175109
}
176110

177111
LayerResult PressureEqualizer::process_layer(LayerResult &&input)
@@ -465,6 +399,8 @@ bool PressureEqualizer::process_line(const char *line, const char *line_end, GCo
465399

466400
buf.extruder_id = m_current_extruder;
467401
memcpy(buf.pos_end, m_current_pos, sizeof(float)*5);
402+
403+
adjust_volumetric_rate();
468404
#ifdef PRESSURE_EQUALIZER_DEBUG
469405
++line_idx;
470406
#endif
@@ -579,12 +515,14 @@ void PressureEqualizer::output_gcode_line(const size_t line_idx)
579515
}
580516
}
581517

582-
void PressureEqualizer::adjust_volumetric_rate(const size_t fist_line_idx, const size_t last_line_idx)
518+
void PressureEqualizer::adjust_volumetric_rate()
583519
{
584-
// don't bother adjusting volumetric rate if there's no gcode to adjust
585-
if (last_line_idx-fist_line_idx < 2)
520+
if (m_gcode_lines.size() < 2)
586521
return;
587522

523+
// Go back from the current circular_buffer_pos and lower the feedtrate to decrease the slope of the extrusion rate changes.
524+
size_t fist_line_idx = size_t(std::max<int>(0, int(m_gcode_lines.size()) - max_look_back_limit));
525+
const size_t last_line_idx = m_gcode_lines.size() - 1;
588526
size_t line_idx = last_line_idx;
589527
if (line_idx == fist_line_idx || !m_gcode_lines[line_idx].extruding())
590528
// Nothing to do, the last move is not extruding.
@@ -599,8 +537,9 @@ void PressureEqualizer::adjust_volumetric_rate(const size_t fist_line_idx, const
599537
for (; !m_gcode_lines[idx_prev].extruding() && idx_prev != fist_line_idx; --idx_prev);
600538
if (!m_gcode_lines[idx_prev].extruding())
601539
break;
602-
// Don't decelerate before ironing.
603-
if (m_gcode_lines[line_idx].extrusion_role == GCodeExtrusionRole::Ironing) { line_idx = idx_prev;
540+
// Don't decelerate before ironing and gap-fill.
541+
if (m_gcode_lines[line_idx].extrusion_role == GCodeExtrusionRole::Ironing || m_gcode_lines[line_idx].extrusion_role == GCodeExtrusionRole::GapFill) {
542+
line_idx = idx_prev;
604543
continue;
605544
}
606545
// Volumetric extrusion rate at the start of the succeding segment.
@@ -619,8 +558,7 @@ void PressureEqualizer::adjust_volumetric_rate(const size_t fist_line_idx, const
619558
// Limit by the succeeding volumetric flow rate.
620559
rate_end = rate_succ;
621560

622-
// don't alter the flow rate for these extrusion types
623-
if (!line.adjustable_flow || line.extrusion_role == GCodeExtrusionRole::BridgeInfill || line.extrusion_role == GCodeExtrusionRole::Ironing) {
561+
if (!line.adjustable_flow || line.extrusion_role == GCodeExtrusionRole::ExternalPerimeter || line.extrusion_role == GCodeExtrusionRole::GapFill || line.extrusion_role == GCodeExtrusionRole::BridgeInfill || line.extrusion_role == GCodeExtrusionRole::Ironing) {
624562
rate_end = line.volumetric_extrusion_rate_end;
625563
} else if (line.volumetric_extrusion_rate_end > rate_end) {
626564
line.volumetric_extrusion_rate_end = rate_end;
@@ -643,8 +581,8 @@ void PressureEqualizer::adjust_volumetric_rate(const size_t fist_line_idx, const
643581
}
644582
}
645583
// feedrate_per_extrusion_role[iRole] = (iRole == line.extrusion_role) ? line.volumetric_extrusion_rate_start : rate_start;
646-
// Don't store feed rate for ironing
647-
if (line.extrusion_role != GCodeExtrusionRole::Ironing)
584+
// Don't store feed rate for ironing and gap-fill.
585+
if (line.extrusion_role != GCodeExtrusionRole::Ironing && line.extrusion_role != GCodeExtrusionRole::GapFill)
648586
feedrate_per_extrusion_role[iRole] = line.volumetric_extrusion_rate_start;
649587
}
650588
}
@@ -658,8 +596,8 @@ void PressureEqualizer::adjust_volumetric_rate(const size_t fist_line_idx, const
658596
for (; !m_gcode_lines[idx_next].extruding() && idx_next != last_line_idx; ++idx_next);
659597
if (!m_gcode_lines[idx_next].extruding())
660598
break;
661-
// Don't accelerate after ironing.
662-
if (m_gcode_lines[line_idx].extrusion_role == GCodeExtrusionRole::Ironing) {
599+
// Don't accelerate after ironing and gap-fill.
600+
if (m_gcode_lines[line_idx].extrusion_role == GCodeExtrusionRole::Ironing || m_gcode_lines[line_idx].extrusion_role == GCodeExtrusionRole::GapFill) {
663601
line_idx = idx_next;
664602
continue;
665603
}
@@ -674,8 +612,7 @@ void PressureEqualizer::adjust_volumetric_rate(const size_t fist_line_idx, const
674612
continue; // The positive rate is unlimited or the rate for GCodeExtrusionRole iRole is unlimited.
675613

676614
float rate_start = feedrate_per_extrusion_role[iRole];
677-
// don't alter the flow rate for these extrusion types
678-
if (!line.adjustable_flow || line.extrusion_role == GCodeExtrusionRole::BridgeInfill || line.extrusion_role == GCodeExtrusionRole::Ironing) {
615+
if (!line.adjustable_flow || line.extrusion_role == GCodeExtrusionRole::ExternalPerimeter || line.extrusion_role == GCodeExtrusionRole::GapFill || line.extrusion_role == GCodeExtrusionRole::BridgeInfill || line.extrusion_role == GCodeExtrusionRole::Ironing) {
679616
rate_start = line.volumetric_extrusion_rate_start;
680617
} else if (iRole == size_t(line.extrusion_role) && rate_prec < rate_start)
681618
rate_start = rate_prec;
@@ -700,8 +637,8 @@ void PressureEqualizer::adjust_volumetric_rate(const size_t fist_line_idx, const
700637
}
701638
}
702639
// feedrate_per_extrusion_role[iRole] = (iRole == line.extrusion_role) ? line.volumetric_extrusion_rate_end : rate_end;
703-
// Don't store feed rate for ironing
704-
if (line.extrusion_role != GCodeExtrusionRole::Ironing)
640+
// Don't store feed rate for ironing and gap-fill.
641+
if (line.extrusion_role != GCodeExtrusionRole::Ironing && line.extrusion_role != GCodeExtrusionRole::GapFill)
705642
feedrate_per_extrusion_role[iRole] = line.volumetric_extrusion_rate_end;
706643
}
707644
}

src/libslic3r/GCode/PressureEqualizer.hpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ class PressureEqualizer
8686
bool m_retracted;
8787
bool m_use_relative_e_distances;
8888

89-
// Maximum segment length to split a long segment if the initial and the final flow rate differ.
89+
// Maximum segment length to split a long segment if the initial and the final flow rate differ.
9090
// Smaller value means a smoother transition between two different flow rates.
9191
float m_max_segment_length;
9292

@@ -189,12 +189,11 @@ class PressureEqualizer
189189
#endif
190190

191191
bool process_line(const char *line, const char *line_end, GCodeLine &buf);
192-
long advance_segment_beyond_small_gap(long idx_cur_pos);
193192
void output_gcode_line(size_t line_idx);
194193

195194
// Go back from the current circular_buffer_pos and lower the feedtrate to decrease the slope of the extrusion rate changes.
196195
// Then go forward and adjust the feedrate to decrease the slope of the extrusion rate changes.
197-
void adjust_volumetric_rate(size_t first_line_idx, size_t last_line_idx);
196+
void adjust_volumetric_rate();
198197

199198
// Push the text to the end of the output_buffer.
200199
inline void push_to_output(GCodeG1Formatter &formatter);

0 commit comments

Comments
 (0)