Changed handling of priming extrusions to allow injection of filament and toolchange custom gcodes

The priming extrusions were handled separately from the rest of the wipe tower toolchanges. In order to be able to use the logic from previous commit for them (custom toolchange gcodes etc), some unpleasant code shuffling was needed
This commit is contained in:
Lukas Matena 2019-06-14 12:28:24 +02:00
parent 41164a9cb3
commit aee376762e
9 changed files with 146 additions and 92 deletions

View file

@ -176,24 +176,29 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
float alpha = m_wipe_tower_rotation/180.f * float(M_PI);
WipeTower::xy start_pos = tcr.start_pos;
WipeTower::xy end_pos = tcr.end_pos;
start_pos.rotate(alpha);
start_pos.translate(m_wipe_tower_pos);
end_pos.rotate(alpha);
end_pos.translate(m_wipe_tower_pos);
std::string tcr_rotated_gcode = rotate_wipe_tower_moves(tcr.gcode, tcr.start_pos, m_wipe_tower_pos, alpha);
if (!tcr.priming) {
start_pos.rotate(alpha);
start_pos.translate(m_wipe_tower_pos);
end_pos.rotate(alpha);
end_pos.translate(m_wipe_tower_pos);
}
std::string tcr_rotated_gcode = tcr.priming ? tcr.gcode : rotate_wipe_tower_moves(tcr.gcode, tcr.start_pos, m_wipe_tower_pos, alpha);
// Disable linear advance for the wipe tower operations.
gcode += (gcodegen.config().gcode_flavor == gcfRepRap ? std::string("M572 D0 S0\n") : std::string("M900 K0\n"));
// Move over the wipe tower.
// Retract for a tool change, using the toolchange retract value and setting the priming extra length.
gcode += gcodegen.retract(true);
gcodegen.m_avoid_crossing_perimeters.use_external_mp_once = true;
gcode += gcodegen.travel_to(
wipe_tower_point_to_object_point(gcodegen, start_pos),
erMixed,
"Travel to a Wipe Tower");
gcode += gcodegen.unretract();
if (!tcr.priming) {
// Move over the wipe tower.
// Retract for a tool change, using the toolchange retract value and setting the priming extra length.
gcode += gcodegen.retract(true);
gcodegen.m_avoid_crossing_perimeters.use_external_mp_once = true;
gcode += gcodegen.travel_to(
wipe_tower_point_to_object_point(gcodegen, start_pos),
erMixed,
"Travel to a Wipe Tower");
gcode += gcodegen.unretract();
}
// Process the end filament gcode.
@ -211,11 +216,12 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
// Process the custom toolchange_gcode. If it is empty, provide a simple Tn command to change the filament.
// Otherwise, leave control to the user completely.
std::string toolchange_gcode_str;
if (gcodegen.writer().extruder() != nullptr) {
if (true /*gcodegen.writer().extruder() != nullptr*/) {
const std::string& toolchange_gcode = gcodegen.config().toolchange_gcode.value;
if (!toolchange_gcode.empty()) {
DynamicConfig config;
config.set_key_value("previous_extruder", new ConfigOptionInt((int)gcodegen.writer().extruder()->id()));
int previous_extruder_id = gcodegen.writer().extruder() ? (int)gcodegen.writer().extruder()->id() : -1;
config.set_key_value("previous_extruder", new ConfigOptionInt(previous_extruder_id));
config.set_key_value("next_extruder", new ConfigOptionInt((int)new_extruder_id));
config.set_key_value("layer_num", new ConfigOptionInt(gcodegen.m_layer_index));
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
@ -224,7 +230,7 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
}
std::string toolchange_command;
if (new_extruder_id >= 0 && gcodegen.writer().need_toolchange(new_extruder_id))
if (tcr.priming || (new_extruder_id >= 0 && gcodegen.writer().need_toolchange(new_extruder_id)))
toolchange_command = gcodegen.writer().toolchange(new_extruder_id);
if (toolchange_gcode.empty())
toolchange_gcode_str = toolchange_command;
@ -233,8 +239,6 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
}
}
gcodegen.placeholder_parser().set("current_extruder", new_extruder_id);
// Process the start filament gcode.
@ -334,27 +338,36 @@ std::string WipeTowerIntegration::prime(GCode &gcodegen)
assert(m_layer_idx == 0);
std::string gcode;
if (&m_priming != nullptr && ! m_priming.extrusions.empty()) {
if (&m_priming != nullptr) {
// Disable linear advance for the wipe tower operations.
gcode += (gcodegen.config().gcode_flavor == gcfRepRap ? std::string("M572 D0 S0\n") : std::string("M900 K0\n"));
// Let the tool change be executed by the wipe tower class.
// Inform the G-code writer about the changes done behind its back.
gcode += m_priming.gcode;
// Let the m_writer know the current extruder_id, but ignore the generated G-code.
unsigned int current_extruder_id = m_priming.extrusions.back().tool;
gcodegen.writer().toolchange(current_extruder_id);
gcodegen.placeholder_parser().set("current_extruder", current_extruder_id);
//gcode += (gcodegen.config().gcode_flavor == gcfRepRap ? std::string("M572 D0 S0\n") : std::string("M900 K0\n"));
for (const WipeTower::ToolChangeResult& tcr : m_priming) {
if (!tcr.extrusions.empty())
gcode += append_tcr(gcodegen, tcr, tcr.new_tool, tcr.print_z);
// Let the tool change be executed by the wipe tower class.
// Inform the G-code writer about the changes done behind its back.
//gcode += tcr.gcode;
// Let the m_writer know the current extruder_id, but ignore the generated G-code.
// unsigned int current_extruder_id = tcr.extrusions.back().tool;
// gcodegen.writer().toolchange(current_extruder_id);
// gcodegen.placeholder_parser().set("current_extruder", current_extruder_id);
}
// A phony move to the end position at the wipe tower.
gcodegen.writer().travel_to_xy(Vec2d(m_priming.end_pos.x, m_priming.end_pos.y));
gcodegen.set_last_pos(wipe_tower_point_to_object_point(gcodegen, m_priming.end_pos));
/* gcodegen.writer().travel_to_xy(Vec2d(m_priming.back().end_pos.x, m_priming.back().end_pos.y));
gcodegen.set_last_pos(wipe_tower_point_to_object_point(gcodegen, m_priming.back().end_pos));
// Prepare a future wipe.
gcodegen.m_wipe.path.points.clear();
// Start the wipe at the current position.
gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen, m_priming.end_pos));
gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen, m_priming.back().end_pos));
// Wipe end point: Wipe direction away from the closer tower edge to the further tower edge.
gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen,
WipeTower::xy((std::abs(m_left - m_priming.end_pos.x) < std::abs(m_right - m_priming.end_pos.x)) ? m_right : m_left,
m_priming.end_pos.y)));
gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen,
WipeTower::xy((std::abs(m_left - m_priming.back().end_pos.x) < std::abs(m_right - m_priming.back().end_pos.x)) ? m_right : m_left,
m_priming.back().end_pos.y)));*/
}
return gcode;
}

View file

@ -83,7 +83,7 @@ class WipeTowerIntegration {
public:
WipeTowerIntegration(
const PrintConfig &print_config,
const WipeTower::ToolChangeResult &priming,
const std::vector<WipeTower::ToolChangeResult> &priming,
const std::vector<std::vector<WipeTower::ToolChangeResult>> &tool_changes,
const WipeTower::ToolChangeResult &final_purge) :
m_left(/*float(print_config.wipe_tower_x.value)*/ 0.f),
@ -116,7 +116,7 @@ private:
const WipeTower::xy m_wipe_tower_pos;
const float m_wipe_tower_rotation;
// Reference to cached values at the Printer class.
const WipeTower::ToolChangeResult &m_priming;
const std::vector<WipeTower::ToolChangeResult> &m_priming;
const std::vector<std::vector<WipeTower::ToolChangeResult>> &m_tool_changes;
const WipeTower::ToolChangeResult &m_final_purge;
// Current layer index.

View file

@ -165,18 +165,19 @@ BoundingBoxf get_wipe_tower_priming_extrusions_extents(const Print &print)
{
BoundingBoxf bbox;
if (print.wipe_tower_data().priming != nullptr) {
const WipeTower::ToolChangeResult &tcr = *print.wipe_tower_data().priming;
for (size_t i = 1; i < tcr.extrusions.size(); ++ i) {
const WipeTower::Extrusion &e = tcr.extrusions[i];
if (e.width > 0) {
Vec2d p1((&e - 1)->pos.x, (&e - 1)->pos.y);
Vec2d p2(e.pos.x, e.pos.y);
bbox.merge(p1);
coordf_t radius = 0.5 * e.width;
bbox.min(0) = std::min(bbox.min(0), std::min(p1(0), p2(0)) - radius);
bbox.min(1) = std::min(bbox.min(1), std::min(p1(1), p2(1)) - radius);
bbox.max(0) = std::max(bbox.max(0), std::max(p1(0), p2(0)) + radius);
bbox.max(1) = std::max(bbox.max(1), std::max(p1(1), p2(1)) + radius);
for (const WipeTower::ToolChangeResult &tcr : *print.wipe_tower_data().priming) {
for (size_t i = 1; i < tcr.extrusions.size(); ++ i) {
const WipeTower::Extrusion &e = tcr.extrusions[i];
if (e.width > 0) {
Vec2d p1((&e - 1)->pos.x, (&e - 1)->pos.y);
Vec2d p2(e.pos.x, e.pos.y);
bbox.merge(p1);
coordf_t radius = 0.5 * e.width;
bbox.min(0) = std::min(bbox.min(0), std::min(p1(0), p2(0)) - radius);
bbox.min(1) = std::min(bbox.min(1), std::min(p1(1), p2(1)) - radius);
bbox.max(0) = std::max(bbox.max(0), std::max(p1(0), p2(0)) + radius);
bbox.max(1) = std::max(bbox.max(1), std::max(p1(1), p2(1)) + radius);
}
}
}
}

View file

@ -119,6 +119,12 @@ public:
// Is this a priming extrusion? (If so, the wipe tower rotation & translation will not be applied later)
bool priming;
// Initial tool
int initial_tool;
// New tool
int new_tool;
// Sum the total length of the extrusion.
float total_extrusion_length_in_plane() {
float e_length = 0.f;
@ -134,7 +140,7 @@ public:
};
// Returns gcode to prime the nozzles at the front edge of the print bed.
virtual ToolChangeResult prime(
virtual std::vector<ToolChangeResult> prime(
// print_z of the first layer.
float first_layer_height,
// Extruder indices, in the order to be primed. The last extruder will later print the wipe tower brim, print brim and the object.

View file

@ -515,7 +515,7 @@ std::string WipeTowerPrusaMM::to_string(material_type material)
}
// Returns gcode to prime the nozzles at the front edge of the print bed.
WipeTower::ToolChangeResult WipeTowerPrusaMM::prime(
std::vector<WipeTower::ToolChangeResult> WipeTowerPrusaMM::prime(
// print_z of the first layer.
float first_layer_height,
// Extruder indices, in the order to be primed. The last extruder will later print the wipe tower brim, print brim and the object.
@ -535,22 +535,34 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime(
const float prime_section_width = std::min(240.f / tools.size(), 60.f);
box_coordinates cleaning_box(xy(5.f, 0.01f + m_perimeter_width/2.f), prime_section_width, 100.f);
PrusaMultiMaterial::Writer writer(m_layer_height, m_perimeter_width, m_gcode_flavor, m_filpar);
writer.set_extrusion_flow(m_extrusion_flow)
.set_z(m_z_pos)
.set_initial_tool(m_current_tool)
.append(";--------------------\n"
"; CP PRIMING START\n")
.append(";--------------------\n");
writer.speed_override_backup();
writer.speed_override(100);
writer.set_initial_position(xy(0.f, 0.f)) // Always move to the starting position
.travel(cleaning_box.ld, 7200);
if (m_set_extruder_trimpot)
writer.set_extruder_trimpot(750); // Increase the extruder driver current to allow fast ramming.
std::vector<ToolChangeResult> results;
// Iterate over all priming toolchanges and push respective ToolChangeResults into results vector.
for (size_t idx_tool = 0; idx_tool < tools.size(); ++ idx_tool) {
int old_tool = m_current_tool;
PrusaMultiMaterial::Writer writer(m_layer_height, m_perimeter_width, m_gcode_flavor, m_filpar);
writer.set_extrusion_flow(m_extrusion_flow)
.set_z(m_z_pos)
.set_initial_tool(m_current_tool);
// This is the first toolchange - initiate priming
if (idx_tool == 0) {
writer.append(";--------------------\n"
"; CP PRIMING START\n")
.append(";--------------------\n")
.speed_override_backup()
.speed_override(100)
.set_initial_position(xy(0.f, 0.f)) // Always move to the starting position
.travel(cleaning_box.ld, 7200);
if (m_set_extruder_trimpot)
writer.set_extruder_trimpot(750); // Increase the extruder driver current to allow fast ramming.
}
else
writer.set_initial_position(results.back().end_pos);
unsigned int tool = tools[idx_tool];
m_left_to_right = true;
toolchange_Change(writer, tool, m_filpar[tool].material); // Select the tool, set a speed override for soluble and flex materials.
@ -569,39 +581,48 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime(
writer.travel(cleaning_box.ld, 7200);
}
++ m_num_tool_changes;
// Ask our writer about how much material was consumed:
if (m_current_tool < m_used_filament_length.size())
m_used_filament_length[m_current_tool] += writer.get_and_reset_used_filament_length();
ToolChangeResult result;
result.priming = true;
result.initial_tool = old_tool;
result.new_tool = m_current_tool;
result.print_z = this->m_z_pos;
result.layer_height = this->m_layer_height;
result.gcode = writer.gcode();
result.elapsed_time = writer.elapsed_time();
result.extrusions = writer.extrusions();
result.start_pos = writer.start_pos_rotated();
result.end_pos = writer.pos_rotated();
results.push_back(std::move(result));
// This is the last priming toolchange - finish priming
if (idx_tool+1 == tools.size()) {
// Reset the extruder current to a normal value.
if (m_set_extruder_trimpot)
writer.set_extruder_trimpot(550);
writer.speed_override_restore()
.feedrate(6000)
.flush_planner_queue()
.reset_extruder()
.append("; CP PRIMING END\n"
";------------------\n"
"\n\n");
}
}
m_old_temperature = -1; // If the priming is turned off in config, the temperature changing commands will not actually appear
// in the output gcode - we should not remember emitting them (we will output them twice in the worst case)
// Reset the extruder current to a normal value.
if (m_set_extruder_trimpot)
writer.set_extruder_trimpot(550);
writer.speed_override_restore();
writer.feedrate(6000)
.flush_planner_queue()
.reset_extruder()
.append("; CP PRIMING END\n"
";------------------\n"
"\n\n");
// so that tool_change() will know to extrude the wipe tower brim:
m_print_brim = true;
// Ask our writer about how much material was consumed:
if (m_current_tool < m_used_filament_length.size())
m_used_filament_length[m_current_tool] += writer.get_and_reset_used_filament_length();
ToolChangeResult result;
result.priming = true;
result.print_z = this->m_z_pos;
result.layer_height = this->m_layer_height;
result.gcode = writer.gcode();
result.elapsed_time = writer.elapsed_time();
result.extrusions = writer.extrusions();
result.start_pos = writer.start_pos_rotated();
result.end_pos = writer.pos_rotated();
return result;
return results;
}
WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, bool last_in_layer)
@ -609,6 +630,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo
if ( m_print_brim )
return toolchange_Brim();
int old_tool = m_current_tool;
float wipe_area = 0.f;
bool last_change_in_layer = false;
float wipe_volume = 0.f;
@ -697,6 +720,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo
ToolChangeResult result;
result.priming = false;
result.initial_tool = old_tool;
result.new_tool = m_current_tool;
result.print_z = this->m_z_pos;
result.layer_height = this->m_layer_height;
result.gcode = writer.gcode();
@ -709,6 +734,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo
WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(bool sideOnly, float y_offset)
{
int old_tool = m_current_tool;
const box_coordinates wipeTower_box(
WipeTower::xy(0.f, 0.f),
m_wipe_tower_width,
@ -751,6 +778,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(bool sideOnly, flo
ToolChangeResult result;
result.priming = false;
result.initial_tool = old_tool;
result.new_tool = m_current_tool;
result.print_z = this->m_z_pos;
result.layer_height = this->m_layer_height;
result.gcode = writer.gcode();
@ -1044,6 +1073,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer()
// Otherwise the caller would likely travel to the wipe tower in vain.
assert(! this->layer_finished());
int old_tool = m_current_tool;
PrusaMultiMaterial::Writer writer(m_layer_height, m_perimeter_width, m_gcode_flavor, m_filpar);
writer.set_extrusion_flow(m_extrusion_flow)
.set_z(m_z_pos)
@ -1125,6 +1156,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer()
ToolChangeResult result;
result.priming = false;
result.initial_tool = old_tool;
result.new_tool = m_current_tool;
result.print_z = this->m_z_pos;
result.layer_height = this->m_layer_height;
result.gcode = writer.gcode();

View file

@ -172,7 +172,7 @@ public:
virtual bool finished() const { return m_max_color_changes == 0; }
// Returns gcode to prime the nozzles at the front edge of the print bed.
virtual ToolChangeResult prime(
virtual std::vector<ToolChangeResult> prime(
// print_z of the first layer.
float first_layer_height,
// Extruder indices, in the order to be primed. The last extruder will later print the wipe tower brim, print brim and the object.

View file

@ -1824,7 +1824,7 @@ void Print::_make_wipe_tower()
m_config.filament_max_volumetric_speed.get_at(i),
m_config.nozzle_diameter.get_at(i));
m_wipe_tower_data.priming = Slic3r::make_unique<WipeTower::ToolChangeResult>(
m_wipe_tower_data.priming = Slic3r::make_unique<std::vector<WipeTower::ToolChangeResult>>(
wipe_tower.prime(this->skirt_first_layer_height(), m_wipe_tower_data.tool_ordering.all_extruders(), false));
// Lets go through the wipe tower layers and determine pairs of extruder changes for each

View file

@ -213,7 +213,7 @@ struct WipeTowerData
// Cache it here, so it does not need to be recalculated during the G-code generation.
ToolOrdering tool_ordering;
// Cache of tool changes per print layer.
std::unique_ptr<WipeTower::ToolChangeResult> priming;
std::unique_ptr<std::vector<WipeTower::ToolChangeResult>> priming;
std::vector<std::vector<WipeTower::ToolChangeResult>> tool_changes;
std::unique_ptr<WipeTower::ToolChangeResult> final_purge;
std::vector<float> used_filament;

View file

@ -4804,7 +4804,8 @@ void GLCanvas3D::_load_wipe_tower_toolpaths(const std::vector<std::string>& str_
ctxt.print = print;
ctxt.tool_colors = tool_colors.empty() ? nullptr : &tool_colors;
if (print->wipe_tower_data().priming && print->config().single_extruder_multi_material_priming)
ctxt.priming.emplace_back(*print->wipe_tower_data().priming.get());
for (int i=0; i<print->wipe_tower_data().priming.get()->size(); ++i)
ctxt.priming.emplace_back(print->wipe_tower_data().priming.get()->at(i));
if (print->wipe_tower_data().final_purge)
ctxt.final.emplace_back(*print->wipe_tower_data().final_purge.get());