mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-07-23 23:54:26 +08:00
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
This commit is contained in:
parent
905deba7a7
commit
37a3596b3a
@ -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")
|
||||
|
@ -57,20 +57,20 @@ 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
bool ok = false;
|
||||
size_t from_pos = 0;
|
||||
size_t pos = 0;
|
||||
while ((pos = custom_gcode.find(tch_prefix, from_pos)) != std::string::npos) {
|
||||
// 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;
|
||||
@ -89,17 +89,27 @@ namespace Slic3r {
|
||||
NEXT:;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
|
||||
double get_default_acceleration(PrintConfig& config) {
|
||||
double get_default_acceleration(PrintConfig& config) {
|
||||
double max = 0;
|
||||
max = config.machine_max_acceleration_extruding.values.front();
|
||||
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.default_acceleration.get_abs_value(max), max);
|
||||
return std::min(config.get_computed_value("default_acceleration"), max);
|
||||
else
|
||||
return config.default_acceleration.get_abs_value(max);
|
||||
}
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
@ -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";
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user