From c789a3fe0af8e62ea8ace2c3cccee8a7cb38398d Mon Sep 17 00:00:00 2001 From: Lars Brubaker Date: Thu, 20 Dec 2018 16:00:27 -0800 Subject: [PATCH] More GCode export fixes More GCode export tests --- .../Library/Export/GCodeExport.cs | 51 +++++++------ .../Io/FeedRateMultiplyerStream.cs | 5 +- .../PrinterCommunication/Io/GCodeStream.cs | 13 +++- .../PrinterCommunication/Io/OffsetStream.cs | 6 +- .../PrinterCommunication/Io/PrinterMove.cs | 10 +++ .../Io/RemoveCommentsStream.cs | 60 +++++++++++++++ .../PrinterCommunication/PrinterConnection.cs | 2 +- .../MatterControl/GCodeStreamTests.cs | 74 ++++++++++++++++++- 8 files changed, 193 insertions(+), 28 deletions(-) create mode 100644 MatterControlLib/PrinterCommunication/Io/RemoveCommentsStream.cs diff --git a/MatterControlLib/Library/Export/GCodeExport.cs b/MatterControlLib/Library/Export/GCodeExport.cs index 7c9bbb651..d55d64d65 100644 --- a/MatterControlLib/Library/Export/GCodeExport.cs +++ b/MatterControlLib/Library/Export/GCodeExport.cs @@ -252,31 +252,40 @@ namespace MatterHackers.MatterControl.Library.Export public bool CenterOnBed { get; set; } + public static GCodeStream GetExportStream(PrinterConfig printer, GCodeStream gCodeBaseStream, bool applyLeveling) + { + var queueStream = new QueuedCommandsStream(printer, gCodeBaseStream); + GCodeStream accumulatedStream = queueStream; + + accumulatedStream = new RelativeToAbsoluteStream(printer, accumulatedStream); + + if (printer.Settings.GetValue(SettingsKey.enable_line_splitting)) + { + accumulatedStream = new BabyStepsStream(printer, accumulatedStream, 1); + } + else + { + accumulatedStream = new BabyStepsStream(printer, accumulatedStream, 1000); + } + + if (printer.Settings.GetValue(SettingsKey.print_leveling_enabled) && applyLeveling) + { + accumulatedStream = new PrintLevelingStream(printer, accumulatedStream, false); + } + + // this is added to ensure we are rewriting the G0 G1 commands as needed + accumulatedStream = new ProcessWriteRegexStream(printer, accumulatedStream, queueStream); + + accumulatedStream = new RemoveCommentsStream(printer, accumulatedStream); + + return accumulatedStream; + } + private void ApplyStreamPipelineAndExport(GCodeFileStream gCodeFileStream, string outputPath) { try { - var queueStream = new QueuedCommandsStream(printer, gCodeFileStream); - GCodeStream accumulatedStream = queueStream; - - accumulatedStream = new RelativeToAbsoluteStream(printer, accumulatedStream); - - if (printer.Settings.GetValue(SettingsKey.enable_line_splitting)) - { - accumulatedStream = new BabyStepsStream(printer, accumulatedStream, 1); - } - else - { - accumulatedStream = new BabyStepsStream(printer, accumulatedStream, 1000); - } - - if (printer.Settings.GetValue(SettingsKey.print_leveling_enabled) && this.ApplyLeveling) - { - accumulatedStream = new PrintLevelingStream(printer, accumulatedStream, false); - } - - // this is added to ensure we are rewriting the G0 G1 commands as needed - GCodeStream finalStream = new ProcessWriteRegexStream(printer, accumulatedStream, queueStream); + var finalStream = GetExportStream(printer, gCodeFileStream, this.ApplyLeveling); // Run each line from the source gcode through the loaded pipeline and dump to the output location using (var file = new StreamWriter(outputPath)) diff --git a/MatterControlLib/PrinterCommunication/Io/FeedRateMultiplyerStream.cs b/MatterControlLib/PrinterCommunication/Io/FeedRateMultiplyerStream.cs index 6b3006b22..703cf3946 100644 --- a/MatterControlLib/PrinterCommunication/Io/FeedRateMultiplyerStream.cs +++ b/MatterControlLib/PrinterCommunication/Io/FeedRateMultiplyerStream.cs @@ -68,7 +68,10 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io PrinterMove moveToSend = currentMove; moveToSend.feedRate *= FeedRateRatio; - lineToSend = CreateMovementLine(moveToSend, this.lastDestination); + if (moveToSend.HaveAnyPosition) + { + lineToSend = CreateMovementLine(moveToSend, this.lastDestination); + } this.lastDestination = currentMove; return lineToSend; } diff --git a/MatterControlLib/PrinterCommunication/Io/GCodeStream.cs b/MatterControlLib/PrinterCommunication/Io/GCodeStream.cs index 91ade5e3c..963f17337 100644 --- a/MatterControlLib/PrinterCommunication/Io/GCodeStream.cs +++ b/MatterControlLib/PrinterCommunication/Io/GCodeStream.cs @@ -104,19 +104,30 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io public static PrinterMove GetPosition(string lineBeingSent, PrinterMove startPositionPosition) { + if (lineBeingSent.StartsWith("G28") + || lineBeingSent.StartsWith("G29") + || lineBeingSent.StartsWith("G30")) + { + return PrinterMove.Unknown; + } + PrinterMove currentDestination = startPositionPosition; GCodeFile.GetFirstNumberAfter("X", lineBeingSent, ref currentDestination.position.X); GCodeFile.GetFirstNumberAfter("Y", lineBeingSent, ref currentDestination.position.Y); GCodeFile.GetFirstNumberAfter("Z", lineBeingSent, ref currentDestination.position.Z); GCodeFile.GetFirstNumberAfter("E", lineBeingSent, ref currentDestination.extrusion); GCodeFile.GetFirstNumberAfter("F", lineBeingSent, ref currentDestination.feedRate); + return currentDestination; } public static bool LineIsMovement(string lineBeingSent) { if (lineBeingSent.StartsWith("G0 ") - || lineBeingSent.StartsWith("G1 ")) + || lineBeingSent.StartsWith("G1 ") + || lineBeingSent.StartsWith("G28") + || lineBeingSent.StartsWith("G29") + || lineBeingSent.StartsWith("G30")) { return true; } diff --git a/MatterControlLib/PrinterCommunication/Io/OffsetStream.cs b/MatterControlLib/PrinterCommunication/Io/OffsetStream.cs index e056d8535..842b69486 100644 --- a/MatterControlLib/PrinterCommunication/Io/OffsetStream.cs +++ b/MatterControlLib/PrinterCommunication/Io/OffsetStream.cs @@ -128,8 +128,12 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io moveToSend.position -= extruderOffsets[extruderIndex]; } - lineToSend = CreateMovementLine(moveToSend, lastDestination); + if (moveToSend.HaveAnyPosition) + { + lineToSend = CreateMovementLine(moveToSend, lastDestination); + } lastDestination = currentMove; + return lineToSend; } diff --git a/MatterControlLib/PrinterCommunication/Io/PrinterMove.cs b/MatterControlLib/PrinterCommunication/Io/PrinterMove.cs index 65eb303d8..698414c58 100644 --- a/MatterControlLib/PrinterCommunication/Io/PrinterMove.cs +++ b/MatterControlLib/PrinterCommunication/Io/PrinterMove.cs @@ -74,6 +74,16 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io } } + public bool HaveAnyPosition + { + get + { + return position.X != double.PositiveInfinity + || position.Y != double.PositiveInfinity + || position.Z != double.PositiveInfinity; + } + } + public bool PositionFullyKnown { get diff --git a/MatterControlLib/PrinterCommunication/Io/RemoveCommentsStream.cs b/MatterControlLib/PrinterCommunication/Io/RemoveCommentsStream.cs new file mode 100644 index 000000000..a75c795a3 --- /dev/null +++ b/MatterControlLib/PrinterCommunication/Io/RemoveCommentsStream.cs @@ -0,0 +1,60 @@ +/* +Copyright (c) 2017, Lars Brubaker, John Lewin +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 MatterControl.Printing; + +namespace MatterHackers.MatterControl.PrinterCommunication.Io +{ + public class RemoveCommentsStream : GCodeStreamProxy + { + public RemoveCommentsStream(PrinterConfig printer, GCodeStream internalStream) + : base(printer, internalStream) + { + } + + public override string ReadLine() + { + do + { + var lineToSend = internalStream.ReadLine(); + if (lineToSend == null) + { + return null; + } + + var splitLine = lineToSend.Split(';')[0].Trim(); + if (splitLine.Trim().Length > 0) + { + // sometimes we need to send code without buffering (like when we are closing the program). + return splitLine; + } + } while (true); + } + } +} \ No newline at end of file diff --git a/MatterControlLib/PrinterCommunication/PrinterConnection.cs b/MatterControlLib/PrinterCommunication/PrinterConnection.cs index 94e3292b6..4bf2cc397 100644 --- a/MatterControlLib/PrinterCommunication/PrinterConnection.cs +++ b/MatterControlLib/PrinterCommunication/PrinterConnection.cs @@ -1723,7 +1723,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication || forceImmediateWrites) { lineToWrite = lineToWrite.Split(';')[0].Trim(); - if (lineToWrite.Trim().Length > 0) + if (lineToWrite.Length > 0) { // sometimes we need to send code without buffering (like when we are closing the program). WriteRaw(lineToWrite + "\n", lineToWrite); diff --git a/Tests/MatterControl.Tests/MatterControl/GCodeStreamTests.cs b/Tests/MatterControl.Tests/MatterControl/GCodeStreamTests.cs index 6fb16b677..f5609b39e 100644 --- a/Tests/MatterControl.Tests/MatterControl/GCodeStreamTests.cs +++ b/Tests/MatterControl.Tests/MatterControl/GCodeStreamTests.cs @@ -33,6 +33,7 @@ using MatterControl.Printing; using MatterHackers.Agg; using MatterHackers.Agg.Platform; using MatterHackers.MatterControl; +using MatterHackers.MatterControl.Library.Export; using MatterHackers.MatterControl.PrinterCommunication.Io; using MatterHackers.MatterControl.SlicerConfiguration; using MatterHackers.MatterControl.Tests.Automation; @@ -67,9 +68,7 @@ namespace MatterControl.Tests.MatterControl "G1 X12", "G1 X18", "G28", - "G1 X12 F500", - "G1 X6", - "G1 X0", + "G1 X0 Y0 Z0 E0 F500", null, }; @@ -95,6 +94,75 @@ namespace MatterControl.Tests.MatterControl } } + [Test] + public void ExportStreamCorrectForG30() + { + string[] inputLines = new string[] + { + "M117 Starting Print", + "M104 S0", + "; comment line", + "G28 ; home all axes", + "G0 Z10 F1800", + "G0 Z11 F1800", + "G0 X1Y0Z9 F1800", + "G0 Z10 F1801", + "G30 Z0", + "M114", + "G0 Z10 F1800", + "M114", + "M109 S[temperature]", + null, + }; + + // We should go back to the above code when possible. It requires making pause part and move while paused part of the stream. + // All communication should go through stream to minimize the difference between printing and controlling while not printing (all printing in essence). + string[] expected = new string[] + { + "M117 Starting Print", + "M104 S0", + "G28", + "G1 Z10 F1800", + "G1 Z11", + "G1 X1 Y0 Z9", + "G1 Z10 F1801", + "G30 Z0", + "M114", + "G1 Z10 F1800", + "M114", + "M109 S[temperature]", + null, + }; + + AggContext.StaticData = new FileSystemStaticData(TestContext.CurrentContext.ResolveProjectPath(4, "StaticData")); + MatterControlUtilities.OverrideAppDataLocation(TestContext.CurrentContext.ResolveProjectPath(4)); + + var printer = new PrinterConfig(new PrinterSettings()); + + var testStream = GCodeExport.GetExportStream(printer, new TestGCodeStream(printer, inputLines), true); + + int expectedIndex = 0; + string actualLine = testStream.ReadLine(); + string expectedLine = expected[expectedIndex++]; + + Assert.AreEqual(expectedLine, actualLine, "Unexpected response from testStream"); + Debug.WriteLine(actualLine); + + while (actualLine != null) + { + actualLine = testStream.ReadLine(); + if (actualLine == "G92 E0") + { + testStream.SetPrinterPosition(new PrinterMove(new Vector3(), 0, 300)); + } + + expectedLine = expected[expectedIndex++]; + + Debug.WriteLine(actualLine); + Assert.AreEqual(expectedLine, actualLine, "Unexpected response from testStream"); + } + } + public static GCodeStream CreateTestGCodeStream(PrinterConfig printer, string[] inputLines, out List streamList) { streamList = new List();