Refactored the cooling buffer: Removed ElapsedTime.

This commit is contained in:
bubnikv 2017-06-30 20:01:32 +02:00
parent bf9027ff2d
commit 0ad4e9d51f
5 changed files with 19 additions and 105 deletions

View File

@ -168,11 +168,6 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
// Let the m_writer know the current extruder_id, but ignore the generated G-code. // Let the m_writer know the current extruder_id, but ignore the generated G-code.
if (new_extruder_id >= 0 && gcodegen.writer().need_toolchange(new_extruder_id)) if (new_extruder_id >= 0 && gcodegen.writer().need_toolchange(new_extruder_id))
gcodegen.writer().toolchange(new_extruder_id); gcodegen.writer().toolchange(new_extruder_id);
// Accumulate the elapsed time for the correct calculation of layer cooling.
//FIXME currently disabled as Slic3r PE needs to be updated to differentiate the moves it could slow down
// from the moves it could not.
gcodegen.writer().elapsed_time()->total += tcr.elapsed_time;
gcodegen.writer().elapsed_time()->other += tcr.elapsed_time;
// A phony move to the end position at the wipe tower. // A phony move to the end position at the wipe tower.
gcodegen.writer().travel_to_xy(Pointf(tcr.end_pos.x, tcr.end_pos.y)); gcodegen.writer().travel_to_xy(Pointf(tcr.end_pos.x, tcr.end_pos.y));
gcodegen.set_last_pos(wipe_tower_point_to_object_point(gcodegen, tcr.end_pos)); gcodegen.set_last_pos(wipe_tower_point_to_object_point(gcodegen, tcr.end_pos));
@ -1868,24 +1863,6 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
gcode += is_bridge(path.role()) ? ";_BRIDGE_FAN_END\n" : ";_EXTRUDE_END\n"; gcode += is_bridge(path.role()) ? ";_BRIDGE_FAN_END\n" : ";_EXTRUDE_END\n";
this->set_last_pos(path.last_point()); this->set_last_pos(path.last_point());
if (m_config.cooling.values.front()) {
float t = float(path_length / F * 60);
m_writer.elapsed_time()->total += t;
assert(! (is_bridge(path.role()) && path.role() == erExternalPerimeter));
if (is_bridge(path.role()))
m_writer.elapsed_time()->bridges += t;
else {
// Maximum print time of this extrusion, respecting the min_print_speed.
float t_max = std::max(t, float(path_length / std::max(0.1, EXTRUDER_CONFIG(min_print_speed))));
if (path.role() == erExternalPerimeter)
m_writer.elapsed_time()->external_perimeters += t;
else
m_writer.elapsed_time()->max_stretch_time_no_ext_perimetes += t_max;
m_writer.elapsed_time()->max_stretch_time_total += t_max;
}
}
return gcode; return gcode;
} }
@ -1931,9 +1908,6 @@ std::string GCode::travel_to(const Point &point, ExtrusionRole role, std::string
for (Lines::const_iterator line = lines.begin(); line != lines.end(); ++line) for (Lines::const_iterator line = lines.begin(); line != lines.end(); ++line)
gcode += m_writer.travel_to_xy(this->point_to_gcode(line->b), comment); gcode += m_writer.travel_to_xy(this->point_to_gcode(line->b), comment);
if (m_config.cooling.values.front())
m_writer.elapsed_time()->travel += unscale(travel.length()) / m_config.get_abs_value("travel_speed");
return gcode; return gcode;
} }

View File

@ -34,13 +34,13 @@ void CoolingBuffer::reset()
std::string CoolingBuffer::process_layer(const std::string &gcode, size_t layer_id) std::string CoolingBuffer::process_layer(const std::string &gcode, size_t layer_id)
{ {
const FullPrintConfig &config = m_gcodegen.config(); const FullPrintConfig &config = m_gcodegen.config();
const auto &elapsed_times = m_gcodegen.writer().elapsed_times(); const std::vector<Extruder> &extruders = m_gcodegen.writer().extruders();
const size_t num_extruders = elapsed_times.size(); const size_t num_extruders = extruders.size();
// Calculate the required per extruder time stretches. // Calculate the required per extruder time stretches.
struct Adjustment { struct Adjustment {
Adjustment() {} Adjustment(unsigned int extruder_id = 0) : extruder_id(extruder_id) {}
// Calculate the total elapsed time per this extruder, adjusted for the slowdown. // Calculate the total elapsed time per this extruder, adjusted for the slowdown.
float elapsed_time_total() { float elapsed_time_total() {
float time_total = 0.f; float time_total = 0.f;
@ -94,6 +94,8 @@ std::string CoolingBuffer::process_layer(const std::string &gcode, size_t layer_
return time_total; return time_total;
} }
bool operator<(const Adjustment &rhs) const { return this->extruder_id < rhs.extruder_id; }
struct Line struct Line
{ {
enum Type { enum Type {
@ -135,16 +137,19 @@ std::string CoolingBuffer::process_layer(const std::string &gcode, size_t layer_
bool slowdown; bool slowdown;
}; };
// Extruder, for which the G-code will be adjusted.
unsigned int extruder_id;
// Parsed lines. // Parsed lines.
std::vector<Line> lines; std::vector<Line> lines;
}; };
std::vector<Adjustment> adjustments(num_extruders, Adjustment()); std::vector<Adjustment> adjustments(num_extruders, Adjustment());
for (size_t i = 0; i < num_extruders; ++ i)
adjustments[i].extruder_id = extruders[i].id();
const std::string toolchange_prefix = m_gcodegen.writer().toolchange_prefix(); const std::string toolchange_prefix = m_gcodegen.writer().toolchange_prefix();
// Parse the layer G-code for the moves, which could be adjusted. // Parse the layer G-code for the moves, which could be adjusted.
{ {
float min_print_speed = float(EXTRUDER_CONFIG(min_print_speed)); float min_print_speed = float(EXTRUDER_CONFIG(min_print_speed));
auto it_elapsed_time = std::lower_bound(elapsed_times.begin(), elapsed_times.end(), ElapsedTime(m_current_extruder)); auto adjustment = std::lower_bound(adjustments.begin(), adjustments.end(), Adjustment(m_current_extruder));
Adjustment *adjustment = &adjustments[it_elapsed_time - elapsed_times.begin()];
unsigned int initial_extruder = m_current_extruder; unsigned int initial_extruder = m_current_extruder;
const char *line_start = gcode.c_str(); const char *line_start = gcode.c_str();
const char *line_end = line_start; const char *line_end = line_start;
@ -242,8 +247,7 @@ std::string CoolingBuffer::process_layer(const std::string &gcode, size_t layer_
if (new_extruder != m_current_extruder) { if (new_extruder != m_current_extruder) {
m_current_extruder = new_extruder; m_current_extruder = new_extruder;
min_print_speed = float(EXTRUDER_CONFIG(min_print_speed)); min_print_speed = float(EXTRUDER_CONFIG(min_print_speed));
it_elapsed_time = std::lower_bound(elapsed_times.begin(), elapsed_times.end(), ElapsedTime(m_current_extruder)); adjustment = std::lower_bound(adjustments.begin(), adjustments.end(), Adjustment(m_current_extruder));
adjustment = &adjustments[it_elapsed_time - elapsed_times.begin()];
} }
} else if (boost::starts_with(sline, ";_BRIDGE_FAN_START")) { } else if (boost::starts_with(sline, ";_BRIDGE_FAN_START")) {
line.type = Adjustment::Line::TYPE_BRIDGE_FAN_START; line.type = Adjustment::Line::TYPE_BRIDGE_FAN_START;
@ -273,15 +277,15 @@ std::string CoolingBuffer::process_layer(const std::string &gcode, size_t layer_
// Collect total print time of non-adjustable extruders. // Collect total print time of non-adjustable extruders.
float elapsed_time_total_non_adjustable = 0.f; float elapsed_time_total_non_adjustable = 0.f;
for (size_t i = 0; i < num_extruders; ++ i) { for (size_t i = 0; i < num_extruders; ++ i) {
if (config.cooling.get_at(elapsed_times[i].extruder_id)) if (config.cooling.get_at(extruders[i].id()))
by_slowdown_layer_time.emplace_back(i); by_slowdown_layer_time.emplace_back(i);
else else
elapsed_time_total_non_adjustable += adjustments[i].elapsed_time_total(); elapsed_time_total_non_adjustable += adjustments[i].elapsed_time_total();
} }
std::sort(by_slowdown_layer_time.begin(), by_slowdown_layer_time.end(), std::sort(by_slowdown_layer_time.begin(), by_slowdown_layer_time.end(),
[&config, &elapsed_times](const size_t idx1, const size_t idx2){ [&config, &extruders](const size_t idx1, const size_t idx2){
return config.slowdown_below_layer_time.get_at(elapsed_times[idx1].extruder_id) < return config.slowdown_below_layer_time.get_at(extruders[idx1].id()) <
config.slowdown_below_layer_time.get_at(elapsed_times[idx2].extruder_id); config.slowdown_below_layer_time.get_at(extruders[idx2].id());
}); });
// Elapsed time after adjustment. // Elapsed time after adjustment.
@ -290,7 +294,7 @@ std::string CoolingBuffer::process_layer(const std::string &gcode, size_t layer_
// Elapsed time for the already adjusted extruders. // Elapsed time for the already adjusted extruders.
float elapsed_time_total0 = elapsed_time_total_non_adjustable; float elapsed_time_total0 = elapsed_time_total_non_adjustable;
for (size_t i_by_slowdown_layer_time = 0; i_by_slowdown_layer_time < by_slowdown_layer_time.size(); ++ i_by_slowdown_layer_time) { for (size_t i_by_slowdown_layer_time = 0; i_by_slowdown_layer_time < by_slowdown_layer_time.size(); ++ i_by_slowdown_layer_time) {
// Idx in elapsed_times and adjustments. // Idx in adjustments.
size_t idx = by_slowdown_layer_time[i_by_slowdown_layer_time]; size_t idx = by_slowdown_layer_time[i_by_slowdown_layer_time];
// Macro to sum or adjust all sections starting with i_by_slowdown_layer_time. // Macro to sum or adjust all sections starting with i_by_slowdown_layer_time.
#define FORALL_UNPROCESSED(ACCUMULATOR, ACTION) \ #define FORALL_UNPROCESSED(ACCUMULATOR, ACTION) \
@ -300,7 +304,7 @@ std::string CoolingBuffer::process_layer(const std::string &gcode, size_t layer_
// Calculate the current adjusted elapsed_time_total over the non-finalized extruders. // Calculate the current adjusted elapsed_time_total over the non-finalized extruders.
float total; float total;
FORALL_UNPROCESSED(total, elapsed_time_total()); FORALL_UNPROCESSED(total, elapsed_time_total());
float slowdown_below_layer_time = float(config.slowdown_below_layer_time.get_at(elapsed_times[idx].extruder_id)) * 1.001f; float slowdown_below_layer_time = float(config.slowdown_below_layer_time.get_at(adjustments[idx].extruder_id)) * 1.001f;
if (total > slowdown_below_layer_time) { if (total > slowdown_below_layer_time) {
// The current total time is above the minimum threshold of the rest of the extruders, don't adjust anything. // The current total time is above the minimum threshold of the rest of the extruders, don't adjust anything.
} else { } else {
@ -462,7 +466,6 @@ std::string CoolingBuffer::process_layer(const std::string &gcode, size_t layer_
if (pos < gcode.size()) if (pos < gcode.size())
new_gcode.append(gcode.c_str() + pos, gcode.size() - pos); new_gcode.append(gcode.c_str() + pos, gcode.size() - pos);
m_gcodegen.writer().reset_elapsed_times();
return new_gcode; return new_gcode;
} }

View File

@ -10,54 +10,6 @@ namespace Slic3r {
class GCode; class GCode;
class Layer; class Layer;
struct ElapsedTime
{
ElapsedTime(unsigned int extruder_id = 0) : extruder_id(extruder_id) { this->reset(); }
void reset() {
total = bridges = external_perimeters = travel = other = 0.f;
max_stretch_time_total = max_stretch_time_no_ext_perimetes = 0.f;
}
ElapsedTime& operator+=(const ElapsedTime &rhs) {
this->total += rhs.total;
this->bridges += rhs.bridges;
this->external_perimeters += rhs.external_perimeters;
this->travel += rhs.travel;
this->other += rhs.other;
this->max_stretch_time_total += rhs.max_stretch_time_total;
this->max_stretch_time_no_ext_perimetes += rhs.max_stretch_time_no_ext_perimetes;
return *this;
}
// Potion of the total time, which cannot be stretched to heed the minimum layer print time.
float non_stretchable(bool stretch_external_perimeters = true) const
{ return this->bridges + this->travel + this->other + (stretch_external_perimeters ? 0.f : this->external_perimeters); }
// Potion of the total time, which could be stretched to heed the minimum layer print time.
float stretchable(bool stretch_external_perimeters = true) const
{ return this->total - this->non_stretchable(stretch_external_perimeters); }
// For which extruder ID has this statistics been collected?
unsigned int extruder_id;
// Total time.
float total;
// Per feature time slices.
float bridges;
float external_perimeters;
float travel;
float other;
// Per feature maximum time, to which the extrusion could be stretched to respect the extruder specific min_print_speed.
// Maximum stretch time, to which the time this->stretchable() could be extended.
float max_stretch_time_total;
// Maximum stretch time, to which the time (this->stretchable() - external_perimeters) could be extended.
float max_stretch_time_no_ext_perimetes;
};
// Sort ElapsedTime objects by the extruder id by default.
inline bool operator==(const ElapsedTime &e1, const ElapsedTime &e2) { return e1.extruder_id == e2.extruder_id; }
inline bool operator!=(const ElapsedTime &e1, const ElapsedTime &e2) { return e1.extruder_id != e2.extruder_id; }
inline bool operator< (const ElapsedTime &e1, const ElapsedTime &e2) { return e1.extruder_id < e2.extruder_id; }
inline bool operator> (const ElapsedTime &e1, const ElapsedTime &e2) { return e1.extruder_id > e2.extruder_id; }
/* /*
A standalone G-code filter, to control cooling of the print. A standalone G-code filter, to control cooling of the print.
The G-code is processed per layer. Once a layer is collected, fan start / stop commands are edited The G-code is processed per layer. Once a layer is collected, fan start / stop commands are edited

View File

@ -26,11 +26,6 @@ void GCodeWriter::set_extruders(const std::vector<unsigned int> &extruder_ids)
m_extruders.reserve(extruder_ids.size()); m_extruders.reserve(extruder_ids.size());
for (unsigned int extruder_id : extruder_ids) for (unsigned int extruder_id : extruder_ids)
m_extruders.emplace_back(Extruder(extruder_id, &this->config)); m_extruders.emplace_back(Extruder(extruder_id, &this->config));
m_elapsed_times.clear();
m_elapsed_times.reserve(extruder_ids.size());
for (unsigned int extruder_id : extruder_ids)
m_elapsed_times.emplace_back(ElapsedTime(extruder_id));
/* we enable support for multiple extruder if any extruder greater than 0 is used /* we enable support for multiple extruder if any extruder greater than 0 is used
(even if prints only uses that one) since we need to output Tx commands (even if prints only uses that one) since we need to output Tx commands
@ -249,10 +244,6 @@ std::string GCodeWriter::toolchange(unsigned int extruder_id)
assert(it_extruder != m_extruders.end()); assert(it_extruder != m_extruders.end());
m_extruder = const_cast<Extruder*>(&*it_extruder); m_extruder = const_cast<Extruder*>(&*it_extruder);
auto it_elapsed_time = std::lower_bound(m_elapsed_times.begin(), m_elapsed_times.end(), ElapsedTime(extruder_id));
assert(it_elapsed_time != m_elapsed_times.end());
m_elapsed_time = const_cast<ElapsedTime*>(&*it_elapsed_time);
// return the toolchange command // return the toolchange command
// if we are running a single-extruder setup, just set the extruder and return nothing // if we are running a single-extruder setup, just set the extruder and return nothing
std::ostringstream gcode; std::ostringstream gcode;

View File

@ -16,7 +16,7 @@ public:
bool multiple_extruders; bool multiple_extruders;
GCodeWriter() : GCodeWriter() :
multiple_extruders(false), m_extrusion_axis("E"), m_extruder(nullptr), m_elapsed_time(nullptr), multiple_extruders(false), m_extrusion_axis("E"), m_extruder(nullptr),
m_single_extruder_multi_material(false), m_single_extruder_multi_material(false),
m_last_acceleration(0), m_last_fan_speed(0), m_last_acceleration(0), m_last_fan_speed(0),
m_last_bed_temperature(0), m_last_bed_temperature_reached(true), m_last_bed_temperature(0), m_last_bed_temperature_reached(true),
@ -24,10 +24,6 @@ public:
{} {}
Extruder* extruder() { return m_extruder; } Extruder* extruder() { return m_extruder; }
const Extruder* extruder() const { return m_extruder; } const Extruder* extruder() const { return m_extruder; }
ElapsedTime* elapsed_time() { return m_elapsed_time; }
const ElapsedTime* elapsed_time() const { return m_elapsed_time; }
const std::vector<ElapsedTime>& elapsed_times() const { return m_elapsed_times; }
void reset_elapsed_times() { for (auto &et : m_elapsed_times) et.reset(); }
std::string extrusion_axis() const { return m_extrusion_axis; } std::string extrusion_axis() const { return m_extrusion_axis; }
void apply_print_config(const PrintConfig &print_config); void apply_print_config(const PrintConfig &print_config);
@ -74,11 +70,9 @@ public:
private: private:
std::vector<Extruder> m_extruders; std::vector<Extruder> m_extruders;
std::vector<ElapsedTime> m_elapsed_times;
std::string m_extrusion_axis; std::string m_extrusion_axis;
bool m_single_extruder_multi_material; bool m_single_extruder_multi_material;
Extruder* m_extruder; Extruder* m_extruder;
ElapsedTime* m_elapsed_time;
unsigned int m_last_acceleration; unsigned int m_last_acceleration;
unsigned int m_last_fan_speed; unsigned int m_last_fan_speed;
unsigned int m_last_bed_temperature; unsigned int m_last_bed_temperature;