Calibration Cornering Jerk Test + Generic interpolator + Fix (#10962)
Some checks failed
Build all / Build All (push) Waiting to run
Build all / Flatpak (push) Waiting to run
Publish docs to Wiki / Publish docs to Wiki (push) Has been cancelled

This commit is contained in:
Ian Bassi 2025-10-26 09:44:19 -03:00 committed by GitHub
parent e922411371
commit a839b81fdf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
25 changed files with 431 additions and 197 deletions

View file

@ -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)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Before After
Before After

View file

@ -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.}}

Binary file not shown.

View file

@ -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<LayerToPrint>, which contains Object and Support layers for the current print_z, collected for
// a single object, or for possibly multiple objects with multiple instances.

View file

@ -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; }

View file

@ -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 "

View file

@ -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);

View file

@ -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

View file

@ -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 };

View file

@ -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;

View file

@ -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<ConfigOptionFloats>("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<DraftShield>("draft_shield") != dsEnabled);

View file

@ -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);

View file

@ -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 };

View file

@ -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<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor");
const auto junction_dev = printer_config->option<ConfigOptionFloats>("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<ConfigOptionFloat>("default_jerk")->value > 0){ // we have set a jerk value
if(!has_junction_deviation(printer_config) && print_config.option<ConfigOptionFloat>("default_jerk")->value > 0){ // we have set a jerk value
auto jerk = print_config.option<ConfigOptionFloat>("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<ConfigOptionFloat>("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<ConfigOptionEnum<GCodeFlavor>>("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<ConfigOptionFloats>("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<ConfigOptionFloats>("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<ConfigOptionFloats>("machine_max_jerk_x")->values.front(), jerk_value)});
printer_config->set_key_value("machine_max_jerk_y", new ConfigOptionFloats{std::max(printer_config->option<ConfigOptionFloats>("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<ConfigOptionFloats>("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<ConfigOptionFloats>("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<BrimType>(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<ConfigOptionEnum<GCodeFlavor>>("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<ConfigOptionFloats>("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<ConfigOptionFloats>("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<ConfigOptionFloats>("machine_max_jerk_x")->values.front(), jerk_value)});
printer_config->set_key_value("machine_max_jerk_y", new ConfigOptionFloats{std::max(printer_config->option<ConfigOptionFloats>("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<ConfigOptionFloats>("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<ConfigOptionFloats>("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<BrimType>(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<BrimType>(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);
}

View file

@ -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;

View file

@ -56,6 +56,8 @@
#include <commctrl.h>
#endif // WIN32
#include <algorithm>
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<ConfigOptionFloats>("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);

View file

@ -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<wxString>{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<ConfigOptionEnum<GCodeFlavor>>("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<ConfigOptionFloats>("machine_max_junction_deviation") &&
!preset_bundle->printers.get_edited_preset().config.option<ConfigOptionFloats>("machine_max_junction_deviation")->values.empty() &&
preset_bundle->printers.get_edited_preset().config.option<ConfigOptionFloats>("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<ConfigOptionFloats>("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<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")
: nullptr;
if (gcode_flavor_option &&
gcode_flavor_option->value == GCodeFlavor::gcfMarlinFirmware &&
preset_bundle->printers.get_edited_preset().config.option<ConfigOptionFloats>("machine_max_junction_deviation") &&
!preset_bundle->printers.get_edited_preset().config.option<ConfigOptionFloats>("machine_max_junction_deviation")->values.empty() &&
preset_bundle->printers.get_edited_preset().config.option<ConfigOptionFloats>("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();
}

View file

@ -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:

View file

@ -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;
}