Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsupermerill <merill@free.fr>2021-11-06 02:33:57 +0300
committersupermerill <merill@free.fr>2021-11-06 23:19:44 +0300
commit37a3596b3a18b056f2354fd6a6aaeddee4ef23fd (patch)
tree9bf6751e69ce3dd6e7d9dcbdf9a11c8e091d4a68 /src
parent905deba7a7951623ac4b088bba0508b9dc77bd0e (diff)
travel speed & acceleration update:
* travel can now slow down to avoid going out of the max_gcode_per_second (useful for avoid_crossing_perimeter) * travel acceleration is now bound by machine_max_acceleration_travel and not machine_max_acceleration_extruding supermerill/SuperSlicer#1350 supermerill/SuperSlicer#1210
Diffstat (limited to 'src')
-rw-r--r--src/libslic3r/Config.cpp41
-rw-r--r--src/libslic3r/GCode.cpp257
-rw-r--r--src/libslic3r/GCodeWriter.cpp25
-rw-r--r--src/libslic3r/GCodeWriter.hpp10
-rw-r--r--src/libslic3r/PrintConfig.cpp3
5 files changed, 199 insertions, 137 deletions
diff --git a/src/libslic3r/Config.cpp b/src/libslic3r/Config.cpp
index 21d3a835f..208a041d2 100644
--- a/src/libslic3r/Config.cpp
+++ b/src/libslic3r/Config.cpp
@@ -1,4 +1,5 @@
#include "Config.hpp"
+#include "Preset.hpp"
#include "format.hpp"
#include "Utils.hpp"
#include <assert.h>
@@ -673,6 +674,12 @@ double ConfigBase::get_computed_value(const t_config_option_key &opt_key, int ex
std::stringstream ss; ss << "You can't define an option that need " << opt_key << " without defining it!";
throw std::runtime_error(ss.str());
}
+ // Get option definition.
+ const ConfigDef* def = this->def();
+ if (def == nullptr)
+ throw NoDefinitionException(opt_key);
+ const ConfigOptionDef* opt_def = def->get(opt_key);
+ assert(opt_def != nullptr);
if (!raw_opt->is_vector()) {
if (raw_opt->type() == coFloat)
@@ -681,26 +688,13 @@ double ConfigBase::get_computed_value(const t_config_option_key &opt_key, int ex
return static_cast<const ConfigOptionInt*>(raw_opt)->value;
if (raw_opt->type() == coBool)
return static_cast<const ConfigOptionBool*>(raw_opt)->value ? 1 : 0;
- const ConfigOptionDef* opt_def = nullptr;
const ConfigOptionPercent* cast_opt = nullptr;
if (raw_opt->type() == coFloatOrPercent) {
if (!static_cast<const ConfigOptionFloatOrPercent*>(raw_opt)->percent)
return static_cast<const ConfigOptionFloatOrPercent*>(raw_opt)->value;
- // Get option definition.
- const ConfigDef* def = this->def();
- if (def == nullptr)
- throw NoDefinitionException(opt_key);
- opt_def = def->get(opt_key);
cast_opt = static_cast<const ConfigOptionFloatOrPercent*>(raw_opt);
- assert(opt_def != nullptr);
}
if (raw_opt->type() == coPercent) {
- // Get option definition.
- const ConfigDef* def = this->def();
- if (def == nullptr)
- throw NoDefinitionException(opt_key);
- opt_def = def->get(opt_key);
- assert(opt_def != nullptr);
cast_opt = static_cast<const ConfigOptionPercent*>(raw_opt);
}
if (opt_def != nullptr) {
@@ -719,7 +713,9 @@ double ConfigBase::get_computed_value(const t_config_option_key &opt_key, int ex
} else {
// check if it's an extruder_id array
const ConfigOptionVectorBase* vector_opt = static_cast<const ConfigOptionVectorBase*>(raw_opt);
+ int idx = -1;
if (vector_opt->is_extruder_size()) {
+ idx = extruder_id;
if (extruder_id < 0) {
const ConfigOption* opt_extruder_id = nullptr;
if ((opt_extruder_id = this->option("extruder")) == nullptr)
@@ -729,8 +725,15 @@ double ConfigBase::get_computed_value(const t_config_option_key &opt_key, int ex
throw ConfigurationError(ss.str());
}
extruder_id = opt_extruder_id->getInt();
+ idx = extruder_id;
}
-
+ } else {
+ t_config_option_keys machine_limits = Preset::machine_limits_options();
+ if (std::find(machine_limits.begin(), machine_limits.end(), opt_key) != machine_limits.end()) {
+ idx = 0;
+ }
+ }
+ if (idx >= 0) {
if (raw_opt->type() == coFloats || raw_opt->type() == coInts || raw_opt->type() == coBools)
return vector_opt->getFloat(extruder_id);
if (raw_opt->type() == coFloatsOrPercents) {
@@ -738,10 +741,6 @@ double ConfigBase::get_computed_value(const t_config_option_key &opt_key, int ex
if (!opt_fl_per->values[extruder_id].percent)
return opt_fl_per->values[extruder_id].value;
- const ConfigDef* def = this->def();
- if (def == nullptr)
- throw NoDefinitionException(opt_key);
- const ConfigOptionDef* opt_def = def->get(opt_key);
if (opt_def->ratio_over.empty())
return opt_fl_per->get_abs_value(extruder_id, 1);
if (opt_def->ratio_over != "depends")
@@ -751,10 +750,6 @@ double ConfigBase::get_computed_value(const t_config_option_key &opt_key, int ex
}
if (raw_opt->type() == coPercents) {
const ConfigOptionPercents* opt_per = static_cast<const ConfigOptionPercents*>(raw_opt);
- const ConfigDef* def = this->def();
- if (def == nullptr)
- throw NoDefinitionException(opt_key);
- const ConfigOptionDef* opt_def = def->get(opt_key);
if (opt_def->ratio_over.empty())
return opt_per->get_abs_value(extruder_id, 1);
if (opt_def->ratio_over != "depends")
@@ -762,7 +757,7 @@ double ConfigBase::get_computed_value(const t_config_option_key &opt_key, int ex
std::stringstream ss; ss << "ConfigBase::get_abs_value(): " << opt_key << " has no valid ratio_over to compute of";
throw ConfigurationError(ss.str());
}
- }
+ }
}
std::stringstream ss; ss << "ConfigBase::get_abs_value(): "<< opt_key<<" has not a valid option type for get_abs_value()";
throw ConfigurationError(ss.str());
diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp
index b318d56ad..a600c0eb5 100644
--- a/src/libslic3r/GCode.cpp
+++ b/src/libslic3r/GCode.cpp
@@ -57,49 +57,59 @@ namespace Slic3r {
#define _(s) Slic3r::I18N::translate(s)
// Only add a newline in case the current G-code does not end with a newline.
- static inline void check_add_eol(std::string& gcode)
- {
- if (!gcode.empty() && gcode.back() != '\n')
- gcode += '\n';
- }
+static inline void check_add_eol(std::string& gcode)
+{
+ if (!gcode.empty() && gcode.back() != '\n')
+ gcode += '\n';
+}
- // 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)
+// 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)
+{
+bool ok = false;
+size_t from_pos = 0;
+size_t pos = 0;
+while ((pos = custom_gcode.find(tch_prefix, from_pos)) != std::string::npos) {
+ if (pos + 1 == custom_gcode.size())
+ break;
+ from_pos = pos + 1;
+ // only whitespace is allowed before the command
+ while (--pos < custom_gcode.size() && custom_gcode[pos] != '\n') {
+ if (!std::isspace(custom_gcode[pos]))
+ goto NEXT;
+ }
{
- bool ok = false;
- size_t from_pos = 0;
- size_t pos = 0;
- while ((pos = custom_gcode.find(tch_prefix, from_pos)) != std::string::npos) {
- if (pos + 1 == custom_gcode.size())
- break;
- from_pos = pos + 1;
- // only whitespace is allowed before the command
- while (--pos < custom_gcode.size() && custom_gcode[pos] != '\n') {
- if (!std::isspace(custom_gcode[pos]))
- goto NEXT;
- }
- {
- // we should also check that the extruder changes to what was expected
- std::istringstream ss(custom_gcode.substr(from_pos, std::string::npos));
- unsigned num = 0;
- if (ss >> num)
- ok = (num == next_extruder);
- }
- NEXT:;
- }
- return ok;
+ // we should also check that the extruder changes to what was expected
+ std::istringstream ss(custom_gcode.substr(from_pos, std::string::npos));
+ unsigned num = 0;
+ if (ss >> num)
+ ok = (num == next_extruder);
}
-
- double get_default_acceleration(PrintConfig& config) {
- double max = 0;
- max = config.machine_max_acceleration_extruding.values.front();
- // on 2.3, check for enable/disable if(config.machine_limits_usage)
- if (config.machine_limits_usage <= MachineLimitsUsage::Limits)
- return std::min(config.default_acceleration.get_abs_value(max), max);
- else
- return config.default_acceleration.get_abs_value(max);
+ NEXT:;
}
+ return ok;
+}
+
+double get_default_acceleration(PrintConfig& config) {
+ double max = 0;
+ max = config.machine_max_acceleration_extruding.get_at(0);
+ // on 2.3, check for enable/disable if(config.machine_limits_usage)
+ if (config.machine_limits_usage <= MachineLimitsUsage::Limits)
+ return std::min(config.get_computed_value("default_acceleration"), max);
+ else
+ return config.get_computed_value("default_acceleration");
+}
+
+double get_travel_acceleration(PrintConfig& config) {
+ double max = 0;
+ max = config.machine_max_acceleration_travel.get_at(0);
+ // on 2.3, check for enable/disable if(config.machine_limits_usage)
+ if (config.machine_limits_usage <= MachineLimitsUsage::Limits)
+ return std::min(config.get_computed_value("travel_acceleration"), max);
+ else
+ return config.get_computed_value("travel_acceleration");
+}
std::string OozePrevention::pre_toolchange(GCode& gcodegen)
{
@@ -118,8 +128,7 @@ std::string OozePrevention::pre_toolchange(GCode& gcodegen)
/* We don't call gcodegen.travel_to() because we don't need retraction (it was already
triggered by the caller) nor avoid_crossing_perimeters and also because the coordinates
of the destination point must not be transformed by origin nor current extruder offset. */
- gcode += gcodegen.writer().travel_to_xy(unscale(standby_point),
- "move to standby position");
+ gcode += gcodegen.writer().travel_to_xy(unscale(standby_point), 0.0, "move to standby position");
}
if (gcodegen.config().standby_temperature_delta.value != 0 && gcodegen.writer().tool_is_extruder() && this->_get_temp(gcodegen) > 0) {
@@ -157,7 +166,7 @@ std::string Wipe::wipe(GCode& gcodegen, bool toolchange)
/* Reduce feedrate a bit; travel speed is often too high to move on existing material.
Too fast = ripping of existing material; too slow = short wipe path, thus more blob. */
- double wipe_speed = gcodegen.writer().config.travel_speed.value * 0.8;
+ double wipe_speed = gcodegen.writer().config.get_computed_value("travel_speed") * 0.8;
if(gcodegen.writer().tool_is_extruder() && gcodegen.writer().config.wipe_speed.get_at(gcodegen.writer().tool()->id()) > 0)
wipe_speed = gcodegen.writer().config.wipe_speed.get_at(gcodegen.writer().tool()->id());
@@ -1660,7 +1669,7 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
_writeln(file, this->placeholder_parser_process("end_filament_gcode", print.config().end_filament_gcode.get_at(extruder_id), extruder_id, &config));
} else {
for (const std::string& end_gcode : print.config().end_filament_gcode.values) {
- int extruder_id = (uint16_t)(&end_gcode - &print.config().end_filament_gcode.values.front());
+ int extruder_id = (uint16_t)(&end_gcode - &print.config().end_filament_gcode.get_at(0));
config.set_key_value("filament_extruder_id", new ConfigOptionInt(extruder_id));
config.set_key_value("previous_extruder", new ConfigOptionInt(extruder_id));
config.set_key_value("next_extruder", new ConfigOptionInt(0));
@@ -1826,60 +1835,60 @@ void GCode::print_machine_envelope(FILE *file, Print &print)
if (print.config().machine_limits_usage.value == MachineLimitsUsage::EmitToGCode) {
if (std::set<uint8_t>{gcfMarlin, gcfLerdge, gcfRepetier, gcfRepRap, gcfSprinter}.count(print.config().gcode_flavor.value) > 0)
_write_format(file, "M201 X%d Y%d Z%d E%d ; sets maximum accelerations, mm/sec^2\n",
- int(print.config().machine_max_acceleration_x.values.front() + 0.5),
- int(print.config().machine_max_acceleration_y.values.front() + 0.5),
- int(print.config().machine_max_acceleration_z.values.front() + 0.5),
- int(print.config().machine_max_acceleration_e.values.front() + 0.5));
+ int(print.config().machine_max_acceleration_x.get_at(0) + 0.5),
+ int(print.config().machine_max_acceleration_y.get_at(0) + 0.5),
+ int(print.config().machine_max_acceleration_z.get_at(0) + 0.5),
+ int(print.config().machine_max_acceleration_e.get_at(0) + 0.5));
if (std::set<uint8_t>{gcfRepetier}.count(print.config().gcode_flavor.value) > 0)
_write_format(file, "M202 X%d Y%d ; sets maximum travel acceleration\n",
- int(print.config().machine_max_acceleration_travel.values.front() + 0.5),
- int(print.config().machine_max_acceleration_travel.values.front() + 0.5));
+ int(print.config().machine_max_acceleration_travel.get_at(0) + 0.5),
+ int(print.config().machine_max_acceleration_travel.get_at(0) + 0.5));
if (std::set<uint8_t>{gcfMarlin, gcfLerdge, gcfRepetier, gcfSmoothie, gcfSprinter}.count(print.config().gcode_flavor.value) > 0)
_write_format(file, (print.config().gcode_flavor.value == gcfMarlin || print.config().gcode_flavor.value == gcfLerdge || print.config().gcode_flavor.value == gcfSmoothie)
? "M203 X%d Y%d Z%d E%d ; sets maximum feedrates, mm/sec\n"
: "M203 X%d Y%d Z%d E%d ; sets maximum feedrates, mm/min\n",
- int(print.config().machine_max_feedrate_x.values.front() + 0.5),
- int(print.config().machine_max_feedrate_y.values.front() + 0.5),
- int(print.config().machine_max_feedrate_z.values.front() + 0.5),
- int(print.config().machine_max_feedrate_e.values.front() + 0.5));
+ int(print.config().machine_max_feedrate_x.get_at(0) + 0.5),
+ int(print.config().machine_max_feedrate_y.get_at(0) + 0.5),
+ int(print.config().machine_max_feedrate_z.get_at(0) + 0.5),
+ int(print.config().machine_max_feedrate_e.get_at(0) + 0.5));
if (print.config().gcode_flavor.value == gcfRepRap) {
_write_format(file, "M203 X%d Y%d Z%d E%d I%d; sets maximum feedrates, mm/min\n",
- int(print.config().machine_max_feedrate_x.values.front() + 0.5),
- int(print.config().machine_max_feedrate_y.values.front() + 0.5),
- int(print.config().machine_max_feedrate_z.values.front() + 0.5),
- int(print.config().machine_max_feedrate_e.values.front() + 0.5),
- int(print.config().machine_min_extruding_rate.values.front() + 0.5));
+ int(print.config().machine_max_feedrate_x.get_at(0) + 0.5),
+ int(print.config().machine_max_feedrate_y.get_at(0) + 0.5),
+ int(print.config().machine_max_feedrate_z.get_at(0) + 0.5),
+ int(print.config().machine_max_feedrate_e.get_at(0) + 0.5),
+ int(print.config().machine_min_extruding_rate.get_at(0) + 0.5));
}
if (std::set<uint8_t>{gcfMarlin, gcfLerdge}.count(print.config().gcode_flavor.value) > 0)
_write_format(file, "M204 P%d R%d T%d ; sets acceleration (P, T) and retract acceleration (R), mm/sec^2\n",
- int(print.config().machine_max_acceleration_extruding.values.front() + 0.5),
- int(print.config().machine_max_acceleration_retracting.values.front() + 0.5),
- int(print.config().machine_max_acceleration_travel.values.front() + 0.5));
+ int(print.config().machine_max_acceleration_extruding.get_at(0) + 0.5),
+ int(print.config().machine_max_acceleration_retracting.get_at(0) + 0.5),
+ int(print.config().machine_max_acceleration_travel.get_at(0) + 0.5));
if (std::set<uint8_t>{gcfRepRap, gcfKlipper, gcfSprinter}.count(print.config().gcode_flavor.value) > 0)
_write_format(file, "M204 P%d T%d ; sets acceleration (P, T), mm/sec^2\n",
- int(print.config().machine_max_acceleration_extruding.values.front() + 0.5),
- int(print.config().machine_max_acceleration_travel.values.front() + 0.5));
+ int(print.config().machine_max_acceleration_extruding.get_at(0) + 0.5),
+ int(print.config().machine_max_acceleration_travel.get_at(0) + 0.5));
if (std::set<uint8_t>{gcfRepRap}.count(print.config().gcode_flavor.value) > 0)
_write_format(file, "M566 X%.2lf Y%.2lf Z%.2lf E%.2lf ; sets the jerk limits, mm/min\n",
- print.config().machine_max_jerk_x.values.front() * 60,
- print.config().machine_max_jerk_y.values.front() * 60,
- print.config().machine_max_jerk_z.values.front() * 60,
- print.config().machine_max_jerk_e.values.front() * 60);
+ print.config().machine_max_jerk_x.get_at(0) * 60,
+ print.config().machine_max_jerk_y.get_at(0) * 60,
+ print.config().machine_max_jerk_z.get_at(0) * 60,
+ print.config().machine_max_jerk_e.get_at(0) * 60);
if (std::set<uint8_t>{gcfMarlin, gcfLerdge, gcfRepetier}.count(print.config().gcode_flavor.value) > 0)
_write_format(file, "M205 X%.2lf Y%.2lf Z%.2lf E%.2lf ; sets the jerk limits, mm/sec\n",
- print.config().machine_max_jerk_x.values.front(),
- print.config().machine_max_jerk_y.values.front(),
- print.config().machine_max_jerk_z.values.front(),
- print.config().machine_max_jerk_e.values.front());
+ print.config().machine_max_jerk_x.get_at(0),
+ print.config().machine_max_jerk_y.get_at(0),
+ print.config().machine_max_jerk_z.get_at(0),
+ print.config().machine_max_jerk_e.get_at(0));
if (std::set<uint8_t>{gcfSmoothie}.count(print.config().gcode_flavor.value) > 0)
_write_format(file, "M205 X%.2lf Z%.2lf ; sets the jerk limits, mm/sec\n",
- std::min(print.config().machine_max_jerk_x.values.front(),
- print.config().machine_max_jerk_y.values.front()),
- print.config().machine_max_jerk_z.values.front());
+ std::min(print.config().machine_max_jerk_x.get_at(0),
+ print.config().machine_max_jerk_y.get_at(0)),
+ print.config().machine_max_jerk_z.get_at(0));
if (std::set<uint8_t>{gcfMarlin, gcfLerdge, gcfRepetier}.count(print.config().gcode_flavor.value) > 0)
_write_format(file, "M205 S%d T%d ; sets the minimum extruding and travel feed rate, mm/sec\n",
- int(print.config().machine_min_extruding_rate.values.front() + 0.5),
- int(print.config().machine_min_travel_rate.values.front() + 0.5));
+ int(print.config().machine_min_extruding_rate.get_at(0) + 0.5),
+ int(print.config().machine_min_travel_rate.get_at(0) + 0.5));
}
}
@@ -3147,7 +3156,7 @@ std::string GCode::extrude_loop_vase(const ExtrusionLoop &original_loop, const s
inward_point.rotate(angle, paths.front().polyline.points.front());
// generate the travel move
- gcode += m_writer.travel_to_xy(this->point_to_gcode(inward_point), "move inwards before travel");
+ gcode += m_writer.travel_to_xy(this->point_to_gcode(inward_point), 0.0, "move inwards before travel");
}
return gcode;
@@ -3326,7 +3335,7 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s
for (Point& pt : path.polyline.points) {
prev_point = current_point;
current_point = pt;
- gcode += m_writer.travel_to_xy(this->point_to_gcode(pt), config().gcode_comments ? "; extra wipe" : "");
+ gcode += m_writer.travel_to_xy(this->point_to_gcode(pt), 0.0, config().gcode_comments ? "; extra wipe" : "");
}
}
}
@@ -3361,7 +3370,7 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s
Point pt = ((nd * nd >= l2) ? next_pos : (current_pos + vec_dist * (nd / sqrt(l2)))).cast<coord_t>();
pt.rotate(angle, current_point);
// generate the 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), 0.0, "move inwards before travel");
}
return gcode;
@@ -3923,26 +3932,24 @@ std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string
// adjust acceleration, inside the travel to set the deceleration (unless it's deactivated)
double acceleration = get_default_acceleration(m_config);
- double travel_acceleration = m_writer.get_acceleration();
+ double max_acceleration = std::numeric_limits<double>::max();
+ // on 2.3, check for enable/disable if(config.machine_limits_usage)
+ if (m_config.machine_limits_usage <= MachineLimitsUsage::Limits)
+ max_acceleration = m_config.machine_max_acceleration_extruding.get_at(0);
+ double travel_acceleration = get_travel_acceleration(m_config);
if(acceleration > 0){
if (this->on_first_layer() && m_config.first_layer_acceleration.value > 0) {
- acceleration = m_config.first_layer_acceleration.get_abs_value(acceleration);
+ acceleration = std::min(max_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);
+ acceleration = std::min(max_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);
+ acceleration = std::min(max_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);
+ acceleration = std::min(max_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 (m_writer.get_max_acceleration() > 0) {
- acceleration = std::min((double)m_writer.get_max_acceleration(), acceleration);
- travel_acceleration = std::min((double)m_writer.get_max_acceleration(), travel_acceleration);
}
- if (travel_acceleration == 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()) {
@@ -3957,7 +3964,7 @@ std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string
// if length is enough, it's not the hack for first move, and the travel accel is different than the normal accel
// then cut the travel in two to change the accel in-between
// TODO: compute the real point where it should be cut, considering an infinite max speed.
- if (length > std::max(scale_d(EPSILON), scale_d(m_config.min_length)) && m_last_pos_defined && floor(travel_acceleration) != floor(acceleration)) {
+ if (length > std::max(coordf_t(SCALED_EPSILON), scale_d(m_config.min_length)) && m_last_pos_defined) {
Polyline poly_end;
coordf_t min_length = scale_d(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0.5)) * 20;
if (poly_start.size() > 2 && length > min_length * 3) {
@@ -4182,10 +4189,72 @@ Polyline GCode::travel_to(std::string &gcode, const Point &point, ExtrusionRole
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) {
+ if (travel.size() > 4) {
+ //ensure that you won't overload the firmware.
+ // travel are strait lines, but with avoid_crossing_perimeters, there can be many points. Reduce speed instead of deleting points, as it's already optimised as much as possible, even if it can be a bit more => TODO?)
+ // we are using a window of 10 moves.
+ const double max_gcode_per_second = this->config().max_gcode_per_second.value;
+ coordf_t dist_next_10_moves = 0;
+ size_t idx_10 = 1;
+ size_t idx_print = 1;
+ const double max_speed = m_config.get_computed_value("travel_speed");
+ double current_speed = max_speed;
+ for (; idx_10 < travel.size() && idx_10 < 11; ++idx_10) {
+ dist_next_10_moves += travel.points[idx_10 - 1].distance_to(travel.points[idx_10]);
+ }
+
+ while (idx_10 < travel.size()) {
+ //compute speed
+ double time_for10_moves = unscaled(dist_next_10_moves) / current_speed;
+ double min_time = 10 / max_gcode_per_second;
+ double ratio_speed = time_for10_moves / min_time;
+ double possible_speed = current_speed * ratio_speed;
+
+ //write
+ if (possible_speed < max_speed) {
+ if(ratio_speed < 0.95 | ratio_speed > 1.05)
+ current_speed = possible_speed;
+ } else if (current_speed < max_speed) {
+ current_speed = max_speed;
+ }
+ gcode += m_writer.travel_to_xy(
+ this->point_to_gcode(travel.points[idx_print]),
+ current_speed>2 ? double(uint32_t(current_speed * 60)) : current_speed * 60,
+ comment);
+
+ //update for next move
+ dist_next_10_moves -= travel.points[idx_print - 1].distance_to(travel.points[idx_print]);
+ dist_next_10_moves += travel.points[idx_10 - 1].distance_to(travel.points[idx_10]);
+ idx_10++;
+ idx_print++;
+ }
+
+ if (travel.size() < 10) {
+ //compute a global speed
+ double time_for10_moves = unscaled(dist_next_10_moves) / current_speed;
+ double min_time = travel.size() / max_gcode_per_second;
+ double ratio_speed = time_for10_moves / min_time;
+ current_speed *= ratio_speed;
+ current_speed = std::min(max_speed, current_speed);
+ } else {
+ //compute speed for the end
+ double time_for10_moves = unscaled(dist_next_10_moves) / current_speed;
+ double min_time = 10 / max_gcode_per_second;
+ double ratio_speed = time_for10_moves / min_time;
+ current_speed *= ratio_speed;
+ current_speed = std::min(max_speed, current_speed);
+ }
+
+ //finish writing moves at current speed
+ for (; idx_print < travel.size(); ++idx_print)
+ gcode += m_writer.travel_to_xy(this->point_to_gcode(travel.points[idx_print]),
+ current_speed > 2 ? double(uint32_t(current_speed * 60)) : current_speed * 60,
+ comment);
+ this->set_last_pos(travel.points.back());
+ } else if (travel.size() >= 2) {
for (size_t i = 1; i < travel.size(); ++i)
- gcode += m_writer.travel_to_xy(this->point_to_gcode(travel.points[i]), comment);
+ // use G1 because we rely on paths being straight (G0 may make round paths)
+ gcode += m_writer.travel_to_xy(this->point_to_gcode(travel.points[i]), 0.0, comment);
this->set_last_pos(travel.points.back());
}
}
diff --git a/src/libslic3r/GCodeWriter.cpp b/src/libslic3r/GCodeWriter.cpp
index bce90d4a6..ede145d8d 100644
--- a/src/libslic3r/GCodeWriter.cpp
+++ b/src/libslic3r/GCodeWriter.cpp
@@ -52,9 +52,6 @@ void GCodeWriter::apply_print_config(const PrintConfig &print_config)
this->config.apply(print_config, true);
m_extrusion_axis = this->config.get_extrusion_axis();
m_single_extruder_multi_material = print_config.single_extruder_multi_material.value;
- m_max_acceleration = std::lrint((print_config.gcode_flavor.value == gcfMarlin || print_config.gcode_flavor.value == gcfLerdge || print_config.gcode_flavor.value == gcfKlipper)
- && print_config.machine_limits_usage.value <= MachineLimitsUsage::Limits ?
- print_config.machine_max_acceleration_extruding.values.front() : 0);
}
void GCodeWriter::apply_print_region_config(const PrintRegionConfig& print_region_config)
@@ -301,10 +298,6 @@ std::string GCodeWriter::set_fan(const uint8_t speed, bool dont_save, uint16_t d
void GCodeWriter::set_acceleration(uint32_t acceleration)
{
- // Clamp the acceleration to the allowed maximum.
- if (m_max_acceleration > 0 && acceleration > m_max_acceleration)
- acceleration = m_max_acceleration;
-
if (acceleration == 0 || acceleration == m_current_acceleration)
return;
@@ -453,23 +446,27 @@ std::string GCodeWriter::set_speed(double F, const std::string &comment, const s
return gcode.str();
}
-std::string GCodeWriter::travel_to_xy(const Vec2d &point, const std::string &comment)
+std::string GCodeWriter::travel_to_xy(const Vec2d &point, double F, const std::string &comment)
{
std::ostringstream gcode;
gcode << write_acceleration();
+ double speed = this->config.travel_speed.value * 60.0;
+ if ((F > 0) & (F < speed))
+ speed = F;
+
m_pos.x() = point.x();
m_pos.y() = point.y();
gcode << "G1 X" << XYZ_NUM(point.x())
<< " Y" << XYZ_NUM(point.y())
- << " F" << F_NUM(this->config.travel_speed.value * 60.0);
+ << " F" << F_NUM(speed);
COMMENT(comment);
gcode << "\n";
return gcode.str();
}
-std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &comment)
+std::string GCodeWriter::travel_to_xyz(const Vec3d &point, double F, const std::string &comment)
{
/* If target Z is lower than current Z but higher than nominal Z we
don't perform the Z move but we only move in the XY plane and
@@ -482,7 +479,7 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co
// and a retract could be skipped (https://github.com/prusa3d/PrusaSlicer/issues/2154
if (std::abs(m_lifted) < EPSILON)
m_lifted = 0.;
- return this->travel_to_xy(to_2d(point));
+ return this->travel_to_xy(to_2d(point), F, comment);
}
/* In all the other cases, we perform an actual XYZ move and cancel
@@ -490,6 +487,10 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co
m_lifted = 0;
m_pos = point;
+ double speed = this->config.travel_speed.value * 60.0;
+ if ((F > 0) & (F < speed))
+ speed = F;
+
std::ostringstream gcode;
gcode << write_acceleration();
gcode << "G1 X" << XYZ_NUM(point.x())
@@ -498,7 +499,7 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co
gcode << " Z" << PRECISION(point.z(), 6);
else
gcode << " Z" << XYZ_NUM(point.z());
- gcode << " F" << F_NUM(this->config.travel_speed.value * 60.0);
+ gcode << " F" << F_NUM(speed);
COMMENT(comment);
gcode << "\n";
diff --git a/src/libslic3r/GCodeWriter.hpp b/src/libslic3r/GCodeWriter.hpp
index 71def452d..f74eec403 100644
--- a/src/libslic3r/GCodeWriter.hpp
+++ b/src/libslic3r/GCodeWriter.hpp
@@ -21,7 +21,7 @@ public:
GCodeWriter() :
multiple_extruders(false), m_extrusion_axis("E"), m_tool(nullptr),
m_single_extruder_multi_material(false),
- m_last_acceleration(0), m_current_acceleration(0), m_max_acceleration(0), m_last_fan_speed(0),
+ m_last_acceleration(0), m_current_acceleration(0), m_last_fan_speed(0),
m_last_bed_temperature(0), m_last_bed_temperature_reached(true),
m_lifted(0)
{}
@@ -51,7 +51,6 @@ public:
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;
- uint32_t get_max_acceleration() { return this->m_max_acceleration; }
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;
@@ -65,8 +64,8 @@ public:
std::string toolchange_prefix() const;
std::string toolchange(uint16_t tool_id);
std::string set_speed(double F, const std::string &comment = std::string(), const std::string &cooling_marker = std::string()) const;
- std::string travel_to_xy(const Vec2d &point, const std::string &comment = std::string());
- std::string travel_to_xyz(const Vec3d &point, const std::string &comment = std::string());
+ std::string travel_to_xy(const Vec2d &point, double F = 0.0, const std::string &comment = std::string());
+ std::string travel_to_xyz(const Vec3d &point, double F = 0.0, const std::string &comment = std::string());
std::string travel_to_z(double z, const std::string &comment = std::string());
bool will_move_z(double z) const;
std::string extrude_to_xy(const Vec2d &point, double dE, const std::string &comment = std::string());
@@ -89,9 +88,6 @@ private:
Tool* m_tool;
uint32_t m_last_acceleration;
uint32_t m_current_acceleration;
- // Limit for setting the acceleration, to respect the machine limits set for the Marlin firmware.
- // If set to zero, the limit is not in action.
- uint32_t m_max_acceleration;
uint8_t m_last_fan_speed;
uint8_t m_last_fan_speed_with_offset;
int16_t m_last_temperature;
diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp
index 36cd55d22..46d77e229 100644
--- a/src/libslic3r/PrintConfig.cpp
+++ b/src/libslic3r/PrintConfig.cpp
@@ -2558,7 +2558,7 @@ void PrintConfigDef::init_fff_params()
def->category = OptionCategory::firmware;
def->tooltip = L("The firmware supports stealth mode");
def->mode = comAdvanced;
- def->set_default_value(new ConfigOptionBool(true));
+ def->set_default_value(new ConfigOptionBool(false));
def = this->add("fan_speedup_time", coFloat);
def->label = L("Fan startup delay");
@@ -2749,6 +2749,7 @@ void PrintConfigDef::init_fff_params()
def->category = OptionCategory::speed;
def->tooltip = L("If your firmware stops while printing, it may have its gcode queue full."
" Set this parameter to merge extrusions into bigger ones to reduce the number of gcode commands the printer has to process each second."
+ "\nOn 8bit controlers, a value of 150 is typical."
"\nNote that reducing your printing speed (at least for the external extrusions) will reduce the number of time this will triggger and so increase quality."
"\nSet zero to disable.");
def->min = 0;