diff options
author | Alessandro Ranellucci <aar@cpan.org> | 2016-12-22 01:09:58 +0300 |
---|---|---|
committer | bubnikv <bubnikv@gmail.com> | 2017-02-21 16:02:47 +0300 |
commit | a65c9ba0839bcfc4363e369294bdcc3ceeb949d2 (patch) | |
tree | 6eeccd31a50a62e1a1279d67926e80a4c19e8890 /xs | |
parent | c517b0d8f17ced2b93c63f47aa4cc12eed268801 (diff) |
Ported CoolingBuffer to C++/XS
Diffstat (limited to 'xs')
-rw-r--r-- | xs/MANIFEST | 2 | ||||
-rw-r--r-- | xs/src/libslic3r/GCode/CoolingBuffer.cpp | 132 | ||||
-rw-r--r-- | xs/src/libslic3r/GCode/CoolingBuffer.hpp | 39 | ||||
-rw-r--r-- | xs/src/perlglue.cpp | 1 | ||||
-rw-r--r-- | xs/xsp/GCode.xsp | 11 | ||||
-rw-r--r-- | xs/xsp/my.map | 4 | ||||
-rw-r--r-- | xs/xsp/typemap.xspt | 4 |
7 files changed, 193 insertions, 0 deletions
diff --git a/xs/MANIFEST b/xs/MANIFEST index db101d689..03e52ae50 100644 --- a/xs/MANIFEST +++ b/xs/MANIFEST @@ -52,6 +52,8 @@ src/libslic3r/Flow.cpp src/libslic3r/Flow.hpp src/libslic3r/GCode.cpp src/libslic3r/GCode.hpp +src/libslic3r/GCode/CoolingBuffer.cpp +src/libslic3r/GCode/CoolingBuffer.hpp src/libslic3r/GCodeSender.cpp src/libslic3r/GCodeSender.hpp src/libslic3r/GCodeWriter.cpp diff --git a/xs/src/libslic3r/GCode/CoolingBuffer.cpp b/xs/src/libslic3r/GCode/CoolingBuffer.cpp new file mode 100644 index 000000000..84df9cfd3 --- /dev/null +++ b/xs/src/libslic3r/GCode/CoolingBuffer.cpp @@ -0,0 +1,132 @@ +#include "CoolingBuffer.hpp" +#include <boost/algorithm/string/predicate.hpp> +#include <boost/algorithm/string/replace.hpp> +#include <iostream> + +namespace Slic3r { + +std::string +CoolingBuffer::append(const std::string &gcode, std::string obj_id, size_t layer_id, float print_z) +{ + std::string out; + if (this->_last_z.find(obj_id) != this->_last_z.end()) { + // A layer was finished, Z of the object's layer changed. Process the layer. + out = this->flush(); + } + + this->_layer_id = layer_id; + this->_last_z[obj_id] = print_z; + this->_gcode += gcode; + // This is a very rough estimate of the print time, + // not taking into account the acceleration curves generated by the printer firmware. + this->_elapsed_time += this->_gcodegen->elapsed_time; + this->_gcodegen->elapsed_time = 0; + + return out; +} + +void +apply_speed_factor(std::string &line, float speed_factor, float min_print_speed) +{ + // find pos of F + size_t pos = line.find_first_of('F'); + size_t last_pos = line.find_first_of(' ', pos+1); + + // extract current speed + float speed; + { + std::istringstream iss(line.substr(pos+1, last_pos)); + iss >> speed; + } + + // change speed + speed *= speed_factor; + speed = std::max(speed, min_print_speed); + + // replace speed in string + { + std::ostringstream oss; + oss << speed; + line.replace(pos+1, (last_pos-pos), oss.str()); + } +} + +std::string +CoolingBuffer::flush() +{ + GCode &gg = *this->_gcodegen; + + std::string gcode = this->_gcode; + float elapsed = this->_elapsed_time; + this->_gcode = ""; + this->_elapsed_time = 0; + this->_last_z.clear(); // reset the whole table otherwise we would compute overlapping times + + int fan_speed = gg.config.fan_always_on ? gg.config.min_fan_speed.value : 0; + + float speed_factor = 1.0; + + if (gg.config.cooling) { + #ifdef SLIC3R_DEBUG + printf("Layer %zu estimated printing time: %f seconds\n", layer_id, elapsed); + #endif + + if (elapsed < (float)gg.config.slowdown_below_layer_time) { + // Layer time very short. Enable the fan to a full throttle and slow down the print + // (stretch the layer print time to slowdown_below_layer_time). + fan_speed = gg.config.max_fan_speed; + speed_factor = elapsed / (float)gg.config.slowdown_below_layer_time; + } else if (elapsed < (float)gg.config.fan_below_layer_time) { + // Layer time quite short. Enable the fan proportionally according to the current layer time. + fan_speed = gg.config.max_fan_speed + - (gg.config.max_fan_speed - gg.config.min_fan_speed) + * (elapsed - (float)gg.config.slowdown_below_layer_time) + / (gg.config.fan_below_layer_time - gg.config.slowdown_below_layer_time); + } + + #ifdef SLIC3R_DEBUG + printf(" fan = %d%%, speed = %f%%\n", fan_speed, speed_factor * 100); + #endif + + if (speed_factor < 1.0) { + // Adjust feed rate of G1 commands marked with an _EXTRUDE_SET_SPEED + // as long as they are not _WIPE moves (they cannot if they are _EXTRUDE_SET_SPEED) + // and they are not preceded directly by _BRIDGE_FAN_START (do not adjust bridging speed). + std::string new_gcode; + std::istringstream ss(gcode); + std::string line; + bool bridge_fan_start = false; + while (std::getline(ss, line)) { + if (boost::starts_with(line, "G1") + && boost::contains(line, ";_EXTRUDE_SET_SPEED") + && !boost::contains(line, ";_WIPE") + && !bridge_fan_start) { + apply_speed_factor(line, speed_factor, this->_min_print_speed); + boost::replace_first(line, ";_EXTRUDE_SET_SPEED", ""); + } + bridge_fan_start = boost::contains(line, ";_BRIDGE_FAN_START"); + new_gcode += line + '\n'; + } + gcode = new_gcode; + } + } + if (this->_layer_id < gg.config.disable_fan_first_layers) + fan_speed = 0; + + gcode = gg.writer.set_fan(fan_speed) + gcode; + + // bridge fan speed + if (!gg.config.cooling || gg.config.bridge_fan_speed == 0 || this->_layer_id < gg.config.disable_fan_first_layers) { + boost::replace_all(gcode, ";_BRIDGE_FAN_START", ""); + boost::replace_all(gcode, ";_BRIDGE_FAN_END", ""); + } else { + boost::replace_all(gcode, ";_BRIDGE_FAN_START", gg.writer.set_fan(gg.config.bridge_fan_speed, true)); + boost::replace_all(gcode, ";_BRIDGE_FAN_END", gg.writer.set_fan(fan_speed, true)); + } + boost::replace_all(gcode, ";_WIPE", ""); + boost::replace_all(gcode, ";_EXTRUDE_SET_SPEED", ""); + + return gcode; +} + +} diff --git a/xs/src/libslic3r/GCode/CoolingBuffer.hpp b/xs/src/libslic3r/GCode/CoolingBuffer.hpp new file mode 100644 index 000000000..01770a58d --- /dev/null +++ b/xs/src/libslic3r/GCode/CoolingBuffer.hpp @@ -0,0 +1,39 @@ +#ifndef slic3r_CoolingBuffer_hpp_ +#define slic3r_CoolingBuffer_hpp_ + +#include "libslic3r.h" +#include "GCode.hpp" +#include <map> +#include <string> + +namespace Slic3r { + +/* +A standalone G-code filter, to control cooling of the print. +The G-code is processed per layer. Once a layer is collected, fan start / stop commands are edited +and the print is modified to stretch over a minimum layer time. +*/ + +class CoolingBuffer { + public: + CoolingBuffer(GCode &gcodegen) + : _gcodegen(&gcodegen), _elapsed_time(0.), _layer_id(0) + { + this->_min_print_speed = this->_gcodegen->config.min_print_speed * 60; + }; + std::string append(const std::string &gcode, std::string obj_id, size_t layer_id, float print_z); + std::string flush(); + GCode* gcodegen() { return this->_gcodegen; }; + + private: + GCode* _gcodegen; + std::string _gcode; + float _elapsed_time; + size_t _layer_id; + std::map<std::string,float> _last_z; + float _min_print_speed; +}; + +} + +#endif diff --git a/xs/src/perlglue.cpp b/xs/src/perlglue.cpp index 523d3fe06..552524eaa 100644 --- a/xs/src/perlglue.cpp +++ b/xs/src/perlglue.cpp @@ -15,6 +15,7 @@ REGISTER_CLASS(ExtrusionSimulator, "ExtrusionSimulator"); REGISTER_CLASS(Filler, "Filler"); REGISTER_CLASS(Flow, "Flow"); REGISTER_CLASS(AvoidCrossingPerimeters, "GCode::AvoidCrossingPerimeters"); +REGISTER_CLASS(CoolingBuffer, "GCode::CoolingBuffer"); REGISTER_CLASS(OozePrevention, "GCode::OozePrevention"); REGISTER_CLASS(Wipe, "GCode::Wipe"); REGISTER_CLASS(GCode, "GCode"); diff --git a/xs/xsp/GCode.xsp b/xs/xsp/GCode.xsp index 507132dcf..78f1f9d1f 100644 --- a/xs/xsp/GCode.xsp +++ b/xs/xsp/GCode.xsp @@ -3,6 +3,7 @@ %{ #include <xsinit.h> #include "libslic3r/GCode.hpp" +#include "libslic3r/GCode/CoolingBuffer.hpp" %} %name{Slic3r::GCode::AvoidCrossingPerimeters} class AvoidCrossingPerimeters { @@ -70,6 +71,16 @@ %code{% THIS->path = *value; %}; }; +%name{Slic3r::GCode::CoolingBuffer} class CoolingBuffer { + CoolingBuffer(GCode* gcode) + %code{% RETVAL = new CoolingBuffer(*gcode); %}; + ~CoolingBuffer(); + Ref<GCode> gcodegen(); + + std::string append(std::string gcode, std::string obj_id, size_t layer_id, float print_z); + std::string flush(); +}; + %name{Slic3r::GCode} class GCode { GCode(); ~GCode(); diff --git a/xs/xsp/my.map b/xs/xsp/my.map index c6308aca7..8f5f67d4e 100644 --- a/xs/xsp/my.map +++ b/xs/xsp/my.map @@ -197,6 +197,10 @@ OozePrevention* O_OBJECT_SLIC3R Ref<OozePrevention> O_OBJECT_SLIC3R_T Clone<OozePrevention> O_OBJECT_SLIC3R_T +CoolingBuffer* O_OBJECT_SLIC3R +Ref<CoolingBuffer> O_OBJECT_SLIC3R_T +Clone<CoolingBuffer> O_OBJECT_SLIC3R_T + GCode* O_OBJECT_SLIC3R Ref<GCode> O_OBJECT_SLIC3R_T Clone<GCode> O_OBJECT_SLIC3R_T diff --git a/xs/xsp/typemap.xspt b/xs/xsp/typemap.xspt index e32271ac9..57109055a 100644 --- a/xs/xsp/typemap.xspt +++ b/xs/xsp/typemap.xspt @@ -164,6 +164,10 @@ %typemap{Ref<OozePrevention>}{simple}; %typemap{Clone<OozePrevention>}{simple}; +%typemap{CoolingBuffer*}; +%typemap{Ref<CoolingBuffer>}{simple}; +%typemap{Clone<CoolingBuffer>}{simple}; + %typemap{GCode*}; %typemap{Ref<GCode>}{simple}; %typemap{Clone<GCode>}{simple}; |