From 64648e1ed7e9047aeec8b4a79a6880b67f04948b Mon Sep 17 00:00:00 2001 From: Lars Brubaker Date: Mon, 27 Aug 2018 14:57:55 -0700 Subject: [PATCH] Adding in the ability to specify custom leveling probe positions issue: MatterHackers/MCCentral#4048 Allow custom probing positions for bed leveling --- .../PrintLeveling/LevelWizardCustom.cs | 85 +++++++++++++++++++ .../PrintLeveling/LevelingWizard.cs | 4 + .../PrintLeveling/PrintLevelingData.cs | 9 +- MatterControl.csproj | 1 + .../Settings/PrinterSettings.cs | 2 + .../Settings/SettingsHelpers.cs | 1 + .../SlicerMapping/EngineMappingMatterSlice.cs | 1 + StaticData/SliceSettings/Layouts.txt | 1 + StaticData/SliceSettings/Properties.json | 12 ++- Submodules/MatterSlice | 2 +- .../MatterControl/SettingsParseTests.cs | 10 +++ 11 files changed, 125 insertions(+), 3 deletions(-) create mode 100644 ConfigurationPage/PrintLeveling/LevelWizardCustom.cs diff --git a/ConfigurationPage/PrintLeveling/LevelWizardCustom.cs b/ConfigurationPage/PrintLeveling/LevelWizardCustom.cs new file mode 100644 index 000000000..75424af2d --- /dev/null +++ b/ConfigurationPage/PrintLeveling/LevelWizardCustom.cs @@ -0,0 +1,85 @@ +/* +Copyright (c) 2014, Lars Brubaker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using System.Collections.Generic; +using MatterHackers.MatterControl.SlicerConfiguration; +using MatterHackers.MeshVisualizer; +using MatterHackers.VectorMath; + +namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling +{ + public class LevelWizardCustom : LevelingPlan + { + public LevelWizardCustom(PrinterConfig printer) + : base(printer) + { + } + + public static List ParseLevelingSamplePoints(PrinterConfig printer) + { + var pointsToProbe = new List(); + var samples = printer.Settings.GetValue(SettingsKey.leveling_sample_points).Replace("\r", "").Replace("\n", "").Trim(); + double xPos = double.NegativeInfinity; + foreach(var coord in samples.Split(',')) + { + if(double.TryParse(coord, out double result)) + { + if(xPos == double.NegativeInfinity) + { + // this is the first coord it is an x position + xPos = result; + } + else // we have an x + { + pointsToProbe.Add(new Vector2(xPos, result)); + xPos = double.NegativeInfinity; + } + } + } + + return pointsToProbe; + } + + public override int ProbeCount + { + get + { + return ParseLevelingSamplePoints(printer).Count; + } + } + + public override IEnumerable GetPrintLevelPositionToSample() + { + foreach(var position in ParseLevelingSamplePoints(printer)) + { + yield return position; + } + } + } +} \ No newline at end of file diff --git a/ConfigurationPage/PrintLeveling/LevelingWizard.cs b/ConfigurationPage/PrintLeveling/LevelingWizard.cs index a8ec88753..3621b90fc 100644 --- a/ConfigurationPage/PrintLeveling/LevelingWizard.cs +++ b/ConfigurationPage/PrintLeveling/LevelingWizard.cs @@ -117,6 +117,10 @@ namespace MatterHackers.MatterControl levelingPlan = new LevelWizardMesh(printer, 10, 10); break; + case LevelingSystem.ProbeCustom: + levelingPlan = new LevelWizardCustom(printer); + break; + default: throw new NotImplementedException(); } diff --git a/ConfigurationPage/PrintLeveling/PrintLevelingData.cs b/ConfigurationPage/PrintLeveling/PrintLevelingData.cs index d76cfdd0a..d122e0dfe 100644 --- a/ConfigurationPage/PrintLeveling/PrintLevelingData.cs +++ b/ConfigurationPage/PrintLeveling/PrintLevelingData.cs @@ -10,7 +10,7 @@ using System.Linq; namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling { [JsonConverter(typeof(StringEnumConverter))] - public enum LevelingSystem { Probe3Points, Probe7PointRadial, Probe13PointRadial, Probe100PointRadial, Probe3x3Mesh, Probe5x5Mesh, Probe10x10Mesh } + public enum LevelingSystem { Probe3Points, Probe7PointRadial, Probe13PointRadial, Probe100PointRadial, Probe3x3Mesh, Probe5x5Mesh, Probe10x10Mesh, ProbeCustom } public class PrintLevelingData { @@ -133,6 +133,13 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling } break; + case LevelingSystem.ProbeCustom: + if (levelingData.SampledPositions.Count != LevelWizardCustom.ParseLevelingSamplePoints(printer).Count) + { + return true; + } + break; + default: throw new NotImplementedException(); } diff --git a/MatterControl.csproj b/MatterControl.csproj index 3c9bebf4f..19729337c 100644 --- a/MatterControl.csproj +++ b/MatterControl.csproj @@ -84,6 +84,7 @@ + diff --git a/SlicerConfiguration/Settings/PrinterSettings.cs b/SlicerConfiguration/Settings/PrinterSettings.cs index 5340fc00d..c58b2288d 100644 --- a/SlicerConfiguration/Settings/PrinterSettings.cs +++ b/SlicerConfiguration/Settings/PrinterSettings.cs @@ -860,6 +860,8 @@ namespace MatterHackers.MatterControl.SlicerConfiguration return (T)(object)(LevelingSystem.Probe5x5Mesh); case "10x10 Mesh": return (T)(object)(LevelingSystem.Probe10x10Mesh); + case "Custom Points": + return (T)(object)(LevelingSystem.ProbeCustom); default: #if DEBUG throw new NotImplementedException(); diff --git a/SlicerConfiguration/Settings/SettingsHelpers.cs b/SlicerConfiguration/Settings/SettingsHelpers.cs index 995a4368f..aced35cc2 100644 --- a/SlicerConfiguration/Settings/SettingsHelpers.cs +++ b/SlicerConfiguration/Settings/SettingsHelpers.cs @@ -123,6 +123,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration public const string probe_has_been_calibrated = nameof(probe_has_been_calibrated); public const string print_leveling_required_to_print = nameof(print_leveling_required_to_print); public const string print_leveling_solution = nameof(print_leveling_solution); + public const string leveling_sample_points = nameof(leveling_sample_points); public const string printer_name = nameof(printer_name); public const string progress_reporting = nameof(progress_reporting); public const string publish_bed_image = nameof(publish_bed_image); diff --git a/SlicerConfiguration/SlicerMapping/EngineMappingMatterSlice.cs b/SlicerConfiguration/SlicerMapping/EngineMappingMatterSlice.cs index 0146f3b56..ebefa1de2 100644 --- a/SlicerConfiguration/SlicerMapping/EngineMappingMatterSlice.cs +++ b/SlicerConfiguration/SlicerMapping/EngineMappingMatterSlice.cs @@ -83,6 +83,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration SettingsKey.probe_has_been_calibrated, SettingsKey.print_leveling_required_to_print, SettingsKey.print_leveling_solution, + SettingsKey.leveling_sample_points, SettingsKey.recover_first_layer_speed, SettingsKey.number_of_first_layers, SettingsKey.recover_is_enabled, diff --git a/StaticData/SliceSettings/Layouts.txt b/StaticData/SliceSettings/Layouts.txt index fc0da2b4a..6aab83a60 100644 --- a/StaticData/SliceSettings/Layouts.txt +++ b/StaticData/SliceSettings/Layouts.txt @@ -164,6 +164,7 @@ Printer Leveling Print Leveling print_leveling_solution + leveling_sample_points print_leveling_required_to_print Leveling Probe print_leveling_probe_start diff --git a/StaticData/SliceSettings/Properties.json b/StaticData/SliceSettings/Properties.json index f7cd90c82..d5e1ee19c 100644 --- a/StaticData/SliceSettings/Properties.json +++ b/StaticData/SliceSettings/Properties.json @@ -720,10 +720,20 @@ "PresentationName": "Leveling Solution", "HelpText": "The print leveling algorithm to use.", "DataEditType": "LIST", - "ListValues": "3 Point Plane,3x3 Mesh,5x5 Mesh,10x10 Mesh,7 Point Disk,13 Point Disk,100 Point Disk", + "ListValues": "3 Point Plane,3x3 Mesh,5x5 Mesh,10x10 Mesh,7 Point Disk,13 Point Disk,100 Point Disk,Custom Points", "ShowAsOverride": true, "ShowIfSet": "!has_hardware_leveling", "DefaultValue": "3 Point Plane", + "ReloadUiWhenChanged": true, + "RebuildGCodeOnChange": false + }, + { + "SlicerConfigName": "leveling_sample_points", + "PresentationName": "Sample Points", + "HelpText": "A comma separated list of sample points to probje the bed at. You must specify an x and y position for each point. For example: '20,20,100,180,180,20' will saple the bad at 3 points.", + "DataEditType": "MULTI_LINE_TEXT", + "DefaultValue": "20,20,100,180,180,20", + "ShowIfSet": "!sla_printer&!has_hardware_leveling&print_leveling_solution=Custom Points", "RebuildGCodeOnChange": false }, { diff --git a/Submodules/MatterSlice b/Submodules/MatterSlice index c3ef27f60..12d502a86 160000 --- a/Submodules/MatterSlice +++ b/Submodules/MatterSlice @@ -1 +1 @@ -Subproject commit c3ef27f6039c9fd55c60f49317b5eeaa48bb03ad +Subproject commit 12d502a86e25440da51ca5c42e92afa89c7aadb8 diff --git a/Tests/MatterControl.Tests/MatterControl/SettingsParseTests.cs b/Tests/MatterControl.Tests/MatterControl/SettingsParseTests.cs index 1eedd65c0..b70574a2a 100644 --- a/Tests/MatterControl.Tests/MatterControl/SettingsParseTests.cs +++ b/Tests/MatterControl.Tests/MatterControl/SettingsParseTests.cs @@ -42,6 +42,7 @@ namespace MatterControl.Tests.MatterControl AggContext.StaticData = new FileSystemStaticData(TestContext.CurrentContext.ResolveProjectPath(4, "StaticData")); MatterControlUtilities.OverrideAppDataLocation(TestContext.CurrentContext.ResolveProjectPath(4)); + // test single if set to 0 { string[] settings = new string[] { SettingsKey.has_heated_bed, "0" }; var profile = GetProfile(settings); @@ -49,6 +50,7 @@ namespace MatterControl.Tests.MatterControl Assert.IsTrue(profile.ParseShowString("!has_heated_bed", null)); } + // test single if set to 1 { string[] settings = new string[] { SettingsKey.has_heated_bed, "1" }; var profile = GetProfile(settings); @@ -56,6 +58,7 @@ namespace MatterControl.Tests.MatterControl Assert.IsFalse(profile.ParseShowString("!has_heated_bed", null)); } + // test & with set to 0 and 0 { string[] settings = new string[] { SettingsKey.has_heated_bed, "0", SettingsKey.auto_connect, "0" }; var profile = GetProfile(settings); @@ -64,6 +67,8 @@ namespace MatterControl.Tests.MatterControl Assert.IsFalse(profile.ParseShowString("!has_heated_bed&auto_connect", null)); Assert.IsTrue(profile.ParseShowString("!has_heated_bed&!auto_connect", null)); } + + // test & with 0 and 1 { string[] settings = new string[] { SettingsKey.has_heated_bed, "0", SettingsKey.auto_connect, "1" }; var profile = GetProfile(settings); @@ -72,6 +77,8 @@ namespace MatterControl.Tests.MatterControl Assert.IsTrue(profile.ParseShowString("!has_heated_bed&auto_connect", null)); Assert.IsFalse(profile.ParseShowString("!has_heated_bed&!auto_connect", null)); } + + // test & with 1 and 0 { string[] settings = new string[] { SettingsKey.has_heated_bed, "1", SettingsKey.auto_connect, "0" }; var profile = GetProfile(settings); @@ -80,6 +87,8 @@ namespace MatterControl.Tests.MatterControl Assert.IsFalse(profile.ParseShowString("!has_heated_bed&auto_connect", null)); Assert.IsFalse(profile.ParseShowString("!has_heated_bed&!auto_connect", null)); } + + // test & with 1 and 1 { string[] settings = new string[] { SettingsKey.has_heated_bed, "1", SettingsKey.auto_connect, "1" }; var profile = GetProfile(settings); @@ -89,6 +98,7 @@ namespace MatterControl.Tests.MatterControl Assert.IsFalse(profile.ParseShowString("!has_heated_bed&!auto_connect", null)); } + // test 3 &s { string[] settings = new string[] { SettingsKey.has_heated_bed, "1", SettingsKey.auto_connect, "1", SettingsKey.has_fan, "1" }; var profile = GetProfile(settings);