Implemented time estimation for PausePrint (#3544)

DoubleSlider: fixed get_color_for_color_change_tick()
This commit is contained in:
YuSanka 2020-02-20 17:32:46 +01:00
parent 90a8076d25
commit 487ac0423e
8 changed files with 127 additions and 59 deletions

View file

@ -13,6 +13,12 @@ static constexpr char ColorChangeCode[] = "M600";
static constexpr char PausePrintCode[] = "M601"; static constexpr char PausePrintCode[] = "M601";
static constexpr char ToolChangeCode[] = "tool_change"; static constexpr char ToolChangeCode[] = "tool_change";
enum CustomGcodeType
{
cgtColorChange,
cgtPausePrint,
};
namespace CustomGCode { namespace CustomGCode {
struct Item struct Item

View file

@ -1033,9 +1033,9 @@ namespace DoExport {
print_statistics.clear(); print_statistics.clear();
print_statistics.estimated_normal_print_time = normal_time_estimator.get_time_dhm/*s*/(); print_statistics.estimated_normal_print_time = normal_time_estimator.get_time_dhm/*s*/();
print_statistics.estimated_silent_print_time = silent_time_estimator_enabled ? silent_time_estimator.get_time_dhm/*s*/() : "N/A"; print_statistics.estimated_silent_print_time = silent_time_estimator_enabled ? silent_time_estimator.get_time_dhm/*s*/() : "N/A";
print_statistics.estimated_normal_color_print_times = normal_time_estimator.get_color_times_dhms(true); print_statistics.estimated_normal_custom_gcode_print_times = normal_time_estimator.get_custom_gcode_times_dhm(true);
if (silent_time_estimator_enabled) if (silent_time_estimator_enabled)
print_statistics.estimated_silent_color_print_times = silent_time_estimator.get_color_times_dhms(true); print_statistics.estimated_silent_custom_gcode_print_times = silent_time_estimator.get_custom_gcode_times_dhm(true);
print_statistics.total_toolchanges = std::max(0, wipe_tower_data.number_of_toolchanges); print_statistics.total_toolchanges = std::max(0, wipe_tower_data.number_of_toolchanges);
if (! extruders.empty()) { if (! extruders.empty()) {
std::pair<std::string, unsigned int> out_filament_used_mm ("; filament used [mm] = ", 0); std::pair<std::string, unsigned int> out_filament_used_mm ("; filament used [mm] = ", 0);
@ -1823,7 +1823,7 @@ namespace ProcessLayer
if (!pause_print_msg.empty()) if (!pause_print_msg.empty())
gcode += "M117 " + pause_print_msg + "\n"; gcode += "M117 " + pause_print_msg + "\n";
// add tag for time estimator // add tag for time estimator
//gcode += "; " + GCodeTimeEstimator::Pause_Print_Tag + "\n"; gcode += "; " + GCodeTimeEstimator::Pause_Print_Tag + "\n";
} }
else // custom Gcode else // custom Gcode
{ {

View file

@ -174,6 +174,7 @@ namespace Slic3r {
const std::string GCodeTimeEstimator::Silent_Last_M73_Output_Placeholder_Tag = "; _TE_SILENT_LAST_M73_OUTPUT_PLACEHOLDER"; const std::string GCodeTimeEstimator::Silent_Last_M73_Output_Placeholder_Tag = "; _TE_SILENT_LAST_M73_OUTPUT_PLACEHOLDER";
const std::string GCodeTimeEstimator::Color_Change_Tag = "PRINT_COLOR_CHANGE"; const std::string GCodeTimeEstimator::Color_Change_Tag = "PRINT_COLOR_CHANGE";
const std::string GCodeTimeEstimator::Pause_Print_Tag = "PRINT_PAUSE";
GCodeTimeEstimator::GCodeTimeEstimator(EMode mode) GCodeTimeEstimator::GCodeTimeEstimator(EMode mode)
: m_mode(mode) : m_mode(mode)
@ -212,8 +213,8 @@ namespace Slic3r {
} }
_calculate_time(); _calculate_time();
if (m_needs_color_times && (m_color_time_cache != 0.0f)) if (m_needs_custom_gcode_times && (m_custom_gcode_time_cache != 0.0f))
m_color_times.push_back(m_color_time_cache); m_custom_gcode_times.push_back({ cgtColorChange, m_custom_gcode_time_cache });
#if ENABLE_MOVE_STATS #if ENABLE_MOVE_STATS
_log_moves_stats(); _log_moves_stats();
@ -230,8 +231,8 @@ namespace Slic3r {
_calculate_time(); _calculate_time();
if (m_needs_color_times && (m_color_time_cache != 0.0f)) if (m_needs_custom_gcode_times && (m_custom_gcode_time_cache != 0.0f))
m_color_times.push_back(m_color_time_cache); m_custom_gcode_times.push_back({ cgtColorChange, m_custom_gcode_time_cache });
#if ENABLE_MOVE_STATS #if ENABLE_MOVE_STATS
_log_moves_stats(); _log_moves_stats();
@ -245,8 +246,8 @@ namespace Slic3r {
m_parser.parse_file(file, boost::bind(&GCodeTimeEstimator::_process_gcode_line, this, _1, _2)); m_parser.parse_file(file, boost::bind(&GCodeTimeEstimator::_process_gcode_line, this, _1, _2));
_calculate_time(); _calculate_time();
if (m_needs_color_times && (m_color_time_cache != 0.0f)) if (m_needs_custom_gcode_times && (m_custom_gcode_time_cache != 0.0f))
m_color_times.push_back(m_color_time_cache); m_custom_gcode_times.push_back({ cgtColorChange, m_custom_gcode_time_cache });
#if ENABLE_MOVE_STATS #if ENABLE_MOVE_STATS
_log_moves_stats(); _log_moves_stats();
@ -263,8 +264,8 @@ namespace Slic3r {
m_parser.parse_line(line, action); m_parser.parse_line(line, action);
_calculate_time(); _calculate_time();
if (m_needs_color_times && (m_color_time_cache != 0.0f)) if (m_needs_custom_gcode_times && (m_custom_gcode_time_cache != 0.0f))
m_color_times.push_back(m_color_time_cache); m_custom_gcode_times.push_back({ cgtColorChange, m_custom_gcode_time_cache});
#if ENABLE_MOVE_STATS #if ENABLE_MOVE_STATS
_log_moves_stats(); _log_moves_stats();
@ -351,8 +352,8 @@ namespace Slic3r {
} }
// check tags // check tags
// remove color change tag // remove Color_Change_Tag and Pause_Print_Tag
if (gcode_line == "; " + Color_Change_Tag) if (gcode_line == "; " + Color_Change_Tag || gcode_line == "; " + Pause_Print_Tag)
continue; continue;
// replaces placeholders for initial line M73 with the real lines // replaces placeholders for initial line M73 with the real lines
@ -717,25 +718,26 @@ namespace Slic3r {
return _get_time_minutes(get_time()); return _get_time_minutes(get_time());
} }
std::vector<float> GCodeTimeEstimator::get_color_times() const std::vector<std::pair<CustomGcodeType, float>> GCodeTimeEstimator::get_custom_gcode_times() const
{ {
return m_color_times; return m_custom_gcode_times;
} }
std::vector<std::string> GCodeTimeEstimator::get_color_times_dhms(bool include_remaining) const std::vector<std::string> GCodeTimeEstimator::get_color_times_dhms(bool include_remaining) const
{ {
std::vector<std::string> ret; std::vector<std::string> ret;
float total_time = 0.0f; float total_time = 0.0f;
for (float t : m_color_times) // for (float t : m_color_times)
for (auto t : m_custom_gcode_times)
{ {
std::string time = _get_time_dhms(t); std::string time = _get_time_dhms(t.second);
if (include_remaining) if (include_remaining)
{ {
time += " ("; time += " (";
time += _get_time_dhms(m_time - total_time); time += _get_time_dhms(m_time - total_time);
time += ")"; time += ")";
} }
total_time += t; total_time += t.second;
ret.push_back(time); ret.push_back(time);
} }
return ret; return ret;
@ -745,20 +747,42 @@ namespace Slic3r {
{ {
std::vector<std::string> ret; std::vector<std::string> ret;
float total_time = 0.0f; float total_time = 0.0f;
for (float t : m_color_times) // for (float t : m_color_times)
for (auto t : m_custom_gcode_times)
{ {
std::string time = _get_time_minutes(t); std::string time = _get_time_minutes(t.second);
if (include_remaining) if (include_remaining)
{ {
time += " ("; time += " (";
time += _get_time_minutes(m_time - total_time); time += _get_time_minutes(m_time - total_time);
time += ")"; time += ")";
} }
total_time += t; total_time += t.second;
} }
return ret; return ret;
} }
std::vector<std::pair<CustomGcodeType, std::string>> GCodeTimeEstimator::get_custom_gcode_times_dhm(bool include_remaining) const
{
std::vector<std::pair<CustomGcodeType, std::string>> ret;
float total_time = 0.0f;
for (auto t : m_custom_gcode_times)
{
std::string time = _get_time_dhm(t.second);
if (include_remaining)
{
time += " (";
time += _get_time_dhm(m_time - total_time);
time += ")";
}
total_time += t.second;
ret.push_back({t.first, time});
}
return ret;
}
// Return an estimate of the memory consumed by the time estimator. // Return an estimate of the memory consumed by the time estimator.
size_t GCodeTimeEstimator::memory_used() const size_t GCodeTimeEstimator::memory_used() const
{ {
@ -791,9 +815,9 @@ namespace Slic3r {
m_last_st_synchronized_block_id = -1; m_last_st_synchronized_block_id = -1;
m_needs_color_times = false; m_needs_custom_gcode_times = false;
m_color_times.clear(); m_custom_gcode_times.clear();
m_color_time_cache = 0.0f; m_custom_gcode_time_cache = 0.0f;
} }
void GCodeTimeEstimator::_reset_time() void GCodeTimeEstimator::_reset_time()
@ -814,7 +838,7 @@ namespace Slic3r {
_recalculate_trapezoids(); _recalculate_trapezoids();
m_time += get_additional_time(); m_time += get_additional_time();
m_color_time_cache += get_additional_time(); m_custom_gcode_time_cache += get_additional_time();
for (int i = m_last_st_synchronized_block_id + 1; i < (int)m_blocks.size(); ++i) for (int i = m_last_st_synchronized_block_id + 1; i < (int)m_blocks.size(); ++i)
{ {
@ -835,7 +859,7 @@ namespace Slic3r {
it->second.time += block_time; it->second.time += block_time;
#endif // ENABLE_MOVE_STATS #endif // ENABLE_MOVE_STATS
m_color_time_cache += block_time; m_custom_gcode_time_cache += block_time;
} }
m_last_st_synchronized_block_id = (int)m_blocks.size() - 1; m_last_st_synchronized_block_id = (int)m_blocks.size() - 1;
@ -1466,26 +1490,34 @@ namespace Slic3r {
{ {
std::string comment = line.comment(); std::string comment = line.comment();
// color change tag // Color_Change_Tag
size_t pos = comment.find(Color_Change_Tag); size_t pos = comment.find(Color_Change_Tag);
if (pos != comment.npos) if (pos != comment.npos)
{ {
_process_color_change_tag(); _process_custom_gcode_tag(cgtColorChange);
return true;
}
// Pause_Print_Tag
pos = comment.find(Pause_Print_Tag);
if (pos != comment.npos)
{
_process_custom_gcode_tag(cgtPausePrint);
return true; return true;
} }
return false; return false;
} }
void GCodeTimeEstimator::_process_color_change_tag() void GCodeTimeEstimator::_process_custom_gcode_tag(CustomGcodeType code)
{ {
PROFILE_FUNC(); PROFILE_FUNC();
m_needs_color_times = true; m_needs_custom_gcode_times = true;
_calculate_time(); _calculate_time();
if (m_color_time_cache != 0.0f) if (m_custom_gcode_time_cache != 0.0f)
{ {
m_color_times.push_back(m_color_time_cache); m_custom_gcode_times.push_back({code, m_custom_gcode_time_cache});
m_color_time_cache = 0.0f; m_custom_gcode_time_cache = 0.0f;
} }
} }

View file

@ -4,6 +4,7 @@
#include "libslic3r.h" #include "libslic3r.h"
#include "PrintConfig.hpp" #include "PrintConfig.hpp"
#include "GCodeReader.hpp" #include "GCodeReader.hpp"
#include "CustomGCode.hpp"
#define ENABLE_MOVE_STATS 0 #define ENABLE_MOVE_STATS 0
@ -23,6 +24,7 @@ namespace Slic3r {
static const std::string Silent_Last_M73_Output_Placeholder_Tag; static const std::string Silent_Last_M73_Output_Placeholder_Tag;
static const std::string Color_Change_Tag; static const std::string Color_Change_Tag;
static const std::string Pause_Print_Tag;
enum EMode : unsigned char enum EMode : unsigned char
{ {
@ -240,10 +242,10 @@ namespace Slic3r {
int m_last_st_synchronized_block_id; int m_last_st_synchronized_block_id;
float m_time; // s float m_time; // s
// data to calculate color print times // data to calculate custom code times
bool m_needs_color_times; bool m_needs_custom_gcode_times;
std::vector<float> m_color_times; std::vector<std::pair<CustomGcodeType, float>> m_custom_gcode_times;
float m_color_time_cache; float m_custom_gcode_time_cache;
#if ENABLE_MOVE_STATS #if ENABLE_MOVE_STATS
MovesStatsMap _moves_stats; MovesStatsMap _moves_stats;
@ -369,8 +371,8 @@ namespace Slic3r {
// Returns the estimated time, in minutes (integer) // Returns the estimated time, in minutes (integer)
std::string get_time_minutes() const; std::string get_time_minutes() const;
// Returns the estimated time, in seconds, for each color // Returns the estimated time, in seconds, for each custom gcode
std::vector<float> get_color_times() const; std::vector<std::pair<CustomGcodeType, float>> get_custom_gcode_times() const;
// Returns the estimated time, in format DDd HHh MMm SSs, for each color // Returns the estimated time, in format DDd HHh MMm SSs, for each color
// If include_remaining==true the strings will be formatted as: "time for color (remaining time at color start)" // If include_remaining==true the strings will be formatted as: "time for color (remaining time at color start)"
@ -380,6 +382,10 @@ namespace Slic3r {
// If include_remaining==true the strings will be formatted as: "time for color (remaining time at color start)" // If include_remaining==true the strings will be formatted as: "time for color (remaining time at color start)"
std::vector<std::string> get_color_times_minutes(bool include_remaining) const; std::vector<std::string> get_color_times_minutes(bool include_remaining) const;
// Returns the estimated time, in format DDd HHh MMm, for each custom_gcode
// If include_remaining==true the strings will be formatted as: "time for custom_gcode (remaining time at color start)"
std::vector<std::pair<CustomGcodeType, std::string>> get_custom_gcode_times_dhm(bool include_remaining) const;
// Return an estimate of the memory consumed by the time estimator. // Return an estimate of the memory consumed by the time estimator.
size_t memory_used() const; size_t memory_used() const;
@ -460,8 +466,8 @@ namespace Slic3r {
// Returns true if any tag has been processed // Returns true if any tag has been processed
bool _process_tags(const GCodeReader::GCodeLine& line); bool _process_tags(const GCodeReader::GCodeLine& line);
// Processes color change tag // Processes ColorChangeTag and PausePrintTag
void _process_color_change_tag(); void _process_custom_gcode_tag(CustomGcodeType code);
// Simulates firmware st_synchronize() call // Simulates firmware st_synchronize() call
void _simulate_st_synchronize(); void _simulate_st_synchronize();

View file

@ -302,8 +302,8 @@ struct PrintStatistics
PrintStatistics() { clear(); } PrintStatistics() { clear(); }
std::string estimated_normal_print_time; std::string estimated_normal_print_time;
std::string estimated_silent_print_time; std::string estimated_silent_print_time;
std::vector<std::string> estimated_normal_color_print_times; std::vector<std::pair<CustomGcodeType, std::string>> estimated_normal_custom_gcode_print_times;
std::vector<std::string> estimated_silent_color_print_times; std::vector<std::pair<CustomGcodeType, std::string>> estimated_silent_custom_gcode_print_times;
double total_used_filament; double total_used_filament;
double total_extruded_volume; double total_extruded_volume;
double total_cost; double total_cost;
@ -323,8 +323,8 @@ struct PrintStatistics
void clear() { void clear() {
estimated_normal_print_time.clear(); estimated_normal_print_time.clear();
estimated_silent_print_time.clear(); estimated_silent_print_time.clear();
estimated_normal_color_print_times.clear(); estimated_normal_custom_gcode_print_times.clear();
estimated_silent_color_print_times.clear(); estimated_silent_custom_gcode_print_times.clear();
total_used_filament = 0.; total_used_filament = 0.;
total_extruded_volume = 0.; total_extruded_volume = 0.;
total_cost = 0.; total_cost = 0.;

View file

@ -696,9 +696,11 @@ std::string Control::get_color_for_color_change_tick(std::set<TickCode>::const_i
if (it_n->gcode == ToolChangeCode) { if (it_n->gcode == ToolChangeCode) {
is_tool_change = true; is_tool_change = true;
if (it_n->extruder == it->extruder) if (it_n->extruder == it->extruder)
return m_extruder_colors[it->extruder-1]; // return a color for a specific extruder from the colors list return it->color;
break; break;
} }
if (it_n->gcode == ColorChangeCode && it_n->extruder == it->extruder)
return it->color;
} }
if (!is_tool_change && it->extruder == def_extruder) if (!is_tool_change && it->extruder == def_extruder)
return it->color; return it->color;

View file

@ -982,12 +982,17 @@ void GLCanvas3D::LegendTexture::fill_color_print_legend_items( const GLCanvas3D
cp_legend_items.emplace_back(I18N::translate_utf8(L("Pause print or custom G-code"))); cp_legend_items.emplace_back(I18N::translate_utf8(L("Pause print or custom G-code")));
int cnt = custom_gcode_per_print_z.size(); int cnt = custom_gcode_per_print_z.size();
int color_change_idx = color_cnt - extruders_cnt;
for (int i = cnt-1; i >= 0; --i) for (int i = cnt-1; i >= 0; --i)
if (custom_gcode_per_print_z[i].gcode == ColorChangeCode) { if (custom_gcode_per_print_z[i].gcode == ColorChangeCode) {
::memcpy((void*)(colors.data() + color_pos), (const void*)(colors_in.data() + color_in_pos), 4 * sizeof(float)); ::memcpy((void*)(colors.data() + color_pos), (const void*)(colors_in.data() + color_in_pos), 4 * sizeof(float));
color_pos += 4; color_pos += 4;
color_in_pos -= 4; color_in_pos -= 4;
cp_legend_items.emplace_back((boost::format(I18N::translate_utf8(L("Color change for Extruder %d at %.2f mm"))) % custom_gcode_per_print_z[i].extruder % custom_gcode_per_print_z[i].print_z).str());
// create label for color change item
std::string id_str = std::to_string(color_change_idx--) + ": ";
cp_legend_items.emplace_back(id_str + (boost::format(I18N::translate_utf8(L("Color change for Extruder %d at %.2f mm"))) % custom_gcode_per_print_z[i].extruder % custom_gcode_per_print_z[i].print_z).str());
} }
} }
} }

View file

@ -1252,23 +1252,40 @@ void Sidebar::update_sliced_info_sizer()
else { else {
new_label = _(L("Estimated printing time")) +" :"; new_label = _(L("Estimated printing time")) +" :";
info_text = ""; info_text = "";
if (ps.estimated_normal_print_time != "N/A") { wxString str_color = _(L("Color"));
new_label += wxString::Format("\n - %s", _(L("normal mode"))); wxString str_pause = _(L("Pause"));
info_text += wxString::Format("\n%s", ps.estimated_normal_print_time);
for (int i = (int)ps.estimated_normal_color_print_times.size() - 1; i >= 0; --i) auto fill_labels = [str_color, str_pause](const std::vector<std::pair<CustomGcodeType, std::string>>& times,
wxString& new_label, wxString& info_text)
{
int color_change_count = 0;
for (auto time : times)
if (time.first == cgtColorChange)
color_change_count++;
for (int i = (int)times.size() - 1; i >= 0; --i)
{ {
new_label += wxString::Format("\n - %s%d", _(L("Color")) + " ", i + 1); if (i == 0 || times[i - 1].first == cgtPausePrint)
info_text += wxString::Format("\n%s", ps.estimated_normal_color_print_times[i]); new_label += wxString::Format("\n - %s%d", str_color + " ", color_change_count);
else if (times[i - 1].first == cgtColorChange)
new_label += wxString::Format("\n - %s%d", str_color + " ", color_change_count--);
if (i != (int)times.size() - 1 && times[i].first == cgtPausePrint)
new_label += wxString::Format(" -> %s", str_pause);
info_text += wxString::Format("\n%s", times[i].second);
} }
};
if (ps.estimated_normal_print_time != "N/A") {
new_label += wxString::Format("\n - %s", _(L("normal mode")));
info_text += wxString::Format("\n%s", ps.estimated_normal_print_time);
fill_labels(ps.estimated_normal_custom_gcode_print_times, new_label, info_text);
} }
if (ps.estimated_silent_print_time != "N/A") { if (ps.estimated_silent_print_time != "N/A") {
new_label += wxString::Format("\n - %s", _(L("stealth mode"))); new_label += wxString::Format("\n - %s", _(L("stealth mode")));
info_text += wxString::Format("\n%s", ps.estimated_silent_print_time); info_text += wxString::Format("\n%s", ps.estimated_silent_print_time);
for (int i = (int)ps.estimated_silent_color_print_times.size() - 1; i >= 0; --i) fill_labels(ps.estimated_silent_custom_gcode_print_times, new_label, info_text);
{
new_label += wxString::Format("\n - %s%d", _(L("Color")) + " ", i + 1);
info_text += wxString::Format("\n%s", ps.estimated_silent_color_print_times[i]);
}
} }
p->sliced_info->SetTextAndShow(siEstimatedTime, info_text, new_label); p->sliced_info->SetTextAndShow(siEstimatedTime, info_text, new_label);
} }