Skip to content

Commit

Permalink
Implemented priming of all the filaments of the Prusa Multi Material.
Browse files Browse the repository at this point in the history
  • Loading branch information
bubnikv committed Sep 1, 2017
1 parent 247070c commit b610866
Show file tree
Hide file tree
Showing 13 changed files with 325 additions and 94 deletions.
2 changes: 1 addition & 1 deletion slic3r.sublime-project
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"file_regex": "^(..[^:]*)\\(([0-9]+)\\)(.*)$",
// For GCC:
// "file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
"shell_cmd": "chdir & ninja -j 6",
"shell_cmd": "chdir & ninja -j 6 -v",
"env": {
// "PATH": "C:\\Program Files (x86)\\MSBuild\\12.0\\bin\\amd64;C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\BIN\\amd64;C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\Common7\\IDE;C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\Common7\\Tools;%PATH%;c:\\wperl64d\\site\\bin;c:\\wperl64d\\bin",
// "PERL_CPANM_HOME": "c:\\wperl64d\\cpanm",
Expand Down
13 changes: 11 additions & 2 deletions xs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -394,8 +394,15 @@ target_compile_options(XS PRIVATE ${PerlEmbed_CCFLAGS})
# If the Perl is compiled with optimization off, disable optimization over the whole project.
if (WIN32 AND ";${PerlEmbed_CCFLAGS};" MATCHES ";[-/]Od;")
message(STATUS "Perl compiled without optimization. Disabling optimization for the Slic3r build.")
set(CMAKE_CXX_FLAGS_RELEASE /Od /Zi)
set(CMAKE_C_FLAGS_RELEASE /Od /Zi)
message("Old CMAKE_CXX_FLAGS_RELEASE: ${CMAKE_CXX_FLAGS_RELEASE}")
message("Old CMAKE_CXX_FLAGS_RELWITHDEBINFO: ${CMAKE_CXX_FLAGS_RELEASE}")
message("Old CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS_RELEASE}")
set(CMAKE_CXX_FLAGS_RELEASE "/MD /Od /Zi /EHsc /DNDEBUG")
set(CMAKE_C_FLAGS_RELEASE "/MD /Od /Zi /DNDEBUG")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/MD /Od /Zi /EHsc /DNDEBUG")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "/MD /Od /Zi /DNDEBUG")
set(CMAKE_CXX_FLAGS "/MD /Od /Zi /EHsc /DNDEBUG")
set(CMAKE_C_FLAGS "/MD /Od /Zi /DNDEBUG")
endif()
# The following line will add -fPIC on Linux to make the XS.so rellocable.
add_definitions(${PerlEmbed_CCCDLFLAGS})
Expand Down Expand Up @@ -437,6 +444,8 @@ if(MSVC)
# Suppress implicit linking of the TBB libraries by the Visual Studio compiler.
add_definitions(-D__TBB_NO_IMPLICIT_LINKAGE)
endif()
# The Intel TBB library will use the std::exception_ptr feature of C++11.
add_definitions(-DTBB_USE_CAPTURED_EXCEPTION=0)
target_link_libraries(XS ${TBB_LIBRARIES})

# Find and configure wxWidgets
Expand Down
53 changes: 41 additions & 12 deletions xs/src/libslic3r/GCode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,33 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
return gcode;
}

std::string WipeTowerIntegration::prime(GCode &gcodegen)
{
assert(m_layer_idx == 0);
std::string gcode;

if (&m_priming != nullptr && ! m_priming.extrusions.empty()) {
// Let the tool change be executed by the wipe tower class.
// Inform the G-code writer about the changes done behind its back.
gcode += m_priming.gcode;
// Let the m_writer know the current extruder_id, but ignore the generated G-code.
gcodegen.writer().toolchange(m_priming.extrusions.back().tool);
// A phony move to the end position at the wipe tower.
gcodegen.writer().travel_to_xy(Pointf(m_priming.end_pos.x, m_priming.end_pos.y));
gcodegen.set_last_pos(wipe_tower_point_to_object_point(gcodegen, m_priming.end_pos));

// Prepare a future wipe.
gcodegen.m_wipe.path.points.clear();
// Start the wipe at the current position.
gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen, m_priming.end_pos));
// Wipe end point: Wipe direction away from the closer tower edge to the further tower edge.
gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen,
WipeTower::xy((std::abs(m_left - m_priming.end_pos.x) < std::abs(m_right - m_priming.end_pos.x)) ? m_right : m_left,
m_priming.end_pos.y)));
}
return gcode;
}

std::string WipeTowerIntegration::tool_change(GCode &gcodegen, int extruder_id, bool finish_layer)
{
std::string gcode;
Expand Down Expand Up @@ -522,7 +549,7 @@ bool GCode::_do_export(Print &print, FILE *file)
writeln(file, m_placeholder_parser.process(print.config.start_gcode.value, initial_extruder_id));
// Process filament-specific gcode in extruder order.
for (const std::string &start_gcode : print.config.start_filament_gcode.values)
writeln(file, m_placeholder_parser.process(start_gcode, &start_gcode - &print.config.start_filament_gcode.values.front()));
writeln(file, m_placeholder_parser.process(start_gcode, (unsigned int)(&start_gcode - &print.config.start_filament_gcode.values.front())));
this->_print_first_layer_extruder_temperatures(file, print, initial_extruder_id, true);

// Set other general things.
Expand Down Expand Up @@ -647,8 +674,10 @@ bool GCode::_do_export(Print &print, FILE *file)
std::vector<std::pair<coordf_t, std::vector<LayerToPrint>>> layers_to_print = collect_layers_to_print(print);
// Prusa Multi-Material wipe tower.
if (print.has_wipe_tower() &&
! tool_ordering.empty() && tool_ordering.front().wipe_tower_partitions > 0)
m_wipe_tower.reset(new WipeTowerIntegration(print.config, print.m_wipe_tower_tool_changes, *print.m_wipe_tower_final_purge.get()));
! tool_ordering.empty() && tool_ordering.front().wipe_tower_partitions > 0) {
m_wipe_tower.reset(new WipeTowerIntegration(print.config, *print.m_wipe_tower_priming.get(), print.m_wipe_tower_tool_changes, *print.m_wipe_tower_final_purge.get()));
write(file, m_wipe_tower->prime(*this));
}
// Extrude the layers.
for (auto &layer : layers_to_print) {
const ToolOrdering::LayerTools &layer_tools = tool_ordering.tools_for_layer(layer.first);
Expand All @@ -668,7 +697,7 @@ bool GCode::_do_export(Print &print, FILE *file)
write(file, m_writer.set_fan(false));
// Process filament-specific gcode in extruder order.
for (const std::string &end_gcode : print.config.end_filament_gcode.values)
writeln(file, m_placeholder_parser.process(end_gcode, &end_gcode - &print.config.end_filament_gcode.values.front()));
writeln(file, m_placeholder_parser.process(end_gcode, (unsigned int)(&end_gcode - &print.config.end_filament_gcode.values.front())));
writeln(file, m_placeholder_parser.process(print.config.end_gcode, m_writer.extruder()->id()));
write(file, m_writer.update_progress(m_layer_count, m_layer_count, true)); // 100%
write(file, m_writer.postamble());
Expand Down Expand Up @@ -1471,7 +1500,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
} else if (seam_position == spNearest || seam_position == spAligned || seam_position == spRear) {
Polygon polygon = loop.polygon();
const coordf_t nozzle_dmr = EXTRUDER_CONFIG(nozzle_diameter);
const coord_t nozzle_r = scale_(0.5*nozzle_dmr);
const coord_t nozzle_r = coord_t(scale_(0.5 * nozzle_dmr) + 0.5);

// Retrieve the last start position for this object.
float last_pos_weight = 1.f;
Expand Down Expand Up @@ -1524,11 +1553,11 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
penalty = penaltyConvexVertex;
else if (ccwAngle < 0.f) {
// Interpolate penalty between maximum and zero.
penalty = penaltyFlatSurface * bspline_kernel(ccwAngle * (PI * 2. / 3.));
penalty = penaltyFlatSurface * bspline_kernel(ccwAngle * float(PI * 2. / 3.));
} else {
assert(ccwAngle >= 0.f);
// Interpolate penalty between maximum and the penalty for a convex vertex.
penalty = penaltyConvexVertex + (penaltyFlatSurface - penaltyConvexVertex) * bspline_kernel(ccwAngle * (PI * 2. / 3.));
penalty = penaltyConvexVertex + (penaltyFlatSurface - penaltyConvexVertex) * bspline_kernel(ccwAngle * float(PI * 2. / 3.));
}
// Give a negative penalty for points close to the last point or the prefered seam location.
//float dist_to_last_pos_proj = last_pos_proj.distance_to(polygon.points[i]);
Expand All @@ -1543,8 +1572,8 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
// Penalty for overhangs.
if (lower_layer_edge_grid && (*lower_layer_edge_grid)) {
// Use the edge grid distance field structure over the lower layer to calculate overhangs.
coord_t nozzle_r = scale_(0.5*nozzle_dmr);
coord_t search_r = scale_(0.8*nozzle_dmr);
coord_t nozzle_r = coord_t(floor(scale_(0.5 * nozzle_dmr) + 0.5));
coord_t search_r = coord_t(floor(scale_(0.8 * nozzle_dmr) + 0.5));
for (size_t i = 0; i < polygon.points.size(); ++ i) {
const Point &p = polygon.points[i];
coordf_t dist;
Expand All @@ -1555,7 +1584,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
// If the approximate Signed Distance Field was initialized over lower_layer_edge_grid,
// then the signed distnace shall always be known.
assert(found);
penalties[i] += extrudate_overlap_penalty(nozzle_r, penaltyOverhangHalf, dist);
penalties[i] += extrudate_overlap_penalty(float(nozzle_r), penaltyOverhangHalf, float(dist));
}
}

Expand Down Expand Up @@ -1651,7 +1680,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
}

// reset acceleration
gcode += m_writer.set_acceleration(m_config.default_acceleration.value);
gcode += m_writer.set_acceleration((unsigned int)(m_config.default_acceleration.value + 0.5));

if (m_wipe.enable)
m_wipe.path = paths.front().polyline; // TODO: don't limit wipe to last path
Expand Down Expand Up @@ -1708,7 +1737,7 @@ std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, std::string
m_wipe.path.reverse();
}
// reset acceleration
gcode += m_writer.set_acceleration(m_config.default_acceleration.value);
gcode += m_writer.set_acceleration((unsigned int)floor(m_config.default_acceleration.value + 0.5));
return gcode;
}

Expand Down
4 changes: 4 additions & 0 deletions xs/src/libslic3r/GCode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,19 @@ class WipeTowerIntegration {
public:
WipeTowerIntegration(
const PrintConfig &print_config,
const WipeTower::ToolChangeResult &priming,
const std::vector<std::vector<WipeTower::ToolChangeResult>> &tool_changes,
const WipeTower::ToolChangeResult &final_purge) :
m_left(float(print_config.wipe_tower_x.value)),
m_right(float(print_config.wipe_tower_x.value + print_config.wipe_tower_width.value)),
m_priming(priming),
m_tool_changes(tool_changes),
m_final_purge(final_purge),
m_layer_idx(-1),
m_tool_change_idx(0),
m_brim_done(false) {}

std::string prime(GCode &gcodegen);
void next_layer() { ++ m_layer_idx; m_tool_change_idx = 0; }
std::string tool_change(GCode &gcodegen, int extruder_id, bool finish_layer);
std::string finalize(GCode &gcodegen);
Expand All @@ -99,6 +102,7 @@ class WipeTowerIntegration {
const float m_left;
const float m_right;
// Reference to cached values at the Printer class.
const WipeTower::ToolChangeResult &m_priming;
const std::vector<std::vector<WipeTower::ToolChangeResult>> &m_tool_changes;
const WipeTower::ToolChangeResult &m_final_purge;
// Current layer index.
Expand Down
58 changes: 40 additions & 18 deletions xs/src/libslic3r/GCode/ToolOrdering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Slic3r {

// For the use case when each object is printed separately
// (print.config.complete_objects is true).
ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extruder)
ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extruder, bool prime_multi_material)
{
if (object.layers.empty())
return;
Expand All @@ -31,13 +31,15 @@ ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extrude
this->reorder_extruders(first_extruder);

this->fill_wipe_tower_partitions(object.print()->config, object.layers.front()->print_z - object.layers.front()->height);

this->collect_extruder_statistics(prime_multi_material);
}

// For the use case when all objects are printed at once.
// (print.config.complete_objects is false).
ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder)
ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool prime_multi_material)
{
// Initialize the print layers for all objects and all layers.
// Initialize the print layers for all objects and all layers.
coordf_t object_bottom_z = 0.;
{
std::vector<coordf_t> zs;
Expand All @@ -61,22 +63,8 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder)
this->reorder_extruders(first_extruder);

this->fill_wipe_tower_partitions(print.config, object_bottom_z);
}

unsigned int ToolOrdering::first_extruder() const
{
for (const auto &lt : m_layer_tools)
if (! lt.extruders.empty())
return lt.extruders.front();
return (unsigned int)-1;
}

unsigned int ToolOrdering::last_extruder() const
{
for (auto lt_it = m_layer_tools.rbegin(); lt_it != m_layer_tools.rend(); ++ lt_it)
if (! lt_it->extruders.empty())
return lt_it->extruders.back();
return (unsigned int)-1;
this->collect_extruder_statistics(prime_multi_material);
}

ToolOrdering::LayerTools& ToolOrdering::tools_for_layer(coordf_t print_z)
Expand Down Expand Up @@ -289,4 +277,38 @@ void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_
}
}

void ToolOrdering::collect_extruder_statistics(bool prime_multi_material)
{
m_first_printing_extruder = (unsigned int)-1;
for (const auto &lt : m_layer_tools)
if (! lt.extruders.empty()) {
m_first_printing_extruder = lt.extruders.front();
break;
}

m_last_printing_extruder = (unsigned int)-1;
for (auto lt_it = m_layer_tools.rbegin(); lt_it != m_layer_tools.rend(); ++ lt_it)
if (! lt_it->extruders.empty()) {
m_last_printing_extruder = lt_it->extruders.back();
break;
}

m_all_printing_extruders.clear();
for (const auto &lt : m_layer_tools) {
append(m_all_printing_extruders, lt.extruders);
sort_remove_duplicates(m_all_printing_extruders);
}

if (prime_multi_material && ! m_all_printing_extruders.empty()) {
// Reorder m_all_printing_extruders in the sequence they will be primed, the last one will be m_first_printing_extruder.
// Then set m_first_printing_extruder to the 1st extruder primed.
m_all_printing_extruders.erase(
std::remove_if(m_all_printing_extruders.begin(), m_all_printing_extruders.end(),
[ this ](const unsigned int eid) { return eid == m_first_printing_extruder; }),
m_all_printing_extruders.end());
m_all_printing_extruders.emplace_back(m_first_printing_extruder);
m_first_printing_extruder = m_all_printing_extruders.front();
}
}

} // namespace Slic3r
22 changes: 16 additions & 6 deletions xs/src/libslic3r/GCode/ToolOrdering.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,22 @@ class ToolOrdering

// For the use case when each object is printed separately
// (print.config.complete_objects is true).
ToolOrdering(const PrintObject &object, unsigned int first_extruder = (unsigned int)-1);
ToolOrdering(const PrintObject &object, unsigned int first_extruder = (unsigned int)-1, bool prime_multi_material = false);

// For the use case when all objects are printed at once.
// (print.config.complete_objects is false).
ToolOrdering(const Print &print, unsigned int first_extruder = (unsigned int)-1);
ToolOrdering(const Print &print, unsigned int first_extruder = (unsigned int)-1, bool prime_multi_material = false);

void clear() { m_layer_tools.clear(); }

// Get the first extruder printing the layer_tools, returns -1 if there is no layer printed.
unsigned int first_extruder() const;
unsigned int first_extruder() const { return m_first_printing_extruder; }

// Get the first extruder printing the layer_tools, returns -1 if there is no layer printed.
unsigned int last_extruder() const;
unsigned int last_extruder() const { return m_last_printing_extruder; }

// For a multi-material print, the printing extruders are ordered in the order they shall be primed.
std::vector<unsigned int> all_extruders() const { return m_all_printing_extruders; }

// Find LayerTools with the closest print_z.
LayerTools& tools_for_layer(coordf_t print_z);
Expand All @@ -74,8 +77,15 @@ class ToolOrdering
void collect_extruders(const PrintObject &object);
void reorder_extruders(unsigned int last_extruder_id);
void fill_wipe_tower_partitions(const PrintConfig &config, coordf_t object_bottom_z);

std::vector<LayerTools> m_layer_tools;
void collect_extruder_statistics(bool prime_multi_material);

std::vector<LayerTools> m_layer_tools;
// First printing extruder, including the multi-material priming sequence.
unsigned int m_first_printing_extruder;
// Final printing extruder.
unsigned int m_last_printing_extruder;
// All extruders, which extrude some material over m_layer_tools.
std::vector<unsigned int> m_all_printing_extruders;
};

} // namespace SLic3r
Expand Down
18 changes: 17 additions & 1 deletion xs/src/libslic3r/GCode/WipeTower.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,27 @@ class WipeTower
// Time elapsed over this tool change.
// This is useful not only for the print time estimation, but also for the control of layer cooling.
float elapsed_time;

// Sum the total length of the extrusion.
float total_extrusion_length_in_plane() {
float e_length = 0.f;
for (size_t i = 1; i < this->extrusions.size(); ++ i) {
const Extrusion &e = this->extrusions[i];
if (e.width > 0) {
xy v = e.pos - (&e - 1)->pos;
e_length += sqrt(v.x*v.x+v.y*v.y);
}
}
return e_length;
}
};

// Returns gcode to prime the nozzles at the front edge of the print bed.
virtual ToolChangeResult prime(float first_layer_height, std::vector<unsigned int> tools, Purpose purpose = PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) = 0;

// Returns gcode for toolchange and the end position.
// if new_tool == -1, just unload the current filament over the wipe tower.
virtual ToolChangeResult tool_change(int new_tool, bool last_in_layer, Purpose purpose = PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) = 0;
virtual ToolChangeResult tool_change(unsigned int new_tool, bool last_in_layer, Purpose purpose = PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) = 0;

// Close the current wipe tower layer with a perimeter and possibly fill the unfilled space with a zig-zag.
// Call this method only if layer_finished() is false.
Expand Down
Loading

0 comments on commit b610866

Please sign in to comment.