diff --git a/doc/calibration/cornering-calib.md b/doc/calibration/cornering-calib.md index 4ce4a1b2dd..f076a2d792 100644 --- a/doc/calibration/cornering-calib.md +++ b/doc/calibration/cornering-calib.md @@ -2,69 +2,132 @@ Cornering is a critical aspect of 3D printing that affects print quality and accuracy. It's how the printer handles changes in direction during movement, particularly at corners and curves. Proper cornering settings can reduce artifacts such as ringing, ghosting, and overshooting, resulting in cleaner and more precise prints. -## Jerk +## Types of Cornering Settings -TODO: Jerk calibration not implemented yet. +> [!TIP] +> Read more in [Jerk XY](speed_settings_jerk_xy) and check [Cornering Control Types](speed_settings_jerk_xy#cornering-control-types) -## Junction Deviation +## Calibration -Junction Deviation is the default method for controlling cornering speed in **Marlin firmware (Marlin 2.x)**. -Higher values allow more aggressive cornering, while lower values produce smoother, more controlled corners. -The default value in Marlin is often `0.08mm`, which may be too high for some printers and may cause ringing. Consider lowering this value to reduce ringing, but avoid setting it too low that could lead to excessively slow cornering speed. +This test will be set detect automatically your printer firmware type and will adapt to the specific calibration process. -```math -JD = 0.4 \cdot \frac{\text{Jerk}^2}{\text{Acceleration}} -``` +- Klipper: [square_corner_velocity](https://www.klipper3d.org/Config_Reference.html#printer) +- Marlin 2: + - [Junction Deviation](https://marlinfw.org/docs/configuration/configuration.html#junction-deviation-) if `Maximum Junction Deviation` in Printer settings/Motion ability/Jerk limitations is bigger than `0`. + - [Classic Jerk](https://marlinfw.org/docs/configuration/configuration.html#jerk-) if `Maximum Junction Deviation` is set to `0`. +- Marlin Legacy: [Classic Jerk](https://marlinfw.org/docs/configuration/configuration.html#jerk-). +- RepRap: [Maximum instantaneous speed changes](https://docs.duet3d.com/User_manual/Reference/Gcodes#m566-set-allowable-instantaneous-speed-change) + +> [!NOTE] +> This calibration example uses Junction Deviation as an example. The process is similar for Jerk calibration; just read the Jerk values instead of JD values. +> JD values are between `0.0` and `0.3` (in mm) while Jerk values are usually between `1` and `20` or higher (in mm/s). 1. Pre-requisites: - 1. Check if your printer has Junction Deviation enabled. Look for `Junction deviation` in the printer's advanced settings. + 1. If using Marlin 2 firmware, Check if your printer has Junction Deviation enabled. Look for `Junction deviation` in the printer's advanced settings. 2. In OrcaSlicer, set: - 1. Acceleration high enough to trigger ringing (e.g., 2000 mm/s²). + 1. Acceleration high enough to trigger ringing or the speed you want to check out (e.g., 2000 mm/s²). 2. Speed high enough to trigger ringing (e.g., 100 mm/s). 3. Use an opaque, high-gloss filament to make ringing more visible. -2. You need to print the Junction Deviation test. +2. Open the Cornering test. ![jd_first_menu](https://github.com/SoftFever/OrcaSlicer/blob/main/doc/images/JunctionDeviation/jd_first_menu.png?raw=true) - 1. Measure the X and Y heights and read the frequency set at that point in OrcaSlicer. + 1. In this first approximation, set a wide range of Start and End values. + - If you don't see any loss of quality, increase the End value and retry. + - If you do see a loss of quality, measure the maximum height when the corners start losing sharpness and read the Cornering/Jerk/JunctionDeviation value set at that point in OrcaSlicer. ![jd_first_print_measure](https://github.com/SoftFever/OrcaSlicer/blob/main/doc/images/JunctionDeviation/jd_first_print_measure.jpg?raw=true) ![jd_first_slicer_measure](https://github.com/SoftFever/OrcaSlicer/blob/main/doc/images/JunctionDeviation/jd_first_slicer_measure.png?raw=true) - 2. You will likely need values lower than `0.08mm`, as in the example. To find a better maximum JD value, print a new calibration tower with a maximum set near the point where corners start losing sharpness. - 3. Print the second Junction Deviation test with the new maximum value. + 2. Print a new calibration tower with a maximum set near the point where corners start losing sharpness. + **RECOMMENDED:** Use the *Ringing Tower* test model to more easily visualize the jerk limit. + 3. Print the second Cornering test with the new maximum value. ![jd_second_menu](https://github.com/SoftFever/OrcaSlicer/blob/main/doc/images/JunctionDeviation/jd_second_menu.png?raw=true) - 4. Measure the X and Y heights and read the frequency set at that point in OrcaSlicer. + 4. Measure the maximum height when the corners start losing sharpness and read the Cornering/Jerk/JunctionDeviation value set at that point in OrcaSlicer. ![jd_second_print_measure](https://github.com/SoftFever/OrcaSlicer/blob/main/doc/images/JunctionDeviation/jd_second_print_measure.jpg?raw=true) ![jd_second_slicer_measure](https://github.com/SoftFever/OrcaSlicer/blob/main/doc/images/JunctionDeviation/jd_second_slicer_measure.png?raw=true) 3. Save the settings - 1. Set your Maximum Junction Deviation value in [Printer settings/Motion ability/Jerk limitation]. - ![jd_printer_jerk_limitation](https://github.com/SoftFever/OrcaSlicer/blob/main/doc/images/JunctionDeviation/jd_printer_jerk_limitation.png?raw=true) - 2. Use the following G-code to set the value: + - Into your OrcaSlicer printer profile (**RECOMMENDED**): + 1. Go to Printer settings → Motion ability → Jerk limitation: + 2. Set your maximum Jerk X and Y or Junction Deviation values. + ![jd_printer_jerk_limitation](https://github.com/SoftFever/OrcaSlicer/blob/main/doc/images/JunctionDeviation/jd_printer_jerk_limitation.png?raw=true) + - Directly into your printer firmware: + - Restore your 3D Printer settings to avoid keeping high acceleration and jerk values used for the test. - ```gcode - M205 J#JunctionDeviationValue - M500 - ``` + - Klipper: + - Skeleton - Example + ```gcode + SET_VELOCITY_LIMIT SQUARE_CORNER_VELOCITY=#SquareCornerVelocity + ``` - ```gcode - M205 J0.012 - M500 - ``` + Example: - 3. Recompile your MarlinFW - 1. In Configuration.h uncomment and set: + ```gcode + SET_VELOCITY_LIMIT SQUARE_CORNER_VELOCITY=5.0 + ``` - ```cpp - #define JUNCTION_DEVIATION_MM 0.012 // (mm) Distance from real junction edge - ``` + Note: You can also set `square_corner_velocity` persistently in your `printer.cfg` (restart required). - 2. Ensure Classic Jerk is disabled (commented out): + - Marlin 2 (Junction Deviation enabled): + - Skeleton - ```cpp - //#define CLASSIC_JERK - ``` + ```gcode + M205 J#JunctionDeviationValue + M500 + ``` + + Example: + + ```gcode + M205 J0.012 + M500 + ``` + + - To make the change permanent in firmware, set in `Configuration.h` and recompile: + + ```cpp + #define JUNCTION_DEVIATION_MM 0.012 // (mm) Distance from real junction edge + ``` + + Also ensure classic jerk is disabled if using junction deviation: + + ```cpp + //#define CLASSIC_JERK + ``` + + - Marlin Classic Jerk / Marlin Legacy: + - Skeleton — set the per-axis jerk limits using `M205` (X/Y optional depending on firmware build): + + ```gcode + M205 X#JerkX Y#JerkY + M500 + ``` + + Example: + + ```gcode + M205 X10 Y10 + M500 + ``` + + - RepRap (Duet / RepRapFirmware): + **IMPORTANT:** Set in mm/min so convert from mm/s to mm/min multiply by 60. + - Skeleton + + ```gcode + M566 X#max_instantaneous_change Y#max_instantaneous_change + M500 ; if supported by your board + ``` + + Example (Duet-style): + + ```gcode + M566 X3000 Y3000 + ``` + +> [!NOTE] +> RepRapFirmware exposes `M566` to set allowable instantaneous speed changes; some boards may persist settings with `M500` or via their web/config files. ## Credits - **Junction Deviation Machine Limit** [@RF47](https://github.com/RF47) -- **Junction Deviation Calibration** [@IanAlexis](https://github.com/IanAlexis) +- **Cornering Calibration** [@IanAlexis](https://github.com/IanAlexis) - **Fast tower model** [@RF47](https://github.com/RF47) +- **SCV-V2 model** [@chrisheib](https://www.thingiverse.com/chrisheib) diff --git a/doc/images/JunctionDeviation/jd_first_menu.png b/doc/images/JunctionDeviation/jd_first_menu.png index 8888e401d7..4283e0f4bd 100644 Binary files a/doc/images/JunctionDeviation/jd_first_menu.png and b/doc/images/JunctionDeviation/jd_first_menu.png differ diff --git a/doc/images/JunctionDeviation/jd_first_print_measure.jpg b/doc/images/JunctionDeviation/jd_first_print_measure.jpg index efff5efb3c..6438f3e31f 100644 Binary files a/doc/images/JunctionDeviation/jd_first_print_measure.jpg and b/doc/images/JunctionDeviation/jd_first_print_measure.jpg differ diff --git a/doc/images/JunctionDeviation/jd_printer_jerk_limitation.png b/doc/images/JunctionDeviation/jd_printer_jerk_limitation.png index a34e93d1d2..334dd39521 100644 Binary files a/doc/images/JunctionDeviation/jd_printer_jerk_limitation.png and b/doc/images/JunctionDeviation/jd_printer_jerk_limitation.png differ diff --git a/doc/images/JunctionDeviation/jd_second_menu.png b/doc/images/JunctionDeviation/jd_second_menu.png index 683b303f16..e4c860a16d 100644 Binary files a/doc/images/JunctionDeviation/jd_second_menu.png and b/doc/images/JunctionDeviation/jd_second_menu.png differ diff --git a/doc/images/JunctionDeviation/jd_second_print_measure.jpg b/doc/images/JunctionDeviation/jd_second_print_measure.jpg index 03706f0c35..5b76a1ba19 100644 Binary files a/doc/images/JunctionDeviation/jd_second_print_measure.jpg and b/doc/images/JunctionDeviation/jd_second_print_measure.jpg differ diff --git a/doc/images/calibration.png b/doc/images/calibration.png index ae43e04ef6..06a0454f62 100644 Binary files a/doc/images/calibration.png and b/doc/images/calibration.png differ diff --git a/doc/print_settings/speed/speed_settings_jerk_xy.md b/doc/print_settings/speed/speed_settings_jerk_xy.md index 3aaccc4a96..4fafcfe593 100644 --- a/doc/print_settings/speed/speed_settings_jerk_xy.md +++ b/doc/print_settings/speed/speed_settings_jerk_xy.md @@ -5,8 +5,15 @@ ## Cornering Control Types - **Jerk**: Traditional method, sets a maximum speed for direction changes. + - Klipper: [Square corner velocity](https://www.klipper3d.org/Config_Reference.html#printer) + - RepRapFirmware: [Maximum instantaneous speed changes](https://docs.duet3d.com/User_manual/Reference/Gcodes#m566-set-allowable-instantaneous-speed-change) + - Marlin 2: [Classic Jerk](https://marlinfw.org/docs/configuration/configuration.html#jerk-) (deprecated in favor of [Junction Deviation](https://marlinfw.org/docs/configuration/configuration.html#junction-deviation-)) but can still be used. + - Marlin Legacy: [Classic Jerk](https://marlinfw.org/docs/configuration/configuration.html#jerk-). - **[Junction Deviation](#junction-deviation)**: Modern method, calculates cornering speed based on acceleration and speed. +> [!TIP] +> Calibrate your Cornering Values using the [Cornering Calibration guide](cornering-calib). + ## Key Effects - **Corner Control**: Lower values = smoother corners, better quality. Higher values = faster cornering, potential artifacts @@ -16,7 +23,7 @@ This setting overrides firmware jerk values when different motion types need specific settings. Orca limits jerk to not exceed the Printer's Motion Ability settings. > [!TIP] -> Jerk can work in conjunction with [Pressure Advance](pressure-advance-calib), [Adaptive Pressure Advance](adaptive-pressure-advance-calib), and [Input Shaping](input-shaping-calib) to optimize print quality and speed. +> Jerk can work in conjunction with [Pressure Advance](pressure-advance-calib), [Adaptive Pressure Advance](adaptive-pressure-advance-calib), and [Input Shaping](input-shaping-calib) to optimize print quality and speed. > It's recommended to follow the [calibration guide](calibration) order for best results. - [Cornering Control Types](#cornering-control-types) @@ -64,12 +71,14 @@ Jerk for travel printing. This is usually set to a higher value than infill to r ## Junction Deviation -Alternative to Jerk, Junction Deviation is the default method for controlling cornering speed in MarlinFW (Marlin2) printers. +Alternative to Jerk, Junction Deviation is the default method for controlling cornering speed in Marlin 2 printers. Higher values result in more aggressive cornering speeds, while lower values produce smoother, more controlled cornering. -This value will **only be overwritten** if it is lower than the Junction Deviation value set in Printer settings > Motion ability. If it is higher, the value configured in Motion ability will be used. +> [!NOTE] +> Classic Jerk can still be used in Marlin 2, but it is deprecated in favor of Junction Deviation. +> If your printer uses Classic Jerk, you need to set your Junction Deviation to `0` to enable the use of Classic Jerk. -To Calculate your Junction Deviation value, please refer to the [Junction Deviation Calibration guide](cornering-calib#junction-deviation). +This value will **only be overwritten** if it is lower than the Junction Deviation value set in Printer settings > Motion ability. If it is higher, the value configured in Motion ability will be used. ```math JD = 0,4 \cdot \frac{\text{Jerk}^2}{\text{Accel.}} diff --git a/resources/calib/cornering/SCV-V2.stl b/resources/calib/cornering/SCV-V2.stl new file mode 100644 index 0000000000..e60a5a8261 Binary files /dev/null and b/resources/calib/cornering/SCV-V2.stl differ diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index c229b452fc..e3624e8bd9 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -4241,10 +4241,10 @@ LayerResult GCode::process_layer( } } else { if (print.calib_params().freqStartX == print.calib_params().freqStartY && print.calib_params().freqEndX == print.calib_params().freqEndY) { - gcode += writer().set_input_shaping('A', 0.f, (print.calib_params().freqStartX) + ((print.calib_params().freqEndX)-(print.calib_params().freqStartX)) * (m_layer_index - 2) / (m_layer_count - 3), ""); + gcode += writer().set_input_shaping('A', 0.f, this->interpolate_value_across_layers(print.calib_params().freqStartX, print.calib_params().freqEndX), ""); } else { - gcode += writer().set_input_shaping('X', 0.f, (print.calib_params().freqStartX) + ((print.calib_params().freqEndX)-(print.calib_params().freqStartX)) * (m_layer_index - 2) / (m_layer_count - 3), ""); - gcode += writer().set_input_shaping('Y', 0.f, (print.calib_params().freqStartY) + ((print.calib_params().freqEndY)-(print.calib_params().freqStartY)) * (m_layer_index - 2) / (m_layer_count - 3), ""); + gcode += writer().set_input_shaping('X', 0.f, this->interpolate_value_across_layers(print.calib_params().freqStartX, print.calib_params().freqEndX), ""); + gcode += writer().set_input_shaping('Y', 0.f, this->interpolate_value_across_layers(print.calib_params().freqStartY, print.calib_params().freqEndY), ""); } } break; @@ -4258,12 +4258,18 @@ LayerResult GCode::process_layer( gcode += writer().set_input_shaping('X', 0.f, print.calib_params().freqStartX, print.calib_params().shaper_type); gcode += writer().set_input_shaping('Y', 0.f, print.calib_params().freqStartY, print.calib_params().shaper_type); } else { - gcode += writer().set_input_shaping('A', print.calib_params().start + ((print.calib_params().end)-(print.calib_params().start)) * (m_layer_index) / (m_layer_count), 0.f, ""); + gcode += writer().set_input_shaping('A', this->interpolate_value_across_layers(print.calib_params().start, print.calib_params().end), 0.f, ""); } break; } - case CalibMode::Calib_Junction_Deviation: { - gcode += writer().set_junction_deviation(print.calib_params().start + ((print.calib_params().end)-(print.calib_params().start)) * (m_layer_index) / (m_layer_count)); + case CalibMode::Calib_Cornering: { + if (m_writer.get_gcode_flavor() == gcfMarlinFirmware && + !m_config.machine_max_junction_deviation.values.empty() && + m_config.machine_max_junction_deviation.values.front() > 0) { + gcode += writer().set_junction_deviation(this->interpolate_value_across_layers(print.calib_params().start, print.calib_params().end)); + } else { + gcode += writer().set_jerk_xy(this->interpolate_value_across_layers(print.calib_params().start, print.calib_params().end)); + } break; } } @@ -6680,6 +6686,17 @@ std::string GCode::extrusion_role_to_string_for_parser(const ExtrusionRole & rol } } +// Calculate the interpolated value for the current layer between start_value and end_value +float GCode::interpolate_value_across_layers(float start_value, float end_value) const { + if (m_layer_index == 1) { + return start_value; + } else { + float ratio = (m_layer_index - 2.0f) / (m_layer_count - 3.0f); + ratio = std::max(0.0f, std::min(1.0f, ratio)); // clamp + return start_value + ratio * (end_value - start_value); + } +} + std::string encodeBase64(uint64_t value) { //Always use big endian mode @@ -7523,7 +7540,6 @@ void GCode::ObjectByExtruder::Island::Region::append(const Type type, const Extr } } - // Index into std::vector, which contains Object and Support layers for the current print_z, collected for // a single object, or for possibly multiple objects with multiple instances. diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 795ea4472f..5e8dc8bdd1 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -236,6 +236,9 @@ public: bool enable_cooling_markers() const { return m_enable_cooling_markers; } std::string extrusion_role_to_string_for_parser(const ExtrusionRole &); + // Calculate the interpolated value for the current layer between start_value and end_value + float interpolate_value_across_layers(float start_value, float end_value) const; + // For Perl bindings, to be used exclusively by unit tests. unsigned int layer_count() const { return m_layer_count; } void set_layer_count(unsigned int value) { m_layer_count = value; } diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index ff445f426a..77179b5c5c 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -1655,7 +1655,7 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons* } } - // check junction deviation + // Check junction deviation const auto max_junction_deviation = m_config.machine_max_junction_deviation.values[0]; if (warning_key.empty() && m_default_object_config.default_junction_deviation.value > max_junction_deviation) { warning->string = L( "Junction deviation setting exceeds the printer's maximum value " diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index bcd970d824..c525c00755 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -4040,15 +4040,16 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionFloats(axis.max_jerk)); } } - // M205 J... [mm] machine junction deviation limits + // M205 J... [mm] machine junction deviation limits def = this->add("machine_max_junction_deviation", coFloats); def->full_label = L("Maximum Junction Deviation"); def->category = L("Machine limits"); - def->tooltip = L("Maximum junction deviation (M205 J, only apply if JD > 0 for Marlin Firmware)"); + def->tooltip = L("Maximum junction deviation (M205 J, only apply if JD > 0 for Marlin Firmware\nIf your Marlin 2 printer uses Classic Jerk set this value to 0.)"); def->sidetext = "mm"; // milimeters, don't need translation def->min = 0; + def->max = 1; def->mode = comAdvanced; - def->set_default_value(new ConfigOptionFloats{0. ,0. }); + def->set_default_value(new ConfigOptionFloats { 0.01}); // M205 S... [mm/sec] def = this->add("machine_min_extruding_rate", coFloats); diff --git a/src/libslic3r/calib.cpp b/src/libslic3r/calib.cpp index 1a0c1e04ed..4b3e05df8d 100644 --- a/src/libslic3r/calib.cpp +++ b/src/libslic3r/calib.cpp @@ -895,5 +895,4 @@ double CalibPressureAdvancePattern::pattern_shift() const return (wall_count() - 1) * line_spacing_first_layer() + line_width_first_layer() + m_glyph_padding_horizontal; } - } // namespace Slic3r diff --git a/src/libslic3r/calib.hpp b/src/libslic3r/calib.hpp index 1d78b6fca3..0128353643 100644 --- a/src/libslic3r/calib.hpp +++ b/src/libslic3r/calib.hpp @@ -26,7 +26,7 @@ enum class CalibMode : int { Calib_Retraction_tower, Calib_Input_shaping_freq, Calib_Input_shaping_damp, - Calib_Junction_Deviation + Calib_Cornering }; enum class CalibState { Start = 0, Preset, Calibration, CoarseSave, FineCalibration, Save, Finish }; diff --git a/src/slic3r/GUI/CalibrationWizardSavePage.cpp b/src/slic3r/GUI/CalibrationWizardSavePage.cpp index 2133a7b63a..9d1302032b 100644 --- a/src/slic3r/GUI/CalibrationWizardSavePage.cpp +++ b/src/slic3r/GUI/CalibrationWizardSavePage.cpp @@ -50,7 +50,7 @@ static wxString get_default_name(wxString filament_name, CalibMode mode){ break; case Slic3r::CalibMode::Calib_Input_shaping_damp: break; - case Slic3r::CalibMode::Calib_Junction_Deviation: + case Slic3r::CalibMode::Calib_Cornering: break; default: break; diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index bcfbecb9b3..8b2ffb48b7 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -663,12 +663,27 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co "top_surface_acceleration", "travel_acceleration", "bridge_acceleration", "sparse_infill_acceleration", "internal_solid_infill_acceleration"}) toggle_field(el, have_default_acceleration); - bool have_default_jerk = config->opt_float("default_jerk") > 0; - - for (auto el : { "outer_wall_jerk", "inner_wall_jerk", "initial_layer_jerk", "top_surface_jerk", "travel_jerk", "infill_jerk"}) - toggle_field(el, have_default_jerk); - + bool machine_supports_junction_deviation = false; + if (gcflavor == gcfMarlinFirmware) { + if (const auto *machine_jd = preset_bundle->printers.get_edited_preset().config.option("machine_max_junction_deviation")) { + machine_supports_junction_deviation = !machine_jd->values.empty() && machine_jd->values.front() > 0.0; + } + } toggle_line("default_junction_deviation", gcflavor == gcfMarlinFirmware); + if (machine_supports_junction_deviation) { + toggle_field("default_junction_deviation", true); + toggle_field("default_jerk", false); + for (auto el : { "outer_wall_jerk", "inner_wall_jerk", "initial_layer_jerk", "top_surface_jerk", "travel_jerk", "infill_jerk"}) + toggle_line(el, false); + } else { + toggle_field("default_junction_deviation", false); + toggle_field("default_jerk", true); + bool have_default_jerk = config->has("default_jerk") && config->opt_float("default_jerk") > 0; + for (auto el : { "outer_wall_jerk", "inner_wall_jerk", "initial_layer_jerk", "top_surface_jerk", "travel_jerk", "infill_jerk"}) { + toggle_line(el, true); + toggle_field(el, have_default_jerk); + } + } bool have_skirt = config->opt_int("skirt_loops") > 0; toggle_field("skirt_height", have_skirt && config->opt_enum("draft_shield") != dsEnabled); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 1ebbe06e7c..635549d97f 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -3071,36 +3071,32 @@ void MainFrame::init_menubar_as_editor() }, "", nullptr, [this]() {return m_plater->is_view3D_shown();; }, this); - // Cornering (with submenu) - auto cornering_menu = new wxMenu(); - append_menu_item( - cornering_menu, wxID_ANY, _L("Junction Deviation"), _L("Junction Deviation calibration"), + // Cornering + append_menu_item(m_topbar->GetCalibMenu(), wxID_ANY, _L("Cornering"), _L("Cornering calibration"), [this](wxCommandEvent&) { - if (!m_junction_deviation_calib_dlg) - m_junction_deviation_calib_dlg = new Junction_Deviation_Test_Dlg((wxWindow*)this, wxID_ANY, m_plater); - m_junction_deviation_calib_dlg->ShowModal(); - }, - "", nullptr, + auto dlg = new Cornering_Test_Dlg((wxWindow*)this, wxID_ANY, m_plater); + dlg->ShowModal(); + dlg->Destroy(); + }, "", nullptr, [this]() {return m_plater->is_view3D_shown();; }, this); - m_topbar->GetCalibMenu()->AppendSubMenu(cornering_menu, _L("Cornering")); // Input Shaping (with submenu) auto input_shaping_menu = new wxMenu(); append_menu_item( input_shaping_menu, wxID_ANY, _L("Input Shaping Frequency"), _L("Input Shaping Frequency"), [this](wxCommandEvent&) { - if (!m_IS_freq_calib_dlg) - m_IS_freq_calib_dlg = new Input_Shaping_Freq_Test_Dlg((wxWindow*)this, wxID_ANY, m_plater); - m_IS_freq_calib_dlg->ShowModal(); + auto dlg = new Input_Shaping_Freq_Test_Dlg((wxWindow*)this, wxID_ANY, m_plater); + dlg->ShowModal(); + dlg->Destroy(); }, "", nullptr, [this]() {return m_plater->is_view3D_shown();; }, this); append_menu_item( input_shaping_menu, wxID_ANY, _L("Input Shaping Damping/zeta factor"), _L("Input Shaping Damping/zeta factor"), [this](wxCommandEvent&) { - if (!m_IS_damp_calib_dlg) - m_IS_damp_calib_dlg = new Input_Shaping_Damp_Test_Dlg((wxWindow*)this, wxID_ANY, m_plater); - m_IS_damp_calib_dlg->ShowModal(); + auto dlg = new Input_Shaping_Damp_Test_Dlg((wxWindow*)this, wxID_ANY, m_plater); + dlg->ShowModal(); + dlg->Destroy(); }, "", nullptr, [this]() {return m_plater->is_view3D_shown();; }, this); @@ -3193,36 +3189,32 @@ void MainFrame::init_menubar_as_editor() }, "", nullptr, [this]() {return m_plater->is_view3D_shown();; }, this); - // Cornering (with submenu) - auto cornering_menu = new wxMenu(); - append_menu_item( - cornering_menu, wxID_ANY, _L("Junction Deviation"), _L("Junction Deviation calibration"), + // Cornering + append_menu_item(calib_menu, wxID_ANY, _L("Cornering"), _L("Cornering calibration"), [this](wxCommandEvent&) { - if (!m_junction_deviation_calib_dlg) - m_junction_deviation_calib_dlg = new Junction_Deviation_Test_Dlg((wxWindow*)this, wxID_ANY, m_plater); - m_junction_deviation_calib_dlg->ShowModal(); - }, - "", nullptr, + auto dlg = new Cornering_Test_Dlg((wxWindow*)this, wxID_ANY, m_plater); + dlg->ShowModal(); + dlg->Destroy(); + }, "", nullptr, [this]() {return m_plater->is_view3D_shown();; }, this); - calib_menu->AppendSubMenu(cornering_menu, _L("Cornering")); // Input Shaping (with submenu) auto input_shaping_menu = new wxMenu(); append_menu_item( input_shaping_menu, wxID_ANY, _L("Input Shaping Frequency"), _L("Input Shaping Frequency"), [this](wxCommandEvent&) { - if (!m_IS_freq_calib_dlg) - m_IS_freq_calib_dlg = new Input_Shaping_Freq_Test_Dlg((wxWindow*)this, wxID_ANY, m_plater); - m_IS_freq_calib_dlg->ShowModal(); + auto dlg = new Input_Shaping_Freq_Test_Dlg((wxWindow*)this, wxID_ANY, m_plater); + dlg->ShowModal(); + dlg->Destroy(); }, "", nullptr, [this]() {return m_plater->is_view3D_shown();; }, this); append_menu_item( input_shaping_menu, wxID_ANY, _L("Input Shaping Damping/zeta factor"), _L("Input Shaping Damping/zeta factor"), [this](wxCommandEvent&) { - if (!m_IS_damp_calib_dlg) - m_IS_damp_calib_dlg = new Input_Shaping_Damp_Test_Dlg((wxWindow*)this, wxID_ANY, m_plater); - m_IS_damp_calib_dlg->ShowModal(); + auto dlg = new Input_Shaping_Damp_Test_Dlg((wxWindow*)this, wxID_ANY, m_plater); + dlg->ShowModal(); + dlg->Destroy(); }, "", nullptr, [this]() {return m_plater->is_view3D_shown();; }, this); diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index 4cb3044a40..e69a95da0c 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -364,7 +364,7 @@ public: Retraction_Test_Dlg* m_retraction_calib_dlg{ nullptr }; Input_Shaping_Freq_Test_Dlg* m_IS_freq_calib_dlg{ nullptr }; Input_Shaping_Damp_Test_Dlg* m_IS_damp_calib_dlg{ nullptr }; - Junction_Deviation_Test_Dlg* m_junction_deviation_calib_dlg{ nullptr }; + Cornering_Test_Dlg* m_cornering_calib_dlg{ nullptr }; // BBS. Replace title bar and menu bar with top bar. BBLTopbar* m_topbar{ nullptr }; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 65cd061a12..5cc1c21c62 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -853,6 +853,20 @@ struct DynamicFilamentList1Based : DynamicFilamentList }; +// Check if the machine supports Junction Deviation (Marlin firmware with machine_max_junction_deviation > 0) +static bool has_junction_deviation(const DynamicPrintConfig* printer_config) +{ + if (!printer_config) { + return false; + } + const auto gcode_flavor = printer_config->option>("gcode_flavor"); + const auto junction_dev = printer_config->option("machine_max_junction_deviation"); + return gcode_flavor && + gcode_flavor->value == GCodeFlavor::gcfMarlinFirmware && + junction_dev && + !junction_dev->values.empty() && + junction_dev->values.front() > 0.0; +} static DynamicFilamentList dynamic_filament_list; static DynamicFilamentList1Based dynamic_filament_list_1_based; @@ -11635,7 +11649,7 @@ void Plater::_calib_pa_pattern(const Calib_Params& params) print_config.set_key_value( "print_sequence", new ConfigOptionEnum(PrintSequence::ByLayer)); //Orca: find jerk value to use in the test - if(print_config.option("default_jerk")->value > 0){ // we have set a jerk value + if(!has_junction_deviation(printer_config) && print_config.option("default_jerk")->value > 0){ // we have set a jerk value auto jerk = print_config.option("outer_wall_jerk")->value; // get outer wall jerk if (jerk == 0) // if outer wall jerk is not defined, get inner wall jerk jerk = print_config.option("inner_wall_jerk")->value; @@ -11651,7 +11665,11 @@ void Plater::_calib_pa_pattern(const Calib_Params& params) print_config.set_key_value( "infill_jerk", new ConfigOptionFloat(jerk)); print_config.set_key_value( "travel_jerk", new ConfigOptionFloat(jerk)); } - + + if (has_junction_deviation(printer_config)){ + print_config.set_key_value("default_junction_deviation", new ConfigOptionFloat(0)); + } + for (const auto& opt : SuggestedConfigCalibPAPattern().float_pairs) { print_config.set_key_value( opt.first, @@ -12313,27 +12331,15 @@ void Plater::calib_input_shaping_freq(const Calib_Params& params) auto filament_config = &wxGetApp().preset_bundle->filaments.get_edited_preset().config; auto printer_config = &wxGetApp().preset_bundle->printers.get_edited_preset().config; const auto gcode_flavor_option = printer_config->option>("gcode_flavor"); - float junction_deviation_value = 0.f; - if (gcode_flavor_option && gcode_flavor_option->value == GCodeFlavor::gcfMarlinFirmware) { - const auto machine_junction_option = printer_config->option("machine_max_junction_deviation"); - const float current = (machine_junction_option && !machine_junction_option->values.empty()) - ? machine_junction_option->values.front() - : 0.f; - junction_deviation_value = std::max(current, 0.25f); + if (has_junction_deviation(printer_config)) { + printer_config->set_key_value("machine_max_junction_deviation", new ConfigOptionFloats {(std::max(printer_config->option("machine_max_junction_deviation")->values.front(), 0.25))}); + print_config->set_key_value("default_junction_deviation", new ConfigOptionFloat(0)); + } else { + const double jerk_value = (gcode_flavor_option && gcode_flavor_option->value == GCodeFlavor::gcfKlipper) ? 5.0 : 10.0; + printer_config->set_key_value("machine_max_jerk_x", new ConfigOptionFloats{std::max(printer_config->option("machine_max_jerk_x")->values.front(), jerk_value)}); + printer_config->set_key_value("machine_max_jerk_y", new ConfigOptionFloats{std::max(printer_config->option("machine_max_jerk_y")->values.front(), jerk_value)}); + print_config->set_key_value("default_jerk", new ConfigOptionFloat(0)); } - float machine_max_jerk_x = 0.f; - if (const auto option = printer_config->option("machine_max_jerk_x"); - option != nullptr && !option->values.empty()) { - machine_max_jerk_x = option->values.front(); - } - float machine_max_jerk_y = 0.f; - if (const auto option = printer_config->option("machine_max_jerk_y"); - option != nullptr && !option->values.empty()) { - machine_max_jerk_y = option->values.front(); - } - const float jerk_value = std::max((gcode_flavor_option && gcode_flavor_option->value == GCodeFlavor::gcfKlipper) ? 5.f : 10.f, - std::min(machine_max_jerk_x, machine_max_jerk_y)); - printer_config->set_key_value("machine_max_junction_deviation", new ConfigOptionFloats {junction_deviation_value}); printer_config->set_key_value("resonance_avoidance", new ConfigOptionBool{false}); filament_config->set_key_value("slow_down_layer_time", new ConfigOptionFloats { 0.0 }); filament_config->set_key_value("slow_down_min_speed", new ConfigOptionFloats { 0.0 }); @@ -12355,9 +12361,6 @@ void Plater::calib_input_shaping_freq(const Calib_Params& params) print_config->set_key_value("outer_wall_speed", new ConfigOptionFloat(200)); print_config->set_key_value("default_acceleration", new ConfigOptionFloat(20000)); print_config->set_key_value("outer_wall_acceleration", new ConfigOptionFloat(20000)); - print_config->set_key_value("default_jerk", new ConfigOptionFloat(jerk_value)); - print_config->set_key_value("outer_wall_jerk", new ConfigOptionFloat(jerk_value)); - print_config->set_key_value("default_junction_deviation", new ConfigOptionFloat(junction_deviation_value)); model().objects[0]->config.set_key_value("brim_type", new ConfigOptionEnum(btOuterOnly)); model().objects[0]->config.set_key_value("brim_width", new ConfigOptionFloat(3.0)); model().objects[0]->config.set_key_value("brim_object_gap", new ConfigOptionFloat(0.0)); @@ -12384,27 +12387,15 @@ void Plater::calib_input_shaping_damp(const Calib_Params& params) auto filament_config = &wxGetApp().preset_bundle->filaments.get_edited_preset().config; auto printer_config = &wxGetApp().preset_bundle->printers.get_edited_preset().config; const auto gcode_flavor_option = printer_config->option>("gcode_flavor"); - float junction_deviation_value = 0.f; - if (gcode_flavor_option && gcode_flavor_option->value == GCodeFlavor::gcfMarlinFirmware) { - const auto machine_junction_option = printer_config->option("machine_max_junction_deviation"); - const float current = (machine_junction_option && !machine_junction_option->values.empty()) - ? machine_junction_option->values.front() - : 0.f; - junction_deviation_value = std::max(current, 0.25f); + if (has_junction_deviation(printer_config)) { + printer_config->set_key_value("machine_max_junction_deviation", new ConfigOptionFloats {(std::max(printer_config->option("machine_max_junction_deviation")->values.front(), 0.25))}); + print_config->set_key_value("default_junction_deviation", new ConfigOptionFloat(0)); + } else { + const double jerk_value = (gcode_flavor_option && gcode_flavor_option->value == GCodeFlavor::gcfKlipper) ? 5.0 : 10.0; + printer_config->set_key_value("machine_max_jerk_x", new ConfigOptionFloats{std::max(printer_config->option("machine_max_jerk_x")->values.front(), jerk_value)}); + printer_config->set_key_value("machine_max_jerk_y", new ConfigOptionFloats{std::max(printer_config->option("machine_max_jerk_y")->values.front(), jerk_value)}); + print_config->set_key_value("default_jerk", new ConfigOptionFloat(0)); } - float machine_max_jerk_x = 0.f; - if (const auto option = printer_config->option("machine_max_jerk_x"); - option != nullptr && !option->values.empty()) { - machine_max_jerk_x = option->values.front(); - } - float machine_max_jerk_y = 0.f; - if (const auto option = printer_config->option("machine_max_jerk_y"); - option != nullptr && !option->values.empty()) { - machine_max_jerk_y = option->values.front(); - } - const float jerk_value = std::max((gcode_flavor_option && gcode_flavor_option->value == GCodeFlavor::gcfKlipper) ? 5.f : 10.f, - std::min(machine_max_jerk_x, machine_max_jerk_y)); - printer_config->set_key_value("machine_max_junction_deviation", new ConfigOptionFloats{junction_deviation_value}); printer_config->set_key_value("resonance_avoidance", new ConfigOptionBool{false}); filament_config->set_key_value("slow_down_layer_time", new ConfigOptionFloats { 0.0 }); filament_config->set_key_value("slow_down_min_speed", new ConfigOptionFloats { 0.0 }); @@ -12426,9 +12417,6 @@ void Plater::calib_input_shaping_damp(const Calib_Params& params) print_config->set_key_value("outer_wall_speed", new ConfigOptionFloat(200)); print_config->set_key_value("default_acceleration", new ConfigOptionFloat(20000)); print_config->set_key_value("outer_wall_acceleration", new ConfigOptionFloat(20000)); - print_config->set_key_value("default_jerk", new ConfigOptionFloat(jerk_value)); - print_config->set_key_value("outer_wall_jerk", new ConfigOptionFloat(jerk_value)); - print_config->set_key_value("default_junction_deviation", new ConfigOptionFloat(junction_deviation_value)); model().objects[0]->config.set_key_value("brim_type", new ConfigOptionEnum(btOuterOnly)); model().objects[0]->config.set_key_value("brim_width", new ConfigOptionFloat(3.0)); model().objects[0]->config.set_key_value("brim_object_gap", new ConfigOptionFloat(0.0)); @@ -12442,19 +12430,29 @@ void Plater::calib_input_shaping_damp(const Calib_Params& params) p->background_process.fff_print()->set_calib_params(params); } -void Plater::calib_junction_deviation(const Calib_Params& params) +void Plater::Calib_Cornering(const Calib_Params& params) { - const auto calib_junction_deviation = wxString::Format(L"Junction Deviation test"); - new_project(false, false, calib_junction_deviation); + const auto Calib_Cornering = wxString::Format(L"Cornering test"); + new_project(false, false, Calib_Cornering); wxGetApp().mainframe->select_tab(size_t(MainFrame::tp3DEditor)); - if (params.mode != CalibMode::Calib_Junction_Deviation) + if (params.mode != CalibMode::Calib_Cornering) return; - add_model(false, Slic3r::resources_dir() + (params.test_model < 1 ? "/calib/input_shaping/ringing_tower.stl" : "/calib/input_shaping/fast_tower_test.stl")); + const std::string cornering_model_path = params.test_model == 0 + ? "/calib/input_shaping/ringing_tower.stl" + : (params.test_model == 1 ? "/calib/input_shaping/fast_tower_test.stl" : "/calib/cornering/SCV-V2.stl"); + add_model(false, Slic3r::resources_dir() + cornering_model_path); auto print_config = &wxGetApp().preset_bundle->prints.get_edited_preset().config; auto filament_config = &wxGetApp().preset_bundle->filaments.get_edited_preset().config; auto printer_config = &wxGetApp().preset_bundle->printers.get_edited_preset().config; - printer_config->set_key_value("machine_max_junction_deviation", new ConfigOptionFloats{1.0}); + if (has_junction_deviation(printer_config)) { + printer_config->set_key_value("machine_max_junction_deviation", new ConfigOptionFloats{params.end}); + print_config->set_key_value("default_junction_deviation", new ConfigOptionFloat(0.0)); + } else { + printer_config->set_key_value("machine_max_jerk_x", new ConfigOptionFloats{params.end}); + printer_config->set_key_value("machine_max_jerk_y", new ConfigOptionFloats{params.end}); + print_config->set_key_value("default_jerk", new ConfigOptionFloat(0)); + } printer_config->set_key_value("resonance_avoidance", new ConfigOptionBool{false}); filament_config->set_key_value("slow_down_layer_time", new ConfigOptionFloats { 0.0 }); filament_config->set_key_value("slow_down_min_speed", new ConfigOptionFloats { 0.0 }); @@ -12477,8 +12475,6 @@ void Plater::calib_junction_deviation(const Calib_Params& params) print_config->set_key_value("outer_wall_speed", new ConfigOptionFloat(200)); print_config->set_key_value("default_acceleration", new ConfigOptionFloat(2000)); print_config->set_key_value("outer_wall_acceleration", new ConfigOptionFloat(2000)); - print_config->set_key_value("default_jerk", new ConfigOptionFloat(0)); - print_config->set_key_value("default_junction_deviation", new ConfigOptionFloat(0.0)); model().objects[0]->config.set_key_value("brim_type", new ConfigOptionEnum(btOuterOnly)); model().objects[0]->config.set_key_value("brim_width", new ConfigOptionFloat(3.0)); model().objects[0]->config.set_key_value("brim_object_gap", new ConfigOptionFloat(0.0)); @@ -12488,7 +12484,7 @@ void Plater::calib_junction_deviation(const Calib_Params& params) wxGetApp().get_tab(Preset::TYPE_FILAMENT)->update_dirty(); wxGetApp().get_tab(Preset::TYPE_PRINT)->update_ui_from_settings(); wxGetApp().get_tab(Preset::TYPE_FILAMENT)->update_ui_from_settings(); - + p->background_process.fff_print()->set_calib_params(params); } diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index b110e46bbe..412ad275c3 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -333,7 +333,7 @@ public: void calib_VFA(const Calib_Params& params); void calib_input_shaping_freq(const Calib_Params& params); void calib_input_shaping_damp(const Calib_Params& params); - void calib_junction_deviation(const Calib_Params& params); + void Calib_Cornering(const Calib_Params& params); BuildVolume_Type get_build_volume_type() const; diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index a65010168f..8c242e197d 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -56,6 +56,8 @@ #include #endif // WIN32 +#include + namespace Slic3r { t_config_option_keys deep_diff(const ConfigBase &config_this, const ConfigBase &config_other, bool strict = true); @@ -2504,6 +2506,7 @@ void TabPrint::build() optgroup->append_single_option_line("accel_to_decel_factor", "speed_settings_acceleration"); optgroup = page->new_optgroup(L("Jerk(XY)"), L"param_jerk", 15); + optgroup->append_single_option_line("default_junction_deviation", "speed_settings_jerk_xy#junction-deviation"); optgroup->append_single_option_line("default_jerk", "speed_settings_jerk_xy#default"); optgroup->append_single_option_line("outer_wall_jerk", "speed_settings_jerk_xy#outer-wall"); optgroup->append_single_option_line("inner_wall_jerk", "speed_settings_jerk_xy#inner-wall"); @@ -2511,7 +2514,6 @@ void TabPrint::build() optgroup->append_single_option_line("top_surface_jerk", "speed_settings_jerk_xy#top-surface"); optgroup->append_single_option_line("initial_layer_jerk", "speed_settings_jerk_xy#initial-layer"); optgroup->append_single_option_line("travel_jerk", "speed_settings_jerk_xy#travel"); - optgroup->append_single_option_line("default_junction_deviation", "speed_settings_jerk_xy#junction-deviation"); optgroup = page->new_optgroup(L("Advanced"), L"param_advanced", 15); optgroup->append_single_option_line("max_volumetric_extrusion_rate_slope", "speed_settings_advanced"); @@ -4603,12 +4605,12 @@ PageShp TabPrinter::build_kinematics_page() append_option_line(optgroup, "machine_max_acceleration_travel"); optgroup = page->new_optgroup(L("Jerk limitation"), "param_jerk"); + // machine max junction deviation + append_option_line(optgroup, "machine_max_junction_deviation"); for (const std::string &axis : axes) { append_option_line(optgroup, "machine_max_jerk_" + axis); } - // machine max junction deviation - append_option_line(optgroup, "machine_max_junction_deviation"); //optgroup = page->new_optgroup(L("Minimum feedrates")); // append_option_line(optgroup, "machine_min_extruding_rate"); // append_option_line(optgroup, "machine_min_travel_rate"); @@ -5186,6 +5188,24 @@ void TabPrinter::toggle_options() toggle_option("machine_max_junction_deviation", gcf == gcfMarlinFirmware, i); toggle_line("machine_max_junction_deviation", gcf == gcfMarlinFirmware); + // Check if junction deviation value is non-zero and firmware is Marlin + bool enable_jerk = gcf != gcfMarlinFirmware; + if (gcf == gcfMarlinFirmware) { + const auto *junction_deviation = m_config->option("machine_max_junction_deviation"); + if (junction_deviation != nullptr) { + const auto &values = junction_deviation->values; + enable_jerk = std::all_of(values.begin(), values.end(), [](double val) { return val == 0.0; }); + } else { + enable_jerk = true; + } + } + for (int i = 0; i < max_field; ++i) { + toggle_option("machine_max_jerk_x", enable_jerk, i); + toggle_option("machine_max_jerk_y", enable_jerk, i); + toggle_option("machine_max_jerk_z", enable_jerk, i); + toggle_option("machine_max_jerk_e", enable_jerk, i); + } + bool resonance_avoidance = m_config->opt_bool("resonance_avoidance"); toggle_option("min_resonance_avoidance_speed", resonance_avoidance); toggle_option("max_resonance_avoidance_speed", resonance_avoidance); diff --git a/src/slic3r/GUI/calib_dlg.cpp b/src/slic3r/GUI/calib_dlg.cpp index 11873a2bd4..f9d42bc19f 100644 --- a/src/slic3r/GUI/calib_dlg.cpp +++ b/src/slic3r/GUI/calib_dlg.cpp @@ -173,6 +173,20 @@ PA_Calibration_Dlg::PA_Calibration_Dlg(wxWindow* parent, wxWindowID id, Plater* v_sizer->Add(settings_sizer, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10)); v_sizer->AddSpacer(FromDIP(5)); + // Help links + auto help_sizer = new wxBoxSizer(wxVERTICAL); + auto help_link_pa = new wxHyperlinkCtrl(this, wxID_ANY, _L("Pressure Advance Guide"), + "https://github.com/SoftFever/OrcaSlicer/wiki/pressure-advance-calib"); + help_link_pa->SetForegroundColour(wxColour("#1890FF")); + help_sizer->Add(help_link_pa, 0, wxALL, FromDIP(5)); + + auto help_link_apa = new wxHyperlinkCtrl(this, wxID_ANY, _L("Adaptive Pressure Advance Guide"), + "https://github.com/SoftFever/OrcaSlicer/wiki/adaptive-pressure-advance-calib"); + help_link_apa->SetForegroundColour(wxColour("#1890FF")); + help_sizer->Add(help_link_apa, 0, wxALL, FromDIP(5)); + + v_sizer->Add(help_sizer, 0, wxALL, FromDIP(10)); + auto dlg_btns = new DialogButtons(this, {"OK"}); v_sizer->Add(dlg_btns , 0, wxEXPAND); @@ -372,6 +386,11 @@ Temp_Calibration_Dlg::Temp_Calibration_Dlg(wxWindow* parent, wxWindowID id, Plat v_sizer->Add(settings_sizer, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10)); v_sizer->AddSpacer(FromDIP(5)); + auto help_link = new wxHyperlinkCtrl(this, wxID_ANY, _L("Wiki Guide: Temperature Calibration"), + "https://github.com/SoftFever/OrcaSlicer/wiki/temp-calib"); + help_link->SetForegroundColour(wxColour("#1890FF")); + v_sizer->Add(help_link, 0, wxALL, FromDIP(10)); + auto dlg_btns = new DialogButtons(this, {"OK"}); v_sizer->Add(dlg_btns , 0, wxEXPAND); @@ -546,6 +565,11 @@ MaxVolumetricSpeed_Test_Dlg::MaxVolumetricSpeed_Test_Dlg(wxWindow* parent, wxWin v_sizer->Add(settings_sizer, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10)); v_sizer->AddSpacer(FromDIP(5)); + auto help_link = new wxHyperlinkCtrl(this, wxID_ANY, _L("Wiki Guide: Volumetric Speed Calibration"), + "https://github.com/SoftFever/OrcaSlicer/wiki/volumetric-speed-calib"); + help_link->SetForegroundColour(wxColour("#1890FF")); + v_sizer->Add(help_link, 0, wxALL, FromDIP(10)); + auto dlg_btns = new DialogButtons(this, {"OK"}); v_sizer->Add(dlg_btns , 0, wxEXPAND); @@ -647,6 +671,11 @@ VFA_Test_Dlg::VFA_Test_Dlg(wxWindow* parent, wxWindowID id, Plater* plater) v_sizer->Add(settings_sizer, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10)); v_sizer->AddSpacer(FromDIP(5)); + auto help_link = new wxHyperlinkCtrl(this, wxID_ANY, _L("Wiki Guide: VFA"), + "https://github.com/SoftFever/OrcaSlicer/wiki/vfa-calib"); + help_link->SetForegroundColour(wxColour("#1890FF")); + v_sizer->Add(help_link, 0, wxALL, FromDIP(10)); + auto dlg_btns = new DialogButtons(this, {"OK"}); v_sizer->Add(dlg_btns , 0, wxEXPAND); @@ -749,6 +778,11 @@ Retraction_Test_Dlg::Retraction_Test_Dlg(wxWindow* parent, wxWindowID id, Plater v_sizer->Add(settings_sizer, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10)); v_sizer->AddSpacer(FromDIP(5)); + auto help_link = new wxHyperlinkCtrl(this, wxID_ANY, _L("Wiki Guide: Retraction Calibration"), + "https://github.com/SoftFever/OrcaSlicer/wiki/retraction-calib"); + help_link->SetForegroundColour(wxColour("#1890FF")); + v_sizer->Add(help_link, 0, wxALL, FromDIP(10)); + auto dlg_btns = new DialogButtons(this, {"OK"}); v_sizer->Add(dlg_btns , 0, wxEXPAND); @@ -921,6 +955,11 @@ Input_Shaping_Freq_Test_Dlg::Input_Shaping_Freq_Test_Dlg(wxWindow* parent, wxWin v_sizer->Add(settings_sizer, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10)); v_sizer->AddSpacer(FromDIP(5)); + auto help_link = new wxHyperlinkCtrl(this, wxID_ANY, _L("Wiki Guide: Input Shaping Calibration"), + "https://github.com/SoftFever/OrcaSlicer/wiki/input-shaping-calib"); + help_link->SetForegroundColour(wxColour("#1890FF")); + v_sizer->Add(help_link, 0, wxALL, FromDIP(10)); + auto dlg_btns = new DialogButtons(this, {"OK"}); v_sizer->Add(dlg_btns , 0, wxEXPAND); @@ -1113,6 +1152,11 @@ Input_Shaping_Damp_Test_Dlg::Input_Shaping_Damp_Test_Dlg(wxWindow* parent, wxWin v_sizer->Add(settings_sizer, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10)); v_sizer->AddSpacer(FromDIP(5)); + auto help_link = new wxHyperlinkCtrl(this, wxID_ANY, _L("Wiki Guide: Input Shaping Calibration"), + "https://github.com/SoftFever/OrcaSlicer/wiki/input-shaping-calib"); + help_link->SetForegroundColour(wxColour("#1890FF")); + v_sizer->Add(help_link, 0, wxALL, FromDIP(10)); + auto dlg_btns = new DialogButtons(this, {"OK"}); v_sizer->Add(dlg_btns , 0, wxEXPAND); @@ -1185,11 +1229,11 @@ void Input_Shaping_Damp_Test_Dlg::on_dpi_changed(const wxRect& suggested_rect) { Fit(); } -// Junction_Deviation_Test_Dlg +// Cornering_Test_Dlg // -Junction_Deviation_Test_Dlg::Junction_Deviation_Test_Dlg(wxWindow* parent, wxWindowID id, Plater* plater) - : DPIDialog(parent, id, _L("Junction Deviation test"), wxDefaultPosition, parent->FromDIP(wxSize(-1, 280)), wxDEFAULT_DIALOG_STYLE), m_plater(plater) +Cornering_Test_Dlg::Cornering_Test_Dlg(wxWindow* parent, wxWindowID id, Plater* plater) + : DPIDialog(parent, id, _L("Cornering test"), wxDefaultPosition, parent->FromDIP(wxSize(-1, 280)), wxDEFAULT_DIALOG_STYLE), m_plater(plater) { SetBackgroundColour(*wxWHITE); // make sure background color set for dialog SetForegroundColour(wxColour("#363636")); @@ -1202,56 +1246,112 @@ Junction_Deviation_Test_Dlg::Junction_Deviation_Test_Dlg(wxWindow* parent, wxWin auto labeled_box_model = new LabeledStaticBox(this, _L("Test model")); auto model_box = new wxStaticBoxSizer(labeled_box_model, wxHORIZONTAL); - m_rbModel = new RadioGroup(this, { _L("Ringing Tower"), _L("Fast Tower") }, wxHORIZONTAL); + m_rbModel = new RadioGroup(this, { _L("Ringing Tower"), _L("Fast Tower"), _L("SCV-V2") }, wxHORIZONTAL); model_box->Add(m_rbModel, 0, wxALL | wxEXPAND, FromDIP(4)); v_sizer->Add(model_box, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10)); // Settings - wxString start_jd_str = _L("Start junction deviation: "); - wxString end_jd_str = _L("End junction deviation: "); - int text_max = GetTextMax(this, std::vector{start_jd_str, end_jd_str}); + wxString start_jd_str = _L("Start: "); + wxString end_jd_str = _L("End: "); - auto st_size = FromDIP(wxSize(text_max, -1)); - auto ti_size = FromDIP(wxSize(120, -1)); - - LabeledStaticBox* stb = new LabeledStaticBox(this, _L("Junction Deviation settings")); + LabeledStaticBox* stb = new LabeledStaticBox(this, _L("Cornering settings")); wxStaticBoxSizer* settings_sizer = new wxStaticBoxSizer(stb, wxVERTICAL); settings_sizer->AddSpacer(FromDIP(5)); - // Start junction deviation + // Detect GCode Flavor and set appropriate values and units + const auto* preset_bundle = wxGetApp().preset_bundle; + const auto* gcode_flavor_option = (preset_bundle != nullptr) + ? preset_bundle->printers.get_edited_preset().config.option>("gcode_flavor") + : nullptr; + + wxString start_value_str; + wxString end_value_str; + wxString units_str; + + if (gcode_flavor_option && + gcode_flavor_option->value == GCodeFlavor::gcfMarlinFirmware && + preset_bundle->printers.get_edited_preset().config.option("machine_max_junction_deviation") && + !preset_bundle->printers.get_edited_preset().config.option("machine_max_junction_deviation")->values.empty() && + preset_bundle->printers.get_edited_preset().config.option("machine_max_junction_deviation")->values[0] > 0) { + // Using Junction Deviation (mm) + start_value_str = wxString::Format("%.3f", 0.000); + end_value_str = wxString::Format("%.3f", 0.250); + units_str = "mm"; + } else { + // Using Classic Jerk (mm/s) + start_value_str = wxString::Format("%.3f", 1.0); + end_value_str = wxString::Format("%.3f", 15.0); + units_str = "mm/s"; + } + + auto ti_size = FromDIP(wxSize(120, -1)); + + // Start and End cornering on same row + auto cornering_row_sizer = new wxBoxSizer(wxHORIZONTAL); + + // Start cornering auto start_jd_sizer = new wxBoxSizer(wxHORIZONTAL); - auto start_jd_text = new wxStaticText(this, wxID_ANY, start_jd_str, wxDefaultPosition, st_size, wxALIGN_LEFT); - m_tiJDStart = new TextInput(this, wxString::Format("%.3f", 0.000), "mm", "", wxDefaultPosition, ti_size); + auto start_jd_text = new wxStaticText(this, wxID_ANY, start_jd_str, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); + m_tiJDStart = new TextInput(this, start_value_str, units_str, "", wxDefaultPosition, ti_size); m_tiJDStart->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC)); start_jd_sizer->Add(start_jd_text, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2)); start_jd_sizer->Add(m_tiJDStart , 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2)); - settings_sizer->Add(start_jd_sizer, 0, wxLEFT, FromDIP(3)); + cornering_row_sizer->Add(start_jd_sizer, 0, wxLEFT, FromDIP(3)); - // End junction deviation + // End cornering auto end_jd_sizer = new wxBoxSizer(wxHORIZONTAL); - auto end_jd_text = new wxStaticText(this, wxID_ANY, end_jd_str, wxDefaultPosition, st_size, wxALIGN_LEFT); - m_tiJDEnd = new TextInput(this, wxString::Format("%.3f", 0.250), "mm", "", wxDefaultPosition, ti_size); + auto end_jd_text = new wxStaticText(this, wxID_ANY, end_jd_str, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); + m_tiJDEnd = new TextInput(this, end_value_str, units_str, "", wxDefaultPosition, ti_size); m_tiJDEnd->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC)); end_jd_sizer->Add(end_jd_text, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2)); - end_jd_sizer->Add(m_tiJDEnd , 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2)); - settings_sizer->Add(end_jd_sizer, 0, wxLEFT, FromDIP(3)); + end_jd_sizer->Add(m_tiJDEnd , 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2)); + cornering_row_sizer->Add(end_jd_sizer, 0, wxLEFT, FromDIP(3)); + + settings_sizer->Add(cornering_row_sizer, 0, wxLEFT, FromDIP(3)); settings_sizer->AddSpacer(FromDIP(5)); - // Add note about junction deviation - auto note_text = new wxStaticText(this, wxID_ANY, _L("Note: Lower values = sharper corners but slower speeds"), + // Add note about cornering based on GCode Flavor + wxString note_msg = _L("Note: Lower values = sharper corners but slower speeds.\n"); + if (gcode_flavor_option) { + switch (gcode_flavor_option->value) { + case GCodeFlavor::gcfMarlinFirmware: { + // Check if machine_max_junction_deviation is set and > 0 + const auto* max_jd_option = preset_bundle->printers.get_edited_preset().config.option("machine_max_junction_deviation"); + if (max_jd_option && !max_jd_option->values.empty() && max_jd_option->values[0] > 0) { + note_msg += _L("Marlin 2 Junction Deviation detected:\nTo test Classic Jerk, set 'Maximum Junction Deviation' in Motion ability to 0."); + } else { + note_msg += _L("Marlin 2 Classic Jerk detected:\nTo test Junction Deviation, set 'Maximum Junction Deviation' in Motion ability to a value > 0."); + } + break; + } + case GCodeFlavor::gcfRepRapFirmware: + note_msg += _L("RepRap detected: Jerk in mm/s.\nOrcaSlicer will convert the values to mm/min when necessary."); + break; + default: + break; + } + } + + auto note_text = new wxStaticText(this, wxID_ANY, note_msg, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT); note_text->SetForegroundColour(wxColour(128, 128, 128)); + note_text->Wrap(FromDIP(300)); settings_sizer->Add(note_text, 0, wxALL, FromDIP(5)); v_sizer->Add(settings_sizer, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10)); v_sizer->AddSpacer(FromDIP(5)); + auto help_link = new wxHyperlinkCtrl(this, wxID_ANY, _L("Wiki Guide: Cornering Calibration"), + "https://github.com/SoftFever/OrcaSlicer/wiki/cornering-calib"); + help_link->SetForegroundColour(wxColour("#1890FF")); + v_sizer->Add(help_link, 0, wxALL, FromDIP(10)); + auto dlg_btns = new DialogButtons(this, {"OK"}); v_sizer->Add(dlg_btns , 0, wxEXPAND); - dlg_btns->GetOK()->Bind(wxEVT_BUTTON, &Junction_Deviation_Test_Dlg::on_start, this); + dlg_btns->GetOK()->Bind(wxEVT_BUTTON, &Cornering_Test_Dlg::on_start, this); wxGetApp().UpdateDlgDarkUI(this); @@ -1259,34 +1359,54 @@ Junction_Deviation_Test_Dlg::Junction_Deviation_Test_Dlg(wxWindow* parent, wxWin Fit(); } -Junction_Deviation_Test_Dlg::~Junction_Deviation_Test_Dlg() { +Cornering_Test_Dlg::~Cornering_Test_Dlg() { // Disconnect Events } -void Junction_Deviation_Test_Dlg::on_start(wxCommandEvent& event) { +void Cornering_Test_Dlg::on_start(wxCommandEvent& event) { bool read_double = false; read_double = m_tiJDStart->GetTextCtrl()->GetValue().ToDouble(&m_params.start); read_double = read_double && m_tiJDEnd->GetTextCtrl()->GetValue().ToDouble(&m_params.end); - if (!read_double || m_params.start < 0 || m_params.end >= 1 || m_params.start >= m_params.end) { - MessageDialog msg_dlg(nullptr, _L("Please input valid values:\n(0 <= Junction Deviation < 1)"), wxEmptyString, wxICON_WARNING | wxOK); + // Get max values based on GCode Flavor + double max_end_value = 100.0; + double warning_threshold = 20.0; + const auto* preset_bundle = wxGetApp().preset_bundle; + const auto* gcode_flavor_option = (preset_bundle != nullptr) + ? preset_bundle->printers.get_edited_preset().config.option>("gcode_flavor") + : nullptr; + + if (gcode_flavor_option && + gcode_flavor_option->value == GCodeFlavor::gcfMarlinFirmware && + preset_bundle->printers.get_edited_preset().config.option("machine_max_junction_deviation") && + !preset_bundle->printers.get_edited_preset().config.option("machine_max_junction_deviation")->values.empty() && + preset_bundle->printers.get_edited_preset().config.option("machine_max_junction_deviation")->values[0] > 0) { + // Using Junction Deviation (mm) + max_end_value = 1.0; + warning_threshold = 0.3; + } + + if (!read_double || m_params.start < 0 || m_params.end > max_end_value || m_params.start >= m_params.end) { + wxString error_msg = wxString::Format(_L("Please input valid values:\n(0 <= Cornering <= %s)"), wxString::Format("%.3f", max_end_value)); + MessageDialog msg_dlg(nullptr, error_msg, wxEmptyString, wxICON_WARNING | wxOK); msg_dlg.ShowModal(); return; - } else if (m_params.end > 0.3) { - MessageDialog msg_dlg(nullptr, _L("NOTE: High values may cause Layer shift"), wxEmptyString, wxICON_WARNING | wxOK); + } else if (m_params.end > warning_threshold) { + wxString warning_msg = wxString::Format(_L("NOTE: High values may cause Layer shift (>%s)"), wxString::Format("%.3f", warning_threshold)); + MessageDialog msg_dlg(nullptr, warning_msg, wxEmptyString, wxICON_WARNING | wxOK); msg_dlg.ShowModal(); } - m_params.mode = CalibMode::Calib_Junction_Deviation; - + m_params.mode = CalibMode::Calib_Cornering; + // Set model type based on selection - m_params.test_model = m_rbModel->GetSelection() == 0 ? 0 : 1; // 0 = Ringing Tower, 1 = Fast Tower - - m_plater->calib_junction_deviation(m_params); + m_params.test_model = m_rbModel->GetSelection(); + + m_plater->Calib_Cornering(m_params); EndModal(wxID_OK); } -void Junction_Deviation_Test_Dlg::on_dpi_changed(const wxRect& suggested_rect) { +void Cornering_Test_Dlg::on_dpi_changed(const wxRect& suggested_rect) { this->Refresh(); Fit(); } diff --git a/src/slic3r/GUI/calib_dlg.hpp b/src/slic3r/GUI/calib_dlg.hpp index 9f43b71107..759cde1d0d 100644 --- a/src/slic3r/GUI/calib_dlg.hpp +++ b/src/slic3r/GUI/calib_dlg.hpp @@ -164,11 +164,11 @@ protected: Plater* m_plater; }; -class Junction_Deviation_Test_Dlg : public DPIDialog +class Cornering_Test_Dlg : public DPIDialog { public: - Junction_Deviation_Test_Dlg(wxWindow* parent, wxWindowID id, Plater* plater); - ~Junction_Deviation_Test_Dlg(); + Cornering_Test_Dlg(wxWindow* parent, wxWindowID id, Plater* plater); + ~Cornering_Test_Dlg(); void on_dpi_changed(const wxRect& suggested_rect) override; protected: diff --git a/src/slic3r/Utils/CalibUtils.cpp b/src/slic3r/Utils/CalibUtils.cpp index e7459d5e84..51452af4d4 100644 --- a/src/slic3r/Utils/CalibUtils.cpp +++ b/src/slic3r/Utils/CalibUtils.cpp @@ -142,8 +142,8 @@ std::string get_calib_mode_name(CalibMode cali_mode, int stage) return "input_shaping_freq_calib_mode"; case CalibMode::Calib_Input_shaping_damp: return "input_shaping_damp_calib_mode"; - case CalibMode::Calib_Junction_Deviation: - return "junction_deviation_calib_mode"; + case CalibMode::Calib_Cornering: + return "cornering_calib_mode"; default: assert(false); return ""; @@ -339,8 +339,8 @@ CalibMode CalibUtils::get_calib_mode_by_name(const std::string name, int& cali_s return CalibMode::Calib_Input_shaping_freq; else if (name == "input_shaping_damp_calib_mode") return CalibMode::Calib_Input_shaping_damp; - else if (name == "junction_deviation_calib_mode") - return CalibMode::Calib_Junction_Deviation; + else if (name == "cornering_calib_mode") + return CalibMode::Calib_Cornering; return CalibMode::Calib_None; }