OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::GCodeProcessor::PreCoolingInjector Class Reference
Collaboration diagram for Slic3r::GCodeProcessor::PreCoolingInjector:

Classes

struct  ExtruderFreeBlock

Public Member Functions

void process_pre_cooling_and_heating (TimeProcessor::InsertedLinesMap &inserted_operation_lines)
void build_extruder_free_blocks (const std::vector< ExtruderPreHeating::FilamentUsageBlock > &filament_usage_blocks, const std::vector< ExtruderPreHeating::ExtruderUsageBlcok > &extruder_usage_blocks)
 PreCoolingInjector (const std::vector< GCodeProcessorResult::MoveVertex > &moves_, const std::vector< std::string > &filament_types_, const MultiNozzleUtils::LayeredNozzleGroupResult &nozzle_group_result_, const std::vector< int > &filament_nozzle_temps_, const std::vector< int > &filament_nozzle_temps_initial_layer_, const std::vector< int > &physical_extruder_map_, int valid_machine_id_, float inject_time_threshold_, bool handle_hotend_as_extruder_, bool has_filament_switcher_, const std::vector< int > &pre_cooling_temp_, const std::vector< double > &cooling_rate_, const std::vector< double > &heating_rate_, const std::vector< std::pair< unsigned int, unsigned int > > &skippable_blocks_, const std::vector< int > &extruder_max_nozzle_count_, const std::vector< double > &filament_preheat_temperature_delta_, const std::vector< double > &filament_max_temperature_drop_when_ec_, unsigned int machine_start_gcode_end_id_, unsigned int machine_end_gcode_start_id_, const std::vector< ExtruderType > &extruder_types_, const std::vector< double > &nozzle_diameter_)

Private Member Functions

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< ExtruderPreHeating::FilamentUsageBlock > &filament_usage_blocks)
void build_by_extruder_blocks (const std::vector< ExtruderPreHeating::ExtruderUsageBlcok > &extruder_usage_blocks)

Private Attributes

std::vector< ExtruderFreeBlock > m_extruder_free_blocks
const std::vector< GCodeProcessorResult::MoveVertex > & moves
const std::vector< std::string > & filament_types
const MultiNozzleUtils::LayeredNozzleGroupResult & nozzle_group_result
const std::vector< int > & filament_nozzle_temps
const std::vector< int > & filament_nozzle_temps_initial_layer
const std::vector< int > & physical_extruder_map
const int valid_machine_id
const float inject_time_threshold
const bool handle_hotend_as_extruder
const bool has_filament_switcher
const std::vector< double > & cooling_rate
const std::vector< double > & heating_rate
const std::vector< int > & filament_pre_cooling_temps
const std::vector< std::pair< unsigned int, unsigned int > > & skippable_blocks
const std::vector< int > & extruder_max_nozzle_count
const std::vector< double > & filament_preheat_temperature_delta
const std::vector< double > & filament_max_temperature_drop_when_ec
const unsigned int machine_start_gcode_end_id
const unsigned int machine_end_gcode_start_id
const std::vector< ExtruderType > & extruder_types
const std::vector< double > & nozzle_diameter

Detailed Description


Class Documentation

◆ Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock

struct Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock
Class Members
int extruder_id
unsigned int free_lower_gcode_id
unsigned int free_upper_gcode_id
bool ignore_cooling_before_tower = false
int last_filament_id
int last_nozzle_id
int next_filament_id
int next_nozzle_id
unsigned int partial_free_lower_id
unsigned int partial_free_upper_id

Constructor & Destructor Documentation

◆ PreCoolingInjector()

Slic3r::GCodeProcessor::PreCoolingInjector::PreCoolingInjector ( const std::vector< GCodeProcessorResult::MoveVertex > & moves_,
const std::vector< std::string > & filament_types_,
const MultiNozzleUtils::LayeredNozzleGroupResult & nozzle_group_result_,
const std::vector< int > & filament_nozzle_temps_,
const std::vector< int > & filament_nozzle_temps_initial_layer_,
const std::vector< int > & physical_extruder_map_,
int valid_machine_id_,
float inject_time_threshold_,
bool handle_hotend_as_extruder_,
bool has_filament_switcher_,
const std::vector< int > & pre_cooling_temp_,
const std::vector< double > & cooling_rate_,
const std::vector< double > & heating_rate_,
const std::vector< std::pair< unsigned int, unsigned int > > & skippable_blocks_,
const std::vector< int > & extruder_max_nozzle_count_,
const std::vector< double > & filament_preheat_temperature_delta_,
const std::vector< double > & filament_max_temperature_drop_when_ec_,
unsigned int machine_start_gcode_end_id_,
unsigned int machine_end_gcode_start_id_,
const std::vector< ExtruderType > & extruder_types_,
const std::vector< double > & nozzle_diameter_ )
inline
1003 :
1004 moves(moves_),
1005 filament_types(filament_types_),
1006 nozzle_group_result(nozzle_group_result_),
1007 filament_nozzle_temps(filament_nozzle_temps_),
1008 filament_nozzle_temps_initial_layer(filament_nozzle_temps_initial_layer_),
1009 physical_extruder_map(physical_extruder_map_),
1010 valid_machine_id(valid_machine_id_),
1011 inject_time_threshold(inject_time_threshold_),
1012 handle_hotend_as_extruder(handle_hotend_as_extruder_),
1013 has_filament_switcher(has_filament_switcher_),
1014 filament_pre_cooling_temps(pre_cooling_temp_),
1015 cooling_rate(cooling_rate_),
1016 heating_rate(heating_rate_),
1017 skippable_blocks(skippable_blocks_),
1018 extruder_max_nozzle_count(extruder_max_nozzle_count_),
1019 filament_preheat_temperature_delta(filament_preheat_temperature_delta_),
1020 filament_max_temperature_drop_when_ec(filament_max_temperature_drop_when_ec_),
1021 machine_start_gcode_end_id(machine_start_gcode_end_id_),
1022 machine_end_gcode_start_id(machine_end_gcode_start_id_),
1023 extruder_types(extruder_types_),
1024 nozzle_diameter(nozzle_diameter_)
1025 {
1026 }
const std::vector< GCodeProcessorResult::MoveVertex > & moves
Definition GCodeProcessor.hpp:1030
const std::vector< int > & filament_nozzle_temps
Definition GCodeProcessor.hpp:1033
const std::vector< double > & cooling_rate
Definition GCodeProcessor.hpp:1040
const float inject_time_threshold
Definition GCodeProcessor.hpp:1037
const std::vector< double > & heating_rate
Definition GCodeProcessor.hpp:1041
const std::vector< int > & filament_nozzle_temps_initial_layer
Definition GCodeProcessor.hpp:1034
const bool handle_hotend_as_extruder
Definition GCodeProcessor.hpp:1038
const std::vector< int > & extruder_max_nozzle_count
Definition GCodeProcessor.hpp:1044
const std::vector< ExtruderType > & extruder_types
Definition GCodeProcessor.hpp:1049
const unsigned int machine_end_gcode_start_id
Definition GCodeProcessor.hpp:1048
const unsigned int machine_start_gcode_end_id
Definition GCodeProcessor.hpp:1047
const std::vector< int > & physical_extruder_map
Definition GCodeProcessor.hpp:1035
const std::vector< double > & filament_preheat_temperature_delta
Definition GCodeProcessor.hpp:1045
const std::vector< std::string > & filament_types
Definition GCodeProcessor.hpp:1031
const std::vector< double > & filament_max_temperature_drop_when_ec
Definition GCodeProcessor.hpp:1046
const MultiNozzleUtils::LayeredNozzleGroupResult & nozzle_group_result
Definition GCodeProcessor.hpp:1032
const bool has_filament_switcher
Definition GCodeProcessor.hpp:1039
const std::vector< double > & nozzle_diameter
Definition GCodeProcessor.hpp:1050
const std::vector< int > & filament_pre_cooling_temps
Definition GCodeProcessor.hpp:1042
const int valid_machine_id
Definition GCodeProcessor.hpp:1036
const std::vector< std::pair< unsigned int, unsigned int > > & skippable_blocks
Definition GCodeProcessor.hpp:1043

References cooling_rate, extruder_max_nozzle_count, extruder_types, filament_max_temperature_drop_when_ec, filament_nozzle_temps, filament_nozzle_temps_initial_layer, filament_pre_cooling_temps, filament_preheat_temperature_delta, filament_types, handle_hotend_as_extruder, has_filament_switcher, heating_rate, inject_time_threshold, machine_end_gcode_start_id, machine_start_gcode_end_id, moves, nozzle_diameter, nozzle_group_result, physical_extruder_map, skippable_blocks, and valid_machine_id.

Member Function Documentation

◆ build_by_extruder_blocks()

void Slic3r::GCodeProcessor::PreCoolingInjector::build_by_extruder_blocks ( const std::vector< ExtruderPreHeating::ExtruderUsageBlcok > & extruder_usage_blocks)
private
2478{
2479 m_extruder_free_blocks.clear();
2480 std::map<int, std::vector<ExtruderPreHeating::ExtruderUsageBlcok>> per_extruder_usage_blocks;
2481 for (auto& block : extruder_usage_blocks_)
2482 per_extruder_usage_blocks[block.extruder_id].emplace_back(block);
2483
2484 for (auto& elem : per_extruder_usage_blocks) {
2485 size_t extruder_id = elem.first;
2486 auto& blocks = elem.second;
2487 ExtruderPreHeating::ExtruderUsageBlcok start_filament_block;
2488 start_filament_block.initialize_step_1(extruder_id, 0, -1, -1);
2489 start_filament_block.initialize_step_2(machine_start_gcode_end_id);
2490 start_filament_block.initialize_step_3(machine_start_gcode_end_id, -1, machine_start_gcode_end_id, -1);
2491
2492 ExtruderPreHeating::ExtruderUsageBlcok end_filament_block;
2493 end_filament_block.initialize_step_1(extruder_id, machine_end_gcode_start_id, -1, -1);
2494 end_filament_block.initialize_step_2(std::numeric_limits<int>::max());
2495 end_filament_block.initialize_step_3(std::numeric_limits<int>::max(), -1, std::numeric_limits<int>::max(), -1);
2496
2497 blocks.insert(blocks.begin(), start_filament_block);
2498 blocks.emplace_back(end_filament_block);
2499 }
2500
2501 for (auto& elem : per_extruder_usage_blocks) {
2502 size_t extruder_id = elem.first;
2503 const auto& extruder_usage_blocks = elem.second;
2504 for (auto iter = extruder_usage_blocks.begin(); iter != extruder_usage_blocks.end(); ++iter) {
2505 auto niter = std::next(iter);
2506 if (niter == extruder_usage_blocks.end())
2507 break;
2508 ExtruderFreeBlock block;
2509 block.free_lower_gcode_id = iter->end_id;
2510 block.last_filament_id = iter->end_filament;
2511 block.last_nozzle_id = iter->end_nozzle_id;
2512 block.free_upper_gcode_id = niter->start_id;
2513 block.next_filament_id = niter->start_filament;
2514 block.next_nozzle_id = niter->start_nozzle_id;
2515 if (block.last_nozzle_id == -1)
2516 block.last_nozzle_id = block.next_nozzle_id;
2517 block.extruder_id = extruder_id;
2518 block.partial_free_lower_id = iter->post_extrusion_start_id;
2519 block.partial_free_upper_id = iter->post_extrusion_end_id;
2520 block.ignore_cooling_before_tower = niter->ignore_cooling_before_tower;
2521 m_extruder_free_blocks.emplace_back(block);
2522 }
2523 }
2524
2525 sort(m_extruder_free_blocks.begin(), m_extruder_free_blocks.end(), [](const auto& a, const auto& b) {
2526 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);
2527 });
2528}
std::vector< ExtruderFreeBlock > m_extruder_free_blocks
Definition GCodeProcessor.hpp:1029
unsigned int free_lower_gcode_id
Definition GCodeProcessor.hpp:965

References Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::extruder_id, Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::free_lower_gcode_id, Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::free_upper_gcode_id, Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::ignore_cooling_before_tower, Slic3r::ExtruderPreHeating::ExtruderUsageBlcok::initialize_step_1(), Slic3r::ExtruderPreHeating::ExtruderUsageBlcok::initialize_step_2(), Slic3r::ExtruderPreHeating::ExtruderUsageBlcok::initialize_step_3(), Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::last_filament_id, Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::last_nozzle_id, m_extruder_free_blocks, machine_end_gcode_start_id, machine_start_gcode_end_id, Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::next_filament_id, Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::next_nozzle_id, Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::partial_free_lower_id, and Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::partial_free_upper_id.

Referenced by build_extruder_free_blocks().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ build_by_filament_blocks()

void Slic3r::GCodeProcessor::PreCoolingInjector::build_by_filament_blocks ( const std::vector< ExtruderPreHeating::FilamentUsageBlock > & filament_usage_blocks)
private
2430{
2431 m_extruder_free_blocks.clear();
2432
2433 std::map<int, std::vector<ExtruderPreHeating::FilamentUsageBlock>> per_extruder_usage_blocks;
2434 for (auto& block : filament_usage_blocks_) {
2435 per_extruder_usage_blocks[block.extruder_id].emplace_back(block);
2436 }
2437 ExtruderPreHeating::FilamentUsageBlock start_filament_block(-1, -1, -1, 0, machine_start_gcode_end_id);
2438 ExtruderPreHeating::FilamentUsageBlock end_filament_block(-1, -1, -1, machine_end_gcode_start_id, std::numeric_limits<unsigned int>::max());
2439
2440 for (auto& elem : per_extruder_usage_blocks) {
2441 auto& blocks = elem.second;
2442 blocks.insert(blocks.begin(), start_filament_block);
2443 blocks.emplace_back(end_filament_block);
2444 }
2445
2446 for (auto& elem : per_extruder_usage_blocks) {
2447 size_t extruder_id = elem.first;
2448 const auto& filament_blocks = elem.second;
2449
2450 for (auto iter = filament_blocks.begin(); iter < filament_blocks.end(); ++iter) {
2451 auto niter = std::next(iter);
2452 if (niter == filament_blocks.end())
2453 break;
2454 ExtruderFreeBlock block;
2455 block.free_lower_gcode_id = iter->upper_gcode_id;
2456 block.last_filament_id = iter->filament_id;
2457 block.last_nozzle_id = iter->nozzle_id;
2458 block.free_upper_gcode_id = niter->lower_gcode_id;
2459 block.next_filament_id = niter->filament_id;
2460 block.next_nozzle_id = niter->nozzle_id;
2461 if (block.last_nozzle_id == -1)
2462 block.last_nozzle_id = block.next_nozzle_id;
2463 block.extruder_id = extruder_id;
2464 block.partial_free_lower_id = block.free_lower_gcode_id;
2465 block.partial_free_upper_id = block.free_lower_gcode_id;
2466 m_extruder_free_blocks.emplace_back(block);
2467 }
2468 }
2469 std::for_each(m_extruder_free_blocks.begin(), m_extruder_free_blocks.end(), [](ExtruderFreeBlock& block) { block.ignore_cooling_before_tower = true; });
2470 sort(m_extruder_free_blocks.begin(), m_extruder_free_blocks.end(), [](const auto& a, const auto& b) {
2471 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);
2472 });
2473}

References Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::extruder_id, Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::free_lower_gcode_id, Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::free_upper_gcode_id, Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::last_filament_id, Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::last_nozzle_id, m_extruder_free_blocks, machine_end_gcode_start_id, machine_start_gcode_end_id, Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::next_filament_id, Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::next_nozzle_id, Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::partial_free_lower_id, and Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::partial_free_upper_id.

Referenced by build_extruder_free_blocks().

Here is the caller graph for this function:

◆ build_extruder_free_blocks()

void Slic3r::GCodeProcessor::PreCoolingInjector::build_extruder_free_blocks ( const std::vector< ExtruderPreHeating::FilamentUsageBlock > & filament_usage_blocks,
const std::vector< ExtruderPreHeating::ExtruderUsageBlcok > & extruder_usage_blocks )
2199{
2200 if (extruder_usage_blocks.size() <= 1)
2201 build_by_filament_blocks(filament_usage_blocks);
2202 else
2203 build_by_extruder_blocks(extruder_usage_blocks);
2204}
void build_by_filament_blocks(const std::vector< ExtruderPreHeating::FilamentUsageBlock > &filament_usage_blocks)
Definition GCodeProcessor.cpp:2429
void build_by_extruder_blocks(const std::vector< ExtruderPreHeating::ExtruderUsageBlcok > &extruder_usage_blocks)
Definition GCodeProcessor.cpp:2477

References build_by_extruder_blocks(), and build_by_filament_blocks().

Referenced by Slic3r::GCodeProcessor::run_second_pass_injection().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ inject_cooling_heating_command()

void Slic3r::GCodeProcessor::PreCoolingInjector::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 )
private
2218{
2219 auto get_valid_extruder_id = [&](int last_nozzle_id) {
2220 auto nozzle_opt = nozzle_group_result.get_nozzle_from_id(last_nozzle_id);
2221 return nozzle_opt ? nozzle_opt->extruder_id : 0;
2222 };
2223
2224 auto is_pre_cooling_valid = [&nozzle_temps = this->filament_nozzle_temps, &pre_cooling_temps = this->filament_pre_cooling_temps](int idx) -> bool {
2225 if (idx < 0 || idx >= (int) pre_cooling_temps.size() || idx >= (int) nozzle_temps.size())
2226 return false;
2227 return pre_cooling_temps[idx] > 0 && pre_cooling_temps[idx] < nozzle_temps[idx];
2228 };
2229
2230 auto get_partial_free_cooling_thres = [&](int idx) -> float {
2231 if (idx < 0 || idx >= (int) filament_nozzle_temps.size() || idx >= (int) filament_pre_cooling_temps.size())
2232 return 30.f;
2233 float temp_in_tower = filament_nozzle_temps[idx];
2234 return temp_in_tower - (float) (filament_pre_cooling_temps[idx]);
2235 };
2236
2237 auto gcode_move_comp = [](const GCodeProcessorResult::MoveVertex& a, unsigned int gcode_id) {
2238 return a.gcode_id < gcode_id;
2239 };
2240
2241 auto find_skip_block_end = [&skippable_blocks = this->skippable_blocks](unsigned int gcode_id) -> unsigned int {
2242 auto it = std::upper_bound(
2243 skippable_blocks.begin(), skippable_blocks.end(), gcode_id,
2244 [](unsigned int id, const std::pair<unsigned int, unsigned int>& block) { return id < block.first; });
2245 if (it != skippable_blocks.begin()) {
2246 auto candidate = std::prev(it);
2247 if (gcode_id >= candidate->first && gcode_id <= candidate->second)
2248 return candidate->second;
2249 }
2250 return 0;
2251 };
2252
2253 auto find_skip_block_start = [&skippable_blocks = this->skippable_blocks](unsigned int gcode_id) -> unsigned int {
2254 auto it = std::upper_bound(
2255 skippable_blocks.begin(), skippable_blocks.end(), gcode_id,
2256 [](unsigned int id, const std::pair<unsigned int, unsigned int>& block) { return id < block.first; });
2257 if (it != skippable_blocks.begin()) {
2258 auto candidate = std::prev(it);
2259 if (gcode_id >= candidate->first && gcode_id <= candidate->second)
2260 return candidate->first;
2261 }
2262 return 0;
2263 };
2264
2265 auto adjust_iter = [&](std::vector<GCodeProcessorResult::MoveVertex>::const_iterator iter,
2266 const std::vector<GCodeProcessorResult::MoveVertex>::const_iterator& begin,
2267 const std::vector<GCodeProcessorResult::MoveVertex>::const_iterator& end,
2268 bool forward) -> std::vector<GCodeProcessorResult::MoveVertex>::const_iterator {
2269 if (forward) {
2270 while (iter != end) {
2271 unsigned current_id = iter->gcode_id;
2272 unsigned skip_block_end = find_skip_block_end(current_id);
2273 if (skip_block_end == 0)
2274 break;
2275 iter = std::lower_bound(iter, end, skip_block_end + 1, gcode_move_comp);
2276 }
2277 } else {
2278 while (iter != begin) {
2279 unsigned current_id = iter->gcode_id;
2280 unsigned skip_block_start = find_skip_block_start(current_id);
2281 if (skip_block_start == 0)
2282 break;
2283 auto new_iter = std::lower_bound(begin, iter, skip_block_start, gcode_move_comp);
2284 if (new_iter == begin)
2285 break;
2286 iter = std::prev(new_iter);
2287 }
2288 }
2289 return iter;
2290 };
2291
2292 if (!pre_cooling && !pre_heating && block.free_upper_gcode_id <= block.free_lower_gcode_id)
2293 return;
2294
2295 auto move_iter_lower = std::lower_bound(moves.begin(), moves.end(), block.free_lower_gcode_id, gcode_move_comp);
2296 auto move_iter_upper = std::lower_bound(moves.begin(), moves.end(), block.free_upper_gcode_id, gcode_move_comp); // closed iter
2297
2298 if (move_iter_lower == moves.end() || move_iter_upper == moves.begin())
2299 return;
2300 --move_iter_upper;
2301 float complete_free_time_gap = 0; // time of complete free
2302 if (move_iter_lower == moves.begin())
2303 complete_free_time_gap = move_iter_upper->time[valid_machine_id];
2304 else
2305 complete_free_time_gap = move_iter_upper->time[valid_machine_id] - std::prev(move_iter_lower)->time[valid_machine_id];
2306
2307 auto partial_free_move_lower = std::lower_bound(moves.begin(), moves.end(), block.partial_free_lower_id, gcode_move_comp);
2308 auto partial_free_move_upper = std::lower_bound(moves.begin(), moves.end(), block.partial_free_upper_id, gcode_move_comp); // closed iter
2309 if (partial_free_move_lower == moves.end() || partial_free_move_upper == moves.begin())
2310 return;
2311 --partial_free_move_upper;
2312 float partial_free_time_gap = 0; // time of partial free
2313 if (partial_free_move_lower == moves.begin())
2314 partial_free_time_gap = partial_free_move_upper->time[valid_machine_id];
2315 else
2316 partial_free_time_gap = partial_free_move_upper->time[valid_machine_id] - std::prev(partial_free_move_lower)->time[valid_machine_id];
2317
2318 if (move_iter_lower >= move_iter_upper)
2319 return;
2320
2321 bool apply_cooling_when_partial_free = is_pre_cooling_valid(block.last_filament_id) && pre_cooling;
2322
2323 if (apply_cooling_when_partial_free && partial_free_time_gap + complete_free_time_gap < inject_time_threshold)
2324 return;
2325
2326 if (!apply_cooling_when_partial_free && complete_free_time_gap < inject_time_threshold)
2327 return;
2328
2329 int extruder_id = get_valid_extruder_id(block.last_nozzle_id);
2330 float ext_heating_rate = value_at_or_front(heating_rate, extruder_id, 1.0);
2331 float ext_cooling_rate = value_at_or_front(cooling_rate, extruder_id, 1.0);
2332
2333 auto add_M104_lines = [&](int gcode_id, int target_extruder, int target_temp, int target_filament, bool skippable, int next_filament_idx, int next_nozzle_id, TimeProcessor::InsertLineType type, const std::string& comment = std::string()) {
2334 auto format_line_M104 = [&](int target_extruder, int target_temp, int target_filament, bool skippable, int next_filament_idx, int next_nozzle_id, const std::string& comment = std::string()) -> std::vector<std::string> {
2335 std::vector<std::string> buffer;
2336 if (skippable) {
2337 const bool support_dynamic_nozzle_map = this->nozzle_group_result.is_support_dynamic_nozzle_map();
2338 std::string m632_line = "M632 S" + std::to_string(next_filament_idx);
2339 if (support_dynamic_nozzle_map)
2340 m632_line += " H" + std::to_string(next_nozzle_id);
2341 if (value_at_or_front(extruder_max_nozzle_count, target_extruder, 1) > 1)
2342 m632_line += " N R";
2343 m632_line += " W\n";
2344 buffer.emplace_back(std::move(m632_line));
2345 }
2346 buffer.emplace_back("M400\n");
2347 std::string M104_line = "M104";
2349 M104_line += (" I" + std::to_string(target_filament == -1 ? next_filament_idx : target_filament));
2350 } else if (target_extruder != -1) {
2351 M104_line += (" T" + std::to_string(target_extruder < (int) physical_extruder_map.size() ? physical_extruder_map[target_extruder] : target_extruder));
2352 }
2353
2354 M104_line += " S" + std::to_string(target_temp);
2355 M104_line += " N0"; // N0 means the gcode is generated by slicer
2356
2357 if (!comment.empty())
2358 M104_line += " ;" + comment;
2359 M104_line += '\n';
2360
2361 buffer.emplace_back(M104_line);
2362
2363 if (skippable)
2364 buffer.emplace_back("M633\n");
2365
2366 return buffer;
2367 };
2368
2369 std::vector<std::string> line_buf = format_line_M104(target_extruder, target_temp, target_filament, skippable, next_filament_idx, next_nozzle_id, comment);
2370 for (auto& line : line_buf)
2371 inserted_operation_lines[gcode_id].emplace_back(line, type);
2372 };
2373
2374 constexpr float room_temperature = 25.f;
2375
2376 if (apply_cooling_when_partial_free) {
2377 float max_cooling_temp = std::min(curr_temp, std::min(get_partial_free_cooling_thres(block.last_filament_id), partial_free_time_gap * ext_cooling_rate));
2378 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": partial cooling for %1% %2%") % max_cooling_temp % curr_temp;
2379 curr_temp = std::max(room_temperature, curr_temp - max_cooling_temp); // set the temperature after doing cooling when post-extruding
2380 add_M104_lines(block.partial_free_lower_id, extruder_id, curr_temp, block.last_filament_id, false, block.next_filament_id, block.next_nozzle_id, TimeProcessor::InsertLineType::PreCooling, "Multi extruder pre cooling in post extrusion");
2381 }
2382
2383 if (pre_cooling && !pre_heating) {
2384 // only perform cooling
2385 if (target_temp >= curr_temp)
2386 return;
2387 int clamped_target = std::max((int) room_temperature, (int) target_temp);
2388 add_M104_lines(block.free_lower_gcode_id, extruder_id, clamped_target, block.last_filament_id, false, block.next_filament_id, block.next_nozzle_id, TimeProcessor::InsertLineType::PreCooling, "Multi extruder pre cooling");
2389 return;
2390 }
2391 if (!pre_cooling && pre_heating) {
2392 // only perform heating
2393 if (target_temp <= curr_temp)
2394 return;
2395 float heating_start_time = move_iter_upper->time[valid_machine_id] - (target_temp - curr_temp) / ext_heating_rate;
2396 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]; });
2397 if (heating_move_iter == move_iter_lower) {
2398 add_M104_lines(block.free_lower_gcode_id, extruder_id, target_temp, block.next_filament_id, true, block.next_filament_id, block.next_nozzle_id, TimeProcessor::InsertLineType::PreHeating, "Multi extruder pre heating");
2399 } else {
2400 --heating_move_iter;
2401 heating_move_iter = adjust_iter(heating_move_iter, move_iter_lower, move_iter_upper, false);
2402 add_M104_lines(heating_move_iter->gcode_id, extruder_id, target_temp, block.next_filament_id, true, block.next_filament_id, block.next_nozzle_id, TimeProcessor::InsertLineType::PreHeating, "Multi extruder pre heating");
2403 }
2404 return;
2405 }
2406 // perform cooling first and then perform heating
2407 float mid_temp = std::max(room_temperature, (curr_temp * ext_heating_rate + target_temp * ext_cooling_rate - complete_free_time_gap * ext_cooling_rate * ext_heating_rate) / (ext_cooling_rate + ext_heating_rate));
2408 float heating_temp = target_temp - mid_temp;
2409 float heating_start_time = move_iter_upper->time[valid_machine_id] - heating_temp / ext_heating_rate;
2410 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]; });
2411 if (heating_move_iter == move_iter_lower)
2412 return;
2413 --heating_move_iter;
2414 heating_move_iter = adjust_iter(heating_move_iter, move_iter_lower, move_iter_upper, false);
2415
2416 // get the insert pos of heat cmd and recalculate time gap and delta temp
2417 float real_cooling_time = heating_move_iter->time[valid_machine_id] - move_iter_lower->time[valid_machine_id];
2418 int real_delta_temp = std::min((int) (real_cooling_time * ext_cooling_rate), (int) curr_temp);
2419 if (real_delta_temp == 0)
2420 return;
2421 int cooling_temp = std::max((int) room_temperature, (int) curr_temp - real_delta_temp);
2422 add_M104_lines(block.free_lower_gcode_id, extruder_id, cooling_temp, block.last_filament_id, false, block.next_filament_id, block.next_nozzle_id, TimeProcessor::InsertLineType::PreCooling, "Multi extruder pre cooling");
2423 add_M104_lines(heating_move_iter->gcode_id, extruder_id, target_temp, block.next_filament_id, true, block.next_filament_id, block.next_nozzle_id, TimeProcessor::InsertLineType::PreHeating, "Multi extruder pre heating");
2424}
T * begin(Slic3r::Mat< N, M, T > &mat)
Definition Point.hpp:838
T * end(Slic3r::Mat< N, M, T > &mat)
Definition Point.hpp:841
static T value_at_or_front(const std::vector< T > &v, int i, T fallback)
Definition GCodeProcessor.cpp:2207
InsertLineType
Definition GCodeProcessor.hpp:914
@ PreCooling
Definition GCodeProcessor.hpp:919
@ PreHeating
Definition GCodeProcessor.hpp:920

References cooling_rate, extruder_max_nozzle_count, filament_nozzle_temps, filament_pre_cooling_temps, Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::free_lower_gcode_id, Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::free_upper_gcode_id, Slic3r::GCodeProcessorResult::MoveVertex::gcode_id, handle_hotend_as_extruder, heating_rate, inject_time_threshold, Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::last_filament_id, Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::last_nozzle_id, moves, Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::next_filament_id, Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::next_nozzle_id, nozzle_group_result, Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::partial_free_lower_id, Slic3r::GCodeProcessor::PreCoolingInjector::ExtruderFreeBlock::partial_free_upper_id, physical_extruder_map, Slic3r::GCodeProcessor::TimeProcessor::PreCooling, Slic3r::GCodeProcessor::TimeProcessor::PreHeating, skippable_blocks, Slic3r::GCodeProcessorResult::MoveVertex::time, valid_machine_id, and Slic3r::value_at_or_front().

Referenced by process_pre_cooling_and_heating().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ process_pre_cooling_and_heating()

void Slic3r::GCodeProcessor::PreCoolingInjector::process_pre_cooling_and_heating ( TimeProcessor::InsertedLinesMap & inserted_operation_lines)
2151{
2152 bool is_multiple_nozzle = std::any_of(extruder_max_nozzle_count.begin(), extruder_max_nozzle_count.end(), [](auto& elem) { return elem > 1; });
2153 (void) is_multiple_nozzle; // computed but currently unused here
2154 auto get_nozzle_temp = [this](int filament_id, bool is_first_layer, bool from_or_to, bool consider_preheat_temperature_delta) {
2155 if (filament_id == -1)
2156 return from_or_to ? 140 : 0; // default temp
2157 double temp = (is_first_layer ? filament_nozzle_temps_initial_layer[filament_id] : filament_nozzle_temps[filament_id]);
2158 if (consider_preheat_temperature_delta)
2159 return (int) (temp - filament_preheat_temperature_delta[filament_id]);
2160 else
2161 return (int) (temp);
2162 };
2163
2164 // Temporary workaround for X2D: when extruder types are mixed (e.g. DirectDrive + Bowden),
2165 // limit pre-heating target to avoid overshooting on the slower-responding extruder.
2166 bool has_mixed_extruder_types = extruder_types.size() > 1 &&
2167 std::adjacent_find(extruder_types.begin(), extruder_types.end(), std::not_equal_to<>()) != extruder_types.end();
2168 // Temporary workaround for X2D: Use the first nozzle diameter to determine the temp offset: 40 for large nozzles (0.6/0.8), 20 for others
2169 float first_nozzle_dia = nozzle_diameter.empty() ? 0.4 : nozzle_diameter.front();
2170 float switcher_temp_offset = (first_nozzle_dia >= 0.6 - EPSILON) ? 40.f : 20.f;
2171
2172 std::map<int, std::vector<ExtruderFreeBlock>> per_extruder_free_blocks;
2173
2174 for (auto& block : m_extruder_free_blocks)
2175 per_extruder_free_blocks[block.extruder_id].emplace_back(block);
2176
2177 for (auto& elem : per_extruder_free_blocks) {
2178 auto& extruder_free_blcoks = elem.second;
2179 for (auto iter = extruder_free_blcoks.begin(); iter != extruder_free_blcoks.end(); ++iter) {
2180 bool is_end = std::next(iter) == extruder_free_blcoks.end();
2181 bool apply_pre_cooling = true;
2182 bool apply_pre_heating = is_end ? false : true;
2183 float curr_temp = get_nozzle_temp(iter->last_filament_id, false, true, false);
2184 float target_temp = get_nozzle_temp(iter->next_filament_id, false, false, !iter->ignore_cooling_before_tower);
2185 // X2D temporary workaround: only apply temp offset when extruder types are mixed
2186 if (has_filament_switcher && has_mixed_extruder_types && apply_pre_heating) {
2187 float print_temp = get_nozzle_temp(iter->next_filament_id, false, false, false);
2188 target_temp = std::min(target_temp, print_temp - switcher_temp_offset);
2189 }
2190 inject_cooling_heating_command(inserted_operation_lines, *iter, curr_temp, target_temp, apply_pre_cooling, apply_pre_heating);
2191 }
2192 }
2193}
#define EPSILON
Definition ColorUtils.cpp:64
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)
Definition GCodeProcessor.cpp:2217

References EPSILON, extruder_max_nozzle_count, extruder_types, filament_nozzle_temps, filament_nozzle_temps_initial_layer, filament_preheat_temperature_delta, has_filament_switcher, inject_cooling_heating_command(), m_extruder_free_blocks, and nozzle_diameter.

Referenced by Slic3r::GCodeProcessor::run_second_pass_injection().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ cooling_rate

const std::vector<double>& Slic3r::GCodeProcessor::PreCoolingInjector::cooling_rate
private

◆ extruder_max_nozzle_count

const std::vector<int>& Slic3r::GCodeProcessor::PreCoolingInjector::extruder_max_nozzle_count
private

◆ extruder_types

const std::vector<ExtruderType>& Slic3r::GCodeProcessor::PreCoolingInjector::extruder_types
private

◆ filament_max_temperature_drop_when_ec

const std::vector<double>& Slic3r::GCodeProcessor::PreCoolingInjector::filament_max_temperature_drop_when_ec
private

Referenced by PreCoolingInjector().

◆ filament_nozzle_temps

const std::vector<int>& Slic3r::GCodeProcessor::PreCoolingInjector::filament_nozzle_temps
private

◆ filament_nozzle_temps_initial_layer

const std::vector<int>& Slic3r::GCodeProcessor::PreCoolingInjector::filament_nozzle_temps_initial_layer
private

◆ filament_pre_cooling_temps

const std::vector<int>& Slic3r::GCodeProcessor::PreCoolingInjector::filament_pre_cooling_temps
private

◆ filament_preheat_temperature_delta

const std::vector<double>& Slic3r::GCodeProcessor::PreCoolingInjector::filament_preheat_temperature_delta
private

◆ filament_types

const std::vector<std::string>& Slic3r::GCodeProcessor::PreCoolingInjector::filament_types
private

Referenced by PreCoolingInjector().

◆ handle_hotend_as_extruder

const bool Slic3r::GCodeProcessor::PreCoolingInjector::handle_hotend_as_extruder
private

◆ has_filament_switcher

const bool Slic3r::GCodeProcessor::PreCoolingInjector::has_filament_switcher
private

◆ heating_rate

const std::vector<double>& Slic3r::GCodeProcessor::PreCoolingInjector::heating_rate
private

◆ inject_time_threshold

const float Slic3r::GCodeProcessor::PreCoolingInjector::inject_time_threshold
private

◆ m_extruder_free_blocks

std::vector<ExtruderFreeBlock> Slic3r::GCodeProcessor::PreCoolingInjector::m_extruder_free_blocks
private

◆ machine_end_gcode_start_id

const unsigned int Slic3r::GCodeProcessor::PreCoolingInjector::machine_end_gcode_start_id
private

◆ machine_start_gcode_end_id

const unsigned int Slic3r::GCodeProcessor::PreCoolingInjector::machine_start_gcode_end_id
private

◆ moves

const std::vector<GCodeProcessorResult::MoveVertex>& Slic3r::GCodeProcessor::PreCoolingInjector::moves
private

◆ nozzle_diameter

const std::vector<double>& Slic3r::GCodeProcessor::PreCoolingInjector::nozzle_diameter
private

◆ nozzle_group_result

const MultiNozzleUtils::LayeredNozzleGroupResult& Slic3r::GCodeProcessor::PreCoolingInjector::nozzle_group_result
private

◆ physical_extruder_map

const std::vector<int>& Slic3r::GCodeProcessor::PreCoolingInjector::physical_extruder_map
private

◆ skippable_blocks

const std::vector<std::pair<unsigned int, unsigned int> >& Slic3r::GCodeProcessor::PreCoolingInjector::skippable_blocks
private

◆ valid_machine_id

const int Slic3r::GCodeProcessor::PreCoolingInjector::valid_machine_id
private

The documentation for this class was generated from the following files: