mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-19 06:41:14 -06:00
semm
This commit is contained in:
parent
ee4705d6b7
commit
e624632969
142 changed files with 741 additions and 597 deletions
|
@ -22,6 +22,7 @@
|
|||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
|
@ -380,7 +381,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
|||
return Point(scale_(wipe_tower_pt.x() - gcodegen.origin()(0)), scale_(wipe_tower_pt.y() - gcodegen.origin()(1)));
|
||||
}
|
||||
|
||||
std::string WipeTowerIntegration::append_tcr(GCode& gcodegen, const WipeTower::ToolChangeResult& tcr, int new_extruder_id, double z) const
|
||||
std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id, double z) const
|
||||
{
|
||||
if (new_extruder_id != -1 && new_extruder_id != tcr.new_tool)
|
||||
throw Slic3r::InvalidArgument("Error: WipeTowerIntegration::append_tcr was asked to do a toolchange it didn't expect.");
|
||||
|
@ -391,20 +392,20 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
|||
// We want to rotate and shift all extrusions (gcode postprocessing) and starting and ending position
|
||||
float alpha = m_wipe_tower_rotation / 180.f * float(M_PI);
|
||||
|
||||
auto transform_wt_pt = [&alpha, this](const Vec2f& pt) -> Vec2f {
|
||||
auto transform_wt_pt = [&alpha, this](const Vec2f &pt) -> Vec2f {
|
||||
Vec2f out = Eigen::Rotation2Df(alpha) * pt;
|
||||
out += m_wipe_tower_pos;
|
||||
return out;
|
||||
};
|
||||
|
||||
Vec2f start_pos = tcr.start_pos;
|
||||
Vec2f end_pos = tcr.end_pos;
|
||||
if (! tcr.priming) {
|
||||
Vec2f end_pos = tcr.end_pos;
|
||||
if (!tcr.priming) {
|
||||
start_pos = transform_wt_pt(start_pos);
|
||||
end_pos = transform_wt_pt(end_pos);
|
||||
end_pos = transform_wt_pt(end_pos);
|
||||
}
|
||||
|
||||
Vec2f wipe_tower_offset = tcr.priming ? Vec2f::Zero() : m_wipe_tower_pos;
|
||||
Vec2f wipe_tower_offset = tcr.priming ? Vec2f::Zero() : m_wipe_tower_pos;
|
||||
float wipe_tower_rotation = tcr.priming ? 0.f : alpha;
|
||||
|
||||
std::string tcr_rotated_gcode = post_process_wipe_tower_moves(tcr, wipe_tower_offset, wipe_tower_rotation);
|
||||
|
@ -415,42 +416,39 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
|||
// BBS: toolchange gcode will move to start_pos,
|
||||
// so only perform movement when printing sparse partition to support upper layer.
|
||||
// start_pos is the position in plate coordinate.
|
||||
if (! tcr.priming && tcr.is_finish_first) {
|
||||
if (!tcr.priming && tcr.is_finish_first) {
|
||||
// Move over the wipe tower.
|
||||
gcode += gcodegen.retract();
|
||||
gcodegen.m_avoid_crossing_perimeters.use_external_mp_once();
|
||||
gcode += gcodegen.travel_to(
|
||||
wipe_tower_point_to_object_point(gcodegen, start_pos + plate_origin_2d),
|
||||
erMixed,
|
||||
"Travel to a Wipe Tower");
|
||||
gcode += gcodegen.travel_to(wipe_tower_point_to_object_point(gcodegen, start_pos + plate_origin_2d), erMixed,
|
||||
"Travel to a Wipe Tower");
|
||||
gcode += gcodegen.unretract();
|
||||
}
|
||||
|
||||
//BBS: if needed, write the gcode_label_objects_end then priming tower, if the retract, didn't did it.
|
||||
// BBS: if needed, write the gcode_label_objects_end then priming tower, if the retract, didn't did it.
|
||||
gcodegen.m_writer.add_object_end_labels(gcode);
|
||||
|
||||
double current_z = gcodegen.writer().get_position().z();
|
||||
if (z == -1.) // in case no specific z was provided, print at current_z pos
|
||||
z = current_z;
|
||||
if (! is_approx(z, current_z)) {
|
||||
if (!is_approx(z, current_z)) {
|
||||
gcode += gcodegen.writer().retract();
|
||||
gcode += gcodegen.writer().travel_to_z(z, "Travel down to the last wipe tower layer.");
|
||||
gcode += gcodegen.writer().unretract();
|
||||
}
|
||||
|
||||
|
||||
// Process the end filament gcode.
|
||||
std::string end_filament_gcode_str;
|
||||
if (gcodegen.writer().extruder() != nullptr) {
|
||||
// Process the custom filament_end_gcode in case of single_extruder_multi_material.
|
||||
unsigned int old_extruder_id = gcodegen.writer().extruder()->id();
|
||||
const std::string& filament_end_gcode = gcodegen.config().filament_end_gcode.get_at(old_extruder_id);
|
||||
unsigned int old_extruder_id = gcodegen.writer().extruder()->id();
|
||||
const std::string &filament_end_gcode = gcodegen.config().filament_end_gcode.get_at(old_extruder_id);
|
||||
if (gcodegen.writer().extruder() != nullptr && !filament_end_gcode.empty()) {
|
||||
end_filament_gcode_str = gcodegen.placeholder_parser_process("filament_end_gcode", filament_end_gcode, old_extruder_id);
|
||||
check_add_eol(end_filament_gcode_str);
|
||||
}
|
||||
}
|
||||
//BBS: increase toolchange count
|
||||
// BBS: increase toolchange count
|
||||
gcodegen.m_toolchange_count++;
|
||||
|
||||
// BBS: should be placed before toolchange parsing
|
||||
|
@ -459,45 +457,57 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
|||
|
||||
// Process the custom change_filament_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;
|
||||
const std::string& change_filament_gcode = gcodegen.config().change_filament_gcode.value;
|
||||
// m_max_layer_z = std::max(m_max_layer_z, tcr.print_z);
|
||||
if (! change_filament_gcode.empty()) {
|
||||
std::string toolchange_gcode_str;
|
||||
const std::string &change_filament_gcode = gcodegen.config().change_filament_gcode.value;
|
||||
// m_max_layer_z = std::max(m_max_layer_z, tcr.print_z);
|
||||
if (!change_filament_gcode.empty()) {
|
||||
DynamicConfig config;
|
||||
int previous_extruder_id = gcodegen.writer().extruder() ? (int)gcodegen.writer().extruder()->id() : -1;
|
||||
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("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(tcr.print_z));
|
||||
config.set_key_value("toolchange_z", new ConfigOptionFloat(z));
|
||||
// config.set_key_value("max_layer_z", new ConfigOptionFloat(m_max_layer_z));
|
||||
// config.set_key_value("max_layer_z", new ConfigOptionFloat(m_max_layer_z));
|
||||
// BBS
|
||||
{
|
||||
GCodeWriter& gcode_writer = gcodegen.m_writer;
|
||||
FullPrintConfig& full_config = gcodegen.m_config;
|
||||
float old_retract_length = gcode_writer.extruder() != nullptr ? full_config.retraction_length.get_at(previous_extruder_id) : 0;
|
||||
GCodeWriter &gcode_writer = gcodegen.m_writer;
|
||||
FullPrintConfig &full_config = gcodegen.m_config;
|
||||
float old_retract_length = gcode_writer.extruder() != nullptr ? full_config.retraction_length.get_at(previous_extruder_id) :
|
||||
0;
|
||||
float new_retract_length = full_config.retraction_length.get_at(new_extruder_id);
|
||||
float old_retract_length_toolchange = gcode_writer.extruder() != nullptr ? full_config.retract_length_toolchange.get_at(previous_extruder_id) : 0;
|
||||
float old_retract_length_toolchange = gcode_writer.extruder() != nullptr ?
|
||||
full_config.retract_length_toolchange.get_at(previous_extruder_id) :
|
||||
0;
|
||||
float new_retract_length_toolchange = full_config.retract_length_toolchange.get_at(new_extruder_id);
|
||||
int old_filament_temp = gcode_writer.extruder() != nullptr ? (gcodegen.on_first_layer()? full_config.nozzle_temperature_initial_layer.get_at(previous_extruder_id) : full_config.nozzle_temperature.get_at(previous_extruder_id)) : 210;
|
||||
int new_filament_temp = gcodegen.on_first_layer() ? full_config.nozzle_temperature_initial_layer.get_at(new_extruder_id) : full_config.nozzle_temperature.get_at(new_extruder_id);
|
||||
Vec3d nozzle_pos = gcode_writer.get_position();
|
||||
int old_filament_temp = gcode_writer.extruder() != nullptr ?
|
||||
(gcodegen.on_first_layer() ?
|
||||
full_config.nozzle_temperature_initial_layer.get_at(previous_extruder_id) :
|
||||
full_config.nozzle_temperature.get_at(previous_extruder_id)) :
|
||||
210;
|
||||
int new_filament_temp = gcodegen.on_first_layer() ? full_config.nozzle_temperature_initial_layer.get_at(new_extruder_id) :
|
||||
full_config.nozzle_temperature.get_at(new_extruder_id);
|
||||
Vec3d nozzle_pos = gcode_writer.get_position();
|
||||
|
||||
float purge_volume = tcr.purge_volume < EPSILON ? 0 : std::max(tcr.purge_volume, g_min_purge_volume);
|
||||
float purge_volume = tcr.purge_volume < EPSILON ? 0 : std::max(tcr.purge_volume, g_min_purge_volume);
|
||||
float filament_area = float((M_PI / 4.f) * pow(full_config.filament_diameter.get_at(new_extruder_id), 2));
|
||||
float purge_length = purge_volume / filament_area;
|
||||
float purge_length = purge_volume / filament_area;
|
||||
|
||||
int old_filament_e_feedrate = gcode_writer.extruder() != nullptr ? (int)(60.0 * full_config.filament_max_volumetric_speed.get_at(previous_extruder_id) / filament_area) : 200;
|
||||
old_filament_e_feedrate = old_filament_e_feedrate == 0 ? 100 : old_filament_e_feedrate;
|
||||
int new_filament_e_feedrate = (int)(60.0 * full_config.filament_max_volumetric_speed.get_at(new_extruder_id) / filament_area);
|
||||
new_filament_e_feedrate = new_filament_e_feedrate == 0 ? 100 : new_filament_e_feedrate;
|
||||
int old_filament_e_feedrate = gcode_writer.extruder() != nullptr ?
|
||||
(int) (60.0 * full_config.filament_max_volumetric_speed.get_at(previous_extruder_id) /
|
||||
filament_area) :
|
||||
200;
|
||||
old_filament_e_feedrate = old_filament_e_feedrate == 0 ? 100 : old_filament_e_feedrate;
|
||||
int new_filament_e_feedrate = (int) (60.0 * full_config.filament_max_volumetric_speed.get_at(new_extruder_id) /
|
||||
filament_area);
|
||||
new_filament_e_feedrate = new_filament_e_feedrate == 0 ? 100 : new_filament_e_feedrate;
|
||||
|
||||
config.set_key_value("max_layer_z", new ConfigOptionFloat(gcodegen.m_max_layer_z));
|
||||
config.set_key_value("relative_e_axis", new ConfigOptionBool(full_config.use_relative_e_distances));
|
||||
config.set_key_value("toolchange_count", new ConfigOptionInt((int)gcodegen.m_toolchange_count));
|
||||
//BBS: fan speed is useless placeholer now, but we don't remove it to avoid
|
||||
//slicing error in old change_filament_gcode in old 3MF
|
||||
config.set_key_value("fan_speed", new ConfigOptionInt((int)0));
|
||||
config.set_key_value("toolchange_count", new ConfigOptionInt((int) gcodegen.m_toolchange_count));
|
||||
// BBS: fan speed is useless placeholer now, but we don't remove it to avoid
|
||||
// slicing error in old change_filament_gcode in old 3MF
|
||||
config.set_key_value("fan_speed", new ConfigOptionInt((int) 0));
|
||||
config.set_key_value("old_retract_length", new ConfigOptionFloat(old_retract_length));
|
||||
config.set_key_value("new_retract_length", new ConfigOptionFloat(new_retract_length));
|
||||
config.set_key_value("old_retract_length_toolchange", new ConfigOptionFloat(old_retract_length_toolchange));
|
||||
|
@ -518,44 +528,46 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
|||
config.set_key_value("travel_point_3_x", new ConfigOptionFloat(float(travel_point_3.x())));
|
||||
config.set_key_value("travel_point_3_y", new ConfigOptionFloat(float(travel_point_3.y())));
|
||||
|
||||
int flush_count = std::min(g_max_flush_count, (int)std::round(purge_volume / g_purge_volume_one_time));
|
||||
float flush_unit = purge_length / flush_count;
|
||||
int flush_idx = 0;
|
||||
int flush_count = std::min(g_max_flush_count, (int) std::round(purge_volume / g_purge_volume_one_time));
|
||||
float flush_unit = purge_length / flush_count;
|
||||
int flush_idx = 0;
|
||||
for (; flush_idx < flush_count; flush_idx++) {
|
||||
char key_value[64] = { 0 };
|
||||
char key_value[64] = {0};
|
||||
snprintf(key_value, sizeof(key_value), "flush_length_%d", flush_idx + 1);
|
||||
config.set_key_value(key_value, new ConfigOptionFloat(flush_unit));
|
||||
}
|
||||
|
||||
for (; flush_idx < g_max_flush_count; flush_idx++) {
|
||||
char key_value[64] = { 0 };
|
||||
char key_value[64] = {0};
|
||||
snprintf(key_value, sizeof(key_value), "flush_length_%d", flush_idx + 1);
|
||||
config.set_key_value(key_value, new ConfigOptionFloat(0.f));
|
||||
}
|
||||
}
|
||||
toolchange_gcode_str = gcodegen.placeholder_parser_process("change_filament_gcode", change_filament_gcode, new_extruder_id, &config);
|
||||
toolchange_gcode_str = gcodegen.placeholder_parser_process("change_filament_gcode", change_filament_gcode, new_extruder_id,
|
||||
&config);
|
||||
check_add_eol(toolchange_gcode_str);
|
||||
|
||||
// retract before toolchange
|
||||
toolchange_gcode_str = toolchange_retract_str + toolchange_gcode_str;
|
||||
//BBS
|
||||
// BBS
|
||||
{
|
||||
//BBS: current position and fan_speed is unclear after interting change_filament_gcode
|
||||
// BBS: current position and fan_speed is unclear after interting change_filament_gcode
|
||||
check_add_eol(toolchange_gcode_str);
|
||||
toolchange_gcode_str += ";_FORCE_RESUME_FAN_SPEED\n";
|
||||
gcodegen.writer().set_current_position_clear(false);
|
||||
//BBS: check whether custom gcode changes the z position. Update if changed
|
||||
// BBS: check whether custom gcode changes the z position. Update if changed
|
||||
double temp_z_after_tool_change;
|
||||
if (GCodeProcessor::get_last_z_from_gcode(toolchange_gcode_str, temp_z_after_tool_change)) {
|
||||
Vec3d pos = gcodegen.writer().get_position();
|
||||
pos(2) = temp_z_after_tool_change;
|
||||
pos(2) = temp_z_after_tool_change;
|
||||
gcodegen.writer().set_position(pos);
|
||||
}
|
||||
}
|
||||
|
||||
// move to start_pos for wiping after toolchange
|
||||
std::string start_pos_str;
|
||||
start_pos_str = gcodegen.travel_to(wipe_tower_point_to_object_point(gcodegen, start_pos + plate_origin_2d), erMixed, "Move to start pos");
|
||||
start_pos_str = gcodegen.travel_to(wipe_tower_point_to_object_point(gcodegen, start_pos + plate_origin_2d), erMixed,
|
||||
"Move to start pos");
|
||||
check_add_eol(start_pos_str);
|
||||
toolchange_gcode_str += start_pos_str;
|
||||
|
||||
|
@ -576,13 +588,14 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
|||
gcodegen.placeholder_parser().set("current_extruder", new_extruder_id);
|
||||
|
||||
// Process the start filament gcode.
|
||||
std::string start_filament_gcode_str;
|
||||
const std::string& filament_start_gcode = gcodegen.config().filament_start_gcode.get_at(new_extruder_id);
|
||||
std::string start_filament_gcode_str;
|
||||
const std::string &filament_start_gcode = gcodegen.config().filament_start_gcode.get_at(new_extruder_id);
|
||||
if (!filament_start_gcode.empty()) {
|
||||
// Process the filament_start_gcode for the active filament only.
|
||||
DynamicConfig config;
|
||||
config.set_key_value("filament_extruder_id", new ConfigOptionInt(new_extruder_id));
|
||||
start_filament_gcode_str = gcodegen.placeholder_parser_process("filament_start_gcode", filament_start_gcode, new_extruder_id, &config);
|
||||
start_filament_gcode_str = gcodegen.placeholder_parser_process("filament_start_gcode", filament_start_gcode, new_extruder_id,
|
||||
&config);
|
||||
check_add_eol(start_filament_gcode_str);
|
||||
}
|
||||
|
||||
|
@ -591,12 +604,13 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
|||
config.set_key_value("filament_end_gcode", new ConfigOptionString(end_filament_gcode_str));
|
||||
config.set_key_value("change_filament_gcode", new ConfigOptionString(toolchange_gcode_str));
|
||||
config.set_key_value("filament_start_gcode", new ConfigOptionString(start_filament_gcode_str));
|
||||
std::string tcr_gcode, tcr_escaped_gcode = gcodegen.placeholder_parser_process("tcr_rotated_gcode", tcr_rotated_gcode, new_extruder_id, &config);
|
||||
std::string tcr_gcode,
|
||||
tcr_escaped_gcode = gcodegen.placeholder_parser_process("tcr_rotated_gcode", tcr_rotated_gcode, new_extruder_id, &config);
|
||||
unescape_string_cstyle(tcr_escaped_gcode, tcr_gcode);
|
||||
gcode += tcr_gcode;
|
||||
check_add_eol(toolchange_gcode_str);
|
||||
|
||||
//SoftFever: set new PA for new filament
|
||||
// SoftFever: set new PA for new filament
|
||||
if (gcodegen.config().enable_pressure_advance.get_at(new_extruder_id)) {
|
||||
gcode += gcodegen.writer().set_pressure_advance(gcodegen.config().pressure_advance.get_at(new_extruder_id));
|
||||
}
|
||||
|
@ -613,7 +627,193 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
|||
else {
|
||||
// Prepare a future wipe.
|
||||
gcodegen.m_wipe.reset_path();
|
||||
for (const Vec2f& wipe_pt : tcr.wipe_path)
|
||||
for (const Vec2f &wipe_pt : tcr.wipe_path)
|
||||
gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen, transform_wt_pt(wipe_pt)));
|
||||
}
|
||||
|
||||
// Let the planner know we are traveling between objects.
|
||||
gcodegen.m_avoid_crossing_perimeters.use_external_mp_once();
|
||||
return gcode;
|
||||
}
|
||||
|
||||
std::string WipeTowerIntegration::append_tcr2(GCode &gcodegen,
|
||||
const WipeTower::ToolChangeResult &tcr,
|
||||
int new_extruder_id,
|
||||
double z) const
|
||||
{
|
||||
if (new_extruder_id != -1 && new_extruder_id != tcr.new_tool)
|
||||
throw Slic3r::InvalidArgument("Error: WipeTowerIntegration::append_tcr was asked to do a toolchange it didn't expect.");
|
||||
|
||||
std::string gcode;
|
||||
|
||||
// Toolchangeresult.gcode assumes the wipe tower corner is at the origin (except for priming lines)
|
||||
// We want to rotate and shift all extrusions (gcode postprocessing) and starting and ending position
|
||||
float alpha = m_wipe_tower_rotation / 180.f * float(M_PI);
|
||||
|
||||
auto transform_wt_pt = [&alpha, this](const Vec2f &pt) -> Vec2f {
|
||||
Vec2f out = Eigen::Rotation2Df(alpha) * pt;
|
||||
out += m_wipe_tower_pos;
|
||||
return out;
|
||||
};
|
||||
|
||||
Vec2f start_pos = tcr.start_pos;
|
||||
Vec2f end_pos = tcr.end_pos;
|
||||
if (!tcr.priming) {
|
||||
start_pos = transform_wt_pt(start_pos);
|
||||
end_pos = transform_wt_pt(end_pos);
|
||||
}
|
||||
|
||||
Vec2f wipe_tower_offset = tcr.priming ? Vec2f::Zero() : m_wipe_tower_pos;
|
||||
float wipe_tower_rotation = tcr.priming ? 0.f : alpha;
|
||||
|
||||
std::string tcr_rotated_gcode = post_process_wipe_tower_moves(tcr, wipe_tower_offset, wipe_tower_rotation);
|
||||
|
||||
gcode += gcodegen.writer().unlift(); // Make sure there is no z-hop (in most cases, there isn't).
|
||||
|
||||
double current_z = gcodegen.writer().get_position().z();
|
||||
if (z == -1.) // in case no specific z was provided, print at current_z pos
|
||||
z = current_z;
|
||||
|
||||
const bool needs_toolchange = gcodegen.writer().need_toolchange(new_extruder_id);
|
||||
const bool will_go_down = !is_approx(z, current_z);
|
||||
const bool is_ramming = (gcodegen.config().single_extruder_multi_material) ||
|
||||
(!gcodegen.config().single_extruder_multi_material &&
|
||||
gcodegen.config().filament_multitool_ramming.get_at(tcr.initial_tool));
|
||||
const bool should_travel_to_tower = !tcr.priming && (tcr.force_travel // wipe tower says so
|
||||
|| !needs_toolchange // this is just finishing the tower with no toolchange
|
||||
|| is_ramming);
|
||||
|
||||
if (should_travel_to_tower) {
|
||||
// FIXME: It would be better if the wipe tower set the force_travel flag for all toolchanges,
|
||||
// then we could simplify the condition and make it more readable.
|
||||
gcode += gcodegen.retract();
|
||||
gcodegen.m_avoid_crossing_perimeters.use_external_mp_once();
|
||||
gcode += gcodegen.travel_to(wipe_tower_point_to_object_point(gcodegen, start_pos), erMixed, "Travel to a Wipe Tower");
|
||||
gcode += gcodegen.unretract();
|
||||
} else {
|
||||
// When this is multiextruder printer without any ramming, we can just change
|
||||
// the tool without travelling to the tower.
|
||||
}
|
||||
|
||||
if (will_go_down) {
|
||||
gcode += gcodegen.writer().retract();
|
||||
gcode += gcodegen.writer().travel_to_z(z, "Travel down to the last wipe tower layer.");
|
||||
gcode += gcodegen.writer().unretract();
|
||||
}
|
||||
|
||||
std::string toolchange_gcode_str;
|
||||
std::string deretraction_str;
|
||||
if (tcr.priming || (new_extruder_id >= 0 && needs_toolchange)) {
|
||||
if (is_ramming)
|
||||
gcodegen.m_wipe.reset_path(); // We don't want wiping on the ramming lines.
|
||||
toolchange_gcode_str = gcodegen.set_extruder(new_extruder_id, tcr.print_z); // TODO: toolchange_z vs print_z
|
||||
if (gcodegen.config().has_prime_tower)
|
||||
deretraction_str = gcodegen.unretract();
|
||||
}
|
||||
|
||||
// Insert the toolchange and deretraction gcode into the generated gcode.
|
||||
|
||||
DynamicConfig config;
|
||||
config.set_key_value("change_filament_gcode", new ConfigOptionString(toolchange_gcode_str));
|
||||
config.set_key_value("deretraction_from_wipe_tower_generator", new ConfigOptionString(deretraction_str));
|
||||
|
||||
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(tcr.print_z));
|
||||
config.set_key_value("toolchange_z", new ConfigOptionFloat(z));
|
||||
GCodeWriter &gcode_writer = gcodegen.m_writer;
|
||||
FullPrintConfig &full_config = gcodegen.m_config;
|
||||
float old_retract_length = gcode_writer.extruder() != nullptr ? full_config.retraction_length.get_at(previous_extruder_id) : 0;
|
||||
float new_retract_length = full_config.retraction_length.get_at(new_extruder_id);
|
||||
float old_retract_length_toolchange = gcode_writer.extruder() != nullptr ?
|
||||
full_config.retract_length_toolchange.get_at(previous_extruder_id) :
|
||||
0;
|
||||
float new_retract_length_toolchange = full_config.retract_length_toolchange.get_at(new_extruder_id);
|
||||
int old_filament_temp = gcode_writer.extruder() != nullptr ?
|
||||
(gcodegen.on_first_layer() ? full_config.nozzle_temperature_initial_layer.get_at(previous_extruder_id) :
|
||||
full_config.nozzle_temperature.get_at(previous_extruder_id)) :
|
||||
210;
|
||||
int new_filament_temp = gcodegen.on_first_layer() ? full_config.nozzle_temperature_initial_layer.get_at(new_extruder_id) :
|
||||
full_config.nozzle_temperature.get_at(new_extruder_id);
|
||||
Vec3d nozzle_pos = gcode_writer.get_position();
|
||||
|
||||
float purge_volume = tcr.purge_volume < EPSILON ? 0 : std::max(tcr.purge_volume, g_min_purge_volume);
|
||||
float filament_area = float((M_PI / 4.f) * pow(full_config.filament_diameter.get_at(new_extruder_id), 2));
|
||||
float purge_length = purge_volume / filament_area;
|
||||
|
||||
int old_filament_e_feedrate = gcode_writer.extruder() != nullptr ?
|
||||
(int) (60.0 * full_config.filament_max_volumetric_speed.get_at(previous_extruder_id) /
|
||||
filament_area) :
|
||||
200;
|
||||
old_filament_e_feedrate = old_filament_e_feedrate == 0 ? 100 : old_filament_e_feedrate;
|
||||
int new_filament_e_feedrate = (int) (60.0 * full_config.filament_max_volumetric_speed.get_at(new_extruder_id) / filament_area);
|
||||
new_filament_e_feedrate = new_filament_e_feedrate == 0 ? 100 : new_filament_e_feedrate;
|
||||
|
||||
config.set_key_value("max_layer_z", new ConfigOptionFloat(gcodegen.m_max_layer_z));
|
||||
config.set_key_value("relative_e_axis", new ConfigOptionBool(full_config.use_relative_e_distances));
|
||||
config.set_key_value("toolchange_count", new ConfigOptionInt((int) gcodegen.m_toolchange_count));
|
||||
config.set_key_value("fan_speed", new ConfigOptionInt((int) 0));
|
||||
config.set_key_value("old_retract_length", new ConfigOptionFloat(old_retract_length));
|
||||
config.set_key_value("new_retract_length", new ConfigOptionFloat(new_retract_length));
|
||||
config.set_key_value("old_retract_length_toolchange", new ConfigOptionFloat(old_retract_length_toolchange));
|
||||
config.set_key_value("new_retract_length_toolchange", new ConfigOptionFloat(new_retract_length_toolchange));
|
||||
config.set_key_value("old_filament_temp", new ConfigOptionInt(old_filament_temp));
|
||||
config.set_key_value("new_filament_temp", new ConfigOptionInt(new_filament_temp));
|
||||
config.set_key_value("x_after_toolchange", new ConfigOptionFloat(start_pos(0)));
|
||||
config.set_key_value("y_after_toolchange", new ConfigOptionFloat(start_pos(1)));
|
||||
config.set_key_value("z_after_toolchange", new ConfigOptionFloat(nozzle_pos(2)));
|
||||
config.set_key_value("first_flush_volume", new ConfigOptionFloat(purge_length / 2.f));
|
||||
config.set_key_value("second_flush_volume", new ConfigOptionFloat(purge_length / 2.f));
|
||||
config.set_key_value("old_filament_e_feedrate", new ConfigOptionInt(old_filament_e_feedrate));
|
||||
config.set_key_value("new_filament_e_feedrate", new ConfigOptionInt(new_filament_e_feedrate));
|
||||
config.set_key_value("travel_point_1_x", new ConfigOptionFloat(float(travel_point_1.x())));
|
||||
config.set_key_value("travel_point_1_y", new ConfigOptionFloat(float(travel_point_1.y())));
|
||||
config.set_key_value("travel_point_2_x", new ConfigOptionFloat(float(travel_point_2.x())));
|
||||
config.set_key_value("travel_point_2_y", new ConfigOptionFloat(float(travel_point_2.y())));
|
||||
config.set_key_value("travel_point_3_x", new ConfigOptionFloat(float(travel_point_3.x())));
|
||||
config.set_key_value("travel_point_3_y", new ConfigOptionFloat(float(travel_point_3.y())));
|
||||
|
||||
int flush_count = std::min(g_max_flush_count, (int) std::round(purge_volume / g_purge_volume_one_time));
|
||||
float flush_unit = purge_length / flush_count;
|
||||
int flush_idx = 0;
|
||||
for (; flush_idx < flush_count; flush_idx++) {
|
||||
char key_value[64] = {0};
|
||||
snprintf(key_value, sizeof(key_value), "flush_length_%d", flush_idx + 1);
|
||||
config.set_key_value(key_value, new ConfigOptionFloat(flush_unit));
|
||||
}
|
||||
|
||||
for (; flush_idx < g_max_flush_count; flush_idx++) {
|
||||
char key_value[64] = {0};
|
||||
snprintf(key_value, sizeof(key_value), "flush_length_%d", flush_idx + 1);
|
||||
config.set_key_value(key_value, new ConfigOptionFloat(0.f));
|
||||
}
|
||||
|
||||
std::string tcr_gcode,
|
||||
tcr_escaped_gcode = gcodegen.placeholder_parser_process("tcr_rotated_gcode", tcr_rotated_gcode, new_extruder_id, &config);
|
||||
unescape_string_cstyle(tcr_escaped_gcode, tcr_gcode);
|
||||
gcode += tcr_gcode;
|
||||
check_add_eol(toolchange_gcode_str);
|
||||
|
||||
// SoftFever: set new PA for new filament
|
||||
if (gcodegen.config().enable_pressure_advance.get_at(new_extruder_id)) {
|
||||
gcode += gcodegen.writer().set_pressure_advance(gcodegen.config().pressure_advance.get_at(new_extruder_id));
|
||||
}
|
||||
|
||||
// A phony move to the end position at the wipe tower.
|
||||
gcodegen.writer().travel_to_xy(end_pos.cast<double>());
|
||||
gcodegen.set_last_pos(wipe_tower_point_to_object_point(gcodegen, end_pos));
|
||||
if (!is_approx(z, current_z)) {
|
||||
gcode += gcodegen.writer().retract();
|
||||
gcode += gcodegen.writer().travel_to_z(current_z, "Travel back up to the topmost object layer.");
|
||||
gcode += gcodegen.writer().unretract();
|
||||
}
|
||||
|
||||
else {
|
||||
// Prepare a future wipe.
|
||||
gcodegen.m_wipe.reset_path();
|
||||
for (const Vec2f &wipe_pt : tcr.wipe_path)
|
||||
gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen, transform_wt_pt(wipe_pt)));
|
||||
}
|
||||
|
||||
|
@ -703,49 +903,77 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
|||
return gcode_out;
|
||||
}
|
||||
|
||||
|
||||
std::string WipeTowerIntegration::prime(GCode& gcodegen)
|
||||
std::string WipeTowerIntegration::prime(GCode &gcodegen)
|
||||
{
|
||||
std::string gcode;
|
||||
// if (!gcodegen.is_BBL_Printer()) {
|
||||
// for (const WipeTower::ToolChangeResult &tcr : m_priming) {
|
||||
// if (!tcr.extrusions.empty())
|
||||
// gcode += append_tcr(gcodegen, tcr, tcr.new_tool);
|
||||
// }
|
||||
// }
|
||||
if (!gcodegen.is_BBL_Printer()) {
|
||||
for (const WipeTower::ToolChangeResult &tcr : m_priming) {
|
||||
if (!tcr.extrusions.empty())
|
||||
gcode += append_tcr(gcodegen, tcr, tcr.new_tool);
|
||||
}
|
||||
}
|
||||
return gcode;
|
||||
}
|
||||
|
||||
std::string WipeTowerIntegration::tool_change(GCode& gcodegen, int extruder_id, bool finish_layer)
|
||||
std::string WipeTowerIntegration::tool_change(GCode &gcodegen, int extruder_id, bool finish_layer)
|
||||
{
|
||||
std::string gcode;
|
||||
|
||||
assert(m_layer_idx >= 0);
|
||||
if (m_layer_idx >= (int) m_tool_changes.size()) return gcode;
|
||||
if (m_layer_idx >= (int) m_tool_changes.size())
|
||||
return gcode;
|
||||
if (gcodegen.config().purge_in_prime_tower) {
|
||||
if (gcodegen.writer().need_toolchange(extruder_id) || finish_layer) {
|
||||
if (m_layer_idx < (int) m_tool_changes.size()) {
|
||||
if (!(size_t(m_tool_change_idx) < m_tool_changes[m_layer_idx].size()))
|
||||
throw Slic3r::RuntimeError("Wipe tower generation failed, possibly due to empty first layer.");
|
||||
|
||||
// Calculate where the wipe tower layer will be printed. -1 means that print z will not change,
|
||||
// resulting in a wipe tower with sparse layers.
|
||||
double wipe_tower_z = -1;
|
||||
bool ignore_sparse = false;
|
||||
if (gcodegen.config().wipe_tower_no_sparse_layers.value) {
|
||||
wipe_tower_z = m_last_wipe_tower_print_z;
|
||||
ignore_sparse = (m_tool_changes[m_layer_idx].size() == 1 && m_tool_changes[m_layer_idx].front().initial_tool == m_tool_changes[m_layer_idx].front().new_tool);
|
||||
if (m_tool_change_idx == 0 && !ignore_sparse)
|
||||
wipe_tower_z = m_last_wipe_tower_print_z + m_tool_changes[m_layer_idx].front().layer_height;
|
||||
}
|
||||
// Calculate where the wipe tower layer will be printed. -1 means that print z will not change,
|
||||
// resulting in a wipe tower with sparse layers.
|
||||
double wipe_tower_z = -1;
|
||||
bool ignore_sparse = false;
|
||||
if (gcodegen.config().wipe_tower_no_sparse_layers.value) {
|
||||
wipe_tower_z = m_last_wipe_tower_print_z;
|
||||
ignore_sparse = (m_tool_changes[m_layer_idx].size() == 1 &&
|
||||
m_tool_changes[m_layer_idx].front().initial_tool == m_tool_changes[m_layer_idx].front().new_tool &&
|
||||
m_layer_idx != 0);
|
||||
if (m_tool_change_idx == 0 && !ignore_sparse)
|
||||
wipe_tower_z = m_last_wipe_tower_print_z + m_tool_changes[m_layer_idx].front().layer_height;
|
||||
}
|
||||
|
||||
if (m_enable_timelapse_print && m_is_first_print) {
|
||||
gcode += append_tcr(gcodegen, m_tool_changes[m_layer_idx][0], m_tool_changes[m_layer_idx][0].new_tool, wipe_tower_z);
|
||||
m_tool_change_idx++;
|
||||
m_is_first_print = false;
|
||||
}
|
||||
if (!ignore_sparse) {
|
||||
gcode += append_tcr2(gcodegen, m_tool_changes[m_layer_idx][m_tool_change_idx++], extruder_id, wipe_tower_z);
|
||||
m_last_wipe_tower_print_z = wipe_tower_z;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Calculate where the wipe tower layer will be printed. -1 means that print z will not change,
|
||||
// resulting in a wipe tower with sparse layers.
|
||||
double wipe_tower_z = -1;
|
||||
bool ignore_sparse = false;
|
||||
if (gcodegen.config().wipe_tower_no_sparse_layers.value) {
|
||||
wipe_tower_z = m_last_wipe_tower_print_z;
|
||||
ignore_sparse = (m_tool_changes[m_layer_idx].size() == 1 &&
|
||||
m_tool_changes[m_layer_idx].front().initial_tool == m_tool_changes[m_layer_idx].front().new_tool);
|
||||
if (m_tool_change_idx == 0 && !ignore_sparse)
|
||||
wipe_tower_z = m_last_wipe_tower_print_z + m_tool_changes[m_layer_idx].front().layer_height;
|
||||
}
|
||||
|
||||
if (gcodegen.writer().need_toolchange(extruder_id) || finish_layer) {
|
||||
if (!(size_t(m_tool_change_idx) < m_tool_changes[m_layer_idx].size())) throw Slic3r::RuntimeError("Wipe tower generation failed, possibly due to empty first layer.");
|
||||
if (m_enable_timelapse_print && m_is_first_print) {
|
||||
gcode += append_tcr(gcodegen, m_tool_changes[m_layer_idx][0], m_tool_changes[m_layer_idx][0].new_tool, wipe_tower_z);
|
||||
m_tool_change_idx++;
|
||||
m_is_first_print = false;
|
||||
}
|
||||
|
||||
if (!ignore_sparse) {
|
||||
gcode += append_tcr(gcodegen, m_tool_changes[m_layer_idx][m_tool_change_idx++], extruder_id, wipe_tower_z);
|
||||
m_last_wipe_tower_print_z = wipe_tower_z;
|
||||
if (gcodegen.writer().need_toolchange(extruder_id) || finish_layer) {
|
||||
if (!(size_t(m_tool_change_idx) < m_tool_changes[m_layer_idx].size()))
|
||||
throw Slic3r::RuntimeError("Wipe tower generation failed, possibly due to empty first layer.");
|
||||
|
||||
if (!ignore_sparse) {
|
||||
gcode += append_tcr(gcodegen, m_tool_changes[m_layer_idx][m_tool_change_idx++], extruder_id, wipe_tower_z);
|
||||
m_last_wipe_tower_print_z = wipe_tower_z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -753,14 +981,14 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
|||
}
|
||||
|
||||
// Print is finished. Now it remains to unload the filament safely with ramming over the wipe tower.
|
||||
std::string WipeTowerIntegration::finalize(GCode& gcodegen)
|
||||
std::string WipeTowerIntegration::finalize(GCode &gcodegen)
|
||||
{
|
||||
std::string gcode;
|
||||
// if (!gcodegen.is_BBL_Printer()) {
|
||||
// if (std::abs(gcodegen.writer().get_position()(2) - m_final_purge.print_z) > EPSILON)
|
||||
// gcode += gcodegen.change_layer(m_final_purge.print_z);
|
||||
// gcode += append_tcr(gcodegen, m_final_purge, -1);
|
||||
// }
|
||||
if (!gcodegen.is_BBL_Printer()) {
|
||||
if (std::abs(gcodegen.writer().get_position().z() - m_final_purge.print_z) > EPSILON)
|
||||
gcode += gcodegen.change_layer(m_final_purge.print_z);
|
||||
gcode += append_tcr(gcodegen, m_final_purge, -1);
|
||||
}
|
||||
|
||||
return gcode;
|
||||
}
|
||||
|
|
|
@ -104,10 +104,10 @@ public:
|
|||
private:
|
||||
WipeTowerIntegration& operator=(const WipeTowerIntegration&);
|
||||
std::string append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id, double z = -1.) const;
|
||||
std::string append_tcr2(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id, double z = -1.) const;
|
||||
|
||||
// Postprocesses gcode: rotates and moves G1 extrusions and returns result
|
||||
std::string post_process_wipe_tower_moves(const WipeTower::ToolChangeResult& tcr, const Vec2f& translation, float angle) const;
|
||||
|
||||
// Left / right edges of the wipe tower, for the planning of wipe moves.
|
||||
const float m_left;
|
||||
const float m_right;
|
||||
|
|
|
@ -128,9 +128,9 @@ public:
|
|||
}
|
||||
|
||||
WipeTowerWriter& disable_linear_advance() {
|
||||
if(m_gcode_flavor == gcfKlipper)
|
||||
if (m_gcode_flavor == gcfKlipper)
|
||||
m_gcode += "SET_PRESSURE_ADVANCE ADVANCE=0\n";
|
||||
else if(m_gcode_flavor == gcfRepRapFirmware)
|
||||
else if (m_gcode_flavor == gcfRepRapFirmware)
|
||||
m_gcode += std::string("M572 D") + std::to_string(m_current_tool) + " S0\n";
|
||||
else
|
||||
m_gcode += "M900 K0\n";
|
||||
|
@ -418,30 +418,36 @@ public:
|
|||
// Let the firmware back up the active speed override value.
|
||||
WipeTowerWriter& speed_override_backup()
|
||||
{
|
||||
// This is only supported by Prusa at this point (https://github.com/prusa3d/PrusaSlicer/issues/3114)
|
||||
// BBS: BBL machine don't support speed backup
|
||||
#if 0
|
||||
if (m_gcode_flavor == gcfMarlinLegacy || m_gcode_flavor == gcfMarlinFirmware)
|
||||
m_gcode += "M220 B\n";
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Let the firmware restore the active speed override value.
|
||||
WipeTowerWriter& speed_override_restore()
|
||||
{
|
||||
// BBS: BBL machine don't support speed restore
|
||||
#if 0
|
||||
if (m_gcode_flavor == gcfMarlinLegacy || m_gcode_flavor == gcfMarlinFirmware)
|
||||
m_gcode += "M220 R\n";
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Set digital trimpot motor
|
||||
WipeTowerWriter& set_extruder_trimpot(int current)
|
||||
{
|
||||
if (m_gcode_flavor == gcfKlipper)
|
||||
return *this;
|
||||
// BBS: don't control trimpot
|
||||
#if 0
|
||||
if (m_gcode_flavor == gcfRepRapSprinter || m_gcode_flavor == gcfRepRapFirmware)
|
||||
m_gcode += "M906 E";
|
||||
else
|
||||
m_gcode += "M907 E";
|
||||
m_gcode += std::to_string(current) + "\n";
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -1328,33 +1334,6 @@ WipeTower::ToolChangeResult WipeTower::finish_layer(bool extrude_perimeter, bool
|
|||
return construct_tcr(writer, false, old_tool, true, 0.f);
|
||||
}
|
||||
|
||||
// Static method to extract wipe_volumes[from][to] from the configuration.
|
||||
std::vector<std::vector<float>> WipeTower::extract_wipe_volumes(const PrintConfig& config)
|
||||
{
|
||||
// Get wiping matrix to get number of extruders and convert vector<double> to vector<float>:
|
||||
std::vector<float> wiping_matrix(cast<float>(config.flush_volumes_matrix.values));
|
||||
auto scale = config.flush_multiplier;
|
||||
|
||||
// Orca todo: currently we only/always support SEMM.
|
||||
// The values shall only be used when SEMM is enabled. The purging for other printers
|
||||
// is determined by filament_minimal_purge_on_wipe_tower.
|
||||
// if (! config.single_extruder_multi_material.value)
|
||||
// std::fill(wiping_matrix.begin(), wiping_matrix.end(), 0.f);
|
||||
|
||||
// Extract purging volumes for each extruder pair:
|
||||
std::vector<std::vector<float>> wipe_volumes;
|
||||
const unsigned int number_of_extruders = (unsigned int)(sqrt(wiping_matrix.size())+EPSILON);
|
||||
for (unsigned int i = 0; i<number_of_extruders; ++i)
|
||||
wipe_volumes.push_back(std::vector<float>(wiping_matrix.begin()+i*number_of_extruders, wiping_matrix.begin()+(i+1)*number_of_extruders));
|
||||
|
||||
// Also include filament_minimal_purge_on_wipe_tower. This is needed for the preview.
|
||||
for (unsigned int i = 0; i<number_of_extruders; ++i)
|
||||
for (unsigned int j = 0; j<number_of_extruders; ++j)
|
||||
wipe_volumes[i][j] = std::max<float>(wipe_volumes[i][j] * scale, config.filament_minimal_purge_on_wipe_tower.get_at(j));
|
||||
|
||||
return wipe_volumes;
|
||||
}
|
||||
|
||||
// Appends a toolchange into m_plan and calculates neccessary depth of the corresponding box
|
||||
void WipeTower::plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool,
|
||||
unsigned int new_tool, float wipe_volume, float purge_volume)
|
||||
|
|
|
@ -25,7 +25,6 @@ public:
|
|||
|
||||
// WipeTower height to minimum depth map
|
||||
static const std::map<float, float> min_depth_per_height;
|
||||
static std::vector<std::vector<float>> extract_wipe_volumes(const PrintConfig& config);
|
||||
|
||||
struct Extrusion
|
||||
{
|
||||
|
@ -256,15 +255,14 @@ public:
|
|||
bool is_support = false;
|
||||
int nozzle_temperature = 0;
|
||||
int nozzle_temperature_initial_layer = 0;
|
||||
// BBS: remove useless config
|
||||
//float loading_speed = 0.f;
|
||||
//float loading_speed_start = 0.f;
|
||||
//float unloading_speed = 0.f;
|
||||
//float unloading_speed_start = 0.f;
|
||||
//float delay = 0.f ;
|
||||
//int cooling_moves = 0;
|
||||
//float cooling_initial_speed = 0.f;
|
||||
//float cooling_final_speed = 0.f;
|
||||
float loading_speed = 0.f;
|
||||
float loading_speed_start = 0.f;
|
||||
float unloading_speed = 0.f;
|
||||
float unloading_speed_start = 0.f;
|
||||
float delay = 0.f ;
|
||||
int cooling_moves = 0;
|
||||
float cooling_initial_speed = 0.f;
|
||||
float cooling_final_speed = 0.f;
|
||||
float ramming_line_width_multiplicator = 1.f;
|
||||
float ramming_step_multiplicator = 1.f;
|
||||
float max_e_speed = std::numeric_limits<float>::max();
|
||||
|
@ -288,6 +286,7 @@ private:
|
|||
|
||||
bool m_enable_timelapse_print = false;
|
||||
bool m_semm = true; // Are we using a single extruder multimaterial printer?
|
||||
bool m_purge_in_prime_tower = false; // Do we purge in the prime tower?
|
||||
Vec2f m_wipe_tower_pos; // Left front corner of the wipe tower in mm.
|
||||
float m_wipe_tower_width; // Width of the wipe tower.
|
||||
float m_wipe_tower_depth = 0.f; // Depth of the wipe tower
|
||||
|
@ -307,15 +306,13 @@ private:
|
|||
size_t m_first_layer_idx = size_t(-1);
|
||||
|
||||
// G-code generator parameters.
|
||||
// BBS: remove useless config
|
||||
//float m_cooling_tube_retraction = 0.f;
|
||||
//float m_cooling_tube_length = 0.f;
|
||||
//float m_parking_pos_retraction = 0.f;
|
||||
//float m_extra_loading_move = 0.f;
|
||||
float m_cooling_tube_retraction = 0.f;
|
||||
float m_cooling_tube_length = 0.f;
|
||||
float m_parking_pos_retraction = 0.f;
|
||||
float m_extra_loading_move = 0.f;
|
||||
float m_bridging = 0.f;
|
||||
bool m_no_sparse_layers = false;
|
||||
// BBS: remove useless config
|
||||
//bool m_set_extruder_trimpot = false;
|
||||
bool m_set_extruder_trimpot = false;
|
||||
bool m_adhesion = true;
|
||||
GCodeFlavor m_gcode_flavor;
|
||||
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Orca: This file is ported from latest PrusaSlicer
|
||||
|
||||
// Original PrusaSlicer Copyright:
|
||||
///|/ Copyright (c) Prusa Research 2017 - 2023 Lukáš Matěna @lukasmatena, Vojtěch Bubník @bubnikv, Enrico Turri @enricoturri1966
|
||||
///|/ Copyright (c) SuperSlicer 2023 Remi Durand @supermerill
|
||||
///|/ Copyright (c) 2020 Paul Arden @ardenpm
|
||||
|
@ -141,8 +144,8 @@ public:
|
|||
float get_and_reset_used_filament_length() { float temp = m_used_filament_length; m_used_filament_length = 0.f; return temp; }
|
||||
|
||||
// Extrude with an explicitely provided amount of extrusion.
|
||||
WipeTowerWriter2& extrude_explicit(float x, float y, float e, float f = 0.f, bool record_length = false, bool limit_volumetric_flow = true)
|
||||
{
|
||||
WipeTowerWriter2& extrude_explicit(float x, float y, float e, float f = 0.f, bool record_length = false, bool limit_volumetric_flow = true)
|
||||
{
|
||||
if (x == m_current_pos.x() && y == m_current_pos.y() && e == 0.f && (f == 0.f || f == m_current_feedrate))
|
||||
// Neither extrusion nor a travel move.
|
||||
return *this;
|
||||
|
@ -205,17 +208,17 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
WipeTowerWriter2& extrude_explicit(const Vec2f &dest, float e, float f = 0.f, bool record_length = false, bool limit_volumetric_flow = true)
|
||||
{ return extrude_explicit(dest.x(), dest.y(), e, f, record_length); }
|
||||
WipeTowerWriter2& extrude_explicit(const Vec2f &dest, float e, float f = 0.f, bool record_length = false, bool limit_volumetric_flow = true)
|
||||
{ return extrude_explicit(dest.x(), dest.y(), e, f, record_length); }
|
||||
|
||||
// Travel to a new XY position. f=0 means use the current value.
|
||||
// Travel to a new XY position. f=0 means use the current value.
|
||||
WipeTowerWriter2& travel(float x, float y, float f = 0.f)
|
||||
{ return extrude_explicit(x, y, 0.f, f); }
|
||||
{ return extrude_explicit(x, y, 0.f, f); }
|
||||
|
||||
WipeTowerWriter2& travel(const Vec2f &dest, float f = 0.f)
|
||||
{ return extrude_explicit(dest.x(), dest.y(), 0.f, f); }
|
||||
WipeTowerWriter2& travel(const Vec2f &dest, float f = 0.f)
|
||||
{ return extrude_explicit(dest.x(), dest.y(), 0.f, f); }
|
||||
|
||||
// Extrude a line from current position to x, y with the extrusion amount given by m_extrusion_flow.
|
||||
// Extrude a line from current position to x, y with the extrusion amount given by m_extrusion_flow.
|
||||
WipeTowerWriter2& extrude(float x, float y, float f = 0.f)
|
||||
{
|
||||
float dx = x - m_current_pos.x();
|
||||
|
@ -223,8 +226,8 @@ public:
|
|||
return extrude_explicit(x, y, std::sqrt(dx*dx+dy*dy) * m_extrusion_flow, f, true);
|
||||
}
|
||||
|
||||
WipeTowerWriter2& extrude(const Vec2f &dest, const float f = 0.f)
|
||||
{ return extrude(dest.x(), dest.y(), f); }
|
||||
WipeTowerWriter2& extrude(const Vec2f &dest, const float f = 0.f)
|
||||
{ return extrude(dest.x(), dest.y(), f); }
|
||||
|
||||
WipeTowerWriter2& rectangle(const Vec2f& ld,float width,float height,const float f = 0.f)
|
||||
{
|
||||
|
@ -310,8 +313,8 @@ public:
|
|||
// extrude quickly amount e to x2 with feed f.
|
||||
WipeTowerWriter2& ram(float x1, float x2, float dy, float e0, float e, float f)
|
||||
{
|
||||
extrude_explicit(x1, m_current_pos.y() + dy, e0, f, true, false);
|
||||
extrude_explicit(x2, m_current_pos.y(), e, 0.f, true, false);
|
||||
extrude_explicit(x1, m_current_pos.y() + dy, e0, f, true, false);
|
||||
extrude_explicit(x2, m_current_pos.y(), e, 0.f, true, false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -505,7 +508,8 @@ private:
|
|||
|
||||
WipeTower::ToolChangeResult WipeTower2::construct_tcr(WipeTowerWriter2& writer,
|
||||
bool priming,
|
||||
size_t old_tool) const
|
||||
size_t old_tool,
|
||||
bool is_finish) const
|
||||
{
|
||||
WipeTower::ToolChangeResult result;
|
||||
result.priming = priming;
|
||||
|
@ -519,6 +523,7 @@ WipeTower::ToolChangeResult WipeTower2::construct_tcr(WipeTowerWriter2& writer,
|
|||
result.gcode = std::move(writer.gcode());
|
||||
result.extrusions = std::move(writer.extrusions());
|
||||
result.wipe_path = std::move(writer.wipe_path());
|
||||
result.is_finish_first = is_finish;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -526,6 +531,7 @@ WipeTower::ToolChangeResult WipeTower2::construct_tcr(WipeTowerWriter2& writer,
|
|||
|
||||
WipeTower2::WipeTower2(const PrintConfig& config, const PrintRegionConfig& default_region_config,int plate_idx, Vec3d plate_origin, const std::vector<std::vector<float>>& wiping_matrix, size_t initial_tool) :
|
||||
m_semm(config.single_extruder_multi_material.value),
|
||||
m_enable_filament_ramming(config.enable_filament_ramming.value),
|
||||
m_wipe_tower_pos(config.wipe_tower_x.get_at(plate_idx), config.wipe_tower_y.get_at(plate_idx)),
|
||||
m_wipe_tower_width(float(config.prime_tower_width)),
|
||||
m_wipe_tower_rotation_angle(float(config.wipe_tower_rotation_angle)),
|
||||
|
@ -752,7 +758,7 @@ std::vector<WipeTower::ToolChangeResult> WipeTower2::prime(
|
|||
"\n\n");
|
||||
}
|
||||
|
||||
results.emplace_back(construct_tcr(writer, true, old_tool));
|
||||
results.emplace_back(construct_tcr(writer, true, old_tool, true));
|
||||
}
|
||||
|
||||
m_old_temperature = -1; // If the priming is turned off in config, the temperature changing commands will not actually appear
|
||||
|
@ -839,7 +845,7 @@ WipeTower::ToolChangeResult WipeTower2::tool_change(size_t tool)
|
|||
if (m_current_tool < m_used_filament_length.size())
|
||||
m_used_filament_length[m_current_tool] += writer.get_and_reset_used_filament_length();
|
||||
|
||||
return construct_tcr(writer, false, old_tool);
|
||||
return construct_tcr(writer, false, old_tool, false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -866,7 +872,7 @@ void WipeTower2::toolchange_Unload(
|
|||
float remaining = xr - xl ; // keeps track of distance to the next turnaround
|
||||
float e_done = 0; // measures E move done from each segment
|
||||
|
||||
const bool do_ramming = m_semm || m_filpar[m_current_tool].multitool_ramming;
|
||||
const bool do_ramming = m_enable_filament_ramming && (m_semm || m_filpar[m_current_tool].multitool_ramming);
|
||||
|
||||
if (do_ramming) {
|
||||
writer.travel(ramming_start_pos); // move to starting position
|
||||
|
@ -906,6 +912,7 @@ void WipeTower2::toolchange_Unload(
|
|||
}
|
||||
|
||||
|
||||
writer.append("; Ramming\n");
|
||||
// now the ramming itself:
|
||||
while (do_ramming && i < m_filpar[m_current_tool].ramming_speed.size())
|
||||
{
|
||||
|
@ -933,6 +940,7 @@ void WipeTower2::toolchange_Unload(
|
|||
Vec2f end_of_ramming(writer.x(),writer.y());
|
||||
writer.change_analyzer_line_width(m_perimeter_width); // so the next lines are not affected by ramming_line_width_multiplier
|
||||
|
||||
writer.append("; Retract(unload)\n");
|
||||
// Retraction:
|
||||
float old_x = writer.x();
|
||||
float turning_point = (!m_left_to_right ? xl : xr );
|
||||
|
@ -957,6 +965,7 @@ void WipeTower2::toolchange_Unload(
|
|||
}
|
||||
}
|
||||
|
||||
writer.append("; Cooling\n");
|
||||
// Cooling:
|
||||
const int& number_of_moves = m_filpar[m_current_tool].cooling_moves;
|
||||
if (m_semm && number_of_moves > 0) {
|
||||
|
@ -978,6 +987,7 @@ void WipeTower2::toolchange_Unload(
|
|||
}
|
||||
|
||||
if (m_semm) {
|
||||
writer.append("; Cooling park\n");
|
||||
// let's wait is necessary:
|
||||
writer.wait(m_filpar[m_current_tool].delay);
|
||||
// we should be at the beginning of the cooling tube again - let's move to parking position:
|
||||
|
@ -1006,25 +1016,21 @@ void WipeTower2::toolchange_Change(
|
|||
if (m_current_tool < m_used_filament_length.size())
|
||||
m_used_filament_length[m_current_tool] += writer.get_and_reset_used_filament_length();
|
||||
|
||||
// Orca TODO: handle multi extruders
|
||||
|
||||
// This is where we want to place the custom gcodes. We will use placeholders for this.
|
||||
// These will be substituted by the actual gcodes when the gcode is generated.
|
||||
//writer.append("[end_filament_gcode]\n");
|
||||
//writer.append("[toolchange_gcode]\n");
|
||||
|
||||
writer.append("[filament_end_gcode]\n");
|
||||
writer.append("[change_filament_gcode]\n");
|
||||
|
||||
// Travel to where we assume we are. Custom toolchange or some special T code handling (parking extruder etc)
|
||||
// gcode could have left the extruder somewhere, we cannot just start extruding. We should also inform the
|
||||
// postprocessor that we absolutely want to have this in the gcode, even if it thought it is the same as before.
|
||||
// Vec2f current_pos = writer.pos_rotated();
|
||||
// writer.feedrate(m_travel_speed * 60.f) // see https://github.com/prusa3d/PrusaSlicer/issues/5483
|
||||
// .append(std::string("G1 X") + Slic3r::float_to_string_decimal_point(current_pos.x())
|
||||
// + " Y" + Slic3r::float_to_string_decimal_point(current_pos.y())
|
||||
// + never_skip_tag() + "\n");
|
||||
// Orca todo: handle deretraction_from_wipe_tower_generator
|
||||
// writer.append("[deretraction_from_wipe_tower_generator]");
|
||||
Vec2f current_pos = writer.pos_rotated();
|
||||
writer.feedrate(m_travel_speed * 60.f) // see https://github.com/prusa3d/PrusaSlicer/issues/5483
|
||||
.append(std::string("G1 X") + Slic3r::float_to_string_decimal_point(current_pos.x())
|
||||
+ " Y" + Slic3r::float_to_string_decimal_point(current_pos.y())
|
||||
+ never_skip_tag() + "\n");
|
||||
writer.append("[deretraction_from_wipe_tower_generator]");
|
||||
|
||||
// Orca TODO: handle multi extruders
|
||||
// The toolchange Tn command will be inserted later, only in case that the user does
|
||||
|
@ -1379,7 +1385,7 @@ WipeTower::ToolChangeResult WipeTower2::finish_layer()
|
|||
m_current_height += m_layer_info->height;
|
||||
}
|
||||
|
||||
return construct_tcr(writer, false, old_tool);
|
||||
return construct_tcr(writer, false, old_tool, true);
|
||||
}
|
||||
|
||||
// Static method to get the radius and x-scaling of the stabilizing cone base.
|
||||
|
@ -1404,10 +1410,12 @@ std::vector<std::vector<float>> WipeTower2::extract_wipe_volumes(const PrintConf
|
|||
{
|
||||
// Get wiping matrix to get number of extruders and convert vector<double> to vector<float>:
|
||||
std::vector<float> wiping_matrix(cast<float>(config.flush_volumes_matrix.values));
|
||||
auto scale = config.flush_multiplier;
|
||||
|
||||
// Orca todo: currently we only/always support SEMM.
|
||||
// The values shall only be used when SEMM is enabled. The purging for other printers
|
||||
// is determined by filament_minimal_purge_on_wipe_tower.
|
||||
if (! config.single_extruder_multi_material.value)
|
||||
if (! config.purge_in_prime_tower.value)
|
||||
std::fill(wiping_matrix.begin(), wiping_matrix.end(), 0.f);
|
||||
|
||||
// Extract purging volumes for each extruder pair:
|
||||
|
@ -1419,7 +1427,7 @@ std::vector<std::vector<float>> WipeTower2::extract_wipe_volumes(const PrintConf
|
|||
// Also include filament_minimal_purge_on_wipe_tower. This is needed for the preview.
|
||||
for (unsigned int i = 0; i<number_of_extruders; ++i)
|
||||
for (unsigned int j = 0; j<number_of_extruders; ++j)
|
||||
wipe_volumes[i][j] = std::max<float>(wipe_volumes[i][j], config.filament_minimal_purge_on_wipe_tower.get_at(j));
|
||||
wipe_volumes[i][j] = std::max<float>(wipe_volumes[i][j] * scale, config.filament_minimal_purge_on_wipe_tower.get_at(j));
|
||||
|
||||
return wipe_volumes;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// Orca: This file is ported from latest PrusaSlicer
|
||||
|
||||
// Original PrusaSlicer Copyright:
|
||||
///|/ Copyright (c) Prusa Research 2017 - 2023 Lukáš Matěna @lukasmatena, Vojtěch Bubník @bubnikv
|
||||
///|/
|
||||
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
|
||||
|
@ -31,7 +34,8 @@ public:
|
|||
// WipeTowerWriter2 is moved from !
|
||||
WipeTower::ToolChangeResult construct_tcr(WipeTowerWriter2& writer,
|
||||
bool priming,
|
||||
size_t old_tool) const;
|
||||
size_t old_tool,
|
||||
bool is_finish) const;
|
||||
|
||||
// x -- x coordinates of wipe tower in mm ( left bottom corner )
|
||||
// y -- y coordinates of wipe tower in mm ( left bottom corner )
|
||||
|
@ -168,6 +172,7 @@ private:
|
|||
|
||||
|
||||
bool m_semm = true; // Are we using a single extruder multimaterial printer?
|
||||
bool m_enable_filament_ramming = true;
|
||||
Vec2f m_wipe_tower_pos; // Left front corner of the wipe tower in mm.
|
||||
float m_wipe_tower_width; // Width of the wipe tower.
|
||||
float m_wipe_tower_depth = 0.f; // Depth of the wipe tower
|
||||
|
@ -314,9 +319,6 @@ private:
|
|||
float wipe_volume);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // WipeTowerPrusaMM_hpp_
|
||||
|
|
|
@ -764,7 +764,7 @@ static std::vector<std::string> s_Preset_print_options {
|
|||
"bridge_density", "precise_outer_wall", "overhang_speed_classic", "bridge_acceleration",
|
||||
"sparse_infill_acceleration", "internal_solid_infill_acceleration", "tree_support_adaptive_layer_height", "tree_support_auto_brim",
|
||||
"tree_support_brim_width", "gcode_comments", "gcode_label_objects",
|
||||
"initial_layer_travel_speed", "exclude_object", "slow_down_layers", "infill_anchor", "infill_anchor_max",
|
||||
"initial_layer_travel_speed", "exclude_object", "slow_down_layers", "infill_anchor", "infill_anchor_max","initial_layer_min_bead_width",
|
||||
"make_overhang_printable", "make_overhang_printable_angle", "make_overhang_printable_hole_size" ,"notes",
|
||||
"wipe_tower_cone_angle", "wipe_tower_extra_spacing", "wipe_tower_extruder", "wiping_volumes_extruders","wipe_tower_bridging", "single_extruder_multi_material_priming",
|
||||
"wipe_tower_rotation_angle"
|
||||
|
@ -795,7 +795,7 @@ static std::vector<std::string> s_Preset_filament_options {
|
|||
"enable_pressure_advance", "pressure_advance","chamber_temperature", "filament_shrink", "support_material_interface_fan_speed", "filament_notes" /*,"filament_seam_gap"*/,
|
||||
"filament_loading_speed", "filament_loading_speed_start", "filament_load_time",
|
||||
"filament_unloading_speed", "filament_unloading_speed_start", "filament_unload_time", "filament_toolchange_delay", "filament_cooling_moves",
|
||||
"filament_cooling_initial_speed", "filament_cooling_final_speed", "filament_ramming_parameters", "filament_minimal_purge_on_wipe_tower",
|
||||
"filament_cooling_initial_speed", "filament_cooling_final_speed", "filament_ramming_parameters",
|
||||
"filament_multitool_ramming", "filament_multitool_ramming_volume", "filament_multitool_ramming_flow",
|
||||
};
|
||||
|
||||
|
@ -825,7 +825,7 @@ static std::vector<std::string> s_Preset_printer_options {
|
|||
"printhost_user", "printhost_password", "printhost_ssl_ignore_revoke", "thumbnails",
|
||||
"use_firmware_retraction", "use_relative_e_distances", "printer_notes",
|
||||
"cooling_tube_retraction",
|
||||
"cooling_tube_length", "high_current_on_filament_swap", "parking_pos_retraction", "extra_loading_move"};
|
||||
"cooling_tube_length", "high_current_on_filament_swap", "parking_pos_retraction", "extra_loading_move", "purge_in_prime_tower", "enable_filament_ramming"};
|
||||
|
||||
static std::vector<std::string> s_Preset_sla_print_options {
|
||||
"layer_height",
|
||||
|
|
|
@ -224,7 +224,6 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
|||
|| opt_key == "filament_unloading_speed_start"
|
||||
|| opt_key == "filament_toolchange_delay"
|
||||
|| opt_key == "filament_cooling_moves"
|
||||
|| opt_key == "filament_minimal_purge_on_wipe_tower"
|
||||
|| opt_key == "filament_cooling_initial_speed"
|
||||
|| opt_key == "filament_cooling_final_speed"
|
||||
|| opt_key == "filament_ramming_parameters"
|
||||
|
@ -259,6 +258,8 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
|||
|| opt_key == "wipe_tower_extra_spacing"
|
||||
|| opt_key == "wipe_tower_extruder"
|
||||
|| opt_key == "wiping_volumes_extruders"
|
||||
|| opt_key == "enable_filament_ramming"
|
||||
|| opt_key == "purge_in_prime_tower"
|
||||
) {
|
||||
//|| opt_key == "z_offset") {
|
||||
steps.emplace_back(psWipeTower);
|
||||
|
@ -2177,36 +2178,16 @@ bool Print::has_wipe_tower() const
|
|||
return false;
|
||||
}
|
||||
|
||||
const WipeTowerData& Print::wipe_tower_data(size_t filaments_cnt) const
|
||||
const WipeTowerData &Print::wipe_tower_data(size_t filaments_cnt) const
|
||||
{
|
||||
// If the wipe tower wasn't created yet, make sure the depth and brim_width members are set to default.
|
||||
if (! is_step_done(psWipeTower) && filaments_cnt !=0) {
|
||||
if (true || is_BBL_printer()) { // BBS
|
||||
double width = m_config.prime_tower_width;
|
||||
double layer_height = 0.2; // hard code layer height
|
||||
double wipe_volume = m_config.prime_volume;
|
||||
if (filaments_cnt == 1 && enable_timelapse_print()) {
|
||||
const_cast<Print *>(this)->m_wipe_tower_data.depth = wipe_volume / (layer_height * width);
|
||||
} else {
|
||||
auto scale = m_config.flush_multiplier;
|
||||
// Calculating depth should take into account currently set wiping volumes.
|
||||
// For a long time, the initial preview would just use 900/width per toolchange (15mm on a 60mm wide tower)
|
||||
// and it worked well enough. Let's try to do slightly better by accounting for the purging volumes.
|
||||
std::vector<std::vector<float>> wipe_volumes = WipeTower2::extract_wipe_volumes(m_config);
|
||||
std::vector<float> max_wipe_volumes;
|
||||
for (const std::vector<float> &v : wipe_volumes)
|
||||
max_wipe_volumes.emplace_back(scale*(*std::max_element(v.begin(), v.end())));
|
||||
float maximum = std::accumulate(max_wipe_volumes.begin(), max_wipe_volumes.end(), 0.f);
|
||||
maximum = maximum * filaments_cnt / max_wipe_volumes.size();
|
||||
|
||||
const_cast<Print *>(this)->m_wipe_tower_data.depth = maximum * (filaments_cnt - 1) / (layer_height * width);
|
||||
}
|
||||
const_cast<Print *>(this)->m_wipe_tower_data.brim_width = m_config.prime_tower_brim_width;
|
||||
}
|
||||
else{
|
||||
// If the wipe tower wasn't created yet, make sure the depth and brim_width members are set to default.
|
||||
const_cast<Print *>(this)->m_wipe_tower_data.brim_width = m_config.prime_tower_brim_width;
|
||||
|
||||
if (!is_step_done(psWipeTower) && filaments_cnt != 0) {
|
||||
double width = m_config.prime_tower_width;
|
||||
double layer_height = 0.2; // hard code layer height
|
||||
double wipe_volume = m_config.prime_volume;
|
||||
if (m_config.purge_in_prime_tower || (filaments_cnt == 1 && enable_timelapse_print())) {
|
||||
const_cast<Print *>(this)->m_wipe_tower_data.depth = wipe_volume / (layer_height * width);
|
||||
} else {
|
||||
// Calculating depth should take into account currently set wiping volumes.
|
||||
// For a long time, the initial preview would just use 900/width per toolchange (15mm on a 60mm wide tower)
|
||||
// and it worked well enough. Let's try to do slightly better by accounting for the purging volumes.
|
||||
|
@ -2217,12 +2198,9 @@ const WipeTowerData& Print::wipe_tower_data(size_t filaments_cnt) const
|
|||
float maximum = std::accumulate(max_wipe_volumes.begin(), max_wipe_volumes.end(), 0.f);
|
||||
maximum = maximum * filaments_cnt / max_wipe_volumes.size();
|
||||
|
||||
float width = float(m_config.prime_tower_width);
|
||||
float layer_height = 0.2f; // just assume fixed value, it will still be better than before.
|
||||
|
||||
const_cast<Print *>(this)->m_wipe_tower_data.depth = (maximum / layer_height) / width;
|
||||
const_cast<Print *>(this)->m_wipe_tower_data.height = -1.f; // unknown yet
|
||||
const_cast<Print *>(this)->m_wipe_tower_data.depth = maximum / (layer_height * width);
|
||||
}
|
||||
const_cast<Print *>(this)->m_wipe_tower_data.brim_width = m_config.prime_tower_brim_width;
|
||||
}
|
||||
|
||||
return m_wipe_tower_data;
|
||||
|
@ -2292,10 +2270,11 @@ void Print::_make_wipe_tower()
|
|||
}
|
||||
this->throw_if_canceled();
|
||||
|
||||
// Initialize the wipe tower.
|
||||
if(true || is_BBL_printer()) {
|
||||
if (!m_config.purge_in_prime_tower) {
|
||||
// in BBL machine, wipe tower is only use to prime extruder. So just use a global wipe volume.
|
||||
WipeTower wipe_tower(m_config, m_plate_index, m_origin, m_config.prime_volume, m_wipe_tower_data.tool_ordering.first_extruder(),
|
||||
m_wipe_tower_data.tool_ordering.empty() ? 0.f : m_wipe_tower_data.tool_ordering.back().print_z);
|
||||
|
||||
// wipe_tower.set_retract();
|
||||
// wipe_tower.set_zhop();
|
||||
|
||||
|
@ -2338,7 +2317,7 @@ void Print::_make_wipe_tower()
|
|||
|
||||
// request a toolchange at the wipe tower with at least volume_to_wipe purging amount
|
||||
wipe_tower.plan_toolchange((float) layer_tools.print_z, (float) layer_tools.wipe_tower_layer_height,
|
||||
current_extruder_id, extruder_id, volume_to_purge, volume_to_purge);
|
||||
current_extruder_id, extruder_id, m_config.prime_volume, volume_to_purge);
|
||||
current_extruder_id = extruder_id;
|
||||
}
|
||||
}
|
||||
|
@ -2387,90 +2366,93 @@ void Print::_make_wipe_tower()
|
|||
m_fake_wipe_tower.set_fake_extrusion_data(wipe_tower.position(), wipe_tower.width(), wipe_tower.get_height(),
|
||||
wipe_tower.get_layer_height(), m_wipe_tower_data.depth, m_wipe_tower_data.brim_width,
|
||||
{scale_(origin.x()), scale_(origin.y())});
|
||||
}
|
||||
else{
|
||||
// Initialize the wipe tower.
|
||||
WipeTower2 wipe_tower(m_config, m_default_region_config, m_plate_index, m_origin, wipe_volumes, m_wipe_tower_data.tool_ordering.first_extruder());
|
||||
} else {
|
||||
// Initialize the wipe tower.
|
||||
WipeTower2 wipe_tower(m_config, m_default_region_config, m_plate_index, m_origin, wipe_volumes,
|
||||
m_wipe_tower_data.tool_ordering.first_extruder());
|
||||
|
||||
//wipe_tower.set_retract();
|
||||
//wipe_tower.set_zhop();
|
||||
// wipe_tower.set_retract();
|
||||
// wipe_tower.set_zhop();
|
||||
|
||||
// Set the extruder & material properties at the wipe tower object.
|
||||
for (size_t i = 0; i < number_of_extruders; ++i)
|
||||
// Set the extruder & material properties at the wipe tower object.
|
||||
for (size_t i = 0; i < number_of_extruders; ++i)
|
||||
wipe_tower.set_extruder(i, m_config);
|
||||
|
||||
// m_wipe_tower_data.priming = Slic3r::make_unique<std::vector<WipeTower::ToolChangeResult>>(
|
||||
// wipe_tower.prime((float)this->skirt_first_layer_height(), m_wipe_tower_data.tool_ordering.all_extruders(), false));
|
||||
// m_wipe_tower_data.priming = Slic3r::make_unique<std::vector<WipeTower::ToolChangeResult>>(
|
||||
// wipe_tower.prime((float)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
|
||||
// to pass to wipe_tower (so that it can use it for planning the layout of the tower)
|
||||
{
|
||||
unsigned int current_extruder_id = m_wipe_tower_data.tool_ordering.first_extruder();
|
||||
for (auto &layer_tools : m_wipe_tower_data.tool_ordering.layer_tools()) { // for all layers
|
||||
if (!layer_tools.has_wipe_tower) continue;
|
||||
bool first_layer = &layer_tools == &m_wipe_tower_data.tool_ordering.front();
|
||||
wipe_tower.plan_toolchange((float) layer_tools.print_z, (float) layer_tools.wipe_tower_layer_height, current_extruder_id,
|
||||
current_extruder_id, false);
|
||||
for (const auto extruder_id : layer_tools.extruders) {
|
||||
if (/*(first_layer && extruder_id == m_wipe_tower_data.tool_ordering.all_extruders().back()) || */extruder_id != current_extruder_id) {
|
||||
float volume_to_wipe = wipe_volumes[current_extruder_id][extruder_id]; // total volume to wipe after this toolchange
|
||||
volume_to_wipe *= m_config.flush_multiplier;
|
||||
// Not all of that can be used for infill purging:
|
||||
volume_to_wipe -= (float)m_config.filament_minimal_purge_on_wipe_tower.get_at(extruder_id);
|
||||
// Lets go through the wipe tower layers and determine pairs of extruder changes for each
|
||||
// to pass to wipe_tower (so that it can use it for planning the layout of the tower)
|
||||
{
|
||||
unsigned int current_extruder_id = m_wipe_tower_data.tool_ordering.first_extruder();
|
||||
for (auto &layer_tools : m_wipe_tower_data.tool_ordering.layer_tools()) { // for all layers
|
||||
if (!layer_tools.has_wipe_tower)
|
||||
continue;
|
||||
bool first_layer = &layer_tools == &m_wipe_tower_data.tool_ordering.front();
|
||||
wipe_tower.plan_toolchange((float) layer_tools.print_z, (float) layer_tools.wipe_tower_layer_height, current_extruder_id,
|
||||
current_extruder_id, false);
|
||||
for (const auto extruder_id : layer_tools.extruders) {
|
||||
if (/*(first_layer && extruder_id == m_wipe_tower_data.tool_ordering.all_extruders().back()) || */ extruder_id !=
|
||||
current_extruder_id) {
|
||||
float volume_to_wipe = wipe_volumes[current_extruder_id][extruder_id]; // total volume to wipe after this toolchange
|
||||
volume_to_wipe *= m_config.flush_multiplier;
|
||||
// Not all of that can be used for infill purging:
|
||||
volume_to_wipe -= (float) m_config.filament_minimal_purge_on_wipe_tower.get_at(extruder_id);
|
||||
|
||||
// try to assign some infills/objects for the wiping:
|
||||
volume_to_wipe = layer_tools.wiping_extrusions().mark_wiping_extrusions(*this, current_extruder_id, extruder_id, volume_to_wipe);
|
||||
// try to assign some infills/objects for the wiping:
|
||||
volume_to_wipe = layer_tools.wiping_extrusions().mark_wiping_extrusions(*this, current_extruder_id, extruder_id,
|
||||
volume_to_wipe);
|
||||
|
||||
// add back the minimal amount toforce on the wipe tower:
|
||||
volume_to_wipe += (float)m_config.filament_minimal_purge_on_wipe_tower.get_at(extruder_id);
|
||||
// add back the minimal amount toforce on the wipe tower:
|
||||
volume_to_wipe += (float) m_config.filament_minimal_purge_on_wipe_tower.get_at(extruder_id);
|
||||
|
||||
// request a toolchange at the wipe tower with at least volume_to_wipe purging amount
|
||||
wipe_tower.plan_toolchange((float)layer_tools.print_z, (float)layer_tools.wipe_tower_layer_height,
|
||||
current_extruder_id, extruder_id, volume_to_wipe);
|
||||
current_extruder_id = extruder_id;
|
||||
// request a toolchange at the wipe tower with at least volume_to_wipe purging amount
|
||||
wipe_tower.plan_toolchange((float) layer_tools.print_z, (float) layer_tools.wipe_tower_layer_height,
|
||||
current_extruder_id, extruder_id, volume_to_wipe);
|
||||
current_extruder_id = extruder_id;
|
||||
}
|
||||
}
|
||||
layer_tools.wiping_extrusions().ensure_perimeters_infills_order(*this);
|
||||
if (&layer_tools == &m_wipe_tower_data.tool_ordering.back() || (&layer_tools + 1)->wipe_tower_partitions == 0)
|
||||
break;
|
||||
}
|
||||
layer_tools.wiping_extrusions().ensure_perimeters_infills_order(*this);
|
||||
if (&layer_tools == &m_wipe_tower_data.tool_ordering.back() || (&layer_tools + 1)->wipe_tower_partitions == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Generate the wipe tower layers.
|
||||
m_wipe_tower_data.tool_changes.reserve(m_wipe_tower_data.tool_ordering.layer_tools().size());
|
||||
wipe_tower.generate(m_wipe_tower_data.tool_changes);
|
||||
m_wipe_tower_data.depth = wipe_tower.get_depth();
|
||||
m_wipe_tower_data.z_and_depth_pairs = wipe_tower.get_z_and_depth_pairs();
|
||||
m_wipe_tower_data.brim_width = wipe_tower.get_brim_width();
|
||||
m_wipe_tower_data.height = wipe_tower.get_wipe_tower_height();
|
||||
// Generate the wipe tower layers.
|
||||
m_wipe_tower_data.tool_changes.reserve(m_wipe_tower_data.tool_ordering.layer_tools().size());
|
||||
wipe_tower.generate(m_wipe_tower_data.tool_changes);
|
||||
m_wipe_tower_data.depth = wipe_tower.get_depth();
|
||||
m_wipe_tower_data.z_and_depth_pairs = wipe_tower.get_z_and_depth_pairs();
|
||||
m_wipe_tower_data.brim_width = wipe_tower.get_brim_width();
|
||||
m_wipe_tower_data.height = wipe_tower.get_wipe_tower_height();
|
||||
|
||||
// Unload the current filament over the purge tower.
|
||||
coordf_t layer_height = m_objects.front()->config().layer_height.value;
|
||||
if (m_wipe_tower_data.tool_ordering.back().wipe_tower_partitions > 0) {
|
||||
// The wipe tower goes up to the last layer of the print.
|
||||
if (wipe_tower.layer_finished()) {
|
||||
// The wipe tower is printed to the top of the print and it has no space left for the final extruder purge.
|
||||
// Lift Z to the next layer.
|
||||
wipe_tower.set_layer(float(m_wipe_tower_data.tool_ordering.back().print_z + layer_height), float(layer_height), 0, false, true);
|
||||
// Unload the current filament over the purge tower.
|
||||
coordf_t layer_height = m_objects.front()->config().layer_height.value;
|
||||
if (m_wipe_tower_data.tool_ordering.back().wipe_tower_partitions > 0) {
|
||||
// The wipe tower goes up to the last layer of the print.
|
||||
if (wipe_tower.layer_finished()) {
|
||||
// The wipe tower is printed to the top of the print and it has no space left for the final extruder purge.
|
||||
// Lift Z to the next layer.
|
||||
wipe_tower.set_layer(float(m_wipe_tower_data.tool_ordering.back().print_z + layer_height), float(layer_height), 0, false,
|
||||
true);
|
||||
} else {
|
||||
// There is yet enough space at this layer of the wipe tower for the final purge.
|
||||
}
|
||||
} else {
|
||||
// There is yet enough space at this layer of the wipe tower for the final purge.
|
||||
// The wipe tower does not reach the last print layer, perform the pruge at the last print layer.
|
||||
assert(m_wipe_tower_data.tool_ordering.back().wipe_tower_partitions == 0);
|
||||
wipe_tower.set_layer(float(m_wipe_tower_data.tool_ordering.back().print_z), float(layer_height), 0, false, true);
|
||||
}
|
||||
} else {
|
||||
// The wipe tower does not reach the last print layer, perform the pruge at the last print layer.
|
||||
assert(m_wipe_tower_data.tool_ordering.back().wipe_tower_partitions == 0);
|
||||
wipe_tower.set_layer(float(m_wipe_tower_data.tool_ordering.back().print_z), float(layer_height), 0, false, true);
|
||||
}
|
||||
m_wipe_tower_data.final_purge = Slic3r::make_unique<WipeTower::ToolChangeResult>(
|
||||
wipe_tower.tool_change((unsigned int)(-1)));
|
||||
m_wipe_tower_data.final_purge = Slic3r::make_unique<WipeTower::ToolChangeResult>(wipe_tower.tool_change((unsigned int) (-1)));
|
||||
|
||||
m_wipe_tower_data.used_filament = wipe_tower.get_used_filament();
|
||||
m_wipe_tower_data.number_of_toolchanges = wipe_tower.get_number_of_toolchanges();
|
||||
const Vec3d origin = Vec3d::Zero();
|
||||
m_fake_wipe_tower.set_fake_extrusion_data(wipe_tower.position(), wipe_tower.width(), wipe_tower.get_wipe_tower_height(),
|
||||
config().initial_layer_print_height, m_wipe_tower_data.depth,
|
||||
m_wipe_tower_data.z_and_depth_pairs, m_wipe_tower_data.brim_width,
|
||||
config().wipe_tower_rotation_angle, config().wipe_tower_cone_angle,
|
||||
{scale_(origin.x()), scale_(origin.y())});
|
||||
m_wipe_tower_data.used_filament = wipe_tower.get_used_filament();
|
||||
m_wipe_tower_data.number_of_toolchanges = wipe_tower.get_number_of_toolchanges();
|
||||
const Vec3d origin = Vec3d::Zero();
|
||||
m_fake_wipe_tower.set_fake_extrusion_data(wipe_tower.position(), wipe_tower.width(), wipe_tower.get_wipe_tower_height(),
|
||||
config().initial_layer_print_height, m_wipe_tower_data.depth,
|
||||
m_wipe_tower_data.z_and_depth_pairs, m_wipe_tower_data.brim_width,
|
||||
config().wipe_tower_rotation_angle, config().wipe_tower_cone_angle,
|
||||
{scale_(origin.x()), scale_(origin.y())});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1369,17 +1369,6 @@ void PrintConfigDef::init_fff_params()
|
|||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloats { 2. });
|
||||
|
||||
def = this->add("filament_minimal_purge_on_wipe_tower", coFloats);
|
||||
def->label = L("Minimal purge on wipe tower");
|
||||
def->tooltip = L("After a tool change, the exact position of the newly loaded filament inside "
|
||||
"the nozzle may not be known, and the filament pressure is likely not yet stable. "
|
||||
"Before purging the print head into an infill or a sacrificial object, Slic3r will always prime "
|
||||
"this amount of material into the wipe tower to produce successive infill or sacrificial object extrusions reliably.");
|
||||
def->sidetext = L("mm³");
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloats { 15. });
|
||||
|
||||
def = this->add("machine_load_filament_time", coFloat);
|
||||
def->label = L("Filament load time");
|
||||
def->tooltip = L("Time to load new filament when switch filament. For statistics only");
|
||||
|
@ -3197,7 +3186,21 @@ def = this->add("filament_loading_speed", coFloats);
|
|||
def->label = L("Single Extruder Multi Material");
|
||||
def->tooltip = L("Use single nozzle to print multi filament");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
def->readonly = true;
|
||||
def->set_default_value(new ConfigOptionBool(true));
|
||||
|
||||
def = this->add("purge_in_prime_tower", coBool);
|
||||
def->label = L("Purge in prime tower");
|
||||
def->tooltip = L("Purge remaining filament into prime tower");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(true));
|
||||
|
||||
def = this->add("enable_filament_ramming", coBool);
|
||||
def->label = L("Enable filament ramming");
|
||||
def->tooltip = L("Enable filament ramming");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(true));
|
||||
|
||||
|
||||
def = this->add("wipe_tower_no_sparse_layers", coBool);
|
||||
def->label = L("No sparse layers (EXPERIMENTAL)");
|
||||
|
@ -3853,7 +3856,7 @@ def = this->add("filament_loading_speed", coFloats);
|
|||
def->label = L("Flush multiplier");
|
||||
def->tooltip = L("The actual flushing volumes is equal to the flush multiplier multiplied by the flushing volumes in the table.");
|
||||
def->sidetext = "";
|
||||
def->set_default_value(new ConfigOptionFloat(1.0));
|
||||
def->set_default_value(new ConfigOptionFloat(0.3));
|
||||
|
||||
// BBS
|
||||
def = this->add("prime_volume", coFloat);
|
||||
|
@ -3886,7 +3889,7 @@ def = this->add("filament_loading_speed", coFloats);
|
|||
def->sidetext = L("mm");
|
||||
def->min = 2.0;
|
||||
def->mode = comSimple;
|
||||
def->set_default_value(new ConfigOptionFloat(35.));
|
||||
def->set_default_value(new ConfigOptionFloat(60.));
|
||||
|
||||
def = this->add("wipe_tower_rotation_angle", coFloat);
|
||||
def->label = L("Wipe tower rotation angle");
|
||||
|
@ -4912,7 +4915,9 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
|
|||
}
|
||||
} else if (opt_key == "overhang_fan_threshold" && value == "5%") {
|
||||
value = "10%";
|
||||
}
|
||||
} else if(opt_key == "single_extruder_multi_material") {
|
||||
value = "1";
|
||||
}
|
||||
|
||||
// Ignore the following obsolete configuration keys:
|
||||
static std::set<std::string> ignore = {
|
||||
|
|
|
@ -941,6 +941,8 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||
((ConfigOptionBools, filament_multitool_ramming))
|
||||
((ConfigOptionFloats, filament_multitool_ramming_volume))
|
||||
((ConfigOptionFloats, filament_multitool_ramming_flow))
|
||||
((ConfigOptionBool, purge_in_prime_tower))
|
||||
((ConfigOptionBool, enable_filament_ramming))
|
||||
|
||||
)
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue