Follow-up to beee18f229
WIP to G-code export parallelization through pipelining: Decoupled CoolingBuffer from GCode / GCodeWriter, ready to be pipelined on a different thread.
This commit is contained in:
parent
410b5e610b
commit
03b6048684
@ -1219,7 +1219,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
|
||||
// Disable fan.
|
||||
if (! print.config().cooling.get_at(initial_extruder_id) || print.config().disable_fan_first_layers.get_at(initial_extruder_id))
|
||||
file.write(m_writer.set_fan(0, true));
|
||||
file.write(m_writer.set_fan(0));
|
||||
|
||||
// Let the start-up script prime the 1st printing tool.
|
||||
m_placeholder_parser.set("initial_tool", initial_extruder_id);
|
||||
@ -1334,7 +1334,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
file.writeln(between_objects_gcode);
|
||||
}
|
||||
// Reset the cooling buffer internal state (the current position, feed rate, accelerations).
|
||||
m_cooling_buffer->reset();
|
||||
m_cooling_buffer->reset(this->writer().get_position());
|
||||
m_cooling_buffer->set_current_extruder(initial_extruder_id);
|
||||
// Pair the object layers with the support layers by z, extrude them.
|
||||
std::vector<LayerToPrint> layers_to_print = collect_layers_to_print(object);
|
||||
@ -1420,7 +1420,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
|
||||
// Write end commands to file.
|
||||
file.write(this->retract());
|
||||
file.write(m_writer.set_fan(false));
|
||||
file.write(m_writer.set_fan(0));
|
||||
|
||||
// adds tag for processor
|
||||
file.write_format(";%s%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role).c_str(), ExtrusionEntity::role_to_string(erCustom).c_str());
|
||||
|
@ -16,19 +16,25 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
CoolingBuffer::CoolingBuffer(GCode &gcodegen) : m_gcodegen(gcodegen), m_current_extruder(0)
|
||||
CoolingBuffer::CoolingBuffer(GCode &gcodegen) : m_config(gcodegen.config()), m_toolchange_prefix(gcodegen.writer().toolchange_prefix()), m_current_extruder(0)
|
||||
{
|
||||
this->reset();
|
||||
this->reset(gcodegen.writer().get_position());
|
||||
|
||||
const std::vector<Extruder> &extruders = gcodegen.writer().extruders();
|
||||
m_extruder_ids.reserve(extruders.size());
|
||||
for (const Extruder &ex : extruders) {
|
||||
m_num_extruders = std::max(ex.id() + 1, m_num_extruders);
|
||||
m_extruder_ids.emplace_back(ex.id());
|
||||
}
|
||||
}
|
||||
|
||||
void CoolingBuffer::reset()
|
||||
void CoolingBuffer::reset(const Vec3d &position)
|
||||
{
|
||||
m_current_pos.assign(5, 0.f);
|
||||
Vec3d pos = m_gcodegen.writer().get_position();
|
||||
m_current_pos[0] = float(pos(0));
|
||||
m_current_pos[1] = float(pos(1));
|
||||
m_current_pos[2] = float(pos(2));
|
||||
m_current_pos[4] = float(m_gcodegen.config().travel_speed.value);
|
||||
m_current_pos[0] = float(position.x());
|
||||
m_current_pos[1] = float(position.y());
|
||||
m_current_pos[2] = float(position.z());
|
||||
m_current_pos[4] = float(m_config.travel_speed.value);
|
||||
}
|
||||
|
||||
struct CoolingLine
|
||||
@ -303,30 +309,23 @@ std::string CoolingBuffer::process_layer(std::string &&gcode, size_t layer_id, b
|
||||
// Return the list of parsed lines, bucketed by an extruder.
|
||||
std::vector<PerExtruderAdjustments> CoolingBuffer::parse_layer_gcode(const std::string &gcode, std::vector<float> ¤t_pos) const
|
||||
{
|
||||
const FullPrintConfig &config = m_gcodegen.config();
|
||||
const std::vector<Extruder> &extruders = m_gcodegen.writer().extruders();
|
||||
unsigned int num_extruders = 0;
|
||||
for (const Extruder &ex : extruders)
|
||||
num_extruders = std::max(ex.id() + 1, num_extruders);
|
||||
|
||||
std::vector<PerExtruderAdjustments> per_extruder_adjustments(extruders.size());
|
||||
std::vector<size_t> map_extruder_to_per_extruder_adjustment(num_extruders, 0);
|
||||
for (size_t i = 0; i < extruders.size(); ++ i) {
|
||||
std::vector<PerExtruderAdjustments> per_extruder_adjustments(m_extruder_ids.size());
|
||||
std::vector<size_t> map_extruder_to_per_extruder_adjustment(m_num_extruders, 0);
|
||||
for (size_t i = 0; i < m_extruder_ids.size(); ++ i) {
|
||||
PerExtruderAdjustments &adj = per_extruder_adjustments[i];
|
||||
unsigned int extruder_id = extruders[i].id();
|
||||
unsigned int extruder_id = m_extruder_ids[i];
|
||||
adj.extruder_id = extruder_id;
|
||||
adj.cooling_slow_down_enabled = config.cooling.get_at(extruder_id);
|
||||
adj.slowdown_below_layer_time = float(config.slowdown_below_layer_time.get_at(extruder_id));
|
||||
adj.min_print_speed = float(config.min_print_speed.get_at(extruder_id));
|
||||
adj.cooling_slow_down_enabled = m_config.cooling.get_at(extruder_id);
|
||||
adj.slowdown_below_layer_time = float(m_config.slowdown_below_layer_time.get_at(extruder_id));
|
||||
adj.min_print_speed = float(m_config.min_print_speed.get_at(extruder_id));
|
||||
map_extruder_to_per_extruder_adjustment[extruder_id] = i;
|
||||
}
|
||||
|
||||
const std::string toolchange_prefix = m_gcodegen.writer().toolchange_prefix();
|
||||
unsigned int current_extruder = m_current_extruder;
|
||||
PerExtruderAdjustments *adjustment = &per_extruder_adjustments[map_extruder_to_per_extruder_adjustment[current_extruder]];
|
||||
const char *line_start = gcode.c_str();
|
||||
const char *line_end = line_start;
|
||||
const char extrusion_axis = get_extrusion_axis(config)[0];
|
||||
const char extrusion_axis = get_extrusion_axis(m_config)[0];
|
||||
// Index of an existing CoolingLine of the current adjustment, which holds the feedrate setting command
|
||||
// for a sequence of extrusion moves.
|
||||
size_t active_speed_modifier = size_t(-1);
|
||||
@ -387,7 +386,7 @@ std::vector<PerExtruderAdjustments> CoolingBuffer::parse_layer_gcode(const std::
|
||||
}
|
||||
if ((line.type & CoolingLine::TYPE_G92) == 0) {
|
||||
// G0 or G1. Calculate the duration.
|
||||
if (config.use_relative_e_distances.value)
|
||||
if (m_config.use_relative_e_distances.value)
|
||||
// Reset extruder accumulator.
|
||||
current_pos[3] = 0.f;
|
||||
float dif[4];
|
||||
@ -430,8 +429,8 @@ std::vector<PerExtruderAdjustments> CoolingBuffer::parse_layer_gcode(const std::
|
||||
} else if (boost::starts_with(sline, ";_EXTRUDE_END")) {
|
||||
line.type = CoolingLine::TYPE_EXTRUDE_END;
|
||||
active_speed_modifier = size_t(-1);
|
||||
} else if (boost::starts_with(sline, toolchange_prefix)) {
|
||||
unsigned int new_extruder = (unsigned int)atoi(sline.c_str() + toolchange_prefix.size());
|
||||
} else if (boost::starts_with(sline, m_toolchange_prefix)) {
|
||||
unsigned int new_extruder = (unsigned int)atoi(sline.c_str() + m_toolchange_prefix.size());
|
||||
// Only change extruder in case the number is meaningful. User could provide an out-of-range index through custom gcodes - those shall be ignored.
|
||||
if (new_extruder < map_extruder_to_per_extruder_adjustment.size()) {
|
||||
if (new_extruder != current_extruder) {
|
||||
@ -641,7 +640,7 @@ float CoolingBuffer::calculate_layer_slowdown(std::vector<PerExtruderAdjustments
|
||||
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.
|
||||
} else {
|
||||
// Adjust this and all the following (higher config.slowdown_below_layer_time) extruders.
|
||||
// Adjust this and all the following (higher m_config.slowdown_below_layer_time) extruders.
|
||||
// Sum maximum slow down time as if everything was slowed down including the external perimeters.
|
||||
float max_time = elapsed_time_total0;
|
||||
for (auto it = cur_begin; it != by_slowdown_time.end(); ++ it)
|
||||
@ -694,8 +693,7 @@ std::string CoolingBuffer::apply_layer_cooldown(
|
||||
bool bridge_fan_control = false;
|
||||
int bridge_fan_speed = 0;
|
||||
auto change_extruder_set_fan = [ this, layer_id, layer_time, &new_gcode, &fan_speed, &bridge_fan_control, &bridge_fan_speed ]() {
|
||||
const FullPrintConfig &config = m_gcodegen.config();
|
||||
#define EXTRUDER_CONFIG(OPT) config.OPT.get_at(m_current_extruder)
|
||||
#define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_current_extruder)
|
||||
int min_fan_speed = EXTRUDER_CONFIG(min_fan_speed);
|
||||
int fan_speed_new = EXTRUDER_CONFIG(fan_always_on) ? min_fan_speed : 0;
|
||||
int disable_fan_first_layers = EXTRUDER_CONFIG(disable_fan_first_layers);
|
||||
@ -737,13 +735,12 @@ std::string CoolingBuffer::apply_layer_cooldown(
|
||||
}
|
||||
if (fan_speed_new != fan_speed) {
|
||||
fan_speed = fan_speed_new;
|
||||
new_gcode += m_gcodegen.writer().set_fan(fan_speed);
|
||||
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, fan_speed);
|
||||
}
|
||||
};
|
||||
|
||||
const char *pos = gcode.c_str();
|
||||
int current_feedrate = 0;
|
||||
const std::string toolchange_prefix = m_gcodegen.writer().toolchange_prefix();
|
||||
change_extruder_set_fan();
|
||||
for (const CoolingLine *line : lines) {
|
||||
const char *line_start = gcode.c_str() + line->line_start;
|
||||
@ -751,7 +748,7 @@ std::string CoolingBuffer::apply_layer_cooldown(
|
||||
if (line_start > pos)
|
||||
new_gcode.append(pos, line_start - pos);
|
||||
if (line->type & CoolingLine::TYPE_SET_TOOL) {
|
||||
unsigned int new_extruder = (unsigned int)atoi(line_start + toolchange_prefix.size());
|
||||
unsigned int new_extruder = (unsigned int)atoi(line_start + m_toolchange_prefix.size());
|
||||
if (new_extruder != m_current_extruder) {
|
||||
m_current_extruder = new_extruder;
|
||||
change_extruder_set_fan();
|
||||
@ -759,10 +756,10 @@ std::string CoolingBuffer::apply_layer_cooldown(
|
||||
new_gcode.append(line_start, line_end - line_start);
|
||||
} else if (line->type & CoolingLine::TYPE_BRIDGE_FAN_START) {
|
||||
if (bridge_fan_control)
|
||||
new_gcode += m_gcodegen.writer().set_fan(bridge_fan_speed, true);
|
||||
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, bridge_fan_speed);
|
||||
} else if (line->type & CoolingLine::TYPE_BRIDGE_FAN_END) {
|
||||
if (bridge_fan_control)
|
||||
new_gcode += m_gcodegen.writer().set_fan(fan_speed, true);
|
||||
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, fan_speed);
|
||||
} else if (line->type & CoolingLine::TYPE_EXTRUDE_END) {
|
||||
// Just remove this comment.
|
||||
} else if (line->type & (CoolingLine::TYPE_ADJUSTABLE | CoolingLine::TYPE_EXTERNAL_PERIMETER | CoolingLine::TYPE_WIPE | CoolingLine::TYPE_HAS_F)) {
|
||||
|
@ -23,10 +23,9 @@ struct PerExtruderAdjustments;
|
||||
class CoolingBuffer {
|
||||
public:
|
||||
CoolingBuffer(GCode &gcodegen);
|
||||
void reset();
|
||||
void reset(const Vec3d &position);
|
||||
void set_current_extruder(unsigned int extruder_id) { m_current_extruder = extruder_id; }
|
||||
std::string process_layer(std::string &&gcode, size_t layer_id, bool flush);
|
||||
GCode* gcodegen() { return &m_gcodegen; }
|
||||
|
||||
private:
|
||||
CoolingBuffer& operator=(const CoolingBuffer&) = delete;
|
||||
@ -36,13 +35,21 @@ private:
|
||||
// Returns the adjusted G-code.
|
||||
std::string apply_layer_cooldown(const std::string &gcode, size_t layer_id, float layer_time, std::vector<PerExtruderAdjustments> &per_extruder_adjustments);
|
||||
|
||||
GCode& m_gcodegen;
|
||||
// G-code snippet cached for the support layers preceding an object layer.
|
||||
std::string m_gcode;
|
||||
// Internal data.
|
||||
// X,Y,Z,E,F
|
||||
std::vector<char> m_axis;
|
||||
std::vector<float> m_current_pos;
|
||||
// Cached from GCodeWriter.
|
||||
// Printing extruder IDs, zero based.
|
||||
std::vector<unsigned int> m_extruder_ids;
|
||||
// Highest of m_extruder_ids plus 1.
|
||||
unsigned int m_num_extruders { 0 };
|
||||
const std::string m_toolchange_prefix;
|
||||
// Referencs GCode::m_config, which is FullPrintConfig. While the PrintObjectConfig slice of FullPrintConfig is being modified,
|
||||
// the PrintConfig slice of FullPrintConfig is constant, thus no thread synchronization is required.
|
||||
const PrintConfig &m_config;
|
||||
unsigned int m_current_extruder;
|
||||
|
||||
// Old logic: proportional.
|
||||
|
@ -156,41 +156,6 @@ std::string GCodeWriter::set_bed_temperature(unsigned int temperature, bool wait
|
||||
return gcode.str();
|
||||
}
|
||||
|
||||
std::string GCodeWriter::set_fan(unsigned int speed, bool dont_save)
|
||||
{
|
||||
std::ostringstream gcode;
|
||||
if (m_last_fan_speed != speed || dont_save) {
|
||||
if (!dont_save) m_last_fan_speed = speed;
|
||||
|
||||
if (speed == 0) {
|
||||
if (FLAVOR_IS(gcfTeacup)) {
|
||||
gcode << "M106 S0";
|
||||
} else if (FLAVOR_IS(gcfMakerWare) || FLAVOR_IS(gcfSailfish)) {
|
||||
gcode << "M127";
|
||||
} else {
|
||||
gcode << "M107";
|
||||
}
|
||||
if (this->config.gcode_comments) gcode << " ; disable fan";
|
||||
gcode << "\n";
|
||||
} else {
|
||||
if (FLAVOR_IS(gcfMakerWare) || FLAVOR_IS(gcfSailfish)) {
|
||||
gcode << "M126";
|
||||
} else {
|
||||
gcode << "M106 ";
|
||||
if (FLAVOR_IS(gcfMach3) || FLAVOR_IS(gcfMachinekit)) {
|
||||
gcode << "P";
|
||||
} else {
|
||||
gcode << "S";
|
||||
}
|
||||
gcode << (255.0 * speed / 100.0);
|
||||
}
|
||||
if (this->config.gcode_comments) gcode << " ; enable fan";
|
||||
gcode << "\n";
|
||||
}
|
||||
}
|
||||
return gcode.str();
|
||||
}
|
||||
|
||||
std::string GCodeWriter::set_acceleration(unsigned int acceleration)
|
||||
{
|
||||
// Clamp the acceleration to the allowed maximum.
|
||||
@ -611,4 +576,43 @@ std::string GCodeWriter::unlift()
|
||||
return gcode;
|
||||
}
|
||||
|
||||
std::string GCodeWriter::set_fan(const GCodeFlavor gcode_flavor, bool gcode_comments, unsigned int speed)
|
||||
{
|
||||
std::ostringstream gcode;
|
||||
if (speed == 0) {
|
||||
switch (gcode_flavor) {
|
||||
case gcfTeacup:
|
||||
gcode << "M106 S0"; break;
|
||||
case gcfMakerWare:
|
||||
case gcfSailfish:
|
||||
gcode << "M127"; break;
|
||||
default:
|
||||
gcode << "M107"; break;
|
||||
}
|
||||
if (gcode_comments)
|
||||
gcode << " ; disable fan";
|
||||
gcode << "\n";
|
||||
} else {
|
||||
switch (gcode_flavor) {
|
||||
case gcfMakerWare:
|
||||
case gcfSailfish:
|
||||
gcode << "M126"; break;
|
||||
case gcfMach3:
|
||||
case gcfMachinekit:
|
||||
gcode << "M106 P" << 255.0 * speed / 100.0; break;
|
||||
default:
|
||||
gcode << "M106 S" << 255.0 * speed / 100.0; break;
|
||||
}
|
||||
if (gcode_comments)
|
||||
gcode << " ; enable fan";
|
||||
gcode << "\n";
|
||||
}
|
||||
return gcode.str();
|
||||
}
|
||||
|
||||
std::string GCodeWriter::set_fan(unsigned int speed) const
|
||||
{
|
||||
return GCodeWriter::set_fan(this->config.gcode_flavor, this->config.gcode_comments, speed);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ public:
|
||||
GCodeWriter() :
|
||||
multiple_extruders(false), m_extrusion_axis("E"), m_extruder(nullptr),
|
||||
m_single_extruder_multi_material(false),
|
||||
m_last_acceleration(0), m_max_acceleration(0), m_last_fan_speed(0),
|
||||
m_last_acceleration(0), m_max_acceleration(0),
|
||||
m_last_bed_temperature(0), m_last_bed_temperature_reached(true),
|
||||
m_lifted(0)
|
||||
{}
|
||||
@ -42,7 +42,6 @@ public:
|
||||
std::string postamble() const;
|
||||
std::string set_temperature(unsigned int temperature, bool wait = false, int tool = -1) const;
|
||||
std::string set_bed_temperature(unsigned int temperature, bool wait = false);
|
||||
std::string set_fan(unsigned int speed, bool dont_save = false);
|
||||
std::string set_acceleration(unsigned int acceleration);
|
||||
std::string reset_e(bool force = false);
|
||||
std::string update_progress(unsigned int num, unsigned int tot, bool allow_100 = false) const;
|
||||
@ -69,6 +68,12 @@ public:
|
||||
std::string unlift();
|
||||
Vec3d get_position() const { return m_pos; }
|
||||
|
||||
// To be called by the CoolingBuffer from another thread.
|
||||
static std::string set_fan(const GCodeFlavor gcode_flavor, bool gcode_comments, unsigned int speed);
|
||||
// To be called by the main thread. It always emits the G-code, it does not remember the previous state.
|
||||
// Keeping the state is left to the CoolingBuffer, which runs asynchronously on another thread.
|
||||
std::string set_fan(unsigned int speed) const;
|
||||
|
||||
private:
|
||||
// Extruders are sorted by their ID, so that binary search is possible.
|
||||
std::vector<Extruder> m_extruders;
|
||||
@ -79,7 +84,6 @@ private:
|
||||
// Limit for setting the acceleration, to respect the machine limits set for the Marlin firmware.
|
||||
// If set to zero, the limit is not in action.
|
||||
unsigned int m_max_acceleration;
|
||||
unsigned int m_last_fan_speed;
|
||||
unsigned int m_last_bed_temperature;
|
||||
bool m_last_bed_temperature_reached;
|
||||
double m_lifted;
|
||||
|
@ -132,7 +132,7 @@ $config->set('disable_fan_first_layers', [ 0 ]);
|
||||
'fan_below_layer_time' => [ $print_time2 + 1, $print_time2 + 1 ],
|
||||
'slowdown_below_layer_time' => [ $print_time2 + 2, $print_time2 + 2 ]
|
||||
});
|
||||
$buffer->gcodegen->set_extruders([ 0, 1 ]);
|
||||
$gcodegen->set_extruders([ 0, 1 ]);
|
||||
my $gcode = $buffer->process_layer($gcode1 . "T1\nG1 X0 E1 F3000\n", 0);
|
||||
like $gcode, qr/^M106/, 'fan is activated for the 1st tool';
|
||||
like $gcode, qr/.*M107/, 'fan is disabled for the 2nd tool';
|
||||
|
@ -10,7 +10,6 @@
|
||||
CoolingBuffer(GCode* gcode)
|
||||
%code{% RETVAL = new CoolingBuffer(*gcode); %};
|
||||
~CoolingBuffer();
|
||||
Ref<GCode> gcodegen();
|
||||
std::string process_layer(std::string gcode, size_t layer_id)
|
||||
%code{% RETVAL = THIS->process_layer(std::move(gcode), layer_id, true); %};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user