From 6cf0e2451ea81b182460319e9bc627ec74a9e280 Mon Sep 17 00:00:00 2001 From: "xun.zhang" Date: Tue, 3 Dec 2024 20:55:43 +0800 Subject: [PATCH] FIX: support pre heating without wipetower jira:NONE Signed-off-by: xun.zhang Change-Id: Ibcd3aacb9eede8bc054669f8fff98ea25f8e5d09 --- src/libslic3r/GCode/GCodeProcessor.cpp | 412 ++++++++++++++++--------- src/libslic3r/GCode/GCodeProcessor.hpp | 100 +++++- 2 files changed, 366 insertions(+), 146 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 66b6b64a5..535c734fa 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -818,16 +818,6 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st return true; }; - enum InsertLineType - { - PlaceholderReplace, - TimePredict, - FilamentChangePredict, - ExtruderChangePredict, - PreCooling, - PreHeating, - }; - constexpr int buffer_size_in_KB = 64; std::vector filament_blocks; std::vector extruder_blocks = { ExtruderUsageBlcok() }; // the first use of extruder will not generate nozzle change tag, so manually add a dummy block @@ -918,8 +908,7 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st } // stores then strings to be inserted. first key is line id ,second key is content - std::map>> inserted_operation_lines; - + InsertedLinesMap inserted_operation_lines; // save filament change block by extruder id std::unordered_map> extruder_change_info; @@ -945,6 +934,10 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st } } + if (!filament_blocks.empty()) { + filament_blocks.back().upper_gcode_id = machine_end_gcode_start_line_id; + } + // After traversing the G-code, the first and last extruder blocks still have uncompleted initialization steps if (!extruder_blocks.empty() && !filament_blocks.empty()) { extruder_blocks.front().initialize_step_1(context.filament_maps[filament_blocks.front().filament_id], machine_start_gcode_end_line_id, filament_blocks.front().filament_id); @@ -965,132 +958,23 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st } } - auto pre_cooling_heating_handle = [&inserted_operation_lines, &format_line_M104, &context = std::as_const(context), &moves = std::as_const(moves), valid_machine_id]( - const unsigned int extruder_free_range_lower, const unsigned int extruder_free_range_upper, - const unsigned int post_extrusion_lower, const unsigned int post_extrusion_upper, - const bool pre_cool, const bool pre_heat, - int curr_temp, int target_temp, - const int extruder_id, bool is_small_flow_filament) - { - auto gcode_move_comp = [](const GCodeProcessorResult::MoveVertex& a, unsigned int gcode_id) { return a.gcode_id < gcode_id; }; - if (!pre_cool && !pre_heat || extruder_free_range_upper <= extruder_free_range_lower) - return; + auto pre_cooling_injector = std::make_unique( + moves, + context.filament_types, + context.filament_maps, + context.filament_nozzle_temp, + context.physical_extruder_map, + valid_machine_id, + context.inject_time_threshold, + context.post_extrusion_cooling_threshold, + context.cooling_rate, + context.heating_rate, + machine_start_gcode_end_line_id, + machine_end_gcode_start_line_id + ); - auto move_iter_lower = std::lower_bound(moves.begin(), moves.end(), extruder_free_range_lower, gcode_move_comp); - auto move_iter_upper = std::lower_bound(moves.begin(), moves.end(), extruder_free_range_upper, gcode_move_comp); // closed iter - if (move_iter_lower == moves.end() || move_iter_upper == moves.end() || move_iter_upper == moves.begin()) - return; - --move_iter_upper; - if (move_iter_lower >= move_iter_upper) - return; - float time_gap = move_iter_upper->time[valid_machine_id] - move_iter_lower->time[valid_machine_id]; - // the free time of extruder is too short, do not perform pre cooling and heating - if (time_gap < context.pre_heating_time_threshold) - return; - - if (is_small_flow_filament && pre_cool) { - auto post_extrusion_move_lower = std::lower_bound(moves.begin(), moves.end(), post_extrusion_lower, gcode_move_comp); - auto post_extrusion_move_upper = std::lower_bound(moves.begin(), moves.end(), post_extrusion_upper, gcode_move_comp); // closed iter - if (post_extrusion_move_lower != moves.end() && post_extrusion_move_upper != moves.end() && post_extrusion_move_upper != moves.begin()){ - --post_extrusion_move_upper; - if (post_extrusion_move_lower < post_extrusion_move_upper) { - float time_gap = post_extrusion_move_upper->time[valid_machine_id] - post_extrusion_move_lower->time[valid_machine_id]; - float max_cooling_temp = std::min((float)(curr_temp), std::min(context.post_extrusion_cooling_threshold, time_gap * context.cooling_rate)); - curr_temp -= max_cooling_temp; // set the temperature after doing cooling when post-extruding - inserted_operation_lines[post_extrusion_move_lower->gcode_id].emplace_back(format_line_M104(curr_temp, extruder_id, "Multi extruder pre cooling"), InsertLineType::PreCooling); - } - } - } - - if (pre_cool && !pre_heat) { - // only perform cooling - if (target_temp > curr_temp) - return; - inserted_operation_lines[extruder_free_range_lower].emplace_back(format_line_M104(target_temp, extruder_id, "Multi extruder pre cooling"), InsertLineType::PreCooling); - return; - } - if (!pre_cool && pre_heat) { - // only perform heating - if (target_temp < curr_temp) - return; - float heating_start_time = move_iter_upper->time[valid_machine_id] - (target_temp - curr_temp) / context.heating_rate; - auto heating_move_iter = std::upper_bound(move_iter_lower, move_iter_upper + 1, heating_start_time, [valid_machine_id](float time, const GCodeProcessorResult::MoveVertex& a) {return time < a.time[valid_machine_id]; }); - if (heating_move_iter == move_iter_upper + 1 || heating_move_iter == move_iter_lower) { - inserted_operation_lines[extruder_free_range_lower].emplace_back(format_line_M104(target_temp, extruder_id, "Multi extruder pre heating"), InsertLineType::PreHeating); - } - else { - --heating_move_iter; - inserted_operation_lines[heating_move_iter->gcode_id].emplace_back(format_line_M104(target_temp, extruder_id, "Multi extruder pre heating"), InsertLineType::PreHeating); - } - return; - } - // perform cooling first and then perform heating - float mid_temp = std::max(0.f, (curr_temp * context.heating_rate + target_temp * context.cooling_rate - time_gap * context.cooling_rate * context.heating_rate) / (context.cooling_rate + context.heating_rate)); - float heating_temp = target_temp - mid_temp; - float heating_start_time = move_iter_upper->time[valid_machine_id] - heating_temp / context.heating_rate; - auto heating_move_iter = std::upper_bound(move_iter_lower, move_iter_upper + 1, heating_start_time, [valid_machine_id](float time, const GCodeProcessorResult::MoveVertex& a) {return time < a.time[valid_machine_id]; }); - if (heating_move_iter == move_iter_lower || heating_move_iter == move_iter_upper + 1) - return; - - --heating_move_iter; - // get the insert pos of heat cmd and recalculate time gap and delta temp - float real_cooling_time = heating_move_iter->time[valid_machine_id] - move_iter_lower->time[valid_machine_id]; - if (real_cooling_time < context.pre_heating_time_threshold / 2) - return; - - int real_delta_temp = std::min((int)(real_cooling_time * context.cooling_rate), curr_temp); - inserted_operation_lines[extruder_free_range_lower].emplace_back(format_line_M104(curr_temp - real_delta_temp, extruder_id, "Multi extruder pre cooling"), InsertLineType::PreCooling); - inserted_operation_lines[heating_move_iter->gcode_id].emplace_back(format_line_M104(target_temp, extruder_id, "Multi extruder pre heating"), InsertLineType::PreHeating); - }; - - // collect the insert position of gcode line for pre heating and cooling - for (auto& extruder_changes : extruder_change_info) { - auto check_filament_type = [&filament_types = std::as_const(context.filament_types)](const int filament_id, const std::string& type)->bool { - return filament_types[filament_id] == type; - }; - int extruder_id = extruder_changes.first; - const auto& extruder_blocks = extruder_changes.second; - if (extruder_blocks.empty()) - continue; - auto iter_lower = extruder_blocks.begin(); - auto iter_upper = extruder_blocks.end(); - - // only consider T command(filament change) in [machine_start_gcode_end,machine_end_gcode_start) - while (iter_lower != extruder_blocks.end() && iter_lower->start_id < machine_start_gcode_end_line_id) - ++iter_lower; - while (iter_upper != extruder_blocks.begin() && std::prev(iter_upper)->start_id >= machine_end_gcode_start_line_id) - --iter_upper; - - if (iter_lower >= iter_upper) - continue; - - pre_cooling_heating_handle( - machine_start_gcode_end_line_id, std::min(iter_lower->start_id, machine_end_gcode_start_line_id), - machine_start_gcode_end_line_id, machine_start_gcode_end_line_id, - true, true, - context.filament_nozzle_temp[iter_lower->start_filament], context.filament_nozzle_temp[iter_lower->start_filament], - extruder_id, check_filament_type(iter_lower->start_filament, "TPU")); - - for (auto iter = iter_lower; iter != iter_upper; ++iter) { - auto niter = std::next(iter); - if (niter != iter_upper) { - pre_cooling_heating_handle( - std::max(machine_start_gcode_end_line_id, iter->end_id), std::min(machine_end_gcode_start_line_id, niter->start_id), - iter->post_extrusion_start_id, iter->post_extrusion_end_id, - true, true, - context.filament_nozzle_temp[iter->end_filament], context.filament_nozzle_temp[niter->start_filament], - extruder_id, check_filament_type(iter->end_filament,"TPU")); - } - else { - pre_cooling_heating_handle( - std::max(machine_start_gcode_end_line_id, iter->end_id), machine_end_gcode_start_line_id, - iter->post_extrusion_start_id, iter->post_extrusion_end_id, - true, false, - context.filament_nozzle_temp[iter->end_filament], 0, - extruder_id, check_filament_type(iter->end_filament,"TPU")); - } - } - } + pre_cooling_injector->build_extruder_free_blocks(filament_blocks, extruder_blocks); + pre_cooling_injector->process_pre_cooling_and_heating(inserted_operation_lines); } auto pre_operation_iter = inserted_operation_lines.begin(); @@ -1100,7 +984,7 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st if (line_id == pre_operation_iter->first) { for (auto& elem : pre_operation_iter->second) { const std::string& str = elem.first; - const InsertLineType& type = elem.second; + const InsertLineType type = elem.second; switch (type) { case InsertLineType::PlaceholderReplace: @@ -2216,7 +2100,7 @@ void GCodeProcessor::finalize(bool post_process) m_width_compare.output(); #endif // ENABLE_GCODE_VIEWER_DATA_CHECKING if (post_process){ - constexpr float pre_heating_time_threshold = 30.f; + constexpr float inject_time_threshold = 30.f; TimeProcessContext context( m_used_filaments, m_filament_lists, @@ -2227,7 +2111,7 @@ void GCodeProcessor::finalize(bool post_process) m_layer_id, m_hotend_cooling_rate, m_hotend_heating_rate, - pre_heating_time_threshold, + inject_time_threshold, m_enable_pre_heating ); m_time_processor.post_process(m_result.filename, m_result.moves, m_result.lines_ends, context); @@ -5709,5 +5593,253 @@ int GCodeProcessor::get_extruder_id(bool force_initialize)const return static_cast(m_extruder_id); } +void GCodeProcessor::PreCoolingInjector::process_pre_cooling_and_heating(TimeProcessor::InsertedLinesMap& inserted_operation_lines) +{ + std::map> per_extruder_free_blocks; + + for (auto& block : m_extruder_free_blocks) + per_extruder_free_blocks[block.extruder_id].emplace_back(block); + + for (auto& elem : per_extruder_free_blocks) { + int extruder_id = elem.first; + auto& extruder_free_blcoks = elem.second; + for (auto iter = extruder_free_blcoks.begin(); iter != extruder_free_blcoks.end(); ++iter) { + bool is_end = std::next(iter) == extruder_free_blcoks.end(); + bool apply_pre_cooling = true; + bool apply_pre_heating = !is_end; + float curr_temp = (float)(filament_nozzle_temps[iter->last_filament_id]); + float target_temp = (float)(is_end ? 0 : filament_nozzle_temps[iter->next_filament_id]); + inject_cooling_heating_command(inserted_operation_lines, *iter, curr_temp, target_temp, apply_pre_cooling, apply_pre_heating); + } + } +} + +void GCodeProcessor::PreCoolingInjector::build_extruder_free_blocks(const std::vector& filament_usage_blocks, const std::vector& extruder_usage_blocks) +{ + if (extruder_usage_blocks.size() <= 1) + build_by_filament_blocks(filament_usage_blocks); + else + build_by_extruder_blocks(extruder_usage_blocks); +} + +void GCodeProcessor::PreCoolingInjector::inject_cooling_heating_command(TimeProcessor::InsertedLinesMap& inserted_operation_lines, const ExtruderFreeBlock& block, float curr_temp, float target_temp, bool pre_cooling, bool pre_heating) +{ + auto format_line_M104 = [&physical_extruder_map = this->physical_extruder_map](int target_temp, int target_extruder = -1, const std::string& comment = std::string()) { + std::string buffer = "M104"; + if (target_extruder != -1) + buffer += (" T" + std::to_string(physical_extruder_map[target_extruder])); + buffer += " S" + std::to_string(target_temp) + " N0"; // N0 means the gcode is generated by slicer + if (!comment.empty()) + buffer += " ;" + comment; + buffer += '\n'; + return buffer; + }; + + auto is_tpu_filament = [&filament_types = this->filament_types](int idx) { + return filament_types[idx] == "TPU"; + }; + + auto gcode_move_comp = [](const GCodeProcessorResult::MoveVertex& a, unsigned int gcode_id) { + return a.gcode_id < gcode_id; + }; + + if (!pre_cooling && !pre_heating && block.free_upper_gcode_id <= block.free_lower_gcode_id) + return; + + auto move_iter_lower = std::lower_bound(moves.begin(), moves.end(), block.free_lower_gcode_id, gcode_move_comp); + auto move_iter_upper = std::lower_bound(moves.begin(), moves.end(), block.free_upper_gcode_id, gcode_move_comp); // closed iter + if (move_iter_lower == moves.end() || move_iter_upper == moves.end() || move_iter_upper == moves.begin()) + return; + --move_iter_upper; + + auto partial_free_move_lower = std::lower_bound(moves.begin(), moves.end(), block.partial_free_lower_id, gcode_move_comp); + auto partial_free_move_upper = std::lower_bound(moves.begin(), moves.end(), block.partial_free_upper_id, gcode_move_comp); // closed iter + + if (partial_free_move_lower == moves.end() || partial_free_move_upper == moves.end() || partial_free_move_upper == moves.begin()) + return; + --partial_free_move_upper; + + if (move_iter_lower >= move_iter_upper) + return; + + bool apply_cooling_when_partial_free = is_tpu_filament(block.last_filament_id) && pre_cooling; + + float partial_free_time_gap = partial_free_move_upper->time[valid_machine_id] - partial_free_move_lower->time[valid_machine_id]; // time of partial free + float complete_free_time_gap = move_iter_upper->time[valid_machine_id] - move_iter_lower->time[valid_machine_id]; // time of complete free + + if (apply_cooling_when_partial_free && partial_free_time_gap + complete_free_time_gap < inject_time_threshold) + return; + + if (!apply_cooling_when_partial_free && complete_free_time_gap < inject_time_threshold) + return; + + if (is_tpu_filament(block.last_filament_id) && pre_cooling) { + if (partial_free_move_lower < partial_free_move_upper) { + float max_cooling_temp = std::min(curr_temp, std::min(partial_free_cooling_thres, partial_free_time_gap * cooling_rate)); + curr_temp -= max_cooling_temp; // set the temperature after doing cooling when post-extruding + inserted_operation_lines[partial_free_move_lower->gcode_id].emplace_back(format_line_M104(curr_temp, block.extruder_id, "Multi extruder pre cooling"), TimeProcessor::InsertLineType::PreCooling); + } + } + + if (pre_cooling && !pre_heating) { + // only perform cooling + if (target_temp > curr_temp) + return; + inserted_operation_lines[block.free_lower_gcode_id].emplace_back(format_line_M104(target_temp, block.extruder_id, "Multi extruder pre cooling"), TimeProcessor::InsertLineType::PreCooling); + return; + } + if (!pre_cooling && pre_heating) { + // only perform heating + if (target_temp < curr_temp) + return; + float heating_start_time = move_iter_upper->time[valid_machine_id] - (target_temp - curr_temp) / heating_rate; + auto heating_move_iter = std::upper_bound(move_iter_lower, move_iter_upper + 1, heating_start_time, [valid_machine_id = this->valid_machine_id](float time, const GCodeProcessorResult::MoveVertex& a) {return time < a.time[valid_machine_id]; }); + if (heating_move_iter == move_iter_upper + 1 || heating_move_iter == move_iter_lower) { + inserted_operation_lines[block.free_lower_gcode_id].emplace_back(format_line_M104(target_temp, block.extruder_id, "Multi extruder pre heating"), TimeProcessor::InsertLineType::PreHeating); + } + else { + --heating_move_iter; + inserted_operation_lines[heating_move_iter->gcode_id].emplace_back(format_line_M104(target_temp, block.extruder_id, "Multi extruder pre heating"), TimeProcessor::InsertLineType::PreHeating); + } + return; + } + // perform cooling first and then perform heating + float mid_temp = std::max(0.f, (curr_temp * heating_rate + target_temp * cooling_rate - complete_free_time_gap * cooling_rate * heating_rate) / (cooling_rate + heating_rate)); + float heating_temp = target_temp - mid_temp; + float heating_start_time = move_iter_upper->time[valid_machine_id] - heating_temp / heating_rate; + auto heating_move_iter = std::upper_bound(move_iter_lower, move_iter_upper + 1, heating_start_time, [valid_machine_id = this->valid_machine_id](float time, const GCodeProcessorResult::MoveVertex& a) {return time < a.time[valid_machine_id]; }); + if (heating_move_iter == move_iter_lower || heating_move_iter == move_iter_upper + 1) + return; + + --heating_move_iter; + // get the insert pos of heat cmd and recalculate time gap and delta temp + float real_cooling_time = heating_move_iter->time[valid_machine_id] - move_iter_lower->time[valid_machine_id]; + int real_delta_temp = std::min((int)(real_cooling_time * cooling_rate), (int)curr_temp); + inserted_operation_lines[block.free_lower_gcode_id].emplace_back(format_line_M104(curr_temp - real_delta_temp, block.extruder_id, "Multi extruder pre cooling"), TimeProcessor::InsertLineType::PreCooling); + inserted_operation_lines[heating_move_iter->gcode_id].emplace_back(format_line_M104(target_temp, block.extruder_id, "Multi extruder pre heating"), TimeProcessor::InsertLineType::PreHeating); +} + +void GCodeProcessor::PreCoolingInjector::build_by_filament_blocks(const std::vector& filament_usage_blocks_) +{ + m_extruder_free_blocks.clear(); + std::map> per_extruder_usage_blocks; + for (auto& block : filament_usage_blocks_) + per_extruder_usage_blocks[filament_maps[block.filament_id]].emplace_back(block); + + for (auto& extruder_usages : per_extruder_usage_blocks) { + int extruder_id = extruder_usages.first; + const auto& filament_blocks = extruder_usages.second; + + auto iter_lower = filament_blocks.begin(); + auto iter_upper = filament_blocks.end(); + + while (iter_lower != filament_blocks.end() && iter_lower->lower_gcode_id < machine_start_gcode_end_id) + ++iter_lower; + while (iter_upper != filament_blocks.begin() && std::prev(iter_upper)->upper_gcode_id > machine_end_gcode_start_id) + --iter_upper; + + if (iter_lower >= iter_upper) + continue; + + { + ExtruderFreeBlock block; + block.free_lower_gcode_id = machine_start_gcode_end_id; + block.free_upper_gcode_id = std::min(machine_end_gcode_start_id, iter_lower->lower_gcode_id); + block.last_filament_id = iter_lower->filament_id; + block.next_filament_id = iter_lower->filament_id; + block.extruder_id = extruder_id; + block.partial_free_lower_id = block.free_lower_gcode_id; + block.partial_free_upper_id = block.free_lower_gcode_id; + m_extruder_free_blocks.emplace_back(block); + } + + for (auto iter = iter_lower; iter < iter_upper; ++iter) { + auto niter = std::next(iter); + ExtruderFreeBlock block; + block.free_lower_gcode_id = std::max(iter->upper_gcode_id, machine_start_gcode_end_id); + block.last_filament_id = iter->filament_id; + if (niter != iter_upper) { + block.free_upper_gcode_id = std::min(niter->lower_gcode_id, machine_end_gcode_start_id); + block.next_filament_id = niter->filament_id; + } + else { + block.free_upper_gcode_id = machine_end_gcode_start_id; + block.next_filament_id = iter->filament_id; + } + block.extruder_id = extruder_id; + block.partial_free_lower_id = block.free_lower_gcode_id; + block.partial_free_upper_id = block.free_lower_gcode_id; + m_extruder_free_blocks.emplace_back(block); + } + } + + sort(m_extruder_free_blocks.begin(), m_extruder_free_blocks.end(), [](const auto& a, const auto& b) { + return a.free_lower_gcode_id < b.free_lower_gcode_id || (a.free_lower_gcode_id == b.free_lower_gcode_id && a.free_upper_gcode_id < b.free_upper_gcode_id); + }); +} + +void GCodeProcessor::PreCoolingInjector::build_by_extruder_blocks(const std::vector& extruder_usage_blocks_) +{ + m_extruder_free_blocks.clear(); + std::map> per_extruder_usage_blocks; + + for (auto& block : extruder_usage_blocks_) + per_extruder_usage_blocks[block.extruder_id].emplace_back(block); + + for (auto& extruder_usages : per_extruder_usage_blocks) { + int extruder_id = extruder_usages.first; + const auto& extruder_usage_blocks = extruder_usages.second; + if (extruder_usage_blocks.empty()) + continue; + + auto iter_lower = extruder_usage_blocks.begin(); + auto iter_upper = extruder_usage_blocks.end(); + while (iter_lower != extruder_usage_blocks.end() && iter_lower->start_id < machine_start_gcode_end_id) + ++iter_lower; + while (iter_upper != extruder_usage_blocks.begin() && std::prev(iter_upper)->end_id > machine_end_gcode_start_id) + --iter_upper; + + if (iter_lower >= iter_upper) + continue; + + { + ExtruderFreeBlock block; + block.free_lower_gcode_id = machine_start_gcode_end_id; + block.free_upper_gcode_id = std::min(iter_lower->start_id, machine_end_gcode_start_id); + block.extruder_id = extruder_id; + block.last_filament_id = iter_lower->start_filament; + block.next_filament_id = iter_lower->start_filament; + block.partial_free_lower_id = machine_start_gcode_end_id; + block.partial_free_upper_id = machine_start_gcode_end_id; // invalid + + m_extruder_free_blocks.emplace_back(block); + } + + for (auto iter = iter_lower; iter != iter_upper; ++iter) { + auto niter = std::next(iter); + ExtruderFreeBlock block; + block.free_lower_gcode_id = std::max(iter->end_id, machine_start_gcode_end_id); + block.last_filament_id = iter->end_filament; + if (niter != iter_upper) { + block.free_upper_gcode_id = std::min(niter->start_id, machine_end_gcode_start_id); + block.next_filament_id = niter->start_filament; + + } + else { + block.free_upper_gcode_id = machine_end_gcode_start_id; + block.next_filament_id = iter->end_filament; + } + block.extruder_id = extruder_id; + block.partial_free_lower_id = iter->post_extrusion_start_id; + block.partial_free_upper_id = iter->post_extrusion_end_id; + m_extruder_free_blocks.emplace_back(block); + } + } + + sort(m_extruder_free_blocks.begin(), m_extruder_free_blocks.end(), [](const auto& a, const auto& b) { + return a.free_lower_gcode_id < b.free_lower_gcode_id || (a.free_lower_gcode_id == b.free_lower_gcode_id && a.free_upper_gcode_id < b.free_upper_gcode_id); + }); +} + } /* namespace Slic3r */ diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index 3529f1586..4549645d3 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -613,13 +613,13 @@ namespace Slic3r { std::vector filament_lists; std::vector filament_types; std::vector filament_maps; // map each filament to extruder - std::vector filament_nozzle_temp; + std::vector filament_nozzle_temp; std::vector physical_extruder_map; size_t total_layer_num; float cooling_rate{ 2.f }; // Celsius degree per second float heating_rate{ 2.f }; // Celsius degree per second - float pre_heating_time_threshold{ 30.f }; // only active pre cooling & heating if time gap is bigger than threshold + float inject_time_threshold{ 30.f }; // only active pre cooling & heating if time gap is bigger than threshold float post_extrusion_cooling_threshold{ 30.f }; // threshold of temp if do cooling in post extrusion bool enable_pre_heating{ false }; @@ -628,12 +628,12 @@ namespace Slic3r { const std::vector& filament_lists_, const std::vector& filament_maps_, const std::vector& filament_types_, - const std::vector& filament_nozzle_temp_, + const std::vector& filament_nozzle_temp_, const std::vector& physical_extruder_map_, const size_t total_layer_num_, const float cooling_rate_, const float heating_rate_, - const float pre_heating_time_threshold_, + const float inject_time_threshold_, const bool enable_pre_heating_ ) : used_filaments(used_filaments_), @@ -646,7 +646,7 @@ namespace Slic3r { cooling_rate(cooling_rate_), heating_rate(heating_rate_), enable_pre_heating(enable_pre_heating_), - pre_heating_time_threshold(pre_heating_time_threshold_) + inject_time_threshold(inject_time_threshold_) { } @@ -654,6 +654,19 @@ namespace Slic3r { struct TimeProcessor { + enum InsertLineType + { + PlaceholderReplace, + TimePredict, + FilamentChangePredict, + ExtruderChangePredict, + PreCooling, + PreHeating, + }; + + // first key is line id ,second key is content + using InsertedLinesMap = std::map>>; + struct Planner { // Size of the firmware planner queue. The old 8-bit Marlins usually just managed 16 trapezoidal blocks. @@ -684,6 +697,81 @@ namespace Slic3r { // and updates moves' gcode ids accordingly void post_process(const std::string& filename, std::vector& moves, std::vector& lines_ends, const TimeProcessContext& context); }; + + class PreCoolingInjector { + public: + struct ExtruderFreeBlock { + unsigned int free_lower_gcode_id; + unsigned int free_upper_gcode_id; + unsigned int partial_free_lower_id; // stores the range of extrusion in wipe tower. Without wipetower, partial free lower_id and upper id will be same as free lower id + unsigned int partial_free_upper_id; + int last_filament_id; + int next_filament_id; + int extruder_id; + }; + + void process_pre_cooling_and_heating(TimeProcessor::InsertedLinesMap& inserted_operation_lines); + void build_extruder_free_blocks(const std::vector& filament_usage_blocks, const std::vector& extruder_usage_blocks); + + PreCoolingInjector( + const std::vector& moves_, + const std::vector& filament_types_, + const std::vector& filament_maps_, + const std::vector& filament_nozzle_temps_, + const std::vector& physical_extruder_map_, + int valid_machine_id_, + float inject_time_threshold_, + float partial_free_cooling_thres_, + float cooling_rate_, + float heating_rate_, + unsigned int machine_start_gcode_end_id_, + unsigned int machine_end_gcode_start_id_ + ) : + moves(moves_), + filament_types(filament_types_), + filament_maps(filament_maps_), + filament_nozzle_temps(filament_nozzle_temps_), + physical_extruder_map(physical_extruder_map_), + valid_machine_id(valid_machine_id_), + inject_time_threshold(inject_time_threshold_), + partial_free_cooling_thres(partial_free_cooling_thres_), + cooling_rate(cooling_rate_), + heating_rate(heating_rate_), + machine_start_gcode_end_id(machine_start_gcode_end_id_), + machine_end_gcode_start_id(machine_end_gcode_start_id_) + { + } + + private: + std::vector m_extruder_free_blocks; + const std::vector& moves; + const std::vector& filament_types; + const std::vector& filament_maps; + const std::vector& filament_nozzle_temps; + const std::vector& physical_extruder_map; + const int valid_machine_id; + const float inject_time_threshold; + const float partial_free_cooling_thres; // threshold of cooling temp during post extrusion + const float cooling_rate; + const float heating_rate; + + const unsigned int machine_start_gcode_end_id; + const unsigned int machine_end_gcode_start_id; + + void inject_cooling_heating_command( + TimeProcessor::InsertedLinesMap& inserted_operation_lines, + const ExtruderFreeBlock& free_block, + float curr_temp, + float target_temp, + bool pre_cooling, + bool pre_heating + ); + + void build_by_filament_blocks(const std::vector& filament_usage_blocks); + void build_by_extruder_blocks(const std::vector& extruder_usage_blocks); + }; + + public: class SeamsDetector { @@ -831,7 +919,7 @@ namespace Slic3r { float m_print_z{0.0f}; std::vector m_remaining_volume; std::vector m_filament_lists; - std::vector m_filament_nozzle_temp; + std::vector m_filament_nozzle_temp; std::vector m_filament_types; float m_hotend_cooling_rate{ 2.f }; float m_hotend_heating_rate{ 2.f };