diff options
author | Lukas Matena <lukasmatena@seznam.cz> | 2018-02-28 18:04:56 +0300 |
---|---|---|
committer | Lukas Matena <lukasmatena@seznam.cz> | 2018-02-28 18:04:56 +0300 |
commit | a62ad3323f389e3ce93915b7fea92bd1eccf321e (patch) | |
tree | ea1b311809d552e4e91b2c5ad8e0dca0785acc3a /xs/src/libslic3r | |
parent | 3099c32d0805a6fff26929e9be3dcb27e50f9bfa (diff) |
First naive implementation of wipe tower settings dialog
Diffstat (limited to 'xs/src/libslic3r')
-rw-r--r-- | xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 65 | ||||
-rw-r--r-- | xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 152 | ||||
-rw-r--r-- | xs/src/libslic3r/Print.cpp | 4 | ||||
-rw-r--r-- | xs/src/libslic3r/PrintConfig.cpp | 9 | ||||
-rw-r--r-- | xs/src/libslic3r/PrintConfig.hpp | 2 |
5 files changed, 181 insertions, 51 deletions
diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 2a78ed6f1..d7492fdbb 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -33,33 +33,6 @@ TODO LIST constexpr bool peters_wipe_tower = false; // sparse wipe tower inspired by Peter's post processor - not finished yet constexpr float min_layer_difference = 2*m_perimeter_width; -constexpr float max_bridge_distance = 10.f; // in mm -constexpr bool improve_first_layer_adhesion = true; -// experimental: ramming speed (mm^3/s) sampled in 0.25s intervals (one filament so far) -const std::vector<float> ramming_speed = {7.6, 7.6, 7.6, 7.6, 9.0, 9.0, 9.0, 10.7, 10.7, 10.7}; -constexpr float ramming_step_multiplicator = 1.2f; // extra spacing may be needed for some materials -constexpr float ramming_line_width_multiplicator = 1.5f; - -// experimental: time requested for cooling in seconds (common for all materials so far) -constexpr float cooling_time = 14; // PVA: 20; SCAFF: 17; PLA+others: 14 - - -// volumes in mm^3 required for wipe: {{from 0 to ...},{from 1 to ...},{from 2 to ...},{from 3 to ...}}, usage [from][to] -const std::vector<std::vector<float>> wipe_volumes = {{ 0,120, 10, 50}, - { 20, 0, 30, 40}, - { 90, 20, 0, 85}, - {100,140, 30, 0}}; - -/*const std::vector<std::vector<float>> wipe_volumes = {{0, 67, 67, 67}, - {67, 0, 67, 67}, - {67, 67, 0, 67}, - {67, 67, 67, 0}}; -*/ -/*const std::vector<std::vector<float>> wipe_volumes = {{0, 10, 10, 10}, - {10, 0, 10, 10}, - {10, 10, 0, 10}, - {10, 10, 10, 0}}; -*/ namespace Slic3r { @@ -614,7 +587,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo { for (const auto &b : m_layer_info->tool_changes) if ( b.new_tool == tool ) { - wipe_volume = wipe_volumes[b.old_tool][b.new_tool]; + wipe_volume = m_par.wipe_volumes[b.old_tool][b.new_tool]; if (tool == m_layer_info->tool_changes.back().new_tool) last_change_in_layer = true; wipe_area = b.required_depth * m_layer_info->extra_spacing; @@ -804,20 +777,20 @@ void WipeTowerPrusaMM::toolchange_Unload( writer.append("; CP TOOLCHANGE UNLOAD\n"); - const float line_width = m_line_width * ramming_line_width_multiplicator; // desired ramming line thickness - const float y_step = line_width * ramming_step_multiplicator * m_extra_spacing; // spacing between lines in mm + const float line_width = m_line_width * m_par.ramming_line_width_multiplicator[m_current_tool]; // desired ramming line thickness + const float y_step = line_width * m_par.ramming_step_multiplicator[m_current_tool] * m_extra_spacing; // spacing between lines in mm unsigned i = 0; // iterates through ramming_speed m_left_to_right = true; // current direction of ramming float remaining = xr - xl ; // keeps track of distance to the next turnaround float e_done = 0; // measures E move done from each segment - + writer.travel(xl, cleaning_box.ld.y + m_depth_traversed + y_step/2.f ); // move to starting position - while (i < ramming_speed.size()) + while (i < m_par.ramming_speed[m_current_tool].size()) { - const float x = volume_to_length(ramming_speed[i] * 0.25f, line_width, m_layer_height); - const float e = ramming_speed[i] * 0.25f / Filament_Area; // transform volume per sec to E move; + const float x = volume_to_length(m_par.ramming_speed[m_current_tool][i] * 0.25f, line_width, m_layer_height); + const float e = m_par.ramming_speed[m_current_tool][i] * 0.25f / Filament_Area; // transform volume per sec to E move; const float dist = std::min(x - e_done, remaining); // distance to travel for either the next 0.25s, or to the next turnaround const float actual_time = dist/x * 0.25; writer.ram(writer.x(), writer.x() + (m_left_to_right ? 1.f : -1.f) * dist, 0, 0, e * (dist / x), std::hypot(dist, e * (dist / x)) / (actual_time / 60.)); @@ -880,21 +853,21 @@ void WipeTowerPrusaMM::toolchange_Unload( const float start_x = writer.x(); const float turning_point = ( xr-start_x > start_x-xl ? xr : xl ); const float max_x_dist = 2*std::abs(start_x-turning_point); - const int N = 4 + (cooling_time-14)/3; - float time = cooling_time / N; - + const unsigned int N = 4 + std::max(0,(m_par.cooling_time[m_current_tool]-14)/3); + float time = m_par.cooling_time[m_current_tool] / N; + i = 0; - while (i<N) { + while (i<N) { const float speed = std::min(3.4,2.2 + i*0.3 + (i==0 ? 0 : 0.3)); // mm per second: 2.2, 2.8, 3.1, 3.4, 3.4, 3.4, ... const float e_dist = std::min(speed * time,10.f); // distance to travel if (speed * time < 10.f) { // this move is the last one at this speed ++i; - time = cooling_time / N; + time = m_par.cooling_time[m_current_tool] / N; } else time -= e_dist / speed; // subtract time this part will really take - + // as for x, we will make sure the feedrate is at most 2000 float x_dist = (turning_point - WT_EPSILON < xl ? -1.f : 1.f) * std::min(e_dist * (float)sqrt(pow(2000 / (60 * speed), 2) - 1),max_x_dist); const float feedrate = std::hypot(e_dist, x_dist) / ((e_dist / speed) / 60.f); @@ -1124,7 +1097,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) .extrude(box.ld); } - if (m_is_first_layer && improve_first_layer_adhesion) { + if (m_is_first_layer && m_par.adhesion) { // Extrude a dense infill at the 1st layer to improve 1st layer adhesion of the wipe tower. box.expand(-m_perimeter_width/2.f); unsigned nsteps = int(floor((box.lu.y - box.ld.y) / (2*m_perimeter_width))); @@ -1150,7 +1123,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose) const float left = fill_box.lu.x+2*m_perimeter_width; const float right = fill_box.ru.x - 2 * m_perimeter_width; - const int n = 1+(right-left)/max_bridge_distance; + const int n = 1+(right-left)/(m_par.bridging); const float dx = (right-left)/n; for (int i=1;i<=n;++i) { float x=left+dx*i; @@ -1207,12 +1180,12 @@ void WipeTowerPrusaMM::plan_toolchange(float z_par, float layer_height_par, unsi // this is an actual toolchange - let's calculate depth to reserve on the wipe tower float depth = 0.f; float width = m_wipe_tower_width - 3*m_perimeter_width; - float length_to_extrude = volume_to_length(0.25f * std::accumulate(ramming_speed.begin(), ramming_speed.end(), 0.f), - m_line_width * ramming_line_width_multiplicator, + float length_to_extrude = volume_to_length(0.25f * std::accumulate(m_par.ramming_speed[old_tool].begin(), m_par.ramming_speed[old_tool].end(), 0.f), + m_line_width * m_par.ramming_line_width_multiplicator[old_tool], layer_height_par); - depth = (int(length_to_extrude / width) + 1) * (m_line_width * ramming_line_width_multiplicator * ramming_step_multiplicator); + depth = (int(length_to_extrude / width) + 1) * (m_line_width * m_par.ramming_line_width_multiplicator[old_tool] * m_par.ramming_step_multiplicator[old_tool]); length_to_extrude = width*((length_to_extrude / width)-int(length_to_extrude / width)) - width; - length_to_extrude += volume_to_length(wipe_volumes[old_tool][new_tool], m_line_width, layer_height_par); + length_to_extrude += volume_to_length(m_par.wipe_volumes[old_tool][new_tool], m_line_width, layer_height_par); length_to_extrude = std::max(length_to_extrude,0.f); depth += (int(length_to_extrude / width) + 1) * m_line_width; depth *= m_extra_spacing; diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index f5fc2985e..43163a73a 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -4,6 +4,7 @@ #include <algorithm> #include <cmath> #include <string> +#include <sstream> #include <utility> #include "WipeTower.hpp" @@ -22,6 +23,11 @@ constexpr float m_perimeter_width = Nozzle_Diameter * Width_To_Nozzle_Ratio * Ko constexpr float WT_EPSILON = 1e-3f; + + + + + namespace Slic3r { @@ -29,6 +35,141 @@ namespace PrusaMultiMaterial { class Writer; }; + + +// Operator overload to output std::pairs +template <typename T> +std::ostream& operator<<(std::ostream& stream,const std::pair<T,T>& pair) { + return stream << pair.first << " " << pair.second; +} + +// Operator overload to output elements of a vector to std::ofstream easily: +template <typename T> +std::ostream& operator<<(std::ostream& stream,const std::vector<T>& vect) { + for (const auto& element : vect) + stream << element << " "; + return stream; +} + +// Operator overload to input elements of a vector from std::ifstream easily (reads until a fail) +template <typename T> +std::istream& operator>>(std::istream& stream, std::vector<T>& vect) { + vect.clear(); + T value{}; + bool we_read_something = false; + while (stream >> value) { + vect.push_back(value); + we_read_something = true; + } + if (!stream.eof() && we_read_something) { // if this is not eof, we might be at separator - let's get rid of it + stream.clear(); // if we failed on very first line or reached eof, return stream in !good() state + stream.get(); // get() whatever we are stuck at + } + return stream; +} + + +// This struct is used to store parameters and to pass it to wipe tower generator +struct WipeTowerParameters { + WipeTowerParameters() { } // create new empty object + WipeTowerParameters(const std::string& init_data) { // create object and initialize from std::string + std::istringstream in(init_data); // validation of input is left to the caller + in >> bridging >> adhesion >> sampling; + for (std::vector<float> vect{} ; in >> vect ;) { // until we get to fail state ("**")... + if (vect.size()>=3) { + cooling_time.push_back(vect[0]); + ramming_line_width_multiplicator.push_back(vect[1]); + ramming_step_multiplicator.push_back(vect[2]); + vect.erase(vect.begin(),vect.begin()+3); + } + else vect.clear(); // something's not right, we will restore defaults anyway + ramming_speed.push_back(vect); + + if (in.good()) { + in >> vect; + std::vector<std::pair<float,float>> pairs; + for (unsigned int i=0;i<vect.size();++i) + if (i%2==1) + pairs.push_back(std::make_pair(vect[i-1],vect[i])); + ramming_buttons.push_back(pairs); + } + } + in.clear(); + in.get(); + + for (std::vector<float> vect{} ; in >> vect ;) { // let's keep reading + wipe_volumes.push_back(vect); + } + in.clear(); + in.get(); + + std::vector<int> vect{}; + in >> vect; + for (unsigned int i=0;i<vect.size();++i) + if (i%2==1) + filament_wipe_volumes.push_back(std::make_pair(vect[i-1],vect[i])); + } + + std::string to_string() { + std::ostringstream out; + out << bridging << " " << int(adhesion) << " " << sampling << "\n"; + for (unsigned extruder=0;extruder<cooling_time.size();++extruder) { + out << "\n" << cooling_time[extruder] << " " << ramming_line_width_multiplicator[extruder] << " " + << ramming_step_multiplicator[extruder] << " " << ramming_speed[extruder] << "*" + << ramming_buttons[extruder] << "*"; + } + out << "*\n"; + for (auto& radek : wipe_volumes) + out << "\n" << radek << "*"; + out << "*\n"; + out << filament_wipe_volumes << "*"; + return out.str(); + } + + bool validate() const { // basic check for validity to distinguish most dramatic failures + const unsigned int num = cooling_time.size(); + if ( num < 1 || ramming_line_width_multiplicator.size()!=num || ramming_step_multiplicator.size()!=num || + ramming_buttons.size()!=num || wipe_volumes.size()!=num || + filament_wipe_volumes.size()!=num) + return false; + for (const auto& row : wipe_volumes) + if (row.size()!=num) + return false; + return true; + } + void set_defaults() { + bridging = 10; + adhesion = true; + sampling = 0.25f; + cooling_time = {15,15,15,15}; + ramming_line_width_multiplicator = {1.5f, 1.5f, 1.5f, 1.5f}; + ramming_step_multiplicator = {1.1f, 1.1f, 1.1f, 1.1f}; + ramming_speed.clear(); + ramming_buttons.clear(); + for (unsigned int i=0;i<4;++i) { + ramming_speed.push_back(std::vector<float>{7.6, 7.6, 7.6, 7.6, 9.0, 9.0, 9.0, 10.7, 10.7, 10.7}); + ramming_buttons.push_back(std::vector<std::pair<float,float>>{{0.05, 6.6},{0.45, 6.8},{0.95, 7.8},{1.45, 8.3},{1.95, 9.7},{2.45,10},{2.95, 7.6},{3.45, 7.6},{3.95, 7.6},{4.45, 7.6},{4.95, 7.6}}); + } + wipe_volumes = {{ 0, 60, 60, 60}, + { 60, 0, 60, 60}, + { 60, 60, 0, 60}, + { 60, 60, 60, 0}}; + filament_wipe_volumes = {{30,30},{30,30},{30,30},{30,30}}; + } + + int bridging = 0.f; + bool adhesion = false; + float sampling = 0.25f; // this does not quite work yet, keep it fixed to 0.25f + std::vector<int> cooling_time; + std::vector<float> ramming_line_width_multiplicator; + std::vector<float> ramming_step_multiplicator; + std::vector<std::vector<float>> ramming_speed; + std::vector<std::vector<std::pair<float,float>>> ramming_buttons; + std::vector<std::vector<float>> wipe_volumes; + std::vector<std::pair<int,int>> filament_wipe_volumes; +}; + + class WipeTowerPrusaMM : public WipeTower { public: @@ -53,15 +194,16 @@ public: // y -- y coordinates of wipe tower in mm ( left bottom corner ) // width -- width of wipe tower in mm ( default 60 mm - leave as it is ) // wipe_area -- space available for one toolchange in mm - WipeTowerPrusaMM(float x, float y, float width, float wipe_area, float rotation_angle, unsigned int initial_tool) : + WipeTowerPrusaMM(float x, float y, float width, float wipe_area, float rotation_angle, unsigned int initial_tool,std::string& parameters) : m_wipe_tower_pos(x, y), m_wipe_tower_width(width), m_wipe_tower_rotation_angle(rotation_angle), m_y_shift(0.f), m_z_pos(0.f), m_is_first_layer(false), - m_is_last_layer(false), - m_current_tool(initial_tool) + m_is_last_layer(false), + m_current_tool(initial_tool), + m_par(parameters) { for (size_t i = 0; i < 4; ++ i) { // Extruder specific parameters. @@ -206,6 +348,7 @@ private: // A fill-in direction (positive Y, negative Y) alternates with each layer. wipe_shape m_current_shape = SHAPE_NORMAL; unsigned int m_current_tool = 0; + WipeTowerParameters m_par; float m_depth_traversed = 0.f; // Current y position at the wipe tower. // How much to wipe the 1st extruder over the wipe tower at the 1st layer @@ -310,6 +453,9 @@ private: float wipe_volume); }; + + + }; // namespace Slic3r #endif /* WipeTowerPrusaMM_hpp_ */ diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 1c63dbf60..fe98612cf 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -187,6 +187,7 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option || opt_key == "spiral_vase" || opt_key == "temperature" || opt_key == "wipe_tower" + || opt_key == "wipe_tower_advanced" || opt_key == "wipe_tower_x" || opt_key == "wipe_tower_y" || opt_key == "wipe_tower_width" @@ -1021,7 +1022,8 @@ void Print::_make_wipe_tower() WipeTowerPrusaMM wipe_tower( float(this->config.wipe_tower_x.value), float(this->config.wipe_tower_y.value), float(this->config.wipe_tower_width.value), float(this->config.wipe_tower_per_color_wipe.value), - float(this->config.wipe_tower_rotation_angle.value), m_tool_ordering.first_extruder()); + float(this->config.wipe_tower_rotation_angle.value), m_tool_ordering.first_extruder(), + this->config.wipe_tower_advanced.value); //wipe_tower.set_retract(); //wipe_tower.set_zhop(); diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index 995dcee99..7a48b3a32 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -1701,6 +1701,13 @@ PrintConfigDef::PrintConfigDef() def->cli = "wipe-tower!"; def->default_value = new ConfigOptionBool(false); + def = this->add("wipe_tower_advanced", coString); + def->label = _L("Advanced string"); + def->tooltip = _L("Advanced tooltip "); + def->sidetext = _L("advanced sidetext"); + def->cli = "wipe-tower-advanced=s"; + def->default_value = new ConfigOptionString(""); + def = this->add("wipe_tower_x", coFloat); def->label = _L("Position X"); def->tooltip = _L("X coordinate of the left front corner of a wipe tower"); @@ -1723,7 +1730,7 @@ PrintConfigDef::PrintConfigDef() def->default_value = new ConfigOptionFloat(60.); def = this->add("wipe_tower_per_color_wipe", coFloat); - def->label = _L("Per color change depth"); + def->label = "(Unused and will be likely removed)";//_L("Per color change depth"); def->tooltip = _L("Depth of a wipe color per color change. For N colors, there will be " "maximum (N-1) tool switches performed, therefore the total depth " "of the wipe tower will be (N-1) times this value."); diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index 7c2d40458..d55aafed6 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -605,6 +605,7 @@ public: ConfigOptionInt threads; ConfigOptionBools wipe; ConfigOptionBool wipe_tower; + ConfigOptionString wipe_tower_advanced; ConfigOptionFloat wipe_tower_x; ConfigOptionFloat wipe_tower_y; ConfigOptionFloat wipe_tower_width; @@ -670,6 +671,7 @@ protected: OPT_PTR(threads); OPT_PTR(wipe); OPT_PTR(wipe_tower); + OPT_PTR(wipe_tower_advanced); OPT_PTR(wipe_tower_x); OPT_PTR(wipe_tower_y); OPT_PTR(wipe_tower_width); |