diff --git a/resources/ui_layout/print.ui b/resources/ui_layout/print.ui index a24e6c135..d3fa1a0fc 100644 --- a/resources/ui_layout/print.ui +++ b/resources/ui_layout/print.ui @@ -259,11 +259,12 @@ group:sidetext_width$7:Modifiers setting:label_width$8:width$4:small_perimeter_max_length setting:label_width$8:width$4:small_perimeter_speed group:Acceleration control (advanced) + setting:default_acceleration setting:perimeter_acceleration setting:infill_acceleration setting:bridge_acceleration setting:first_layer_acceleration - setting:default_acceleration + setting:travel_acceleration group:Autospeed (advanced) setting:label$Volumetric speed for Autospeed:max_volumetric_speed setting:max_print_speed diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 9503319c8..7541e1912 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -273,10 +273,11 @@ static inline void set_extra_lift(const Layer& layer, const Print& print, GCodeW // Retract for a tool change, using the toolchange retract value and setting the priming extra length. gcode += gcodegen.retract(true); gcodegen.m_avoid_crossing_perimeters.use_external_mp_once(); - gcode += gcodegen.travel_to( + Polyline polyline = gcodegen.travel_to( + gcode, wipe_tower_point_to_object_point(gcodegen, start_pos), - erMixed, - "Travel to a Wipe Tower"); + erMixed); + gcodegen.write_travel_to(gcode, polyline, "Travel to a Wipe Tower"); gcode += gcodegen.unretract(); } @@ -1505,7 +1506,10 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu m_enable_cooling_markers = false; // we're not filtering these moves through CoolingBuffer m_avoid_crossing_perimeters.use_external_mp_once(); _write(file, this->retract()); - _write(file, this->travel_to(Point(0, 0), erNone, "move to origin position for next object")); + std::string gcode; + Polyline polyline = this->travel_to(gcode, Point(0, 0), erNone); + this->write_travel_to(gcode, polyline, "move to origin position for next object"); + _write(file, gcode); m_enable_cooling_markers = true; // Disable motion planner when traveling to first object point. m_avoid_crossing_perimeters.disable_once(); @@ -3737,13 +3741,69 @@ std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string std::string gcode; std::string description{ description_in }; - // go to first point of extrusion path - if (!m_last_pos_defined || m_last_pos != path.first_point()) { - gcode += this->travel_to( - path.first_point(), - path.role(), - "move to first " + description + " point" - ); + + // adjust acceleration, inside the travel to set the deceleration + double acceleration = get_default_acceleration(m_config); + double travel_acceleration = m_writer.get_acceleration(); + { + if (this->on_first_layer() && m_config.first_layer_acceleration.value > 0) { + acceleration = m_config.first_layer_acceleration.get_abs_value(acceleration); + } else if (m_config.perimeter_acceleration.value > 0 && is_perimeter(path.role())) { + acceleration = m_config.perimeter_acceleration.get_abs_value(acceleration); + } else if (m_config.bridge_acceleration.value > 0 && is_bridge(path.role()) + && path.role() != erOverhangPerimeter) { + acceleration = m_config.bridge_acceleration.get_abs_value(acceleration); + } else if (m_config.infill_acceleration.value > 0 && is_infill(path.role())) { + acceleration = m_config.infill_acceleration.get_abs_value(acceleration); + } + if (m_config.travel_acceleration.value > 0) + travel_acceleration = m_config.travel_acceleration.get_abs_value(acceleration); + } + + if (travel_acceleration == acceleration) { + m_writer.set_acceleration((uint32_t)floor(acceleration + 0.5)); + // go to first point of extrusion path (stop at midpoint to let us set the decel speed) + if (!m_last_pos_defined || m_last_pos != path.first_point()) { + Polyline polyline = this->travel_to(gcode, path.first_point(), path.role()); + this->write_travel_to(gcode, polyline, "move to first " + description + " point (" + std::to_string(acceleration) +" == "+ std::to_string(travel_acceleration)+")"); + } + } else { + // go to midpoint to let us set the decel speed) + if (!m_last_pos_defined || m_last_pos != path.first_point()) { + Polyline poly_start = this->travel_to(gcode, path.first_point(), path.role()); + coordf_t length = poly_start.length(); + if (length > SCALED_EPSILON) { + Polyline poly_end; + coordf_t min_length = scale_(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0.5)) * 20; + if (poly_start.size() > 2 && length > min_length * 3) { + //if complex travel, try to deccelerate only at the end, unless it's less than ~ 20 nozzle + if (poly_start.lines().back().length() < min_length) { + poly_end = poly_start; + poly_start.clip_end(min_length); + poly_end.clip_start(length - min_length); + } else { + poly_end.points.push_back(poly_start.points.back()); + poly_start.points.pop_back(); + poly_end.points.push_back(poly_start.points.back()); + poly_end.reverse(); + } + } else { + poly_end = poly_start; + poly_start.clip_end(length / 2); + poly_end.clip_start(length / 2); + } + m_writer.set_acceleration((uint32_t)floor(travel_acceleration + 0.5)); + this->write_travel_to(gcode, poly_start, "move to first " + description + " point (acceleration)"); + //travel acceleration should be already set at startup via special gcode, and so it's automatically used by G0. + m_writer.set_acceleration((uint32_t)floor(acceleration + 0.5)); + this->write_travel_to(gcode, poly_end, "move to first " + description + " point (deceleration)"); + } else { + m_writer.set_acceleration((uint32_t)floor(travel_acceleration + 0.5)); + this->write_travel_to(gcode, poly_start, "move to first " + description + " point (acceleration)"); + } + } else { + m_writer.set_acceleration((uint32_t)floor(acceleration + 0.5)); + } } //if needed, write the gcode_label_objects_end then gcode_label_objects_start @@ -3753,24 +3813,6 @@ std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string // compensate retraction gcode += this->unretract(); - // adjust acceleration - { - double acceleration = get_default_acceleration(m_config); - if (this->on_first_layer() && m_config.first_layer_acceleration.value > 0) { - acceleration = m_config.first_layer_acceleration.get_abs_value(acceleration); - } else if (m_config.perimeter_acceleration.value > 0 && is_perimeter(path.role())) { - acceleration = m_config.perimeter_acceleration.get_abs_value(acceleration); - } else if (m_config.bridge_acceleration.value > 0 && is_bridge(path.role()) - && path.role() != erOverhangPerimeter ) { - acceleration = m_config.bridge_acceleration.get_abs_value(acceleration); - } else if (m_config.infill_acceleration.value > 0 && is_infill(path.role())) { - acceleration = m_config.infill_acceleration.get_abs_value(acceleration); - } - //travel acceleration should be already set at startup via special gcode, and so it's automatically used by G0. - m_writer.set_acceleration((uint32_t)floor(acceleration + 0.5)); - } - - // set speed if (speed < 0) { //if speed == -1, then it's means "choose yourself, but if it's -1 < speed <0 , then it's a scaling from small_periemter. @@ -3966,7 +4008,7 @@ void GCode::_add_object_change_labels(std::string& gcode) { } // This method accepts &point in print coordinates. -std::string GCode::travel_to(const Point &point, ExtrusionRole role, std::string comment) +Polyline GCode::travel_to(std::string &gcode, const Point &point, ExtrusionRole role) { /* Define the travel move as a line between current position and the taget point. This is expressed in print coordinates, so it will need to be translated by @@ -3995,7 +4037,6 @@ std::string GCode::travel_to(const Point &point, ExtrusionRole role, std::string m_avoid_crossing_perimeters.reset_once_modifiers(); // generate G-code for the travel move - std::string gcode; if (needs_retraction) { if (m_config.avoid_crossing_perimeters && could_be_wipe_disabled) m_wipe.reset_path(); @@ -4016,15 +4057,19 @@ std::string GCode::travel_to(const Point &point, ExtrusionRole role, std::string //if needed, write the gcode_label_objects_end then gcode_label_objects_start _add_object_change_labels(gcode); + return travel; +} + + +void GCode::write_travel_to(std::string &gcode, const Polyline& travel, std::string comment) +{ // use G1 because we rely on paths being straight (G0 may make round paths) if (travel.size() >= 2) { - for (size_t i = 1; i < travel.size(); ++ i) + for (size_t i = 1; i < travel.size(); ++i) gcode += m_writer.travel_to_xy(this->point_to_gcode(travel.points[i]), comment); this->set_last_pos(travel.points.back()); } - return gcode; } - bool GCode::needs_retraction(const Polyline &travel, ExtrusionRole role) { if (travel.length() < scale_(EXTRUDER_CONFIG_WITH_DEFAULT(retract_before_travel, 0))) { diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 3c92322fc..2546de461 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -315,7 +315,8 @@ private: std::string extrude_ironing(const Print& print, const std::vector& by_region); std::string extrude_support(const ExtrusionEntityCollection &support_fills); - std::string travel_to(const Point &point, ExtrusionRole role, std::string comment); + Polyline travel_to(std::string& gcode, const Point &point, ExtrusionRole role); + void write_travel_to(std::string& gcode, const Polyline& travel, std::string comment); bool needs_retraction(const Polyline &travel, ExtrusionRole role = erNone); std::string retract(bool toolchange = false); std::string unretract() { return m_writer.unlift() + m_writer.unretract(); } diff --git a/src/libslic3r/GCodeWriter.cpp b/src/libslic3r/GCodeWriter.cpp index 03393b7c1..085f6369f 100644 --- a/src/libslic3r/GCodeWriter.cpp +++ b/src/libslic3r/GCodeWriter.cpp @@ -281,6 +281,11 @@ void GCodeWriter::set_acceleration(uint32_t acceleration) m_current_acceleration = acceleration; } +uint32_t GCodeWriter::get_acceleration() const +{ + return m_current_acceleration; +} + std::string GCodeWriter::write_acceleration(){ if (m_current_acceleration == m_last_acceleration || m_current_acceleration == 0) return ""; @@ -292,9 +297,12 @@ std::string GCodeWriter::write_acceleration(){ if (FLAVOR_IS(gcfRepetier)) { // M201: Set max printing acceleration gcode << "M201 X" << m_current_acceleration << " Y" << m_current_acceleration; - } else if(FLAVOR_IS(gcfMarlin) || FLAVOR_IS(gcfLerdge) || FLAVOR_IS(gcfRepRap) || FLAVOR_IS(gcfSprinter)){ + } else if(FLAVOR_IS(gcfMarlin) || FLAVOR_IS(gcfLerdge) || FLAVOR_IS(gcfSprinter)){ // M204: Set printing acceleration gcode << "M204 P" << m_current_acceleration; + } else if (FLAVOR_IS(gcfRepRap)) { + // M204: Set printing & travel acceleration + gcode << "M204 P" << m_current_acceleration <<" T" << m_current_acceleration; } else { // M204: Set default acceleration gcode << "M204 S" << m_current_acceleration; diff --git a/src/libslic3r/GCodeWriter.hpp b/src/libslic3r/GCodeWriter.hpp index 912ec65da..084b8e4e1 100644 --- a/src/libslic3r/GCodeWriter.hpp +++ b/src/libslic3r/GCodeWriter.hpp @@ -50,6 +50,7 @@ public: /// set fan at speed. Save it as current fan speed if !dont_save, and use tool default_tool if the internal m_tool is null (no toolchange done yet). std::string set_fan(uint8_t speed, bool dont_save = false, uint16_t default_tool = 0); void set_acceleration(uint32_t acceleration); + uint32_t get_acceleration() const; std::string write_acceleration(); std::string reset_e(bool force = false); std::string update_progress(uint32_t num, uint32_t tot, bool allow_100 = false) const; diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 90d2d5b3d..c7b69e862 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -446,6 +446,7 @@ const std::vector& Preset::print_options() "top_solid_min_thickness", "bottom_solid_layers", "bottom_solid_min_thickness", + "duplicate_distance", "extra_perimeters", "extra_perimeters_odd_layers", "extra_perimeters_overhangs", @@ -456,26 +457,28 @@ const std::vector& Preset::print_options() "avoid_crossing_perimeters", "avoid_crossing_not_first_layer", "thin_perimeters", "thin_perimeters_all", - "thin_walls", "overhangs_speed", "overhangs_width", "overhangs_width_speed", "overhangs_reverse", "overhangs_reverse_threshold", - "seam_position", + "seam_position", + // external_perimeters "external_perimeters_first", "external_perimeters_vase", "external_perimeters_nothole", "external_perimeters_hole", - "fill_density" - , "fill_pattern" - , "fill_top_flow_ratio" - , "fill_smooth_width" - , "fill_smooth_distribution" - , "top_fill_pattern" - , "bottom_fill_pattern" - , "solid_fill_pattern", + // fill pattern + "fill_density", + "fill_pattern", + "fill_top_flow_ratio", + "fill_smooth_width", + "fill_smooth_distribution", + "top_fill_pattern", + "bottom_fill_pattern", + "solid_fill_pattern", "infill_every_layers", "infill_only_where_needed", "solid_infill_every_layers", + // ironing "ironing", "ironing_type", "ironing_flowrate", @@ -493,25 +496,40 @@ const std::vector& Preset::print_options() "max_volumetric_extrusion_rate_slope_positive", "max_volumetric_extrusion_rate_slope_negative", #endif /* HAS_PRESSURE_EQUALIZER */ "min_width_top_surface", - "perimeter_speed", - "small_perimeter_speed", - "small_perimeter_min_length", - "small_perimeter_max_length", - "external_perimeter_speed", "infill_speed", "solid_infill_speed", - "top_solid_infill_speed", "support_material_speed", "support_material_xy_spacing", "support_material_interface_speed", "bridge_speed", "bridge_speed_internal", + // speeds + "external_perimeter_speed", + "first_layer_speed", + "infill_speed", + "perimeter_speed", + "small_perimeter_speed", + "small_perimeter_max_length", + "small_perimeter_min_length", + "solid_infill_speed", + "support_material_interface_speed", + "support_material_speed", + "support_material_xy_spacing", + "top_solid_infill_speed", + "travel_speed", "travel_speed_z", + // gapfill "gap_fill", "gap_fill_min_area", "gap_fill_overlap", "gap_fill_speed", - "travel_speed", "travel_speed_z", "first_layer_speed", "perimeter_acceleration", "infill_acceleration", - "bridge_acceleration", "first_layer_acceleration", "default_acceleration", - "duplicate_distance", + // acceleration + "bridge_acceleration", + "default_acceleration", + "first_layer_acceleration", + "infill_acceleration", + "perimeter_acceleration", + "travel_acceleration", + // skirt "skirts", "skirt_distance", "skirt_height", "skirt_extrusion_width", "min_skirt_length", "draft_shield", + // brim "brim_inside_holes", "brim_width", "brim_width_interior", @@ -520,15 +538,16 @@ const std::vector& Preset::print_options() "brim_ears_max_angle", "brim_ears_pattern", "brim_offset", - "support_material", "support_material_auto", "support_material_threshold", "support_material_enforce_layers", - "raft_layers", "support_material_pattern", "support_material_with_sheath", "support_material_spacing", + // support + "support_material", "support_material_auto", "support_material_threshold", "support_material_enforce_layers", + "raft_layers", "support_material_pattern", "support_material_with_sheath", "support_material_spacing", "support_material_interface_pattern", - "support_material_synchronize_layers", "support_material_angle", "support_material_interface_layers", - "support_material_interface_spacing", "support_material_interface_contact_loops" - , "support_material_contact_distance_type" - , "support_material_contact_distance_top" - , "support_material_contact_distance_bottom" - , "support_material_buildplate_only", "dont_support_bridges", "notes", + "support_material_synchronize_layers", "support_material_angle", "support_material_interface_layers", + "support_material_interface_spacing", "support_material_interface_contact_loops", + "support_material_contact_distance_type", + "support_material_contact_distance_top", + "support_material_contact_distance_bottom", + "support_material_buildplate_only", "dont_support_bridges", "notes", "complete_objects", "complete_objects_one_skirt", "complete_objects_one_brim", @@ -537,23 +556,25 @@ const std::vector& Preset::print_options() "extruder_clearance_height", "gcode_comments", "gcode_label_objects", "output_filename_format", "post_process", "perimeter_extruder", "infill_extruder", "solid_infill_extruder", "support_material_extruder", "support_material_interface_extruder", "ooze_prevention", "standby_temperature_delta", "interface_shells", + // width & spacing "extrusion_spacing", "extrusion_width", "first_layer_extrusion_spacing", "first_layer_extrusion_width", "perimeter_round_corners", - "perimeter_extrusion_spacing", - "perimeter_extrusion_width", - "external_perimeter_extrusion_spacing", - "external_perimeter_extrusion_width", - "infill_extrusion_spacing", - "infill_extrusion_width", - "solid_infill_extrusion_spacing", - "solid_infill_extrusion_width", - "top_infill_extrusion_spacing", - "top_infill_extrusion_width", - "support_material_extrusion_width", - "infill_overlap", "bridge_flow_ratio", + "perimeter_extrusion_spacing", + "perimeter_extrusion_width", + "external_perimeter_extrusion_spacing", + "external_perimeter_extrusion_width", + "infill_extrusion_spacing", + "infill_extrusion_width", + "solid_infill_extrusion_spacing", + "solid_infill_extrusion_width", + "top_infill_extrusion_spacing", + "top_infill_extrusion_width", + "support_material_extrusion_width", + // overlap, ratios + "infill_overlap", "bridge_flow_ratio", "infill_anchor", "infill_anchor_max", "clip_multipart_objects", @@ -561,6 +582,7 @@ const std::vector& Preset::print_options() "bridge_overlap", "first_layer_flow_ratio", "clip_multipart_objects", "enforce_full_fill_volume", "external_infill_margin", "bridged_infill_margin", + // compensation "first_layer_size_compensation", "first_layer_size_compensation_layers", "xy_size_compensation", @@ -569,7 +591,8 @@ const std::vector& Preset::print_options() "hole_size_threshold", "hole_to_polyhole", "hole_to_polyhole_threshold", - "threads", "resolution", + "threads", + // wipe tower "wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging", "wipe_tower_brim", "single_extruder_multi_material_priming", @@ -585,14 +608,19 @@ const std::vector& Preset::print_options() "seam_travel_cost", "infill_connection", "infill_connection_solid", "infill_connection_top", "infill_connection_bottom", "first_layer_infill_speed", + // thin wall + "thin_walls", "thin_walls_min_width", "thin_walls_overlap", - "thin_walls_speed" - , "model_precision" - , "curve_smoothing_precision" - , "curve_smoothing_cutoff_dist" - , "curve_smoothing_angle_convex" - , "curve_smoothing_angle_concave", + "thin_walls_speed", + "thin_walls_merge", + //precision, spoothign + "model_precision", + "resolution", + "curve_smoothing_precision", + "curve_smoothing_cutoff_dist", + "curve_smoothing_angle_convex", + "curve_smoothing_angle_concave", "print_extrusion_multiplier", "print_retract_length", "print_temperature", @@ -601,11 +629,11 @@ const std::vector& Preset::print_options() "external_perimeter_overlap", "perimeter_bonding", "perimeter_overlap", + //milling "milling_after_z", "milling_post_process", "milling_extra_size", "milling_speed", - "thin_walls_merge", }; return s_opts; } diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 379123666..ba47f88fc 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -172,6 +172,7 @@ bool Print::invalidate_state_by_config_options(const std::vectormin = 0; def->set_default_value(new ConfigOptionFloat(0.)); + def = this->add("travel_acceleration", coFloatOrPercent); + def->label = L("Travel"); + def->full_label = L("Travel acceleration"); + def->category = OptionCategory::speed; + def->tooltip = L("Acceleration for travel moves (jumps between distant extrusion points)." + "\nNote that the deceleration of a travel will use the acceleration value of the extrusion that will be printed after it (if any)"); + def->sidetext = L("mm/s² or %"); + def->ratio_over = "default_acceleration"; + def->min = 0; + def->mode = comExpert; + def->set_default_value(new ConfigOptionFloatOrPercent(1500, false)); + def = this->add("travel_speed", coFloat); def->label = L("Travel"); def->full_label = L("Travel speed"); @@ -5541,6 +5553,7 @@ void PrintConfigDef::to_prusa(t_config_option_key& opt_key, std::string& value, "perimeter_round_corners", "travel_speed_z", "first_layer_size_compensation_layers", +"travel_acceleration", }; //looks if it's to be removed, or have to be transformed if (to_remove_keys.find(opt_key) != to_remove_keys.end()) { diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 33aa3686b..e6975ceb9 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -1331,6 +1331,7 @@ public: ConfigOptionBool thumbnails_with_bed; ConfigOptionPercent time_estimation_compensation; ConfigOptionInts top_fan_speed; + ConfigOptionFloatOrPercent travel_acceleration; ConfigOptionBools wipe; ConfigOptionBool wipe_tower; ConfigOptionFloatOrPercent wipe_tower_brim; @@ -1427,6 +1428,7 @@ protected: OPT_PTR(thumbnails_with_bed); OPT_PTR(time_estimation_compensation); OPT_PTR(top_fan_speed); + OPT_PTR(travel_acceleration); OPT_PTR(wipe); OPT_PTR(wipe_tower); OPT_PTR(wipe_tower_brim); diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 48e2efa17..85b3d494e 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -433,7 +433,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) bool have_default_acceleration = config->option("default_acceleration")->value > 0; for (auto el : { "perimeter_acceleration", "infill_acceleration", - "bridge_acceleration", "first_layer_acceleration" }) + "bridge_acceleration", "first_layer_acceleration", "travel_acceleration" }) toggle_field(el, have_default_acceleration); bool have_skirt = config->opt_int("skirts") > 0;