diff options
Diffstat (limited to 'src/libslic3r/GCode/WipeTowerPrusaMM.hpp')
-rw-r--r-- | src/libslic3r/GCode/WipeTowerPrusaMM.hpp | 374 |
1 files changed, 374 insertions, 0 deletions
diff --git a/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/src/libslic3r/GCode/WipeTowerPrusaMM.hpp new file mode 100644 index 000000000..06625d189 --- /dev/null +++ b/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -0,0 +1,374 @@ +#ifndef WipeTowerPrusaMM_hpp_ +#define WipeTowerPrusaMM_hpp_ + +#include <cmath> +#include <string> +#include <sstream> +#include <utility> +#include <algorithm> + +#include "WipeTower.hpp" + + +namespace Slic3r +{ + +namespace PrusaMultiMaterial { + class Writer; +}; + + + +class WipeTowerPrusaMM : public WipeTower +{ +public: + enum material_type + { + INVALID = -1, + PLA = 0, // E:210C B:55C + ABS = 1, // E:255C B:100C + PET = 2, // E:240C B:90C + HIPS = 3, // E:220C B:100C + FLEX = 4, // E:245C B:80C + SCAFF = 5, // E:215C B:55C + EDGE = 6, // E:240C B:80C + NGEN = 7, // E:230C B:80C + PVA = 8 // E:210C B:80C + }; + + // Parse material name into material_type. + static material_type parse_material(const char *name); + + // x -- x coordinates of wipe tower in mm ( left bottom corner ) + // 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 rotation_angle, float cooling_tube_retraction, + float cooling_tube_length, float parking_pos_retraction, float extra_loading_move, float bridging, + const std::vector<std::vector<float>>& wiping_matrix, unsigned int initial_tool) : + 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_cooling_tube_retraction(cooling_tube_retraction), + m_cooling_tube_length(cooling_tube_length), + m_parking_pos_retraction(parking_pos_retraction), + m_extra_loading_move(extra_loading_move), + m_bridging(bridging), + m_current_tool(initial_tool), + wipe_volumes(wiping_matrix) + {} + + virtual ~WipeTowerPrusaMM() {} + + + // Set the extruder properties. + void set_extruder(size_t idx, material_type material, int temp, int first_layer_temp, float loading_speed, float loading_speed_start, + float unloading_speed, float unloading_speed_start, float delay, int cooling_moves, + float cooling_initial_speed, float cooling_final_speed, std::string ramming_parameters, float nozzle_diameter) + { + //while (m_filpar.size() < idx+1) // makes sure the required element is in the vector + m_filpar.push_back(FilamentParameters()); + + m_filpar[idx].material = material; + m_filpar[idx].temperature = temp; + m_filpar[idx].first_layer_temperature = first_layer_temp; + m_filpar[idx].loading_speed = loading_speed; + m_filpar[idx].loading_speed_start = loading_speed_start; + m_filpar[idx].unloading_speed = unloading_speed; + m_filpar[idx].unloading_speed_start = unloading_speed_start; + m_filpar[idx].delay = delay; + m_filpar[idx].cooling_moves = cooling_moves; + m_filpar[idx].cooling_initial_speed = cooling_initial_speed; + m_filpar[idx].cooling_final_speed = cooling_final_speed; + m_filpar[idx].nozzle_diameter = nozzle_diameter; // to be used in future with (non-single) multiextruder MM + + m_perimeter_width = nozzle_diameter * Width_To_Nozzle_Ratio; // all extruders are now assumed to have the same diameter + + std::stringstream stream{ramming_parameters}; + float speed = 0.f; + stream >> m_filpar[idx].ramming_line_width_multiplicator >> m_filpar[idx].ramming_step_multiplicator; + m_filpar[idx].ramming_line_width_multiplicator /= 100; + m_filpar[idx].ramming_step_multiplicator /= 100; + while (stream >> speed) + m_filpar[idx].ramming_speed.push_back(speed); + + m_used_filament_length.resize(std::max(m_used_filament_length.size(), idx + 1)); // makes sure that the vector is big enough so we don't have to check later + } + + + // Appends into internal structure m_plan containing info about the future wipe tower + // to be used before building begins. The entries must be added ordered in z. + void plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool, unsigned int new_tool, bool brim, float wipe_volume = 0.f); + + // Iterates through prepared m_plan, generates ToolChangeResults and appends them to "result" + void generate(std::vector<std::vector<WipeTower::ToolChangeResult>> &result); + + float get_depth() const { return m_wipe_tower_depth; } + + + + // Switch to a next layer. + virtual void set_layer( + // Print height of this layer. + float print_z, + // Layer height, used to calculate extrusion the rate. + float layer_height, + // Maximum number of tool changes on this layer or the layers below. + size_t max_tool_changes, + // Is this the first layer of the print? In that case print the brim first. + bool is_first_layer, + // Is this the last layer of the waste tower? + bool is_last_layer) + { + m_z_pos = print_z; + m_layer_height = layer_height; + m_is_first_layer = is_first_layer; + m_print_brim = is_first_layer; + m_depth_traversed = 0.f; + m_current_shape = (! is_first_layer && m_current_shape == SHAPE_NORMAL) ? SHAPE_REVERSED : SHAPE_NORMAL; + if (is_first_layer) { + this->m_num_layer_changes = 0; + this->m_num_tool_changes = 0; + } + else + ++ m_num_layer_changes; + + // Calculate extrusion flow from desired line width, nozzle diameter, filament diameter and layer_height: + m_extrusion_flow = extrusion_flow(layer_height); + + // Advance m_layer_info iterator, making sure we got it right + while (!m_plan.empty() && m_layer_info->z < print_z - WT_EPSILON && m_layer_info+1 != m_plan.end()) + ++m_layer_info; + } + + // Return the wipe tower position. + virtual const xy& position() const { return m_wipe_tower_pos; } + // Return the wipe tower width. + virtual float width() const { return m_wipe_tower_width; } + // The wipe tower is finished, there should be no more tool changes or wipe tower prints. + virtual bool finished() const { return m_max_color_changes == 0; } + + // Returns gcode to prime the nozzles at the front edge of the print bed. + virtual ToolChangeResult prime( + // print_z of the first layer. + float first_layer_height, + // Extruder indices, in the order to be primed. The last extruder will later print the wipe tower brim, print brim and the object. + const std::vector<unsigned int> &tools, + // If true, the last priming are will be the same as the other priming areas, and the rest of the wipe will be performed inside the wipe tower. + // If false, the last priming are will be large enough to wipe the last extruder sufficiently. + bool last_wipe_inside_wipe_tower); + + // Returns gcode for a toolchange and a final print head position. + // On the first layer, extrude a brim around the future wipe tower first. + virtual ToolChangeResult tool_change(unsigned int new_tool, bool last_in_layer); + + // Fill the unfilled space with a sparse infill. + // Call this method only if layer_finished() is false. + virtual ToolChangeResult finish_layer(); + + // Is the current layer finished? + virtual bool layer_finished() const { + return ( (m_is_first_layer ? m_wipe_tower_depth - m_perimeter_width : m_layer_info->depth) - WT_EPSILON < m_depth_traversed); + } + + virtual std::vector<float> get_used_filament() const override { return m_used_filament_length; } + virtual int get_number_of_toolchanges() const override { return m_num_tool_changes; } + + +private: + WipeTowerPrusaMM(); + + enum wipe_shape // A fill-in direction + { + SHAPE_NORMAL = 1, + SHAPE_REVERSED = -1 + }; + + + const bool m_peters_wipe_tower = false; // sparse wipe tower inspired by Peter's post processor - not finished yet + const float Filament_Area = M_PI * 1.75f * 1.75f / 4.f; // filament area in mm^2 + const float Width_To_Nozzle_Ratio = 1.25f; // desired line width (oval) in multiples of nozzle diameter - may not be actually neccessary to adjust + const float WT_EPSILON = 1e-3f; + + + xy m_wipe_tower_pos; // Left front corner of the wipe tower in mm. + float m_wipe_tower_width; // Width of the wipe tower. + float m_wipe_tower_depth = 0.f; // Depth of the wipe tower + float m_wipe_tower_rotation_angle = 0.f; // Wipe tower rotation angle in degrees (with respect to x axis) + float m_internal_rotation = 0.f; + float m_y_shift = 0.f; // y shift passed to writer + float m_z_pos = 0.f; // Current Z position. + float m_layer_height = 0.f; // Current layer height. + size_t m_max_color_changes = 0; // Maximum number of color changes per layer. + bool m_is_first_layer = false;// Is this the 1st layer of the print? If so, print the brim around the waste tower. + int m_old_temperature = -1; // To keep track of what was the last temp that we set (so we don't issue the command when not neccessary) + + // G-code generator parameters. + float m_cooling_tube_retraction = 0.f; + float m_cooling_tube_length = 0.f; + float m_parking_pos_retraction = 0.f; + float m_extra_loading_move = 0.f; + float m_bridging = 0.f; + bool m_adhesion = true; + + float m_perimeter_width = 0.4 * Width_To_Nozzle_Ratio; // Width of an extrusion line, also a perimeter spacing for 100% infill. + float m_extrusion_flow = 0.038; //0.029f;// Extrusion flow is derived from m_perimeter_width, layer height and filament diameter. + + + struct FilamentParameters { + material_type material = PLA; + int temperature = 0; + int first_layer_temperature = 0; + float loading_speed = 0.f; + float loading_speed_start = 0.f; + float unloading_speed = 0.f; + float unloading_speed_start = 0.f; + float delay = 0.f ; + int cooling_moves = 0; + float cooling_initial_speed = 0.f; + float cooling_final_speed = 0.f; + float ramming_line_width_multiplicator = 0.f; + float ramming_step_multiplicator = 0.f; + std::vector<float> ramming_speed; + float nozzle_diameter; + }; + + // Extruder specific parameters. + std::vector<FilamentParameters> m_filpar; + + + // State of the wipe tower generator. + unsigned int m_num_layer_changes = 0; // Layer change counter for the output statistics. + unsigned int m_num_tool_changes = 0; // Tool change change counter for the output statistics. + ///unsigned int m_idx_tool_change_in_layer = 0; // Layer change counter in this layer. Counting up to m_max_color_changes. + bool m_print_brim = true; + // 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; + const std::vector<std::vector<float>> wipe_volumes; + + float m_depth_traversed = 0.f; // Current y position at the wipe tower. + bool m_left_to_right = true; + float m_extra_spacing = 1.f; + + // Calculates extrusion flow needed to produce required line width for given layer height + float extrusion_flow(float layer_height = -1.f) const // negative layer_height - return current m_extrusion_flow + { + if ( layer_height < 0 ) + return m_extrusion_flow; + return layer_height * ( m_perimeter_width - layer_height * (1-M_PI/4.f)) / Filament_Area; + } + + // Calculates length of extrusion line to extrude given volume + float volume_to_length(float volume, float line_width, float layer_height) const { + return std::max(0., volume / (layer_height * (line_width - layer_height * (1. - M_PI / 4.)))); + } + + // Calculates depth for all layers and propagates them downwards + void plan_tower(); + + // Goes through m_plan and recalculates depths and width of the WT to make it exactly square - experimental + void make_wipe_tower_square(); + + // Goes through m_plan, calculates border and finish_layer extrusions and subtracts them from last wipe + void save_on_last_wipe(); + + + struct box_coordinates + { + box_coordinates(float left, float bottom, float width, float height) : + ld(left , bottom ), + lu(left , bottom + height), + rd(left + width, bottom ), + ru(left + width, bottom + height) {} + box_coordinates(const xy &pos, float width, float height) : box_coordinates(pos.x, pos.y, width, height) {} + void translate(const xy &shift) { + ld += shift; lu += shift; + rd += shift; ru += shift; + } + void translate(const float dx, const float dy) { translate(xy(dx, dy)); } + void expand(const float offset) { + ld += xy(- offset, - offset); + lu += xy(- offset, offset); + rd += xy( offset, - offset); + ru += xy( offset, offset); + } + void expand(const float offset_x, const float offset_y) { + ld += xy(- offset_x, - offset_y); + lu += xy(- offset_x, offset_y); + rd += xy( offset_x, - offset_y); + ru += xy( offset_x, offset_y); + } + xy ld; // left down + xy lu; // left upper + xy rd; // right lower + xy ru; // right upper + }; + + + // to store information about tool changes for a given layer + struct WipeTowerInfo{ + struct ToolChange { + unsigned int old_tool; + unsigned int new_tool; + float required_depth; + float ramming_depth; + float first_wipe_line; + float wipe_volume; + ToolChange(unsigned int old, unsigned int newtool, float depth=0.f, float ramming_depth=0.f, float fwl=0.f, float wv=0.f) + : old_tool{old}, new_tool{newtool}, required_depth{depth}, ramming_depth{ramming_depth}, first_wipe_line{fwl}, wipe_volume{wv} {} + }; + float z; // z position of the layer + float height; // layer height + float depth; // depth of the layer based on all layers above + float extra_spacing; + float toolchanges_depth() const { float sum = 0.f; for (const auto &a : tool_changes) sum += a.required_depth; return sum; } + + std::vector<ToolChange> tool_changes; + + WipeTowerInfo(float z_par, float layer_height_par) + : z{z_par}, height{layer_height_par}, depth{0}, extra_spacing{1.f} {} + }; + + std::vector<WipeTowerInfo> m_plan; // Stores information about all layers and toolchanges for the future wipe tower (filled by plan_toolchange(...)) + std::vector<WipeTowerInfo>::iterator m_layer_info = m_plan.end(); + + // Stores information about used filament length per extruder: + std::vector<float> m_used_filament_length; + + + // Returns gcode for wipe tower brim + // sideOnly -- set to false -- experimental, draw brim on sides of wipe tower + // offset -- set to 0 -- experimental, offset to replace brim in front / rear of wipe tower + ToolChangeResult toolchange_Brim(bool sideOnly = false, float y_offset = 0.f); + + void toolchange_Unload( + PrusaMultiMaterial::Writer &writer, + const box_coordinates &cleaning_box, + const material_type current_material, + const int new_temperature); + + void toolchange_Change( + PrusaMultiMaterial::Writer &writer, + const unsigned int new_tool, + material_type new_material); + + void toolchange_Load( + PrusaMultiMaterial::Writer &writer, + const box_coordinates &cleaning_box); + + void toolchange_Wipe( + PrusaMultiMaterial::Writer &writer, + const box_coordinates &cleaning_box, + float wipe_volume); +}; + + + + +}; // namespace Slic3r + +#endif /* WipeTowerPrusaMM_hpp_ */ |