OrcaSlicer/src/libslic3r/GCode/PressureEqualizer.hpp
Ioannis Giannakas cf846195cc
Porting of Pressure Equalizer feature from Prusa Slicer 2.6.x (#2161)
* Overhang perimeter handling

Updated code to handle overhang perimeters as an overhang and not as a bridge.

* Preparing to add curled extrusions identification

* Porting curling calculations from Prusa Slier 2.6.1

* Prototype 1 - slowdown extended to detect curled edges and further reduce speed

First prototype of the code submitted.

* Working prototype - 2

Code is now finally working - external perimeters are slowed down as needed when there is likelyhood of curling up.

ToDo:
1. Reslicing the model causes the algorithm not to run - need to find where this fails to trigger the call for this.
2. Slowdown of internal perimeters not working yet.

* Updated to use overhang wall speed instead of bridging speed for this algorithm

* Fixed bug in speed calculation and tweaked parameters for high speed printer

Fixed bug in speed calculation and tweaked parameters for high speed printer

* Attempting to fix "set started" not being set

* Parameter tweak after print tests

* Fixed estimation not running when model is re-sliced.

* Removing debug printf statements and fixed threading flag.

* Fixed threading

* Parameter tweaks following print tests

* Made this as an option in the GUI

* Reintroduced handling of bridges as per original design

* UI line toggling when option makes sense to be visible.

* Fixed bug in field visibility & made it default to off

* Code optimisation

* Initial commit of code from Prusa Slicer 2.6.1

* Ported ExtrusionRole from Prusa Slicer 2.6.1

* fix compile errors

* Update GCode.hpp

* code changes to invoke pressure equalizer

* attempting to trigger pressure equalizer

(Not compiling)

* Update Fill.cpp

* Update Fill.cpp

* Pressure equaliser layer result update

* Further commits

* Merged PR https://github.com/prusa3d/PrusaSlicer/pull/9622

* First complete working version

* Update PressureEqualizer.cpp

* Implemented parameter in GUI

* Toggle fields according to compatibility

* Updated UI toggles between extrusion rate slope and arc fitting.

* Updated tooltip

* Introduced parameter smoothing segment length

This parameter influences the number of division a line will undergo in response to the requirement to adhere to the extrusion rate flow adjustment.

* Internal parameter and tool tip tweaking

* Parameter and tool tip tweaking

* Updated parameters and tooltip following testing.

* Sync PressureEq with latest PrusaSlicer

* Revert "Sync PressureEq with latest PrusaSlicer"

This reverts commit 131fb94c6b.

---------

Co-authored-by: MGunlogson <MGunlogson@users.noreply.github.com>
Co-authored-by: Vojtech Bubnik <bubnikv@gmail.com>
2023-09-27 21:44:45 +08:00

214 lines
9 KiB
C++

///|/ Copyright (c) Prusa Research 2016 - 2023 Vojtěch Bubník @bubnikv, Lukáš Hejl @hejllukas
///|/ Copyright (c) SuperSlicer 2023 Remi Durand @supermerill
///|/
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
///|/
#ifndef slic3r_GCode_PressureEqualizer_hpp_
#define slic3r_GCode_PressureEqualizer_hpp_
#include "../libslic3r.h"
#include "../PrintConfig.hpp"
#include "../ExtrusionRole.hpp"
#include <queue>
namespace Slic3r {
struct LayerResult;
class GCodeG1Formatter;
//#define PRESSURE_EQUALIZER_STATISTIC
//#define PRESSURE_EQUALIZER_DEBUG
// Processes a G-code. Finds changes in the volumetric extrusion speed and adjusts the transitions
// between these paths to limit fast changes in the volumetric extrusion speed.
class PressureEqualizer
{
public:
PressureEqualizer() = delete;
explicit PressureEqualizer(const Slic3r::GCodeConfig &config);
~PressureEqualizer() = default;
// Process a next batch of G-code lines.
// The last LayerResult must be LayerResult::make_nop_layer_result() because it always returns GCode for the previous layer.
// When process_layer is called for the first layer, then LayerResult::make_nop_layer_result() is returned.
LayerResult process_layer(LayerResult &&input);
private:
void process_layer(const std::string &gcode);
#ifdef PRESSURE_EQUALIZER_STATISTIC
struct Statistics
{
void reset()
{
volumetric_extrusion_rate_min = std::numeric_limits<float>::max();
volumetric_extrusion_rate_max = 0.f;
volumetric_extrusion_rate_avg = 0.f;
extrusion_length = 0.f;
}
void update(float volumetric_extrusion_rate, float length)
{
volumetric_extrusion_rate_min = std::min(volumetric_extrusion_rate_min, volumetric_extrusion_rate);
volumetric_extrusion_rate_max = std::max(volumetric_extrusion_rate_max, volumetric_extrusion_rate);
volumetric_extrusion_rate_avg += volumetric_extrusion_rate * length;
extrusion_length += length;
}
float volumetric_extrusion_rate_min;
float volumetric_extrusion_rate_max;
float volumetric_extrusion_rate_avg;
float extrusion_length;
};
struct Statistics m_stat;
#endif
// Private configuration values
// How fast could the volumetric extrusion rate increase / decrase? mm^3/sec^2
struct ExtrusionRateSlope {
float positive;
float negative;
};
ExtrusionRateSlope m_max_volumetric_extrusion_rate_slopes[size_t(GCodeExtrusionRole::Count)];
float m_max_volumetric_extrusion_rate_slope_positive;
float m_max_volumetric_extrusion_rate_slope_negative;
// Configuration extracted from config.
// Area of the crossestion of each filament. Necessary to calculate the volumetric flow rate.
std::vector<float> m_filament_crossections;
// Internal data.
// X,Y,Z,E,F
float m_current_pos[5];
size_t m_current_extruder;
GCodeExtrusionRole m_current_extrusion_role;
bool m_retracted;
bool m_use_relative_e_distances;
// Maximum segment length to split a long segment if the initial and the final flow rate differ.
// Smaller value means a smoother transition between two different flow rates.
float m_max_segment_length;
// Indicate if extrude set speed block was opened using the tag ";_EXTRUDE_SET_SPEED"
// or not (not opened, or it was closed using the tag ";_EXTRUDE_END").
bool opened_extrude_set_speed_block = false;
enum GCodeLineType {
GCODELINETYPE_INVALID,
GCODELINETYPE_NOOP,
GCODELINETYPE_OTHER,
GCODELINETYPE_RETRACT,
GCODELINETYPE_UNRETRACT,
GCODELINETYPE_TOOL_CHANGE,
GCODELINETYPE_MOVE,
GCODELINETYPE_EXTRUDE,
};
struct GCodeLine
{
GCodeLine() :
type(GCODELINETYPE_INVALID),
raw_length(0),
modified(false),
extruder_id(0),
volumetric_extrusion_rate(0.f),
volumetric_extrusion_rate_start(0.f),
volumetric_extrusion_rate_end(0.f)
{}
bool moving_xy() const { return fabs(pos_end[0] - pos_start[0]) > 0.f || fabs(pos_end[1] - pos_start[1]) > 0.f; }
bool moving_z () const { return fabs(pos_end[2] - pos_start[2]) > 0.f; }
bool extruding() const { return moving_xy() && pos_end[3] > pos_start[3]; }
bool retracting() const { return pos_end[3] < pos_start[3]; }
bool deretracting() const { return ! moving_xy() && pos_end[3] > pos_start[3]; }
float dist_xy2() const { return (pos_end[0] - pos_start[0]) * (pos_end[0] - pos_start[0]) + (pos_end[1] - pos_start[1]) * (pos_end[1] - pos_start[1]); }
float dist_xyz2() const { return (pos_end[0] - pos_start[0]) * (pos_end[0] - pos_start[0]) + (pos_end[1] - pos_start[1]) * (pos_end[1] - pos_start[1]) + (pos_end[2] - pos_start[2]) * (pos_end[2] - pos_start[2]); }
float dist_xy() const { return sqrt(dist_xy2()); }
float dist_xyz() const { return sqrt(dist_xyz2()); }
float dist_e() const { return fabs(pos_end[3] - pos_start[3]); }
float feedrate() const { return pos_end[4]; }
float time() const { return dist_xyz() / feedrate(); }
float time_inv() const { return feedrate() / dist_xyz(); }
float volumetric_correction_avg() const {
float avg_correction = 0.5f * (volumetric_extrusion_rate_start + volumetric_extrusion_rate_end) / volumetric_extrusion_rate;
assert(avg_correction > 0.f);
assert(avg_correction <= 1.00000001f);
return avg_correction;
}
float time_corrected() const { return time() * volumetric_correction_avg(); }
GCodeLineType type;
// We try to keep the string buffer once it has been allocated, so it will not be reallocated over and over.
std::vector<char> raw;
size_t raw_length;
// If modified, the raw text has to be adapted by the new extrusion rate,
// or maybe the line needs to be split into multiple lines.
bool modified;
// X,Y,Z,E,F. Storing the state of the currently active extruder only.
float pos_start[5];
float pos_end[5];
// Was the axis found on the G-code line? X,Y,Z,E,F
bool pos_provided[5];
// Index of the active extruder.
size_t extruder_id;
// Extrusion role of this segment.
GCodeExtrusionRole extrusion_role;
// Current volumetric extrusion rate.
float volumetric_extrusion_rate;
// Volumetric extrusion rate at the start of this segment.
float volumetric_extrusion_rate_start;
// Volumetric extrusion rate at the end of this segment.
float volumetric_extrusion_rate_end;
// Volumetric extrusion rate slope limiting this segment.
// If set to zero, the slope is unlimited.
float max_volumetric_extrusion_rate_slope_positive;
float max_volumetric_extrusion_rate_slope_negative;
bool adjustable_flow = false;
bool extrude_set_speed_tag = false;
bool extrude_end_tag = false;
};
// Output buffer will only grow. It will not be reallocated over and over.
std::vector<char> output_buffer;
size_t output_buffer_length;
size_t output_buffer_prev_length;
#ifdef PRESSURE_EQUALIZER_DEBUG
// For debugging purposes. Index of the G-code line processed.
size_t line_idx;
#endif
bool process_line(const char *line, const char *line_end, GCodeLine &buf);
long advance_segment_beyond_small_gap(long idx_cur_pos);
void output_gcode_line(size_t line_idx);
// Go back from the current circular_buffer_pos and lower the feedtrate to decrease the slope of the extrusion rate changes.
// Then go forward and adjust the feedrate to decrease the slope of the extrusion rate changes.
void adjust_volumetric_rate(size_t first_line_idx, size_t last_line_idx);
// Push the text to the end of the output_buffer.
inline void push_to_output(GCodeG1Formatter &formatter);
inline void push_to_output(const std::string &text, bool add_eol);
inline void push_to_output(const char *text, size_t len, bool add_eol = true);
// Push a G-code line to the output.
void push_line_to_output(size_t line_idx, float new_feedrate, const char *comment);
public:
std::queue<LayerResult*> m_layer_results;
std::vector<GCodeLine> m_gcode_lines;
};
} // namespace Slic3r
#endif /* slic3r_GCode_PressureEqualizer_hpp_ */