From 6690bdf149b9a410e7768805ddad9afc2d23b3d6 Mon Sep 17 00:00:00 2001 From: Noisyfox Date: Thu, 21 May 2026 23:27:05 +0800 Subject: [PATCH] Fix calibration Co-authored-by: zhimin.zeng --- src/slic3r/GUI/Plater.cpp | 119 +++++++++++++++++++------------- src/slic3r/Utils/CalibUtils.cpp | 67 ++++++++++++++++++ src/slic3r/Utils/CalibUtils.hpp | 3 + 3 files changed, 140 insertions(+), 49 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index beee003213..c6f1dc00cd 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -238,6 +238,32 @@ static string get_diameter_string(float diameter) return s; } +template +static void set_config_values(DynamicPrintConfig *config, const std::string &key, T value) +{ + auto config_opt = config->option(key); + if (config_opt) { + for (size_t i = 0; i < config_opt->values.size(); ++i) { + config_opt->values[i] = value; + } + } + else { + BOOST_LOG_TRIVIAL(info) << "set_config_values: the key" << key << "is empty."; + } +} + +template +static void set_config_values(ModelConfig& config, const std::string &key, T value) +{ + auto config_opt = config.get().option(key); + if (config_opt) { + config.set_key_value(key, new OptionType(config_opt->values.size(), value)); + } + else { + BOOST_LOG_TRIVIAL(info) << "set_config_values: the key" << key << "is empty."; + } +} + bool Plater::has_illegal_filename_characters(const wxString& wxs_name) { std::string name = into_u8(wxs_name); @@ -12672,11 +12698,11 @@ void Plater::_calib_pa_pattern(const Calib_Params& params) DynamicPrintConfig& print_config = wxGetApp().preset_bundle->prints.get_edited_preset().config; auto filament_config = &wxGetApp().preset_bundle->filaments.get_edited_preset().config; double nozzle_diameter = printer_config->option("nozzle_diameter")->get_at(0); - filament_config->set_key_value("filament_retract_when_changing_layer", new ConfigOptionBoolsNullable{false}); - filament_config->set_key_value("filament_wipe", new ConfigOptionBoolsNullable{false}); - printer_config->set_key_value("wipe", new ConfigOptionBools{false}); - printer_config->set_key_value("retract_when_changing_layer", new ConfigOptionBools{false}); - printer_config->set_key_value("resonance_avoidance", new ConfigOptionBool{false}); + set_config_values(filament_config, "filament_retract_when_changing_layer", false); + set_config_values(filament_config, "filament_wipe", false); + set_config_values(printer_config, "wipe", false); + set_config_values(printer_config, "retract_when_changing_layer", false); + printer_config->set_key_value("resonance_avoidance", new ConfigOptionBool(false)); //Orca: find acceleration to use in the test auto accel = print_config.get_abs_value_at("outer_wall_acceleration", params.extruder_id); // get the outer wall acceleration @@ -12695,7 +12721,7 @@ void Plater::_calib_pa_pattern(const Calib_Params& params) // set max acceleration in case of batch mode to get correct test pattern size accel = *std::max_element(accels.begin(), accels.end()); } - print_config.set_key_value("outer_wall_acceleration", new ConfigOptionFloatsNullable({accel})); + set_config_values(&print_config, "outer_wall_acceleration", accel); print_config.set_key_value( "print_sequence", new ConfigOptionEnum(PrintSequence::ByLayer)); //Orca: find jerk value to use in the test @@ -12708,20 +12734,20 @@ void Plater::_calib_pa_pattern(const Calib_Params& params) //Orca: Set jerk values. Again first layer jerk should not matter as it is reset to the travel jerk before the // first PA pattern is printed. - print_config.set_key_value( "default_jerk", new ConfigOptionFloatsNullable({jerk})); - print_config.set_key_value( "outer_wall_jerk", new ConfigOptionFloatsNullable({jerk})); - print_config.set_key_value( "inner_wall_jerk", new ConfigOptionFloatsNullable({jerk})); - print_config.set_key_value( "top_surface_jerk", new ConfigOptionFloatsNullable({jerk})); - print_config.set_key_value( "infill_jerk", new ConfigOptionFloatsNullable({jerk})); - print_config.set_key_value( "travel_jerk", new ConfigOptionFloatsNullable({jerk})); + set_config_values(&print_config, "default_jerk", jerk); + set_config_values(&print_config, "outer_wall_jerk", jerk); + set_config_values(&print_config, "inner_wall_jerk", jerk); + set_config_values(&print_config, "top_surface_jerk", jerk); + set_config_values(&print_config, "infill_jerk", jerk); + set_config_values(&print_config, "travel_jerk", jerk); } if (has_junction_deviation(printer_config)){ - print_config.set_key_value("default_junction_deviation", new ConfigOptionFloatsNullable({0})); + set_config_values(&print_config, "default_junction_deviation", 0); } for (const auto& opt : SuggestedConfigCalibPAPattern().floats_pairs) { - print_config.set_key_value(opt.first, new ConfigOptionFloatsNullable(opt.second)); + set_config_values(&print_config, opt.first, opt.second[0]); } for (const auto& opt : SuggestedConfigCalibPAPattern().nozzle_ratio_pairs) { @@ -12745,11 +12771,12 @@ void Plater::_calib_pa_pattern(const Calib_Params& params) // Orca: Set the outer wall speed to the optimal speed for the test, cap it with max volumetric speed if (speeds.empty()) { + // TODO: per-variant cap double speed = CalibPressureAdvance::find_optimal_PA_speed( wxGetApp().preset_bundle->full_config(), print_config.get_abs_value("line_width", nozzle_diameter), print_config.get_abs_value("layer_height"), 0, 0); - print_config.set_key_value("outer_wall_speed", new ConfigOptionFloatsNullable({speed})); + set_config_values(&print_config, "outer_wall_speed", speed); speeds.assign({speed}); const auto msg{_L("INFO:") + "\n" + @@ -12758,7 +12785,7 @@ void Plater::_calib_pa_pattern(const Calib_Params& params) } else if (speeds.size() == 1) { // If we have single value provided, set speed using global configuration. // per-object config is not set in this case - print_config.set_key_value("outer_wall_speed", new ConfigOptionFloatsNullable({speeds.front()})); + set_config_values(&print_config, "outer_wall_speed", speeds.front()); } wxGetApp().get_tab(Preset::TYPE_PRINT)->update_dirty(); @@ -12833,9 +12860,9 @@ void Plater::_calib_pa_pattern(const Calib_Params& params) auto &obj_config = obj->config; if (speeds.size() > 1) - obj_config.set_key_value("outer_wall_speed", new ConfigOptionFloatsNullable({tspd})); + set_config_values(obj_config, "outer_wall_speed", tspd); if (accels.size() > 1) - obj_config.set_key_value("outer_wall_acceleration", new ConfigOptionFloatsNullable({tacc})); + set_config_values(obj_config, "outer_wall_acceleration", tacc); auto cur_plate = get_partplate_list().get_plate(plate_idx); if (!cur_plate) { @@ -12936,11 +12963,8 @@ void Plater::_calib_pa_tower(const Calib_Params& params) { obj_cfg.set_key_value("alternate_extra_wall", new ConfigOptionBool(false)); auto full_config = wxGetApp().preset_bundle->full_config(); - auto wall_speed = CalibPressureAdvance::find_optimal_PA_speed( - full_config, full_config.get_abs_value("line_width", nozzle_diameter), - full_config.get_abs_value("layer_height"), 0, 0); - obj_cfg.set_key_value("outer_wall_speed", new ConfigOptionFloatsNullable({wall_speed})); - obj_cfg.set_key_value("inner_wall_speed", new ConfigOptionFloatsNullable({wall_speed})); + update_speed_parameter("outer_wall_speed"); + update_speed_parameter("inner_wall_speed"); obj_cfg.set_key_value("seam_position", new ConfigOptionEnum(spRear)); obj_cfg.set_key_value("wall_loops", new ConfigOptionInt(2)); obj_cfg.set_key_value("top_shell_layers", new ConfigOptionInt(0)); @@ -12993,12 +13017,15 @@ void Plater::_calib_pa_select_added_objects() { void adjust_settings_for_flowrate_calib(ModelObjectPtrs& objects, bool linear, int pass, InfillPattern pattern) { auto print_config = &wxGetApp().preset_bundle->prints.get_edited_preset().config; - auto printerConfig = &wxGetApp().preset_bundle->printers.get_edited_preset().config; + auto printer_config = &wxGetApp().preset_bundle->printers.get_edited_preset().config; auto filament_config = &wxGetApp().preset_bundle->filaments.get_edited_preset().config; /// --- scale --- // model is created for a 0.4 nozzle, scale z with nozzle size. - const ConfigOptionFloats* nozzle_diameter_config = printerConfig->option("nozzle_diameter"); + const ConfigOptionFloats* nozzle_diameter_config = printer_config->option("nozzle_diameter"); + std::vector extruder_types = printer_config->option("extruder_type")->values; + std::vector nozzle_volume_types = wxGetApp().preset_bundle->project_config.option("nozzle_volume_type")->values; + assert(nozzle_diameter_config->values.size() > 0); float nozzle_diameter = nozzle_diameter_config->values[0]; float xyScale = nozzle_diameter / 0.6; @@ -13022,17 +13049,9 @@ void adjust_settings_for_flowrate_calib(ModelObjectPtrs& objects, bool linear, i } canvas->do_scale(""); - auto cur_flowrate = filament_config->option("filament_flow_ratio")->get_at(0); - Flow infill_flow = Flow(nozzle_diameter * 1.2f, layer_height, nozzle_diameter); - double filament_max_volumetric_speed = filament_config->option("filament_max_volumetric_speed")->get_at(0); - double max_infill_speed; - if (linear) - max_infill_speed = filament_max_volumetric_speed / - (infill_flow.mm3_per_mm() * (cur_flowrate + (pass == 2 ? 0.035 : 0.05)) / cur_flowrate); - else - max_infill_speed = filament_max_volumetric_speed / (infill_flow.mm3_per_mm() * (pass == 1 ? 1.2 : 1)); - double internal_solid_speed = std::floor(std::min(print_config->opt_float_nullable("internal_solid_infill_speed", 0), max_infill_speed)); - double top_surface_speed = std::floor(std::min(print_config->opt_float_nullable("top_surface_speed", 0), max_infill_speed)); + auto cur_flowrate = filament_config->option("filament_flow_ratio")->get_at(0); // TODO: per-filament param + std::vector internal_solid_speeds = generate_max_speed_parameter_value("internal_solid_infill_speed", linear, pass); + std::vector top_surface_speeds = generate_max_speed_parameter_value("top_surface_speed", linear, pass); // adjust parameters for (auto _obj : objects) { @@ -13060,8 +13079,8 @@ void adjust_settings_for_flowrate_calib(ModelObjectPtrs& objects, bool linear, i _obj->config.set_key_value("solid_infill_direction", new ConfigOptionFloat(135)); _obj->config.set_key_value("align_infill_direction_to_model", new ConfigOptionBool(true)); _obj->config.set_key_value("ironing_type", new ConfigOptionEnum(IroningType::NoIroning)); - _obj->config.set_key_value("internal_solid_infill_speed", new ConfigOptionFloatsNullable({internal_solid_speed})); - _obj->config.set_key_value("top_surface_speed", new ConfigOptionFloatsNullable({top_surface_speed})); + _obj->config.set_key_value("internal_solid_infill_speed", new ConfigOptionFloatsNullable(internal_solid_speeds)); + _obj->config.set_key_value("top_surface_speed", new ConfigOptionFloatsNullable(top_surface_speeds)); _obj->config.set_key_value("seam_slope_type", new ConfigOptionEnum(SeamScarfType::None)); _obj->config.set_key_value("gap_fill_target", new ConfigOptionEnum(GapFillTarget::gftNowhere)); print_config->set_key_value("max_volumetric_extrusion_rate_slope", new ConfigOptionFloat(0)); @@ -13158,8 +13177,7 @@ void Plater::calib_temp(const Calib_Params& params) { const auto calib_temp_name = wxString::Format(L"Nozzle temperature test"); new_project(false, false, calib_temp_name); wxGetApp().mainframe->select_tab(size_t(MainFrame::tp3DEditor)); - if (params.mode != CalibMode::Calib_Temp_Tower) - return; + if (params.mode != CalibMode::Calib_Temp_Tower) return; add_model(false, Slic3r::resources_dir() + "/calib/temperature_tower/temperature_tower.drc"); auto printer_config = &wxGetApp().preset_bundle->printers.get_edited_preset().config; @@ -13205,8 +13223,8 @@ void Plater::calib_temp(const Calib_Params& params) { model().objects[0]->ensure_on_bed(); printer_config->set_key_value("resonance_avoidance", new ConfigOptionBool{false}); - filament_config->set_key_value("nozzle_temperature_initial_layer", new ConfigOptionInts(1,(int)start_temp)); - filament_config->set_key_value("nozzle_temperature", new ConfigOptionInts(1,(int)start_temp)); + set_config_values(filament_config, "nozzle_temperature_initial_layer", (int) start_temp); + set_config_values(filament_config, "nozzle_temperature", (int) start_temp); model().objects[0]->config.set_key_value("layer_height", new ConfigOptionFloat(nozzle_diameter/2)); model().objects[0]->config.set_key_value("brim_type", new ConfigOptionEnum(btOuterOnly)); model().objects[0]->config.set_key_value("brim_width", new ConfigOptionFloat(5.0)); @@ -13258,13 +13276,15 @@ void Plater::calib_max_vol_speed(const Calib_Params& params) double layer_height = nozzle_diameter * 0.8; auto max_lh = printer_config->option("max_layer_height"); - if (max_lh->values[0] < layer_height) - max_lh->values[0] = { layer_height }; + for (size_t i = 0; i < max_lh->values.size(); ++i) { + if (max_lh->values[i] < layer_height) + max_lh->values[i] = layer_height; + } - filament_config->set_key_value("filament_max_volumetric_speed", new ConfigOptionFloats { 200 }); + set_config_values(filament_config, "filament_max_volumetric_speed", 200); filament_config->set_key_value("slow_down_layer_time", new ConfigOptionFloats{0.0}); printer_config->set_key_value("resonance_avoidance", new ConfigOptionBool{false}); - obj_cfg.set_key_value("enable_overhang_speed", new ConfigOptionBoolsNullable({false})); + set_config_values(obj_cfg, "enable_overhang_speed", false); obj_cfg.set_key_value("wall_loops", new ConfigOptionInt(1)); obj_cfg.set_key_value("alternate_extra_wall", new ConfigOptionBool(false)); obj_cfg.set_key_value("top_shell_layers", new ConfigOptionInt(0)); @@ -13333,8 +13353,9 @@ void Plater::calib_retraction(const Calib_Params& params) } auto max_lh = printer_config->option("max_layer_height"); - if (max_lh->values[0] < layer_height) - max_lh->values[0] = { layer_height }; + for (size_t i = 0; i < max_lh->values.size(); ++i) { + if (max_lh->values[i] < layer_height) max_lh->values[i] = layer_height; + } printer_config->set_key_value("resonance_avoidance", new ConfigOptionBool{false}); printer_config->set_key_value("use_firmware_retraction", new ConfigOptionBool(false)); @@ -13379,7 +13400,7 @@ void Plater::calib_VFA(const Calib_Params& params) printer_config->set_key_value("input_shaping_emit", new ConfigOptionBool{true}); printer_config->set_key_value("input_shaping_type", new ConfigOptionEnum(InputShaperType::Disable)); filament_config->set_key_value("slow_down_layer_time", new ConfigOptionFloats { 0.0 }); - print_config->set_key_value("enable_overhang_speed", new ConfigOptionBoolsNullable({false})); + set_config_values(print_config, "enable_overhang_speed", false); print_config->set_key_value("timelapse_type", new ConfigOptionEnum(tlTraditional)); print_config->set_key_value("wall_loops", new ConfigOptionInt(1)); print_config->set_key_value("alternate_extra_wall", new ConfigOptionBool(false)); diff --git a/src/slic3r/Utils/CalibUtils.cpp b/src/slic3r/Utils/CalibUtils.cpp index 68c6e6fb81..a052d86283 100644 --- a/src/slic3r/Utils/CalibUtils.cpp +++ b/src/slic3r/Utils/CalibUtils.cpp @@ -89,6 +89,73 @@ wxString get_nozzle_volume_type_name(NozzleVolumeType type) return wxString(); } +void update_speed_parameter( const std::string& key) +{ + auto preset_bundle = wxGetApp().preset_bundle; + auto& printer_config = preset_bundle->printers.get_edited_preset().config; + auto& filament_config = preset_bundle->filaments.get_edited_preset().config; + auto& print_config = preset_bundle->prints.get_edited_preset().config; + + int extruder_nums = preset_bundle->get_printer_extruder_count(); + std::vector extruder_types = printer_config.option("extruder_type")->values; + std::vector nozzle_volume_types = preset_bundle->project_config.option("nozzle_volume_type")->values; + + float nozzle_diameter = printer_config.option("nozzle_diameter")->values[0]; + float layer_height = print_config.option("layer_height")->value; + float line_width = print_config.get_abs_value("line_width", nozzle_diameter); + if (line_width <= 0.) line_width = Flow::auto_extrusion_width(frPerimeter, nozzle_diameter); + + Flow flow = Flow(line_width, layer_height, nozzle_diameter); + + for (size_t i = 0; i < extruder_nums; ++i) { + int index = get_index_for_extruder_parameter(filament_config, "filament_max_volumetric_speed", i, ExtruderType(extruder_types[i]), NozzleVolumeType(nozzle_volume_types[i])); + double filament_max_volumetric_speed = filament_config.option("filament_max_volumetric_speed")->get_at(index); + double max_speed = filament_max_volumetric_speed / flow.mm3_per_mm(); + + index = get_index_for_extruder_parameter(print_config, key, i, ExtruderType(extruder_types[i]), NozzleVolumeType(nozzle_volume_types[i])); + ConfigOptionFloatsNullable *speed_opt = print_config.option(key); + speed_opt->values[index] = max_speed; + } +} + +std::vector generate_max_speed_parameter_value(const std::string &key, const bool linear, const int pass) +{ + auto preset_bundle = wxGetApp().preset_bundle; + auto &printer_config = preset_bundle->printers.get_edited_preset().config; + auto &filament_config = preset_bundle->filaments.get_edited_preset().config; + auto &print_config = preset_bundle->prints.get_edited_preset().config; + + int extruder_nums = preset_bundle->get_printer_extruder_count(); + std::vector extruder_types = printer_config.option("extruder_type")->values; + std::vector nozzle_volume_types = preset_bundle->project_config.option("nozzle_volume_type")->values; + + float nozzle_diameter = printer_config.option("nozzle_diameter")->values[0]; + float layer_height = print_config.option("layer_height")->value; + float line_width = print_config.get_abs_value("line_width", nozzle_diameter); + + Flow flow = Flow(line_width, layer_height, nozzle_diameter); + + std::vector speed_values; + speed_values.resize(extruder_nums * nozzle_volume_types.size()); + + for (size_t i = 0; i < extruder_nums; ++i) { + int index = get_index_for_extruder_parameter(filament_config, "filament_max_volumetric_speed", i, ExtruderType(extruder_types[i]), + NozzleVolumeType(nozzle_volume_types[i])); + double filament_max_volumetric_speed = filament_config.option("filament_max_volumetric_speed")->get_at(index); + double cur_flowrate = filament_config.option("filament_flow_ratio")->get_at(index); + double max_speed = linear ? filament_max_volumetric_speed / (flow.mm3_per_mm() * (cur_flowrate + (pass == 2 ? 0.035 : 0.05)) / cur_flowrate) : + filament_max_volumetric_speed / (flow.mm3_per_mm() * (pass == 1 ? 1.2 : 1)); + + index = get_index_for_extruder_parameter(print_config, key, i, ExtruderType(extruder_types[i]), NozzleVolumeType(nozzle_volume_types[i])); + ConfigOptionFloatsNullable *speed_opt = print_config.option(key); + double speed_value = std::floor(std::min(speed_opt->values[index], max_speed)); + for (size_t v_id = 0; v_id < nozzle_volume_types.size(); ++v_id) { + speed_values.emplace_back(speed_value); + } + } + return speed_values; +} + static int get_physical_extruder_idx(std::vector physical_extruder_maps, int extruder_id) { for (size_t index = 0; index < physical_extruder_maps.size(); ++index) { diff --git a/src/slic3r/Utils/CalibUtils.hpp b/src/slic3r/Utils/CalibUtils.hpp index e59bbf68ec..11c249b169 100644 --- a/src/slic3r/Utils/CalibUtils.hpp +++ b/src/slic3r/Utils/CalibUtils.hpp @@ -95,5 +95,8 @@ extern void get_tray_ams_and_slot_id(MachineObject* obj, int in_tray_id, int &am extern void get_default_k_n_value(const std::string &filament_id, float &k, float &n); extern wxString get_nozzle_volume_type_name(NozzleVolumeType type); +extern void update_speed_parameter(const std::string &key); +extern std::vector generate_max_speed_parameter_value(const std::string &key, bool linear, int pass); + } } \ No newline at end of file