FIX: support pre heating without wipetower
jira:NONE Signed-off-by: xun.zhang <xun.zhang@bambulab.com> Change-Id: Ibcd3aacb9eede8bc054669f8fff98ea25f8e5d09
This commit is contained in:
parent
f625202c2b
commit
6cf0e2451e
|
@ -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<FilamentUsageBlock> filament_blocks;
|
||||
std::vector<ExtruderUsageBlcok> 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<unsigned int, std::vector<std::pair<std::string, InsertLineType>>> inserted_operation_lines;
|
||||
|
||||
InsertedLinesMap inserted_operation_lines;
|
||||
|
||||
// save filament change block by extruder id
|
||||
std::unordered_map<int, std::vector<ExtruderUsageBlcok>> 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<PreCoolingInjector>(
|
||||
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<int>(m_extruder_id);
|
||||
}
|
||||
|
||||
void GCodeProcessor::PreCoolingInjector::process_pre_cooling_and_heating(TimeProcessor::InsertedLinesMap& inserted_operation_lines)
|
||||
{
|
||||
std::map<int, std::vector<ExtruderFreeBlock>> 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<ExtruderPreHeating::FilamentUsageBlock>& filament_usage_blocks, const std::vector<ExtruderPreHeating::ExtruderUsageBlcok>& 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<ExtruderPreHeating::FilamentUsageBlock>& filament_usage_blocks_)
|
||||
{
|
||||
m_extruder_free_blocks.clear();
|
||||
std::map<int, std::vector<ExtruderPreHeating::FilamentUsageBlock>> 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<ExtruderPreHeating::ExtruderUsageBlcok>& extruder_usage_blocks_)
|
||||
{
|
||||
m_extruder_free_blocks.clear();
|
||||
std::map<int, std::vector<ExtruderPreHeating::ExtruderUsageBlcok>> 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 */
|
||||
|
||||
|
|
|
@ -613,13 +613,13 @@ namespace Slic3r {
|
|||
std::vector<Extruder> filament_lists;
|
||||
std::vector<std::string> filament_types;
|
||||
std::vector<int> filament_maps; // map each filament to extruder
|
||||
std::vector<float> filament_nozzle_temp;
|
||||
std::vector<int> filament_nozzle_temp;
|
||||
std::vector<int> 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<Extruder>& filament_lists_,
|
||||
const std::vector<int>& filament_maps_,
|
||||
const std::vector<std::string>& filament_types_,
|
||||
const std::vector<float>& filament_nozzle_temp_,
|
||||
const std::vector<int>& filament_nozzle_temp_,
|
||||
const std::vector<int>& 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<unsigned int, std::vector<std::pair<std::string, InsertLineType>>>;
|
||||
|
||||
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<GCodeProcessorResult::MoveVertex>& moves, std::vector<size_t>& 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<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 std::vector<int>& filament_maps_,
|
||||
const std::vector<int>& filament_nozzle_temps_,
|
||||
const std::vector<int>& 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<ExtruderFreeBlock> m_extruder_free_blocks;
|
||||
const std::vector<GCodeProcessorResult::MoveVertex>& moves;
|
||||
const std::vector<std::string>& filament_types;
|
||||
const std::vector<int>& filament_maps;
|
||||
const std::vector<int>& filament_nozzle_temps;
|
||||
const std::vector<int>& 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<ExtruderPreHeating::FilamentUsageBlock>& filament_usage_blocks);
|
||||
void build_by_extruder_blocks(const std::vector<ExtruderPreHeating::ExtruderUsageBlcok>& extruder_usage_blocks);
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
class SeamsDetector
|
||||
{
|
||||
|
@ -831,7 +919,7 @@ namespace Slic3r {
|
|||
float m_print_z{0.0f};
|
||||
std::vector<float> m_remaining_volume;
|
||||
std::vector<Extruder> m_filament_lists;
|
||||
std::vector<float> m_filament_nozzle_temp;
|
||||
std::vector<int> m_filament_nozzle_temp;
|
||||
std::vector<std::string> m_filament_types;
|
||||
float m_hotend_cooling_rate{ 2.f };
|
||||
float m_hotend_heating_rate{ 2.f };
|
||||
|
|
Loading…
Reference in New Issue