Update Resonance Avoidance

This commit is contained in:
QIDI TECH
2024-06-21 14:19:23 +08:00
parent b7e961c443
commit 69126621fc
9 changed files with 337 additions and 277 deletions

View File

@@ -128,11 +128,13 @@ ironing_type = top
layer_height = 0.2 layer_height = 0.2
max_bridge_length = 10 max_bridge_length = 10
max_print_speed = 600 max_print_speed = 600
max_resonance_avoidance_speed = 120
max_volumetric_extrusion_rate_slope_negative = 0 max_volumetric_extrusion_rate_slope_negative = 0
max_volumetric_extrusion_rate_slope_positive = 0 max_volumetric_extrusion_rate_slope_positive = 0
max_volumetric_speed = 0 max_volumetric_speed = 0
min_bead_width = 85% min_bead_width = 85%
min_feature_size = 25% min_feature_size = 25%
min_resonance_avoidance_speed = 70
min_skirt_length = 5 min_skirt_length = 5
mmu_segmented_region_interlocking_depth = 0 mmu_segmented_region_interlocking_depth = 0
mmu_segmented_region_max_width = 0 mmu_segmented_region_max_width = 0
@@ -160,6 +162,7 @@ raft_first_layer_density = 90%
raft_first_layer_expansion = 3 raft_first_layer_expansion = 3
raft_layers = 0 raft_layers = 0
resolution = 0 resolution = 0
resonance_avoidance = 1
seam_gap = 15% seam_gap = 15%
seam_position = aligned seam_position = aligned
single_extruder_multi_material_priming = 0 single_extruder_multi_material_priming = 0
@@ -169,7 +172,7 @@ skirts = 0
slice_closing_radius = 0.049 slice_closing_radius = 0.049
slicing_mode = regular slicing_mode = regular
slow_down_layers = 0 slow_down_layers = 0
small_perimeter_speed = 70 small_perimeter_speed = 100
solid_infill_acceleration = 10000 solid_infill_acceleration = 10000
solid_infill_below_area = 15 solid_infill_below_area = 15
solid_infill_every_layers = 0 solid_infill_every_layers = 0
@@ -2529,9 +2532,7 @@ machine_min_extruding_rate = 0
machine_min_travel_rate = 0 machine_min_travel_rate = 0
max_layer_height = 0.28 max_layer_height = 0.28
max_print_height = 315 max_print_height = 315
max_resonance_avoidance_speed = 115
min_layer_height = 0.08 min_layer_height = 0.08
min_resonance_avoidance_speed = 70
multimaterial_purging = 45 multimaterial_purging = 45
nozzle_diameter = 0.4 nozzle_diameter = 0.4
parking_pos_retraction = 92 parking_pos_retraction = 92
@@ -2546,7 +2547,6 @@ printer_vendor = QIDI
printhost_apikey = printhost_apikey =
printhost_cafile = printhost_cafile =
remaining_times = 1 remaining_times = 1
resonance_avoidance = 1
retract_before_travel = 1 retract_before_travel = 1
retract_before_wipe = 0% retract_before_wipe = 0%
retract_layer_change = 1 retract_layer_change = 1

View File

@@ -83,7 +83,6 @@ namespace Slic3r {
gcode += '\n'; gcode += '\n';
} }
// Return true if tch_prefix is found in custom_gcode // Return true if tch_prefix is found in custom_gcode
static bool custom_gcode_changes_tool(const std::string& custom_gcode, const std::string& tch_prefix, unsigned next_extruder) static bool custom_gcode_changes_tool(const std::string& custom_gcode, const std::string& tch_prefix, unsigned next_extruder)
{ {
@@ -146,13 +145,14 @@ namespace Slic3r {
int OozePrevention::_get_temp(const GCodeGenerator &gcodegen) const int OozePrevention::_get_temp(const GCodeGenerator &gcodegen) const
{ {
// First layer temperature should be used when on the first layer (obviously) and when
// "other layers" is set to zero (which means it should not be used).
return (gcodegen.layer() == nullptr || gcodegen.layer()->id() == 0 return (gcodegen.layer() == nullptr || gcodegen.layer()->id() == 0
|| gcodegen.config().temperature.get_at(gcodegen.writer().extruder()->id()) == 0) || gcodegen.config().temperature.get_at(gcodegen.writer().extruder()->id()) == 0)
? gcodegen.config().first_layer_temperature.get_at(gcodegen.writer().extruder()->id()) ? gcodegen.config().first_layer_temperature.get_at(gcodegen.writer().extruder()->id())
: gcodegen.config().temperature.get_at(gcodegen.writer().extruder()->id()); : gcodegen.config().temperature.get_at(gcodegen.writer().extruder()->id());
} }
const std::vector<std::string> ColorPrintColors::Colors = { "#C0392B", "#E67E22", "#F1C40F", "#27AE60", "#1ABC9C", "#2980B9", "#9B59B6" }; const std::vector<std::string> ColorPrintColors::Colors = { "#C0392B", "#E67E22", "#F1C40F", "#27AE60", "#1ABC9C", "#2980B9", "#9B59B6" };
#define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_writer.extruder()->id()) #define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_writer.extruder()->id())
@@ -208,6 +208,7 @@ void GCodeGenerator::PlaceholderParserIntegration::init(const GCodeWriter &write
this->position.assign(3, 0); this->position.assign(3, 0);
this->opt_position = new ConfigOptionFloats(this->position); this->opt_position = new ConfigOptionFloats(this->position);
this->output_config.set_key_value("position", this->opt_position); this->output_config.set_key_value("position", this->opt_position);
// Store zhop variable into the parser itself, it is a read-only variable to the script. // Store zhop variable into the parser itself, it is a read-only variable to the script.
this->opt_zhop = new ConfigOptionFloat(writer.get_zhop()); this->opt_zhop = new ConfigOptionFloat(writer.get_zhop());
this->parser.set("zhop", this->opt_zhop); this->parser.set("zhop", this->opt_zhop);
@@ -230,6 +231,7 @@ void GCodeGenerator::PlaceholderParserIntegration::update_from_gcodewriter(const
for (const Extruder &e : extruders) { for (const Extruder &e : extruders) {
this->e_retracted[e.id()] = e.retracted(); this->e_retracted[e.id()] = e.retracted();
this->e_restart_extra[e.id()] = e.restart_extra(); this->e_restart_extra[e.id()] = e.restart_extra();
// Wipe tower filament consumption has to be added separately, because that gcode is not generated by GCodeWriter. // Wipe tower filament consumption has to be added separately, because that gcode is not generated by GCodeWriter.
double wt_vol = 0.; double wt_vol = 0.;
const std::vector<std::pair<float, std::vector<float>>>& wtuf = wipe_tower_data.used_filament_until_layer; const std::vector<std::pair<float, std::vector<float>>>& wtuf = wipe_tower_data.used_filament_until_layer;
@@ -552,8 +554,11 @@ GCodeGenerator::GCodeGenerator(const Print* print) :
m_brim_done(false), m_brim_done(false),
m_second_layer_things_done(false), m_second_layer_things_done(false),
m_silent_time_estimator_enabled(false), m_silent_time_estimator_enabled(false),
//Y27
m_resonance_avoidance(true),
m_print(print) m_print(print)
{} {}
void GCodeGenerator::do_export(Print* print, const char* path, GCodeProcessorResult* result, ThumbnailsGeneratorCallback thumbnail_cb) void GCodeGenerator::do_export(Print* print, const char* path, GCodeProcessorResult* result, ThumbnailsGeneratorCallback thumbnail_cb)
{ {
CNumericLocalesSetter locales_setter; CNumericLocalesSetter locales_setter;
@@ -789,6 +794,7 @@ namespace DoExport {
print_statistics.total_wipe_tower_filament_weight += has_wipe_tower ? (extruded_volume - extruder.extruded_volume()) * extruder.filament_density() * 0.001 : 0.; print_statistics.total_wipe_tower_filament_weight += has_wipe_tower ? (extruded_volume - extruder.extruded_volume()) * extruder.filament_density() * 0.001 : 0.;
print_statistics.total_wipe_tower_cost += has_wipe_tower ? (extruded_volume - extruder.extruded_volume())* extruder.filament_density() * 0.001 * extruder.filament_cost() * 0.001 : 0.; print_statistics.total_wipe_tower_cost += has_wipe_tower ? (extruded_volume - extruder.extruded_volume())* extruder.filament_density() * 0.001 * extruder.filament_cost() * 0.001 : 0.;
} }
if (!export_binary_data) { if (!export_binary_data) {
filament_stats_string_out += out_filament_used_mm.first; filament_stats_string_out += out_filament_used_mm.first;
filament_stats_string_out += "\n" + out_filament_used_cm3.first; filament_stats_string_out += "\n" + out_filament_used_cm3.first;
@@ -899,6 +905,7 @@ static inline std::optional<std::string> find_M84(const std::string &gcode) {
return std::nullopt; return std::nullopt;
} }
void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGeneratorCallback thumbnail_cb) void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGeneratorCallback thumbnail_cb)
{ {
const bool export_to_binary_gcode = print.full_print_config().option<ConfigOptionBool>("binary_gcode")->value; const bool export_to_binary_gcode = print.full_print_config().option<ConfigOptionBool>("binary_gcode")->value;
@@ -1002,15 +1009,16 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail
// Write information on the generator. // Write information on the generator.
file.write_format("; %s\n\n", Slic3r::header_slic3r_generated().c_str()); file.write_format("; %s\n\n", Slic3r::header_slic3r_generated().c_str());
if (! export_to_binary_gcode) { if (! export_to_binary_gcode) {
// if exporting gcode in ascii format, generate the thumbnails here // if exporting gcode in ascii format, generate the thumbnails here
auto [thumbnails, errors] = GCodeThumbnails::make_and_check_thumbnail_list(print.full_print_config()); auto [thumbnails, errors] = GCodeThumbnails::make_and_check_thumbnail_list(print.full_print_config());
if (errors != enum_bitmask<ThumbnailError>()) { if (errors != enum_bitmask<ThumbnailError>()) {
std::string error_str = format("Invalid thumbnails value:"); std::string error_str = format("Invalid thumbnails value:");
error_str += GCodeThumbnails::get_error_string(errors); error_str += GCodeThumbnails::get_error_string(errors);
throw Slic3r::ExportError(error_str); throw Slic3r::ExportError(error_str);
} }
if (!thumbnails.empty()) if (!thumbnails.empty())
GCodeThumbnails::export_thumbnails_to_file(thumbnail_cb, thumbnails, GCodeThumbnails::export_thumbnails_to_file(thumbnail_cb, thumbnails,
[&file](const char* sz) { file.write(sz); }, [&file](const char* sz) { file.write(sz); },
@@ -1053,8 +1061,9 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail
} }
print.throw_if_canceled(); print.throw_if_canceled();
} }
//B41
// adds tags for time estimators // adds tags for time estimators
//B41
// if (print.config().remaining_times.value) // if (print.config().remaining_times.value)
// file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::First_Line_M73_Placeholder).c_str()); // file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::First_Line_M73_Placeholder).c_str());
@@ -1229,6 +1238,7 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail
} }
GCode::SmoothPathCache smooth_path_cache_global = smooth_path_interpolate_global(print); GCode::SmoothPathCache smooth_path_cache_global = smooth_path_interpolate_global(print);
// Do all objects for each layer. // Do all objects for each layer.
if (print.config().complete_objects.value) { if (print.config().complete_objects.value) {
size_t finished_objects = 0; size_t finished_objects = 0;
@@ -1285,6 +1295,7 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail
m_second_layer_things_done = false; m_second_layer_things_done = false;
prev_object = &object; prev_object = &object;
} }
file.write(m_label_objects.maybe_stop_instance()); file.write(m_label_objects.maybe_stop_instance());
} else { } else {
// Sort layers by Z. // Sort layers by Z.
@@ -1293,10 +1304,12 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail
// QIDI Multi-Material wipe tower. // QIDI Multi-Material wipe tower.
if (has_wipe_tower && ! layers_to_print.empty()) { if (has_wipe_tower && ! layers_to_print.empty()) {
m_wipe_tower = std::make_unique<GCode::WipeTowerIntegration>(print.config(), *print.wipe_tower_data().priming.get(), print.wipe_tower_data().tool_changes, *print.wipe_tower_data().final_purge.get()); m_wipe_tower = std::make_unique<GCode::WipeTowerIntegration>(print.config(), *print.wipe_tower_data().priming.get(), print.wipe_tower_data().tool_changes, *print.wipe_tower_data().final_purge.get());
// Set position for wipe tower generation. // Set position for wipe tower generation.
Vec3d new_position = this->writer().get_position(); Vec3d new_position = this->writer().get_position();
new_position.z() = first_layer_height; new_position.z() = first_layer_height;
this->writer().update_position(new_position); this->writer().update_position(new_position);
if (print.config().single_extruder_multi_material_priming) { if (print.config().single_extruder_multi_material_priming) {
file.write(m_wipe_tower->prime(*this)); file.write(m_wipe_tower->prime(*this));
// Verify, whether the print overaps the priming extrusions. // Verify, whether the print overaps the priming extrusions.
@@ -1414,6 +1427,7 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail
file.write_format("; objects_info = %s\n", m_label_objects.all_objects_header_singleline_json().c_str()); file.write_format("; objects_info = %s\n", m_label_objects.all_objects_header_singleline_json().c_str());
file.write(filament_stats_string_out); file.write(filament_stats_string_out);
} }
if (export_to_binary_gcode) { if (export_to_binary_gcode) {
bgcode::binarize::BinaryData& binary_data = m_processor.get_binary_data(); bgcode::binarize::BinaryData& binary_data = m_processor.get_binary_data();
if (print.m_print_statistics.total_toolchanges > 0) if (print.m_print_statistics.total_toolchanges > 0)
@@ -1421,6 +1435,7 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail
char buf[1024]; char buf[1024];
sprintf(buf, "%.2lf", m_max_layer_z); sprintf(buf, "%.2lf", m_max_layer_z);
binary_data.printer_metadata.raw_data.emplace_back("max_layer_z", buf); binary_data.printer_metadata.raw_data.emplace_back("max_layer_z", buf);
// Now the objects info. // Now the objects info.
binary_data.printer_metadata.raw_data.emplace_back("objects_info", m_label_objects.all_objects_header_singleline_json()); binary_data.printer_metadata.raw_data.emplace_back("objects_info", m_label_objects.all_objects_header_singleline_json());
} }
@@ -1436,7 +1451,6 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail
//B3 //B3
if (!export_to_binary_gcode) { if (!export_to_binary_gcode) {
// if exporting gcode in ascii format, generate the thumbnails here
auto [thumbnails, errors] = GCodeThumbnails::make_and_check_thumbnail_list(print.full_print_config()); auto [thumbnails, errors] = GCodeThumbnails::make_and_check_thumbnail_list(print.full_print_config());
if (errors != enum_bitmask<ThumbnailError>()) { if (errors != enum_bitmask<ThumbnailError>()) {
std::string error_str = format("Invalid thumbnails value:"); std::string error_str = format("Invalid thumbnails value:");
@@ -1450,6 +1464,7 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail
file.write("\n"); file.write("\n");
// if exporting gcode in ascii format, config export is done here
// Append full config, delimited by two 'phony' configuration keys qidislicer_config = begin and qidislicer_config = end. // Append full config, delimited by two 'phony' configuration keys qidislicer_config = begin and qidislicer_config = end.
// The delimiters are structured as configuration key / value pairs to be parsable by older versions of QIDISlicer G-code viewer. // The delimiters are structured as configuration key / value pairs to be parsable by older versions of QIDISlicer G-code viewer.
{ {
@@ -1485,6 +1500,7 @@ void GCodeGenerator::smooth_path_interpolate(
if (const SupportLayer *layer = object_layer_to_print.support_layer; layer) if (const SupportLayer *layer = object_layer_to_print.support_layer; layer)
out.interpolate_add(layer->support_fills, params); out.interpolate_add(layer->support_fills, params);
} }
// Process all layers of all objects (non-sequential mode) with a parallel pipeline: // Process all layers of all objects (non-sequential mode) with a parallel pipeline:
// Generate G-code, run the filters (vase mode, cooling buffer), run the G-code analyser // Generate G-code, run the filters (vase mode, cooling buffer), run the G-code analyser
// and export G-code into file. // and export G-code into file.
@@ -1542,7 +1558,6 @@ void GCodeGenerator::process_layers(
[spiral_vase = this->m_spiral_vase.get(), &layers_to_print](LayerResult in) -> LayerResult { [spiral_vase = this->m_spiral_vase.get(), &layers_to_print](LayerResult in) -> LayerResult {
if (in.nop_layer_result) if (in.nop_layer_result)
return in; return in;
spiral_vase->enable(in.spiral_vase_enable); spiral_vase->enable(in.spiral_vase_enable);
bool last_layer = in.layer_id == layers_to_print.size() - 1; bool last_layer = in.layer_id == layers_to_print.size() - 1;
return { spiral_vase->process_layer(std::move(in.gcode), last_layer), in.layer_id, in.spiral_vase_enable, in.cooling_buffer_flush}; return { spiral_vase->process_layer(std::move(in.gcode), last_layer), in.layer_id, in.spiral_vase_enable, in.cooling_buffer_flush};
@@ -1575,10 +1590,10 @@ void GCodeGenerator::process_layers(
tbb::filter<LayerResult, std::string> pipeline_to_string = cooling; tbb::filter<LayerResult, std::string> pipeline_to_string = cooling;
if (m_find_replace) if (m_find_replace)
pipeline_to_string = pipeline_to_string & find_replace; pipeline_to_string = pipeline_to_string & find_replace;
// It registers a handler that sets locales to "C" before any TBB thread starts participating in tbb::parallel_pipeline. // It registers a handler that sets locales to "C" before any TBB thread starts participating in tbb::parallel_pipeline.
// Handler is unregistered when the destructor is called. // Handler is unregistered when the destructor is called.
TBBLocalesSetter locales_setter; TBBLocalesSetter locales_setter;
// The pipeline elements are joined using const references, thus no copying is performed. // The pipeline elements are joined using const references, thus no copying is performed.
output_stream.find_replace_supress(); output_stream.find_replace_supress();
tbb::parallel_pipeline(12, pipeline_to_layerresult & pipeline_to_string & output); tbb::parallel_pipeline(12, pipeline_to_layerresult & pipeline_to_string & output);
@@ -1668,10 +1683,10 @@ void GCodeGenerator::process_layers(
tbb::filter<LayerResult, std::string> pipeline_to_string = cooling; tbb::filter<LayerResult, std::string> pipeline_to_string = cooling;
if (m_find_replace) if (m_find_replace)
pipeline_to_string = pipeline_to_string & find_replace; pipeline_to_string = pipeline_to_string & find_replace;
// It registers a handler that sets locales to "C" before any TBB thread starts participating in tbb::parallel_pipeline. // It registers a handler that sets locales to "C" before any TBB thread starts participating in tbb::parallel_pipeline.
// Handler is unregistered when the destructor is called. // Handler is unregistered when the destructor is called.
TBBLocalesSetter locales_setter; TBBLocalesSetter locales_setter;
// The pipeline elements are joined using const references, thus no copying is performed. // The pipeline elements are joined using const references, thus no copying is performed.
output_stream.find_replace_supress(); output_stream.find_replace_supress();
tbb::parallel_pipeline(12, pipeline_to_layerresult & pipeline_to_string & output); tbb::parallel_pipeline(12, pipeline_to_layerresult & pipeline_to_string & output);
@@ -1709,6 +1724,7 @@ std::string GCodeGenerator::placeholder_parser_process(
throw Slic3r::PlaceholderParserError(format("\"%s\" custom G-code needs to be added to s_CustomGcodeSpecificOptions", name.c_str())); throw Slic3r::PlaceholderParserError(format("\"%s\" custom G-code needs to be added to s_CustomGcodeSpecificOptions", name.c_str()));
} }
#endif #endif
PlaceholderParserIntegration &ppi = m_placeholder_parser_integration; PlaceholderParserIntegration &ppi = m_placeholder_parser_integration;
try { try {
ppi.update_from_gcodewriter(m_writer, m_print->wipe_tower_data()); ppi.update_from_gcodewriter(m_writer, m_print->wipe_tower_data());
@@ -2016,8 +2032,10 @@ static std::string emit_custom_color_change_gcode_per_print_z(
// see GH issue #6362 // see GH issue #6362
gcodegen.writer().unretract(); gcodegen.writer().unretract();
} }
return gcode; return gcode;
} }
static std::string emit_custom_gcode_per_print_z( static std::string emit_custom_gcode_per_print_z(
GCodeGenerator &gcodegen, GCodeGenerator &gcodegen,
const CustomGCode::Item &custom_gcode, const CustomGCode::Item &custom_gcode,
@@ -2043,11 +2061,13 @@ static std::string emit_custom_color_change_gcode_per_print_z(
} else { } else {
if (gcode_type == CustomGCode::PausePrint) { // Pause print if (gcode_type == CustomGCode::PausePrint) { // Pause print
const std::string pause_print_msg = custom_gcode.extra; const std::string pause_print_msg = custom_gcode.extra;
// add tag for processor // add tag for processor
gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Pause_Print) + "\n"; gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Pause_Print) + "\n";
//! FIXME_in_fw show message during print pause //! FIXME_in_fw show message during print pause
if (!pause_print_msg.empty()) if (!pause_print_msg.empty())
gcode += "M117 " + pause_print_msg + "\n"; gcode += "M117 " + pause_print_msg + "\n";
DynamicConfig cfg; DynamicConfig cfg;
cfg.set_key_value("color_change_extruder", new ConfigOptionInt(int(current_extruder_id))); cfg.set_key_value("color_change_extruder", new ConfigOptionInt(int(current_extruder_id)));
gcode += gcodegen.placeholder_parser_process("pause_print_gcode", config.pause_print_gcode, current_extruder_id, &cfg); gcode += gcodegen.placeholder_parser_process("pause_print_gcode", config.pause_print_gcode, current_extruder_id, &cfg);
@@ -2058,7 +2078,6 @@ static std::string emit_custom_color_change_gcode_per_print_z(
gcode += gcodegen.placeholder_parser_process("template_custom_gcode", config.template_custom_gcode, current_extruder_id); gcode += gcodegen.placeholder_parser_process("template_custom_gcode", config.template_custom_gcode, current_extruder_id);
else // custom Gcode else // custom Gcode
gcode += custom_gcode.extra; gcode += custom_gcode.extra;
} }
gcode += "\n"; gcode += "\n";
} }
@@ -2146,6 +2165,7 @@ bool GCodeGenerator::line_distancer_is_required(const std::vector<unsigned int>&
} }
return false; return false;
} }
Polyline GCodeGenerator::get_layer_change_xy_path(const Vec3d &from, const Vec3d &to) { Polyline GCodeGenerator::get_layer_change_xy_path(const Vec3d &from, const Vec3d &to) {
bool could_be_wipe_disabled{false}; bool could_be_wipe_disabled{false};
@@ -2233,6 +2253,7 @@ std::string GCodeGenerator::generate_ramping_layer_change_gcode(
const GCode::Impl::Travels::ElevatedTravelParams &elevation_params const GCode::Impl::Travels::ElevatedTravelParams &elevation_params
) const { ) const {
using namespace GCode::Impl::Travels; using namespace GCode::Impl::Travels;
const std::vector<double> ensure_points_at_distances = linspace( const std::vector<double> ensure_points_at_distances = linspace(
elevation_params.slope_end - elevation_params.blend_width / 2.0, elevation_params.slope_end - elevation_params.blend_width / 2.0,
elevation_params.slope_end + elevation_params.blend_width / 2.0, elevation_params.slope_end + elevation_params.blend_width / 2.0,
@@ -2254,6 +2275,7 @@ std::string GCodeGenerator::generate_ramping_layer_change_gcode(
} }
return travel_gcode; return travel_gcode;
} }
// In sequential mode, process_layer is called once per each object and its copy, // In sequential mode, process_layer is called once per each object and its copy,
// therefore layers will contain a single entry and single_object_instance_idx will point to the copy of the object. // therefore layers will contain a single entry and single_object_instance_idx will point to the copy of the object.
// In non-sequential mode, process_layer is called per each print_z height with all object and support layers accumulated. // In non-sequential mode, process_layer is called per each print_z height with all object and support layers accumulated.
@@ -2330,6 +2352,7 @@ LayerResult GCodeGenerator::process_layer(
m_enable_loop_clipping = !enable; m_enable_loop_clipping = !enable;
} }
std::string gcode; std::string gcode;
assert(is_decimal_separator_point()); // for the sprintfs assert(is_decimal_separator_point()); // for the sprintfs
@@ -2365,6 +2388,7 @@ LayerResult GCodeGenerator::process_layer(
m_layer = &layer; m_layer = &layer;
if (this->line_distancer_is_required(layer_tools.extruders) && this->m_layer != nullptr && this->m_layer->lower_layer != nullptr) if (this->line_distancer_is_required(layer_tools.extruders) && this->m_layer != nullptr && this->m_layer->lower_layer != nullptr)
m_travel_obstacle_tracker.init_layer(layer, layers); m_travel_obstacle_tracker.init_layer(layer, layers);
m_object_layer_over_raft = false; m_object_layer_over_raft = false;
if (!first_layer && ! print.config().layer_gcode.value.empty()) { if (!first_layer && ! print.config().layer_gcode.value.empty()) {
DynamicConfig config; DynamicConfig config;
@@ -2452,11 +2476,13 @@ LayerResult GCodeGenerator::process_layer(
// Now we have picked the right extruder, so we can emit the custom g-code. // Now we have picked the right extruder, so we can emit the custom g-code.
gcode += ProcessLayer::emit_custom_gcode_per_print_z(*this, *layer_tools.custom_gcode, m_writer.extruder()->id(), first_extruder_id, print.config()); gcode += ProcessLayer::emit_custom_gcode_per_print_z(*this, *layer_tools.custom_gcode, m_writer.extruder()->id(), first_extruder_id, print.config());
} }
if (auto loops_it = skirt_loops_per_extruder.find(extruder_id); loops_it != skirt_loops_per_extruder.end()) { if (auto loops_it = skirt_loops_per_extruder.find(extruder_id); loops_it != skirt_loops_per_extruder.end()) {
if (!this->m_config.complete_objects.value) { if (!this->m_config.complete_objects.value) {
gcode += this->m_label_objects.maybe_stop_instance(); gcode += this->m_label_objects.maybe_stop_instance();
} }
this->m_label_objects.update(nullptr); this->m_label_objects.update(nullptr);
const std::pair<size_t, size_t> loops = loops_it->second; const std::pair<size_t, size_t> loops = loops_it->second;
this->set_origin(0., 0.); this->set_origin(0., 0.);
m_avoid_crossing_perimeters.use_external_mp(); m_avoid_crossing_perimeters.use_external_mp();
@@ -2478,10 +2504,12 @@ LayerResult GCodeGenerator::process_layer(
// Extrude brim with the extruder of the 1st region. // Extrude brim with the extruder of the 1st region.
if (! m_brim_done) { if (! m_brim_done) {
if (!this->m_config.complete_objects.value) { if (!this->m_config.complete_objects.value) {
gcode += this->m_label_objects.maybe_stop_instance(); gcode += this->m_label_objects.maybe_stop_instance();
} }
this->m_label_objects.update(nullptr); this->m_label_objects.update(nullptr);
this->set_origin(0., 0.); this->set_origin(0., 0.);
m_avoid_crossing_perimeters.use_external_mp(); m_avoid_crossing_perimeters.use_external_mp();
for (const ExtrusionEntity *ee : print.brim().entities) for (const ExtrusionEntity *ee : print.brim().entities)
@@ -2491,7 +2519,6 @@ LayerResult GCodeGenerator::process_layer(
// Allow a straight travel move to the first object point. // Allow a straight travel move to the first object point.
m_avoid_crossing_perimeters.disable_once(); m_avoid_crossing_perimeters.disable_once();
} }
this->m_label_objects.update(first_instance); this->m_label_objects.update(first_instance);
// We are almost ready to print. However, we must go through all the objects twice to print the the overridden extrusions first (infill/perimeter wiping feature): // We are almost ready to print. However, we must go through all the objects twice to print the the overridden extrusions first (infill/perimeter wiping feature):
@@ -2515,6 +2542,7 @@ LayerResult GCodeGenerator::process_layer(
is_anything_overridden, false /* print_wipe_extrusions */); is_anything_overridden, false /* print_wipe_extrusions */);
} }
// During layer change the starting position of next layer is now known. // During layer change the starting position of next layer is now known.
// The solution is thus to emplace a temporary tag to the gcode, cache the postion and // The solution is thus to emplace a temporary tag to the gcode, cache the postion and
// replace the tag later. The tag is Layer_Change_Travel, the cached position is // replace the tag later. The tag is Layer_Change_Travel, the cached position is
@@ -2582,6 +2610,7 @@ LayerResult GCodeGenerator::process_layer(
} }
boost::algorithm::replace_first(gcode, tag, layer_change_gcode); boost::algorithm::replace_first(gcode, tag, layer_change_gcode);
BOOST_LOG_TRIVIAL(trace) << "Exported layer " << layer.id() << " print_z " << print_z << BOOST_LOG_TRIVIAL(trace) << "Exported layer " << layer.id() << " print_z " << print_z <<
log_memory_info(); log_memory_info();
@@ -2640,7 +2669,6 @@ void GCodeGenerator::process_layer_single_object(
const PrintObject &print_object = print_instance.print_object; const PrintObject &print_object = print_instance.print_object;
const Print &print = *print_object.print(); const Print &print = *print_object.print();
if (! print_wipe_extrusions && layer_to_print.support_layer != nullptr) if (! print_wipe_extrusions && layer_to_print.support_layer != nullptr)
if (const SupportLayer &support_layer = *layer_to_print.support_layer; ! support_layer.support_fills.entities.empty()) { if (const SupportLayer &support_layer = *layer_to_print.support_layer; ! support_layer.support_fills.entities.empty()) {
ExtrusionRole role = support_layer.support_fills.role(); ExtrusionRole role = support_layer.support_fills.role();
@@ -2814,11 +2842,8 @@ void GCodeGenerator::process_layer_single_object(
} }
} }
} }
} }
void GCodeGenerator::apply_print_config(const PrintConfig &print_config) void GCodeGenerator::apply_print_config(const PrintConfig &print_config)
{ {
m_writer.apply_print_config(print_config); m_writer.apply_print_config(print_config);
@@ -2862,7 +2887,6 @@ void GCodeGenerator::encode_full_config(const Print& print, std::vector<std::pai
void GCodeGenerator::set_extruders(const std::vector<unsigned int> &extruder_ids) void GCodeGenerator::set_extruders(const std::vector<unsigned int> &extruder_ids)
{ {
m_writer.set_extruders(extruder_ids); m_writer.set_extruders(extruder_ids);
m_wipe.init(this->config(), extruder_ids); m_wipe.init(this->config(), extruder_ids);
} }
@@ -2872,6 +2896,7 @@ void GCodeGenerator::set_origin(const Vec2d &pointf)
const auto offset = Point::new_scale(m_origin - pointf); const auto offset = Point::new_scale(m_origin - pointf);
if (last_position.has_value()) if (last_position.has_value())
*(this->last_position) += offset; *(this->last_position) += offset;
m_wipe.offset_path(offset); m_wipe.offset_path(offset);
m_origin = pointf; m_origin = pointf;
} }
@@ -2889,7 +2914,6 @@ std::string GCodeGenerator::preamble()
return gcode; return gcode;
} }
// called by GCodeGenerator::process_layer() // called by GCodeGenerator::process_layer()
std::string GCodeGenerator::change_layer( std::string GCodeGenerator::change_layer(
coordf_t previous_layer_z, coordf_t previous_layer_z,
@@ -2904,6 +2928,7 @@ std::string GCodeGenerator::change_layer(
if (m_writer.multiple_extruders) { if (m_writer.multiple_extruders) {
gcode += m_label_objects.maybe_change_instance(m_writer); gcode += m_label_objects.maybe_change_instance(m_writer);
} }
if (!EXTRUDER_CONFIG(travel_ramping_lift) && EXTRUDER_CONFIG(retract_layer_change)) { if (!EXTRUDER_CONFIG(travel_ramping_lift) && EXTRUDER_CONFIG(retract_layer_change)) {
gcode += this->retract_and_wipe(); gcode += this->retract_and_wipe();
} else if (EXTRUDER_CONFIG(travel_ramping_lift) && !vase_mode){ } else if (EXTRUDER_CONFIG(travel_ramping_lift) && !vase_mode){
@@ -2931,6 +2956,7 @@ std::string GCodeGenerator::change_layer(
// forget last wiping path as wiping after raising Z is pointless // forget last wiping path as wiping after raising Z is pointless
m_wipe.reset_path(); m_wipe.reset_path();
return gcode; return gcode;
} }
@@ -2945,10 +2971,11 @@ static inline bool validate_smooth_path(const GCode::SmoothPath &smooth_path, bo
return true; return true;
} }
#endif //NDEBUG #endif //NDEBUG
static constexpr const double min_gcode_segment_length = 0.002; static constexpr const double min_gcode_segment_length = 0.002;
std::string GCodeGenerator::extrude_loop(const ExtrusionLoop &loop_src, const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed) std::string GCodeGenerator::extrude_loop(const ExtrusionLoop &loop_src, const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed)
{ {
// Extrude all loops CCW. // Extrude all loops CCW.
//w38 //w38
//bool is_hole = loop_src.is_clockwise(); //bool is_hole = loop_src.is_clockwise();
@@ -2966,7 +2993,6 @@ std::string GCodeGenerator::extrude_loop(const ExtrusionLoop &loop_src, const GC
//w38 //w38
seam_point = m_seam_placer.place_seam(m_layer, new_loop_src, m_config.external_perimeters_first, seam_point); seam_point = m_seam_placer.place_seam(m_layer, new_loop_src, m_config.external_perimeters_first, seam_point);
} }
// Because the G-code export has 1um resolution, don't generate segments shorter than 1.5 microns, // Because the G-code export has 1um resolution, don't generate segments shorter than 1.5 microns,
// thus empty path segments will not be produced by G-code export. // thus empty path segments will not be produced by G-code export.
//w38 //w38
@@ -2982,32 +3008,38 @@ std::string GCodeGenerator::extrude_loop(const ExtrusionLoop &loop_src, const GC
if (smooth_path.empty()) if (smooth_path.empty())
return {}; return {};
assert(validate_smooth_path(smooth_path, ! m_enable_loop_clipping)); assert(validate_smooth_path(smooth_path, ! m_enable_loop_clipping));
// Apply the small perimeter speed. // Apply the small perimeter speed.
//w38 //w38//Y27
if (new_loop_src.paths.front().role().is_perimeter() && new_loop_src.length() <= SMALL_PERIMETER_LENGTH && speed == -1) bool is_small_perimeter_length = false;
if (new_loop_src.paths.front().role().is_perimeter() && new_loop_src.length() <= SMALL_PERIMETER_LENGTH && speed == -1) {
speed = m_config.small_perimeter_speed.get_abs_value(m_config.perimeter_speed); speed = m_config.small_perimeter_speed.get_abs_value(m_config.perimeter_speed);
is_small_perimeter_length = true;
}
// Extrude along the smooth path. // Extrude along the smooth path.
std::string gcode; std::string gcode;
for (const GCode::SmoothPathElement &el : smooth_path) //Y27
for (const GCode::SmoothPathElement &el : smooth_path) {
m_resonance_avoidance = !is_small_perimeter_length;
gcode += this->_extrude(el.path_attributes, el.path, description, speed); gcode += this->_extrude(el.path_attributes, el.path, description, speed);
}
// reset acceleration // reset acceleration
gcode += m_writer.set_print_acceleration(fast_round_up<unsigned int>(m_config.default_acceleration.value)); gcode += m_writer.set_print_acceleration(fast_round_up<unsigned int>(m_config.default_acceleration.value));
if (m_wipe.enabled()) { if (m_wipe.enabled()) {
// Wipe will hide the seam. // Wipe will hide the seam.
m_wipe.set_path(std::move(smooth_path)); m_wipe.set_path(std::move(smooth_path));
}//w38 }
//w38
else if (new_loop_src.paths.back().role().is_external_perimeter() && m_layer != nullptr && m_config.perimeters.value > 1) { else if (new_loop_src.paths.back().role().is_external_perimeter() && m_layer != nullptr && m_config.perimeters.value > 1) {
// Only wipe inside if the wipe along the perimeter is disabled. // Only wipe inside if the wipe along the perimeter is disabled.
// Make a little move inwards before leaving loop. // Make a little move inwards before leaving loop.
if (std::optional<Point> pt = wipe_hide_seam(smooth_path, is_hole, scale_(EXTRUDER_CONFIG(nozzle_diameter))); pt) { if (std::optional<Point> pt = wipe_hide_seam(smooth_path, is_hole, scale_(EXTRUDER_CONFIG(nozzle_diameter))); pt) {
// Generate the seam hiding travel move. // Generate the seam hiding travel move.
gcode += m_writer.travel_to_xy(this->point_to_gcode(*pt), "move inwards before travel"); gcode += m_writer.travel_to_xy(this->point_to_gcode(*pt), "move inwards before travel");
this->last_position = *pt; this->last_position = *pt;
@@ -3016,6 +3048,7 @@ std::string GCodeGenerator::extrude_loop(const ExtrusionLoop &loop_src, const GC
return gcode; return gcode;
} }
std::string GCodeGenerator::extrude_skirt( std::string GCodeGenerator::extrude_skirt(
const ExtrusionLoop &loop_src, const ExtrusionFlow &extrusion_flow_override, const ExtrusionLoop &loop_src, const ExtrusionFlow &extrusion_flow_override,
const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed) const GCode::SmoothPathCache &smooth_path_cache, const std::string_view description, double speed)
@@ -3024,13 +3057,16 @@ std::string GCodeGenerator::extrude_skirt(
Point seam_point = this->last_position.has_value() ? *this->last_position : Point::Zero(); Point seam_point = this->last_position.has_value() ? *this->last_position : Point::Zero();
GCode::SmoothPath smooth_path = smooth_path_cache.resolve_or_fit_split_with_seam( GCode::SmoothPath smooth_path = smooth_path_cache.resolve_or_fit_split_with_seam(
loop_src, false, m_scaled_resolution, seam_point, scaled<double>(0.0015)); loop_src, false, m_scaled_resolution, seam_point, scaled<double>(0.0015));
// Clip the path to avoid the extruder to get exactly on the first point of the loop; // Clip the path to avoid the extruder to get exactly on the first point of the loop;
// if polyline was shorter than the clipping distance we'd get a null polyline, so // if polyline was shorter than the clipping distance we'd get a null polyline, so
// we discard it in that case. // we discard it in that case.
if (m_enable_loop_clipping) if (m_enable_loop_clipping)
clip_end(smooth_path, scale_(EXTRUDER_CONFIG(nozzle_diameter)) * LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER, scaled<double>(min_gcode_segment_length)); clip_end(smooth_path, scale_(EXTRUDER_CONFIG(nozzle_diameter)) * LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER, scaled<double>(min_gcode_segment_length));
if (smooth_path.empty()) if (smooth_path.empty())
return {}; return {};
assert(validate_smooth_path(smooth_path, ! m_enable_loop_clipping)); assert(validate_smooth_path(smooth_path, ! m_enable_loop_clipping));
// Extrude along the smooth path. // Extrude along the smooth path.
@@ -3041,8 +3077,10 @@ std::string GCodeGenerator::extrude_skirt(
el.path_attributes.height = extrusion_flow_override.height; el.path_attributes.height = extrusion_flow_override.height;
gcode += this->_extrude(el.path_attributes, el.path, description, speed); gcode += this->_extrude(el.path_attributes, el.path, description, speed);
} }
// reset acceleration // reset acceleration
gcode += m_writer.set_print_acceleration(fast_round_up<unsigned int>(m_config.default_acceleration.value)); gcode += m_writer.set_print_acceleration(fast_round_up<unsigned int>(m_config.default_acceleration.value));
if (m_wipe.enabled()) if (m_wipe.enabled())
// Wipe will hide the seam. // Wipe will hide the seam.
m_wipe.set_path(std::move(smooth_path)); m_wipe.set_path(std::move(smooth_path));
@@ -3059,13 +3097,15 @@ std::string GCodeGenerator::extrude_multi_path(const ExtrusionMultiPath &multipa
} }
#endif // NDEBUG #endif // NDEBUG
GCode::SmoothPath smooth_path = smooth_path_cache.resolve_or_fit(multipath, reverse, m_scaled_resolution); GCode::SmoothPath smooth_path = smooth_path_cache.resolve_or_fit(multipath, reverse, m_scaled_resolution);
// extrude along the path
// extrude along the path
std::string gcode; std::string gcode;
for (GCode::SmoothPathElement &el : smooth_path) for (GCode::SmoothPathElement &el : smooth_path)
gcode += this->_extrude(el.path_attributes, el.path, description, speed); gcode += this->_extrude(el.path_attributes, el.path, description, speed);
GCode::reverse(smooth_path); GCode::reverse(smooth_path);
m_wipe.set_path(std::move(smooth_path)); m_wipe.set_path(std::move(smooth_path));
// reset acceleration // reset acceleration
gcode += m_writer.set_print_acceleration((unsigned int)floor(m_config.default_acceleration.value + 0.5)); gcode += m_writer.set_print_acceleration((unsigned int)floor(m_config.default_acceleration.value + 0.5));
return gcode; return gcode;
@@ -3214,6 +3254,7 @@ std::string GCodeGenerator::travel_to_first_position(const Vec3crd& point, const
this->m_layer_change_used_external_mp = this->m_avoid_crossing_perimeters.use_external_mp_once; this->m_layer_change_used_external_mp = this->m_avoid_crossing_perimeters.use_external_mp_once;
this->m_layer_change_layer = this->layer(); this->m_layer_change_layer = this->layer();
this->m_layer_change_origin = this->origin(); this->m_layer_change_origin = this->origin();
double lift{ double lift{
EXTRUDER_CONFIG(travel_ramping_lift) ? EXTRUDER_CONFIG(travel_max_lift) : EXTRUDER_CONFIG(travel_ramping_lift) ? EXTRUDER_CONFIG(travel_max_lift) :
EXTRUDER_CONFIG(retract_lift)}; EXTRUDER_CONFIG(retract_lift)};
@@ -3230,6 +3271,7 @@ std::string GCodeGenerator::travel_to_first_position(const Vec3crd& point, const
gcode += this->writer().get_travel_to_z_gcode(from_z + lift, "lift"); gcode += this->writer().get_travel_to_z_gcode(from_z + lift, "lift");
} }
} }
const std::string comment{"move to first layer point"}; const std::string comment{"move to first layer point"};
gcode += insert_gcode(); gcode += insert_gcode();
@@ -3240,7 +3282,9 @@ std::string GCodeGenerator::travel_to_first_position(const Vec3crd& point, const
this->last_position = point.head<2>(); this->last_position = point.head<2>();
this->writer().update_position(gcode_point); this->writer().update_position(gcode_point);
} }
m_current_layer_first_position = gcode_point; m_current_layer_first_position = gcode_point;
return gcode; return gcode;
} }
@@ -3257,6 +3301,7 @@ double cap_speed(
} }
return speed; return speed;
} }
std::string GCodeGenerator::_extrude( std::string GCodeGenerator::_extrude(
const ExtrusionAttributes &path_attr, const ExtrusionAttributes &path_attr,
const Geometry::ArcWelder::Path &path, const Geometry::ArcWelder::Path &path,
@@ -3272,6 +3317,7 @@ std::string GCodeGenerator::_extrude(
if (m_writer.multiple_extruders && has_active_instance) { if (m_writer.multiple_extruders && has_active_instance) {
gcode += m_label_objects.maybe_change_instance(m_writer); gcode += m_label_objects.maybe_change_instance(m_writer);
} }
if (!m_current_layer_first_position) { if (!m_current_layer_first_position) {
const Vec3crd point = to_3d(path.front().point, scaled(this->m_last_layer_z)); const Vec3crd point = to_3d(path.front().point, scaled(this->m_last_layer_z));
gcode += this->travel_to_first_position(point, unscaled(point.z()), path_attr.role, [&](){ gcode += this->travel_to_first_position(point, unscaled(point.z()), path_attr.role, [&](){
@@ -3307,6 +3353,7 @@ std::string GCodeGenerator::_extrude(
} else { } else {
this->m_already_unretracted = true; this->m_already_unretracted = true;
gcode += "FIRST_UNRETRACT" + this->unretract(); gcode += "FIRST_UNRETRACT" + this->unretract();
//First unretract may or may not be removed thus we must start from E0. //First unretract may or may not be removed thus we must start from E0.
gcode += this->writer().reset_e(); gcode += this->writer().reset_e();
} }
@@ -3409,7 +3456,6 @@ std::string GCodeGenerator::_extrude(
std::pair<float, float> dynamic_speed_and_fan_speed{-1, -1}; std::pair<float, float> dynamic_speed_and_fan_speed{-1, -1};
if (path_attr.overhang_attributes.has_value()) { if (path_attr.overhang_attributes.has_value()) {
double external_perim_reference_speed = m_config.get_abs_value("external_perimeter_speed"); double external_perim_reference_speed = m_config.get_abs_value("external_perimeter_speed");
if (external_perim_reference_speed == 0) if (external_perim_reference_speed == 0)
external_perim_reference_speed = m_volumetric_speed / path_attr.mm3_per_mm; external_perim_reference_speed = m_volumetric_speed / path_attr.mm3_per_mm;
@@ -3421,22 +3467,33 @@ std::string GCodeGenerator::_extrude(
external_perim_reference_speed, speed); external_perim_reference_speed, speed);
} }
//Y27 //Y27
bool dont_speed_down_by_overhang = true; if (path_attr.role == ExtrusionRole::ExternalPerimeter && m_config.opt_bool("resonance_avoidance")) {
if (dynamic_speed_and_fan_speed.first > -1) { if (dynamic_speed_and_fan_speed.first > -1) {
if (speed != dynamic_speed_and_fan_speed.first) { if (speed != dynamic_speed_and_fan_speed.first) {
dont_speed_down_by_overhang = false; double min_speed = cap_speed(speed, path_attr.mm3_per_mm, m_config, m_writer.extruder()->id());
speed = dynamic_speed_and_fan_speed.first; if (min_speed > m_config.opt_float("max_resonance_avoidance_speed")) {
m_resonance_avoidance = false;
} }
} }
speed = dynamic_speed_and_fan_speed.first;
}
// cap speed with max_volumetric_speed anyway (even if user is not using autospeed) // cap speed with max_volumetric_speed anyway (even if user is not using autospeed)
speed = cap_speed(speed, path_attr.mm3_per_mm, m_config, m_writer.extruder()->id()); speed = cap_speed(speed, path_attr.mm3_per_mm, m_config, m_writer.extruder()->id());
//Y27
if (path_attr.role == ExtrusionRole::ExternalPerimeter && m_config.opt_bool("resonance_avoidance" ) && dont_speed_down_by_overhang) { if (m_resonance_avoidance) {
if (speed <= m_config.opt_float("max_resonance_avoidance_speed")) { if (speed <= m_config.opt_float("max_resonance_avoidance_speed")) {
speed = std::min(speed, m_config.opt_float("min_resonance_avoidance_speed")); speed = std::min(speed, m_config.opt_float("min_resonance_avoidance_speed"));
} }
m_resonance_avoidance = true;
} }
} else {
if (dynamic_speed_and_fan_speed.first > -1) {
speed = dynamic_speed_and_fan_speed.first;
}
speed = cap_speed(speed, path_attr.mm3_per_mm, m_config, m_writer.extruder()->id());
}
double F = speed * 60; // convert mm/sec to mm/min double F = speed * 60; // convert mm/sec to mm/min
// extrude arc or line // extrude arc or line
@@ -3502,6 +3559,7 @@ std::string GCodeGenerator::_extrude(
gcode += m_writer.set_speed(F, "", cooling_marker_setspeed_comments); gcode += m_writer.set_speed(F, "", cooling_marker_setspeed_comments);
if (dynamic_speed_and_fan_speed.second >= 0) if (dynamic_speed_and_fan_speed.second >= 0)
gcode += ";_SET_FAN_SPEED" + std::to_string(int(dynamic_speed_and_fan_speed.second)) + "\n"; gcode += ";_SET_FAN_SPEED" + std::to_string(int(dynamic_speed_and_fan_speed.second)) + "\n";
std::string comment; std::string comment;
if (m_config.gcode_comments) { if (m_config.gcode_comments) {
comment = description; comment = description;
@@ -3550,7 +3608,6 @@ std::string GCodeGenerator::_extrude(
} }
} }
if (m_enable_cooling_markers) if (m_enable_cooling_markers)
gcode += path_attr.role.is_bridge() ? ";_BRIDGE_FAN_END\n" : ";_EXTRUDE_END\n"; gcode += path_attr.role.is_bridge() ? ";_BRIDGE_FAN_END\n" : ";_EXTRUDE_END\n";
@@ -3561,13 +3618,13 @@ std::string GCodeGenerator::_extrude(
return gcode; return gcode;
} }
std::string GCodeGenerator::generate_travel_gcode( std::string GCodeGenerator::generate_travel_gcode(
const Points3& travel, const Points3& travel,
const std::string& comment, const std::string& comment,
const std::function<std::string()>& insert_gcode const std::function<std::string()>& insert_gcode
) { ) {
std::string gcode; std::string gcode;
const unsigned acceleration =(unsigned)(m_config.travel_acceleration.value + 0.5); const unsigned acceleration =(unsigned)(m_config.travel_acceleration.value + 0.5);
if (travel.empty()) { if (travel.empty()) {
@@ -3576,7 +3633,6 @@ std::string GCodeGenerator::generate_travel_gcode(
// generate G-code for the travel move // generate G-code for the travel move
// use G1 because we rely on paths being straight (G0 may make round paths) // use G1 because we rely on paths being straight (G0 may make round paths)
gcode += this->m_writer.set_travel_acceleration(acceleration); gcode += this->m_writer.set_travel_acceleration(acceleration);
Vec3d previous_point{this->point_to_gcode(travel.front())}; Vec3d previous_point{this->point_to_gcode(travel.front())};
@@ -3589,6 +3645,7 @@ std::string GCodeGenerator::generate_travel_gcode(
gcode += insert_gcode(); gcode += insert_gcode();
already_inserted = true; already_inserted = true;
} }
gcode += this->m_writer.travel_to_xyz(previous_point, gcode_point, comment); gcode += this->m_writer.travel_to_xyz(previous_point, gcode_point, comment);
this->last_position = point.head<2>(); this->last_position = point.head<2>();
previous_point = gcode_point; previous_point = gcode_point;
@@ -3690,7 +3747,6 @@ std::string GCodeGenerator::travel_to(
const std::string &comment, const std::string &comment,
const std::function<std::string()>& insert_gcode const std::function<std::string()>& insert_gcode
) { ) {
// check whether a straight travel move would need retraction // check whether a straight travel move would need retraction
bool could_be_wipe_disabled {false}; bool could_be_wipe_disabled {false};
@@ -3735,6 +3791,7 @@ std::string GCodeGenerator::travel_to(
(upper_limit > 0 && initial_elevation > upper_limit)) { (upper_limit > 0 && initial_elevation > upper_limit)) {
can_be_flat = true; can_be_flat = true;
} }
const Points3 travel = ( const Points3 travel = (
can_be_flat ? can_be_flat ?
GCode::Impl::Travels::generate_flat_travel(xy_path.points, initial_elevation) : GCode::Impl::Travels::generate_flat_travel(xy_path.points, initial_elevation) :
@@ -3807,6 +3864,7 @@ std::string GCodeGenerator::set_extruder(unsigned int extruder_id, double print_
if (!this->m_config.complete_objects.value) { if (!this->m_config.complete_objects.value) {
gcode += this->m_label_objects.maybe_stop_instance(); gcode += this->m_label_objects.maybe_stop_instance();
} }
// prepend retraction on the current extruder // prepend retraction on the current extruder
gcode += this->retract_and_wipe(true); gcode += this->retract_and_wipe(true);
@@ -3976,7 +4034,6 @@ Point GCodeGenerator::gcode_to_point(const Vec2d &point) const
// This function may be called at the very start from toolchange G-code when the extruder is not assigned yet. // This function may be called at the very start from toolchange G-code when the extruder is not assigned yet.
pt += m_config.extruder_offset.get_at(extruder->id()); pt += m_config.extruder_offset.get_at(extruder->id());
return scaled<coord_t>(pt); return scaled<coord_t>(pt);
} }
} // namespace Slic3r } // namespace Slic3r

View File

@@ -456,6 +456,9 @@ private:
// Processor // Processor
GCodeProcessor m_processor; GCodeProcessor m_processor;
//Y27
bool m_resonance_avoidance;
// Back-pointer to Print (const). // Back-pointer to Print (const).
const Print* m_print; const Print* m_print;
std::string _extrude( std::string _extrude(

View File

@@ -466,39 +466,42 @@ static std::vector<std::string> s_Preset_print_options {
"wipe_tower_width", "wipe_tower_cone_angle", "wipe_tower_rotation_angle", "wipe_tower_brim_width", "wipe_tower_bridging", "single_extruder_multi_material_priming", "mmu_segmented_region_max_width", "wipe_tower_width", "wipe_tower_cone_angle", "wipe_tower_rotation_angle", "wipe_tower_brim_width", "wipe_tower_bridging", "single_extruder_multi_material_priming", "mmu_segmented_region_max_width",
"mmu_segmented_region_interlocking_depth", "wipe_tower_extruder", "wipe_tower_no_sparse_layers", "wipe_tower_extra_flow", "wipe_tower_extra_spacing", "compatible_printers", "compatible_printers_condition", "inherits", "mmu_segmented_region_interlocking_depth", "wipe_tower_extruder", "wipe_tower_no_sparse_layers", "wipe_tower_extra_flow", "wipe_tower_extra_spacing", "compatible_printers", "compatible_printers_condition", "inherits",
"perimeter_generator", "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle", "perimeter_generator", "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle",
"wall_distribution_count", "min_feature_size", "min_bead_width" "wall_distribution_count", "min_feature_size", "min_bead_width",
//B36 //B36
,"first_layer_travel_speed" "first_layer_travel_speed",
//B37 //B37
,"first_layer_infill_speed" "first_layer_infill_speed",
//w11 //w11
,"detect_narrow_internal_solid_infill" "detect_narrow_internal_solid_infill",
//Y21 //Y21
,"seam_gap" "seam_gap",
//w16 //w16
, "top_one_wall_type" "top_one_wall_type",
//w17 //w17
,"top_area_threshold" "top_area_threshold",
//w21 //w21
,"filter_top_gap_infill" "filter_top_gap_infill",
//w23 //w23
,"only_one_wall_first_layer" "only_one_wall_first_layer",
//w25 //w25
,"slow_down_layers" "slow_down_layers",
//w26 //w26
,"elefant_foot_compensation_layers" "elefant_foot_compensation_layers",
//w27 //w27
,"precise_z_height" "precise_z_height",
//w28 //w28
,"max_bridge_length" "max_bridge_length",
//w30 //w30
,"top_solid_infill_flow_ratio", "bottom_solid_infill_flow_ratio" "top_solid_infill_flow_ratio", "bottom_solid_infill_flow_ratio",
//w33 //w33
,"ironing_pattern" "ironing_pattern",
//w38 //w38
,"overhang_reverse","overhang_reverse_internal_only","overhang_reverse_threshold" "overhang_reverse", "overhang_reverse_internal_only", "overhang_reverse_threshold",
//w39 //w39
,"precise_outer_wall"}; "precise_outer_wall",
//Y27
"resonance_avoidance", "min_resonance_avoidance_speed", "max_resonance_avoidance_speed"
};
static std::vector<std::string> s_Preset_filament_options { static std::vector<std::string> s_Preset_filament_options {
"filament_colour", "filament_diameter", "filament_type", "filament_soluble", "filament_notes", "filament_max_volumetric_speed", "filament_colour", "filament_diameter", "filament_type", "filament_soluble", "filament_notes", "filament_max_volumetric_speed",
@@ -567,8 +570,6 @@ static std::vector<std::string> s_Preset_printer_options {
"bed_exclude_area", "bed_exclude_area",
//Y25 //Y25
"wipe_device", "wipe_device",
//Y27
"resonance_avoidance", "min_resonance_avoidance_speed", "max_resonance_avoidance_speed",
//Y16 //Y16
"chamber_temperature", "auxiliary_fan", "chamber_fan" "chamber_temperature", "auxiliary_fan", "chamber_fan"
}; };

View File

@@ -228,10 +228,6 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|| opt_key == "single_extruder_multi_material" || opt_key == "single_extruder_multi_material"
//Y25 //Y25
|| opt_key == "wipe_device" || opt_key == "wipe_device"
//Y27
|| opt_key == "resonance_avoidance"
|| opt_key == "min_resonance_avoidance_speed"
|| opt_key == "max_resonance_avoidance_speed"
|| opt_key == "temperature" || opt_key == "temperature"
|| opt_key == "idle_temperature" || opt_key == "idle_temperature"
|| opt_key == "wipe_tower" || opt_key == "wipe_tower"

View File

@@ -702,6 +702,30 @@ void PrintConfigDef::init_fff_params()
def->mode = comExpert; def->mode = comExpert;
def->set_default_value(new ConfigOptionBools{false}); def->set_default_value(new ConfigOptionBools{false});
//Y27
def = this->add("resonance_avoidance", coBool);
def->label = L("Resonance avoidance");
def->tooltip = L("By reducing the speed of the outer wall to avoid the resonance zone of the printer, ringing on the surface of the model are avoided.\n"
"Please turn this option off when testing ringing.");
def->mode = comExpert;
def->set_default_value(new ConfigOptionBool(true));
def = this->add("min_resonance_avoidance_speed", coFloat);
def->label = L("Min");
def->tooltip = L("Minimum speed of resonance avoidance.");
def->sidetext = L("mm/s");
def->min = 0;
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(70));
def = this->add("max_resonance_avoidance_speed", coFloat);
def->label = L("Max");
def->tooltip = L("Maximum speed of resonance avoidance.");
def->sidetext = L("mm/s");
def->min = 0;
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(120));
// TRN FilamentSettings : "Dynamic fan speeds" // TRN FilamentSettings : "Dynamic fan speeds"
auto fan_speed_setting_description = L("Overhang size is expressed as a percentage of overlap of the extrusion with the previous layer: " auto fan_speed_setting_description = L("Overhang size is expressed as a percentage of overlap of the extrusion with the previous layer: "
"100% would be full overlap (no overhang), while 0% represents full overhang (floating extrusion, bridge). " "100% would be full overlap (no overhang), while 0% represents full overhang (floating extrusion, bridge). "
@@ -3007,30 +3031,6 @@ void PrintConfigDef::init_fff_params()
def->mode = comExpert; def->mode = comExpert;
def->set_default_value(new ConfigOptionBool(false)); def->set_default_value(new ConfigOptionBool(false));
//Y27
def = this->add("resonance_avoidance", coBool);
def->label = L("Resonance avoidance");
def->tooltip = L("By reducing the speed of the outer wall to avoid the resonance zone of the printer, ringing on the surface of the model are avoided. "
"Turn this option off when testing ringing.");
def->mode = comExpert;
def->set_default_value(new ConfigOptionBool(true));
def = this->add("min_resonance_avoidance_speed", coFloat);
def->label = L("Min");
def->tooltip = L("Minimum speed of resonance avoidance.");
def->sidetext = L("mm/s");
def->min = 0;
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(70));
def = this->add("max_resonance_avoidance_speed", coFloat);
def->label = L("Max");
def->tooltip = L("Maximum speed of resonance avoidance.");
def->sidetext = L("mm/s");
def->min = 0;
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(115));
def = this->add("single_extruder_multi_material_priming", coBool); def = this->add("single_extruder_multi_material_priming", coBool);
def->label = L("Prime all printing extruders"); def->label = L("Prime all printing extruders");
def->tooltip = L("If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print."); def->tooltip = L("If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print.");

View File

@@ -626,6 +626,10 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloatOrPercent, overhang_speed_1)) ((ConfigOptionFloatOrPercent, overhang_speed_1))
((ConfigOptionFloatOrPercent, overhang_speed_2)) ((ConfigOptionFloatOrPercent, overhang_speed_2))
((ConfigOptionFloatOrPercent, overhang_speed_3)) ((ConfigOptionFloatOrPercent, overhang_speed_3))
//Y27
((ConfigOptionBool, resonance_avoidance))
((ConfigOptionFloat, min_resonance_avoidance_speed))
((ConfigOptionFloat, max_resonance_avoidance_speed))
((ConfigOptionBool, external_perimeters_first)) ((ConfigOptionBool, external_perimeters_first))
((ConfigOptionBool, extra_perimeters)) ((ConfigOptionBool, extra_perimeters))
((ConfigOptionBool, extra_perimeters_on_overhangs)) ((ConfigOptionBool, extra_perimeters_on_overhangs))
@@ -785,10 +789,6 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionBool, single_extruder_multi_material)) ((ConfigOptionBool, single_extruder_multi_material))
//Y25 //Y25
((ConfigOptionBool, wipe_device)) ((ConfigOptionBool, wipe_device))
//Y27
((ConfigOptionBool, resonance_avoidance))
((ConfigOptionFloat, min_resonance_avoidance_speed))
((ConfigOptionFloat, max_resonance_avoidance_speed))
((ConfigOptionBool, single_extruder_multi_material_priming)) ((ConfigOptionBool, single_extruder_multi_material_priming))
((ConfigOptionBool, wipe_tower_no_sparse_layers)) ((ConfigOptionBool, wipe_tower_no_sparse_layers))
((ConfigOptionString, toolchange_gcode)) ((ConfigOptionString, toolchange_gcode))

View File

@@ -253,6 +253,11 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
toggle_field("overhang_speed_" + std::to_string(i), config->opt_bool("enable_dynamic_overhang_speeds")); toggle_field("overhang_speed_" + std::to_string(i), config->opt_bool("enable_dynamic_overhang_speeds"));
} }
//Y27
bool resonance_avoidance = config->opt_bool("resonance_avoidance");
toggle_field("min_resonance_avoidance_speed", resonance_avoidance);
toggle_field("max_resonance_avoidance_speed", resonance_avoidance);
bool have_infill = config->option<ConfigOptionPercent>("fill_density")->value > 0; bool have_infill = config->option<ConfigOptionPercent>("fill_density")->value > 0;
// infill_extruder uses the same logic as in Print::extruders() // infill_extruder uses the same logic as in Print::extruders()
for (auto el : { "fill_pattern", "infill_every_layers", "infill_only_where_needed", for (auto el : { "fill_pattern", "infill_every_layers", "infill_only_where_needed",

View File

@@ -1625,6 +1625,14 @@ void TabPrint::build()
optgroup->append_single_option_line("overhang_speed_2"); optgroup->append_single_option_line("overhang_speed_2");
optgroup->append_single_option_line("overhang_speed_3"); optgroup->append_single_option_line("overhang_speed_3");
//Y27
optgroup = page->new_optgroup(L("Resonance Avoidance"));
optgroup->append_single_option_line("resonance_avoidance");
line = { L("Resonance Avoidance Speed"), "" };
line.append_option(optgroup->get_option("min_resonance_avoidance_speed"));
line.append_option(optgroup->get_option("max_resonance_avoidance_speed"));
optgroup->append_line(line);
optgroup = page->new_optgroup(L("Speed for non-print moves")); optgroup = page->new_optgroup(L("Speed for non-print moves"));
optgroup->append_single_option_line("travel_speed"); optgroup->append_single_option_line("travel_speed");
optgroup->append_single_option_line("travel_speed_z"); optgroup->append_single_option_line("travel_speed_z");
@@ -2738,12 +2746,6 @@ void TabPrinter::build_fff()
Option option(def, "extruders_count"); Option option(def, "extruders_count");
optgroup->append_single_option_line(option); optgroup->append_single_option_line(option);
optgroup->append_single_option_line("single_extruder_multi_material"); optgroup->append_single_option_line("single_extruder_multi_material");
//Y27
optgroup->append_single_option_line("resonance_avoidance");
Line line = { L("Resonance Avoidance Speed"), "" };
line.append_option(optgroup->get_option("min_resonance_avoidance_speed"));
line.append_option(optgroup->get_option("max_resonance_avoidance_speed"));
optgroup->append_line(line);
optgroup->m_on_change = [this, optgroup_wk = ConfigOptionsGroupWkp(optgroup)](t_config_option_key opt_key, boost::any value) { optgroup->m_on_change = [this, optgroup_wk = ConfigOptionsGroupWkp(optgroup)](t_config_option_key opt_key, boost::any value) {
auto optgroup_sh = optgroup_wk.lock(); auto optgroup_sh = optgroup_wk.lock();
@@ -3615,10 +3617,6 @@ void TabPrinter::toggle_options()
toggle_option("toolchange_gcode", have_multiple_extruders); toggle_option("toolchange_gcode", have_multiple_extruders);
if (m_active_page->title() == "General") { if (m_active_page->title() == "General") {
toggle_option("single_extruder_multi_material", have_multiple_extruders); toggle_option("single_extruder_multi_material", have_multiple_extruders);
//Y27
bool resonance_avoidance = m_config->opt_bool("resonance_avoidance");
toggle_option("min_resonance_avoidance_speed", resonance_avoidance);
toggle_option("max_resonance_avoidance_speed", resonance_avoidance);
bool is_marlin_flavor = flavor == gcfMarlinLegacy || flavor == gcfMarlinFirmware; bool is_marlin_flavor = flavor == gcfMarlinLegacy || flavor == gcfMarlinFirmware;
// Disable silent mode for non-marlin firmwares. // Disable silent mode for non-marlin firmwares.