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
diff options
context:
space:
mode:
authorEnrico Turri <enricoturri@seznam.cz>2018-05-30 13:08:03 +0300
committerEnrico Turri <enricoturri@seznam.cz>2018-05-30 13:08:03 +0300
commit5a8d1ffdbaed72a2f4b9ee79316f93be070fc1e0 (patch)
tree97d6c00b26bcc75887ad15aa00929f59e59811c4
parente4aff5b08a9e6ac4adb4c70515aa28e607a1b822 (diff)
Prototype for exporting estimated remaining time into gcode for default and silent mode
-rw-r--r--lib/Slic3r/GUI/Plater.pm6
-rw-r--r--xs/src/libslic3r/GCode.cpp36
-rw-r--r--xs/src/libslic3r/GCode.hpp7
-rw-r--r--xs/src/libslic3r/GCodeTimeEstimator.cpp323
-rw-r--r--xs/src/libslic3r/GCodeTimeEstimator.hpp48
-rw-r--r--xs/src/libslic3r/Print.hpp3
-rw-r--r--xs/xsp/Print.xsp6
7 files changed, 340 insertions, 89 deletions
diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm
index 8d4a1a269..911c07cbf 100644
--- a/lib/Slic3r/GUI/Plater.pm
+++ b/lib/Slic3r/GUI/Plater.pm
@@ -472,7 +472,8 @@ sub new {
fil_mm3 => L("Used Filament (mm³)"),
fil_g => L("Used Filament (g)"),
cost => L("Cost"),
- time => L("Estimated printing time"),
+ default_time => L("Estimated printing time (default mode)"),
+ silent_time => L("Estimated printing time (silent mode)"),
);
while (my $field = shift @info) {
my $label = shift @info;
@@ -1542,7 +1543,8 @@ sub on_export_completed {
$self->{"print_info_cost"}->SetLabel(sprintf("%.2f" , $self->{print}->total_cost));
$self->{"print_info_fil_g"}->SetLabel(sprintf("%.2f" , $self->{print}->total_weight));
$self->{"print_info_fil_mm3"}->SetLabel(sprintf("%.2f" , $self->{print}->total_extruded_volume));
- $self->{"print_info_time"}->SetLabel($self->{print}->estimated_print_time);
+ $self->{"print_info_default_time"}->SetLabel($self->{print}->estimated_default_print_time);
+ $self->{"print_info_silent_time"}->SetLabel($self->{print}->estimated_silent_print_time);
$self->{"print_info_fil_m"}->SetLabel(sprintf("%.2f" , $self->{print}->total_used_filament / 1000));
$self->{"print_info_box_show"}->(1);
diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp
index b581b3e76..28c15e2fd 100644
--- a/xs/src/libslic3r/GCode.cpp
+++ b/xs/src/libslic3r/GCode.cpp
@@ -374,6 +374,9 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_
throw std::runtime_error(std::string("G-code export to ") + path + " failed\nIs the disk full?\n");
}
fclose(file);
+
+ GCodeTimeEstimator::post_process_elapsed_times(path_tmp, m_default_time_estimator.get_time(), m_silent_time_estimator.get_time());
+
if (! this->m_placeholder_parser_failed_templates.empty()) {
// G-code export proceeded, but some of the PlaceholderParser substitutions failed.
std::string msg = std::string("G-code export to ") + path + " failed due to invalid custom G-code sections:\n\n";
@@ -403,9 +406,11 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
{
PROFILE_FUNC();
- // resets time estimator
- m_time_estimator.reset();
- m_time_estimator.set_dialect(print.config.gcode_flavor);
+ // resets time estimators
+ m_default_time_estimator.reset();
+ m_default_time_estimator.set_dialect(print.config.gcode_flavor);
+ m_silent_time_estimator.reset();
+ m_silent_time_estimator.set_dialect(print.config.gcode_flavor);
// resets analyzer
m_analyzer.reset();
@@ -596,6 +601,10 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
_writeln(file, buf);
}
+ // before start gcode time estimation
+ _write(file, m_default_time_estimator.get_elapsed_time_string().c_str());
+ _write(file, m_silent_time_estimator.get_elapsed_time_string().c_str());
+
// Write the custom start G-code
_writeln(file, start_gcode);
// Process filament-specific gcode in extruder order.
@@ -800,13 +809,17 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
for (const std::string &end_gcode : print.config.end_filament_gcode.values)
_writeln(file, this->placeholder_parser_process("end_filament_gcode", end_gcode, (unsigned int)(&end_gcode - &print.config.end_filament_gcode.values.front()), &config));
}
+ // before end gcode time estimation
+ _write(file, m_default_time_estimator.get_elapsed_time_string().c_str());
+ _write(file, m_silent_time_estimator.get_elapsed_time_string().c_str());
_writeln(file, this->placeholder_parser_process("end_gcode", print.config.end_gcode, m_writer.extruder()->id(), &config));
}
_write(file, m_writer.update_progress(m_layer_count, m_layer_count, true)); // 100%
_write(file, m_writer.postamble());
// calculates estimated printing time
- m_time_estimator.calculate_time();
+ m_default_time_estimator.calculate_time();
+ m_silent_time_estimator.calculate_time();
// Get filament stats.
print.filament_stats.clear();
@@ -814,7 +827,8 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
print.total_extruded_volume = 0.;
print.total_weight = 0.;
print.total_cost = 0.;
- print.estimated_print_time = m_time_estimator.get_time_hms();
+ print.estimated_default_print_time = m_default_time_estimator.get_time_dhms();
+ print.estimated_silent_print_time = m_silent_time_estimator.get_time_dhms();
for (const Extruder &extruder : m_writer.extruders()) {
double used_filament = extruder.used_filament();
double extruded_volume = extruder.extruded_volume();
@@ -834,7 +848,8 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
print.total_extruded_volume = print.total_extruded_volume + extruded_volume;
}
_write_format(file, "; total filament cost = %.1lf\n", print.total_cost);
- _write_format(file, "; estimated printing time = %s\n", m_time_estimator.get_time_hms().c_str());
+ _write_format(file, "; estimated printing time (default mode) = %s\n", m_default_time_estimator.get_time_dhms().c_str());
+ _write_format(file, "; estimated printing time (silent mode) = %s\n", m_silent_time_estimator.get_time_dhms().c_str());
// Append full config.
_write(file, "\n");
@@ -1399,8 +1414,12 @@ void GCode::process_layer(
if (m_pressure_equalizer)
gcode = m_pressure_equalizer->process(gcode.c_str(), false);
// printf("G-code after filter:\n%s\n", out.c_str());
-
+
_write(file, gcode);
+
+ // after layer time estimation
+ _write(file, m_default_time_estimator.get_elapsed_time_string().c_str());
+ _write(file, m_silent_time_estimator.get_elapsed_time_string().c_str());
}
void GCode::apply_print_config(const PrintConfig &print_config)
@@ -2059,7 +2078,8 @@ void GCode::_write(FILE* file, const char *what)
// writes string to file
fwrite(gcode, 1, ::strlen(gcode), file);
// updates time estimator and gcode lines vector
- m_time_estimator.add_gcode_block(gcode);
+ m_default_time_estimator.add_gcode_block(gcode);
+ m_silent_time_estimator.add_gcode_block(gcode);
}
}
diff --git a/xs/src/libslic3r/GCode.hpp b/xs/src/libslic3r/GCode.hpp
index d028e90aa..b938604ef 100644
--- a/xs/src/libslic3r/GCode.hpp
+++ b/xs/src/libslic3r/GCode.hpp
@@ -133,6 +133,8 @@ public:
m_last_height(GCodeAnalyzer::Default_Height),
m_brim_done(false),
m_second_layer_things_done(false),
+ m_default_time_estimator(GCodeTimeEstimator::Default),
+ m_silent_time_estimator(GCodeTimeEstimator::Silent),
m_last_obj_copy(nullptr, Point(std::numeric_limits<coord_t>::max(), std::numeric_limits<coord_t>::max()))
{}
~GCode() {}
@@ -289,8 +291,9 @@ protected:
// Index of a last object copy extruded.
std::pair<const PrintObject*, Point> m_last_obj_copy;
- // Time estimator
- GCodeTimeEstimator m_time_estimator;
+ // Time estimators
+ GCodeTimeEstimator m_default_time_estimator;
+ GCodeTimeEstimator m_silent_time_estimator;
// Analyzer
GCodeAnalyzer m_analyzer;
diff --git a/xs/src/libslic3r/GCodeTimeEstimator.cpp b/xs/src/libslic3r/GCodeTimeEstimator.cpp
index 176159ff5..553ddba08 100644
--- a/xs/src/libslic3r/GCodeTimeEstimator.cpp
+++ b/xs/src/libslic3r/GCodeTimeEstimator.cpp
@@ -4,9 +4,14 @@
#include <Shiny/Shiny.h>
+#include <boost/nowide/fstream.hpp>
+#include <boost/nowide/cstdio.hpp>
+#include <boost/algorithm/string/predicate.hpp>
+
static const float MMMIN_TO_MMSEC = 1.0f / 60.0f;
static const float MILLISEC_TO_SEC = 0.001f;
static const float INCHES_TO_MM = 25.4f;
+
static const float DEFAULT_FEEDRATE = 1500.0f; // from Prusa Firmware (Marlin_main.cpp)
static const float DEFAULT_ACCELERATION = 1500.0f; // Prusa Firmware 1_75mm_MK2
static const float DEFAULT_RETRACT_ACCELERATION = 1500.0f; // Prusa Firmware 1_75mm_MK2
@@ -17,8 +22,31 @@ static const float DEFAULT_MINIMUM_FEEDRATE = 0.0f; // from Prusa Firmware (Conf
static const float DEFAULT_MINIMUM_TRAVEL_FEEDRATE = 0.0f; // from Prusa Firmware (Configuration_adv.h)
static const float DEFAULT_EXTRUDE_FACTOR_OVERRIDE_PERCENTAGE = 1.0f; // 100 percent
+static const float SILENT_FEEDRATE = 1500.0f; // from Prusa Firmware (Marlin_main.cpp)
+static const float SILENT_ACCELERATION = 1250.0f; // Prusa Firmware 1_75mm_MK25-RAMBo13a-E3Dv6full
+static const float SILENT_RETRACT_ACCELERATION = 1250.0f; // Prusa Firmware 1_75mm_MK25-RAMBo13a-E3Dv6full
+static const float SILENT_AXIS_MAX_FEEDRATE[] = { 200.0f, 200.0f, 12.0f, 120.0f }; // Prusa Firmware 1_75mm_MK25-RAMBo13a-E3Dv6full
+static const float SILENT_AXIS_MAX_ACCELERATION[] = { 1000.0f, 1000.0f, 200.0f, 5000.0f }; // Prusa Firmware 1_75mm_MK25-RAMBo13a-E3Dv6full
+static const float SILENT_AXIS_MAX_JERK[] = { 10.0f, 10.0f, 0.4f, 2.5f }; // from Prusa Firmware (Configuration.h)
+static const float SILENT_MINIMUM_FEEDRATE = 0.0f; // from Prusa Firmware (Configuration_adv.h)
+static const float SILENT_MINIMUM_TRAVEL_FEEDRATE = 0.0f; // from Prusa Firmware (Configuration_adv.h)
+static const float SILENT_EXTRUDE_FACTOR_OVERRIDE_PERCENTAGE = 1.0f; // 100 percent
+
static const float PREVIOUS_FEEDRATE_THRESHOLD = 0.0001f;
+static const std::string ELAPSED_TIME_TAG_DEFAULT = ";_ELAPSED_TIME_DEFAULT: ";
+static const std::string ELAPSED_TIME_TAG_SILENT = ";_ELAPSED_TIME_SILENT: ";
+
+#define REMAINING_TIME_USE_SINGLE_GCODE_COMMAND 1
+#if REMAINING_TIME_USE_SINGLE_GCODE_COMMAND
+static const std::string REMAINING_TIME_CMD = "M998";
+#else
+static const std::string REMAINING_TIME_CMD_DEFAULT = "M998";
+static const std::string REMAINING_TIME_CMD_SILENT = "M999";
+#endif // REMAINING_TIME_USE_SINGLE_GCODE_COMMAND
+
+static const std::string REMAINING_TIME_COMMENT = " ; estimated remaining time";
+
#if ENABLE_MOVE_STATS
static const std::string MOVE_TYPE_STR[Slic3r::GCodeTimeEstimator::Block::Num_Types] =
{
@@ -73,6 +101,11 @@ namespace Slic3r {
return ::sqrt(value);
}
+ GCodeTimeEstimator::Block::Block()
+ : st_synchronized(false)
+ {
+ }
+
float GCodeTimeEstimator::Block::move_length() const
{
float length = ::sqrt(sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z]));
@@ -159,12 +192,45 @@ namespace Slic3r {
}
#endif // ENABLE_MOVE_STATS
- GCodeTimeEstimator::GCodeTimeEstimator()
+ GCodeTimeEstimator::GCodeTimeEstimator(EMode mode)
+ : _mode(mode)
{
reset();
set_default();
}
+ void GCodeTimeEstimator::add_gcode_line(const std::string& gcode_line)
+ {
+ PROFILE_FUNC();
+ _parser.parse_line(gcode_line,
+ [this](GCodeReader &reader, const GCodeReader::GCodeLine &line)
+ { this->_process_gcode_line(reader, line); });
+ }
+
+ void GCodeTimeEstimator::add_gcode_block(const char *ptr)
+ {
+ PROFILE_FUNC();
+ GCodeReader::GCodeLine gline;
+ auto action = [this](GCodeReader &reader, const GCodeReader::GCodeLine &line)
+ { this->_process_gcode_line(reader, line); };
+ for (; *ptr != 0;) {
+ gline.reset();
+ ptr = _parser.parse_line(ptr, gline, action);
+ }
+ }
+
+ void GCodeTimeEstimator::calculate_time()
+ {
+ PROFILE_FUNC();
+ _reset_time();
+ _set_blocks_st_synchronize(false);
+ _calculate_time();
+
+#if ENABLE_MOVE_STATS
+ _log_moves_stats();
+#endif // ENABLE_MOVE_STATS
+ }
+
void GCodeTimeEstimator::calculate_time_from_text(const std::string& gcode)
{
reset();
@@ -178,9 +244,6 @@ namespace Slic3r {
#if ENABLE_MOVE_STATS
_log_moves_stats();
#endif // ENABLE_MOVE_STATS
-
- _reset_blocks();
- _reset();
}
void GCodeTimeEstimator::calculate_time_from_file(const std::string& file)
@@ -193,9 +256,6 @@ namespace Slic3r {
#if ENABLE_MOVE_STATS
_log_moves_stats();
#endif // ENABLE_MOVE_STATS
-
- _reset_blocks();
- _reset();
}
void GCodeTimeEstimator::calculate_time_from_lines(const std::vector<std::string>& gcode_lines)
@@ -211,42 +271,108 @@ namespace Slic3r {
#if ENABLE_MOVE_STATS
_log_moves_stats();
#endif // ENABLE_MOVE_STATS
-
- _reset_blocks();
- _reset();
}
- void GCodeTimeEstimator::add_gcode_line(const std::string& gcode_line)
+ std::string GCodeTimeEstimator::get_elapsed_time_string()
{
- PROFILE_FUNC();
- _parser.parse_line(gcode_line,
- [this](GCodeReader &reader, const GCodeReader::GCodeLine &line)
- { this->_process_gcode_line(reader, line); });
+ calculate_time();
+ switch (_mode)
+ {
+ default:
+ case Default:
+ return ELAPSED_TIME_TAG_DEFAULT + std::to_string(get_time()) + "\n";
+ case Silent:
+ return ELAPSED_TIME_TAG_SILENT + std::to_string(get_time()) + "\n";
+ }
}
- void GCodeTimeEstimator::add_gcode_block(const char *ptr)
+ bool GCodeTimeEstimator::post_process_elapsed_times(const std::string& filename, float default_time, float silent_time)
{
- PROFILE_FUNC();
- GCodeReader::GCodeLine gline;
- auto action = [this](GCodeReader &reader, const GCodeReader::GCodeLine &line)
- { this->_process_gcode_line(reader, line); };
- for (; *ptr != 0;) {
- gline.reset();
- ptr = _parser.parse_line(ptr, gline, action);
+ boost::nowide::ifstream in(filename);
+ if (!in.good())
+ throw std::runtime_error(std::string("Remaining times estimation failed.\nCannot open file for reading.\n"));
+
+ std::string path_tmp = filename + ".times";
+
+ FILE* out = boost::nowide::fopen(path_tmp.c_str(), "wb");
+ if (out == nullptr)
+ throw std::runtime_error(std::string("Remaining times estimation failed.\nCannot open file for writing.\n"));
+
+ std::string line;
+ while (std::getline(in, line))
+ {
+ if (!in.good())
+ {
+ fclose(out);
+ throw std::runtime_error(std::string("Remaining times estimation failed.\nError while reading from file.\n"));
+ }
+
+#if REMAINING_TIME_USE_SINGLE_GCODE_COMMAND
+ // this function expects elapsed time for default and silent mode to be into two consecutive lines inside the gcode
+ if (boost::contains(line, ELAPSED_TIME_TAG_DEFAULT))
+ {
+ std::string default_elapsed_time_str = line.substr(ELAPSED_TIME_TAG_DEFAULT.length());
+ line = REMAINING_TIME_CMD + " D:" + _get_time_dhms(default_time - (float)atof(default_elapsed_time_str.c_str()));
+
+ std::string next_line;
+ std::getline(in, next_line);
+ if (!in.good())
+ {
+ fclose(out);
+ throw std::runtime_error(std::string("Remaining times estimation failed.\nError while reading from file.\n"));
+ }
+
+ if (boost::contains(next_line, ELAPSED_TIME_TAG_SILENT))
+ {
+ std::string silent_elapsed_time_str = next_line.substr(ELAPSED_TIME_TAG_SILENT.length());
+ line += " S:" + _get_time_dhms(silent_time - (float)atof(silent_elapsed_time_str.c_str())) + REMAINING_TIME_COMMENT;
+ }
+ else
+ // found horphaned default elapsed time, skip the remaining time line output
+ line = next_line;
+ }
+ else if (boost::contains(line, ELAPSED_TIME_TAG_SILENT))
+ // found horphaned silent elapsed time, skip the remaining time line output
+ continue;
+#else
+ bool processed = false;
+ if (boost::contains(line, ELAPSED_TIME_TAG_DEFAULT))
+ {
+ std::string elapsed_time_str = line.substr(ELAPSED_TIME_TAG_DEFAULT.length());
+ line = REMAINING_TIME_CMD_DEFAULT + " " + _get_time_dhms(default_time - (float)atof(elapsed_time_str.c_str()));
+ processed = true;
+ }
+ else if (boost::contains(line, ELAPSED_TIME_TAG_SILENT))
+ {
+ std::string elapsed_time_str = line.substr(ELAPSED_TIME_TAG_SILENT.length());
+ line = REMAINING_TIME_CMD_SILENT + " " + _get_time_dhms(silent_time - (float)atof(elapsed_time_str.c_str()));
+ processed = true;
+ }
+
+ if (processed)
+ line += REMAINING_TIME_COMMENT;
+#endif // REMAINING_TIME_USE_SINGLE_GCODE_COMMAND
+
+ line += "\n";
+ fwrite((const void*)line.c_str(), 1, line.length(), out);
+ if (ferror(out))
+ {
+ in.close();
+ fclose(out);
+ boost::nowide::remove(path_tmp.c_str());
+ throw std::runtime_error(std::string("Remaining times estimation failed.\nIs the disk full?\n"));
+ }
}
- }
- void GCodeTimeEstimator::calculate_time()
- {
- PROFILE_FUNC();
- _calculate_time();
+ fclose(out);
+ in.close();
-#if ENABLE_MOVE_STATS
- _log_moves_stats();
-#endif // ENABLE_MOVE_STATS
+ boost::nowide::remove(filename.c_str());
+ if (boost::nowide::rename(path_tmp.c_str(), filename.c_str()) != 0)
+ throw std::runtime_error(std::string("Failed to rename the output G-code file from ") + path_tmp + " to " + filename + '\n' +
+ "Is " + path_tmp + " locked?" + '\n');
- _reset_blocks();
- _reset();
+ return true;
}
void GCodeTimeEstimator::set_axis_position(EAxis axis, float position)
@@ -411,25 +537,25 @@ namespace Slic3r {
set_global_positioning_type(Absolute);
set_e_local_positioning_type(Absolute);
- set_feedrate(DEFAULT_FEEDRATE);
- set_acceleration(DEFAULT_ACCELERATION);
- set_retract_acceleration(DEFAULT_RETRACT_ACCELERATION);
- set_minimum_feedrate(DEFAULT_MINIMUM_FEEDRATE);
- set_minimum_travel_feedrate(DEFAULT_MINIMUM_TRAVEL_FEEDRATE);
- set_extrude_factor_override_percentage(DEFAULT_EXTRUDE_FACTOR_OVERRIDE_PERCENTAGE);
-
- for (unsigned char a = X; a < Num_Axis; ++a)
+ switch (_mode)
{
- EAxis axis = (EAxis)a;
- set_axis_max_feedrate(axis, DEFAULT_AXIS_MAX_FEEDRATE[a]);
- set_axis_max_acceleration(axis, DEFAULT_AXIS_MAX_ACCELERATION[a]);
- set_axis_max_jerk(axis, DEFAULT_AXIS_MAX_JERK[a]);
+ default:
+ case Default:
+ {
+ _set_default_as_default();
+ break;
+ }
+ case Silent:
+ {
+ _set_default_as_silent();
+ break;
+ }
}
}
void GCodeTimeEstimator::reset()
{
- _time = 0.0f;
+ _reset_time();
#if ENABLE_MOVE_STATS
_moves_stats.clear();
#endif // ENABLE_MOVE_STATS
@@ -442,23 +568,9 @@ namespace Slic3r {
return _time;
}
- std::string GCodeTimeEstimator::get_time_hms() const
+ std::string GCodeTimeEstimator::get_time_dhms() const
{
- float timeinsecs = get_time();
- int hours = (int)(timeinsecs / 3600.0f);
- timeinsecs -= (float)hours * 3600.0f;
- int minutes = (int)(timeinsecs / 60.0f);
- timeinsecs -= (float)minutes * 60.0f;
-
- char buffer[64];
- if (hours > 0)
- ::sprintf(buffer, "%dh %dm %ds", hours, minutes, (int)timeinsecs);
- else if (minutes > 0)
- ::sprintf(buffer, "%dm %ds", minutes, (int)timeinsecs);
- else
- ::sprintf(buffer, "%ds", (int)timeinsecs);
-
- return buffer;
+ return _get_time_dhms(get_time());
}
void GCodeTimeEstimator::_reset()
@@ -473,11 +585,60 @@ namespace Slic3r {
set_additional_time(0.0f);
}
+ void GCodeTimeEstimator::_reset_time()
+ {
+ _time = 0.0f;
+ }
+
void GCodeTimeEstimator::_reset_blocks()
{
_blocks.clear();
}
+ void GCodeTimeEstimator::_set_default_as_default()
+ {
+ set_feedrate(DEFAULT_FEEDRATE);
+ set_acceleration(DEFAULT_ACCELERATION);
+ set_retract_acceleration(DEFAULT_RETRACT_ACCELERATION);
+ set_minimum_feedrate(DEFAULT_MINIMUM_FEEDRATE);
+ set_minimum_travel_feedrate(DEFAULT_MINIMUM_TRAVEL_FEEDRATE);
+ set_extrude_factor_override_percentage(DEFAULT_EXTRUDE_FACTOR_OVERRIDE_PERCENTAGE);
+
+ for (unsigned char a = X; a < Num_Axis; ++a)
+ {
+ EAxis axis = (EAxis)a;
+ set_axis_max_feedrate(axis, DEFAULT_AXIS_MAX_FEEDRATE[a]);
+ set_axis_max_acceleration(axis, DEFAULT_AXIS_MAX_ACCELERATION[a]);
+ set_axis_max_jerk(axis, DEFAULT_AXIS_MAX_JERK[a]);
+ }
+ }
+
+ void GCodeTimeEstimator::_set_default_as_silent()
+ {
+ set_feedrate(SILENT_FEEDRATE);
+ set_acceleration(SILENT_ACCELERATION);
+ set_retract_acceleration(SILENT_RETRACT_ACCELERATION);
+ set_minimum_feedrate(SILENT_MINIMUM_FEEDRATE);
+ set_minimum_travel_feedrate(SILENT_MINIMUM_TRAVEL_FEEDRATE);
+ set_extrude_factor_override_percentage(SILENT_EXTRUDE_FACTOR_OVERRIDE_PERCENTAGE);
+
+ for (unsigned char a = X; a < Num_Axis; ++a)
+ {
+ EAxis axis = (EAxis)a;
+ set_axis_max_feedrate(axis, SILENT_AXIS_MAX_FEEDRATE[a]);
+ set_axis_max_acceleration(axis, SILENT_AXIS_MAX_ACCELERATION[a]);
+ set_axis_max_jerk(axis, SILENT_AXIS_MAX_JERK[a]);
+ }
+ }
+
+ void GCodeTimeEstimator::_set_blocks_st_synchronize(bool state)
+ {
+ for (Block& block : _blocks)
+ {
+ block.st_synchronized = state;
+ }
+ }
+
void GCodeTimeEstimator::_calculate_time()
{
_forward_pass();
@@ -488,6 +649,9 @@ namespace Slic3r {
for (const Block& block : _blocks)
{
+ if (block.st_synchronized)
+ continue;
+
#if ENABLE_MOVE_STATS
float block_time = 0.0f;
block_time += block.acceleration_time();
@@ -1043,7 +1207,7 @@ namespace Slic3r {
void GCodeTimeEstimator::_simulate_st_synchronize()
{
_calculate_time();
- _reset_blocks();
+ _set_blocks_st_synchronize(true);
}
void GCodeTimeEstimator::_forward_pass()
@@ -1051,7 +1215,10 @@ namespace Slic3r {
if (_blocks.size() > 1)
{
for (unsigned int i = 0; i < (unsigned int)_blocks.size() - 1; ++i)
- {
+ {
+ if (_blocks[i].st_synchronized || _blocks[i + 1].st_synchronized)
+ continue;
+
_planner_forward_pass_kernel(_blocks[i], _blocks[i + 1]);
}
}
@@ -1063,6 +1230,9 @@ namespace Slic3r {
{
for (int i = (int)_blocks.size() - 1; i >= 1; --i)
{
+ if (_blocks[i - 1].st_synchronized || _blocks[i].st_synchronized)
+ continue;
+
_planner_reverse_pass_kernel(_blocks[i - 1], _blocks[i]);
}
}
@@ -1115,6 +1285,9 @@ namespace Slic3r {
for (Block& b : _blocks)
{
+ if (b.st_synchronized)
+ continue;
+
curr = next;
next = &b;
@@ -1144,6 +1317,28 @@ namespace Slic3r {
}
}
+ std::string GCodeTimeEstimator::_get_time_dhms(float time_in_secs)
+ {
+ int days = (int)(time_in_secs / 86400.0f);
+ time_in_secs -= (float)days * 86400.0f;
+ int hours = (int)(time_in_secs / 3600.0f);
+ time_in_secs -= (float)hours * 3600.0f;
+ int minutes = (int)(time_in_secs / 60.0f);
+ time_in_secs -= (float)minutes * 60.0f;
+
+ char buffer[64];
+ if (days > 0)
+ ::sprintf(buffer, "%dd %dh %dm %ds", days, hours, minutes, (int)time_in_secs);
+ else if (hours > 0)
+ ::sprintf(buffer, "%dh %dm %ds", hours, minutes, (int)time_in_secs);
+ else if (minutes > 0)
+ ::sprintf(buffer, "%dm %ds", minutes, (int)time_in_secs);
+ else
+ ::sprintf(buffer, "%ds", (int)time_in_secs);
+
+ return buffer;
+ }
+
#if ENABLE_MOVE_STATS
void GCodeTimeEstimator::_log_moves_stats() const
{
diff --git a/xs/src/libslic3r/GCodeTimeEstimator.hpp b/xs/src/libslic3r/GCodeTimeEstimator.hpp
index 8f948abd1..c3fe0f04c 100644
--- a/xs/src/libslic3r/GCodeTimeEstimator.hpp
+++ b/xs/src/libslic3r/GCodeTimeEstimator.hpp
@@ -17,6 +17,12 @@ namespace Slic3r {
class GCodeTimeEstimator
{
public:
+ enum EMode : unsigned char
+ {
+ Default,
+ Silent
+ };
+
enum EUnits : unsigned char
{
Millimeters,
@@ -135,6 +141,10 @@ namespace Slic3r {
FeedrateProfile feedrate;
Trapezoid trapezoid;
+ bool st_synchronized;
+
+ Block();
+
// Returns the length of the move covered by this block, in mm
float move_length() const;
@@ -188,18 +198,29 @@ namespace Slic3r {
#endif // ENABLE_MOVE_STATS
private:
+ EMode _mode;
GCodeReader _parser;
State _state;
Feedrates _curr;
Feedrates _prev;
BlocksList _blocks;
float _time; // s
+
#if ENABLE_MOVE_STATS
MovesStatsMap _moves_stats;
#endif // ENABLE_MOVE_STATS
public:
- GCodeTimeEstimator();
+ explicit GCodeTimeEstimator(EMode mode);
+
+ // Adds the given gcode line
+ void add_gcode_line(const std::string& gcode_line);
+
+ void add_gcode_block(const char *ptr);
+ void add_gcode_block(const std::string &str) { this->add_gcode_block(str.c_str()); }
+
+ // Calculates the time estimate from the gcode lines added using add_gcode_line() or add_gcode_block()
+ void calculate_time();
// Calculates the time estimate from the given gcode in string format
void calculate_time_from_text(const std::string& gcode);
@@ -210,14 +231,12 @@ namespace Slic3r {
// Calculates the time estimate from the gcode contained in given list of gcode lines
void calculate_time_from_lines(const std::vector<std::string>& gcode_lines);
- // Adds the given gcode line
- void add_gcode_line(const std::string& gcode_line);
+ // Calculates the time estimate from the gcode lines added using add_gcode_line() or add_gcode_block()
+ // and returns it in a formatted string
+ std::string get_elapsed_time_string();
- void add_gcode_block(const char *ptr);
- void add_gcode_block(const std::string &str) { this->add_gcode_block(str.c_str()); }
-
- // Calculates the time estimate from the gcode lines added using add_gcode_line()
- void calculate_time();
+ // Converts elapsed time lines, contained in the gcode saved with the given filename, into remaining time commands
+ static bool post_process_elapsed_times(const std::string& filename, float default_time, float silent_time);
// Set current position on the given axis with the given value
void set_axis_position(EAxis axis, float position);
@@ -275,13 +294,19 @@ namespace Slic3r {
// Returns the estimated time, in seconds
float get_time() const;
- // Returns the estimated time, in format HHh MMm SSs
- std::string get_time_hms() const;
+ // Returns the estimated time, in format DDd HHh MMm SSs
+ std::string get_time_dhms() const;
private:
void _reset();
+ void _reset_time();
void _reset_blocks();
+ void _set_default_as_default();
+ void _set_default_as_silent();
+
+ void _set_blocks_st_synchronize(bool state);
+
// Calculates the time estimate
void _calculate_time();
@@ -353,6 +378,9 @@ namespace Slic3r {
void _recalculate_trapezoids();
+ // Returns the given time is seconds in format DDd HHh MMm SSs
+ static std::string _get_time_dhms(float time_in_secs);
+
#if ENABLE_MOVE_STATS
void _log_moves_stats() const;
#endif // ENABLE_MOVE_STATS
diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp
index c56e64c6c..c5b0edbdd 100644
--- a/xs/src/libslic3r/Print.hpp
+++ b/xs/src/libslic3r/Print.hpp
@@ -233,7 +233,8 @@ public:
PrintRegionPtrs regions;
PlaceholderParser placeholder_parser;
// TODO: status_cb
- std::string estimated_print_time;
+ std::string estimated_default_print_time;
+ std::string estimated_silent_print_time;
double total_used_filament, total_extruded_volume, total_cost, total_weight;
std::map<size_t, float> filament_stats;
PrintState<PrintStep, psCount> state;
diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp
index ef9c5345f..7ccbe0111 100644
--- a/xs/xsp/Print.xsp
+++ b/xs/xsp/Print.xsp
@@ -152,8 +152,10 @@ _constant()
%code%{ RETVAL = &THIS->skirt; %};
Ref<ExtrusionEntityCollection> brim()
%code%{ RETVAL = &THIS->brim; %};
- std::string estimated_print_time()
- %code%{ RETVAL = THIS->estimated_print_time; %};
+ std::string estimated_default_print_time()
+ %code%{ RETVAL = THIS->estimated_default_print_time; %};
+ std::string estimated_silent_print_time()
+ %code%{ RETVAL = THIS->estimated_silent_print_time; %};
PrintObjectPtrs* objects()
%code%{ RETVAL = &THIS->objects; %};