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

@ -27,11 +27,6 @@ void GCodeWriter::set_extruders(const std::vector<unsigned int> &extruder_ids)
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
first extruder has index 0 */ first extruder has index 0 */
@ -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;