From f559415975bdb61c2707df919d928e670fff0413 Mon Sep 17 00:00:00 2001 From: Martin Pittermann Date: Mon, 24 Dec 2018 14:07:53 +0100 Subject: [PATCH] replace some errors with warnings in gcode parser --- OpenCNCPilot/GCode/GCodeFile.cs | 26 ++++++++- OpenCNCPilot/GCode/GCodeParser.cs | 58 +++++++------------ OpenCNCPilot/MainWindow.xaml.FileTab.cs | 4 ++ OpenCNCPilot/MainWindow.xaml.MachineStatus.cs | 10 +++- 4 files changed, 57 insertions(+), 41 deletions(-) diff --git a/OpenCNCPilot/GCode/GCodeFile.cs b/OpenCNCPilot/GCode/GCodeFile.cs index e33cf5f..2827265 100644 --- a/OpenCNCPilot/GCode/GCodeFile.cs +++ b/OpenCNCPilot/GCode/GCodeFile.cs @@ -30,8 +30,26 @@ class GCodeFile public double TravelDistance { get; private set; } = 0; public TimeSpan TotalTime { get; private set; } = TimeSpan.Zero; + public List Warnings = new List(); + private GCodeFile(List toolpath) { + for (int i = 0; i < toolpath.Count; i++) + { + Command c = toolpath[i]; + + if (c is Motion) + { + Motion m = (Motion)c; + + if (m.Start == m.End) + { + Warnings.Add($"ignoring empty move at position {i} (not equal to line number)"); + toolpath.RemoveAt(i--); + } + } + } + Toolpath = new ReadOnlyCollection(toolpath); Vector3 min = Vector3.MaxValue, max = Vector3.MinValue; @@ -99,7 +117,9 @@ public static GCodeFile Load(string path) GCodeParser.Reset(); GCodeParser.ParseFile(path); - return new GCodeFile(GCodeParser.Commands) { FileName = path.Substring(path.LastIndexOf('\\') + 1) }; + GCodeFile gcodeFile = new GCodeFile(GCodeParser.Commands) { FileName = path.Substring(path.LastIndexOf('\\') + 1) }; + gcodeFile.Warnings.InsertRange(0, GCodeParser.Warnings); + return gcodeFile; } public static GCodeFile FromList(IEnumerable file) @@ -107,7 +127,9 @@ public static GCodeFile FromList(IEnumerable file) GCodeParser.Reset(); GCodeParser.Parse(file); - return new GCodeFile(GCodeParser.Commands) { FileName = "output.nc" }; + GCodeFile gcodeFile = new GCodeFile(GCodeParser.Commands) { FileName = "output.nc" }; + gcodeFile.Warnings.InsertRange(0, GCodeParser.Warnings); + return gcodeFile; } public static GCodeFile Empty diff --git a/OpenCNCPilot/GCode/GCodeParser.cs b/OpenCNCPilot/GCode/GCodeParser.cs index 0e68953..75dc172 100644 --- a/OpenCNCPilot/GCode/GCodeParser.cs +++ b/OpenCNCPilot/GCode/GCodeParser.cs @@ -46,6 +46,11 @@ struct Word { public char Command; public double Parameter; + + public override string ToString() + { + return $"{Command}{Parameter}"; + } } static class GCodeParser @@ -57,11 +62,13 @@ static class GCodeParser private static string ValidWords = "GMXYZIJKFRSP"; private static string IgnoreAxes = "ABC"; public static List Commands; + public static List Warnings; public static void Reset() { State = new ParserState(); Commands = new List(); //don't reuse, might be used elsewhere + Warnings = new List(); } static GCodeParser() @@ -145,7 +152,9 @@ static void Parse(string line, int lineNumber) if (!ValidWords.Contains(Words[i].Command)) { - throw new ParseException($"unknown word (letter): \"{Words[i].Command} {Words[i].Parameter}\"", lineNumber); + Warnings.Add($"ignoring unknown word (letter): \"{Words[i]}\" in line {lineNumber}"); + Words.RemoveAt(i--); + continue; } if (Words[i].Command != 'F') @@ -179,9 +188,9 @@ static void Parse(string line, int lineNumber) double param = Words[i].Parameter; if (param < 0) - throw new ParseException("Spindle Speed must be positive", lineNumber); + Warnings.Add($"Spindle Speed must be positive in line {lineNumber}"); - Commands.Add(new Spindle() { Speed = param }); + Commands.Add(new Spindle() { Speed = Math.Abs(param) }); Words.RemoveAt(i); i--; @@ -261,9 +270,9 @@ static void Parse(string line, int lineNumber) if (Words.Count >= 2 && Words[i + 1].Command == 'P') { if (Words[i + 1].Parameter < 0) - throw new ParseException("Negative dwell time", lineNumber); + Warnings.Add($"Dwell time must be positive in line {lineNumber}"); - Commands.Add(new Dwell() { Seconds = Words[i + 1].Parameter }); + Commands.Add(new Dwell() { Seconds = Math.Abs(Words[i + 1].Parameter) }); Words.RemoveAt(i + 1); Words.RemoveAt(i); i--; @@ -271,15 +280,8 @@ static void Parse(string line, int lineNumber) } } - if (param == 54 || param == 94 || param == 40) - { - // discard Gxx words - Words.RemoveAt(i); - i--; - continue; - } - - throw new ParseException($"G{param} is not supported", lineNumber); + Warnings.Add($"ignoring unknown command G{param} in line {lineNumber}"); + Words.RemoveAt(i--); #endregion } } @@ -344,7 +346,7 @@ static void Parse(string line, int lineNumber) if (MotionMode <= 1) { if (Words.Count > 0) - throw new ParseException("Motion Command must be last in line (unused Words in Block)", lineNumber); + Warnings.Add($"Motion Command must be last in line (ignoring unused Words {string.Join(" ", Words)} in Block) in line {lineNumber}"); Line motion = new Line(); motion.Start = State.Position; @@ -487,29 +489,6 @@ static void Parse(string line, int lineNumber) A -= U; //(AB) = vector from start to end of arc along the axes of the current plane B -= V; - /* - double C = -B; //(UV) = vector perpendicular to (AB) - double D = A; - - { //normalize perpendicular vector - double perpLength = Math.Sqrt(C * C + D * D); - C /= perpLength; - D /= perpLength; - } - - double PerpSquare = (Radius * Radius) - ((A * A + B * B) / 4); - - if (PerpSquare < 0) - throw new ParseException("arc radius too small to reach both ends", lineNumber); - - double PerpLength = Math.Sqrt(PerpSquare); - - if (MotionMode == 3 ^ Radius < 0) - PerpLength = -PerpLength; - - U += (A / 2) + C * (PerpLength); - V += (B / 2) + (D * PerpLength); - */ //see grbl/gcode.c double h_x2_div_d = 4.0 * (Radius * Radius) - (A * A + B * B); if (h_x2_div_d < 0) @@ -532,6 +511,9 @@ static void Parse(string line, int lineNumber) } #endregion + if (Words.Count > 0) + Warnings.Add($"Motion Command must be last in line (ignoring unused Words {string.Join(" ", Words)} in Block) in line {lineNumber}"); + Arc arc = new Arc(); arc.Start = State.Position; arc.End = EndPos; diff --git a/OpenCNCPilot/MainWindow.xaml.FileTab.cs b/OpenCNCPilot/MainWindow.xaml.FileTab.cs index d4e056e..b6981f1 100644 --- a/OpenCNCPilot/MainWindow.xaml.FileTab.cs +++ b/OpenCNCPilot/MainWindow.xaml.FileTab.cs @@ -1,4 +1,5 @@ using OpenCNCPilot.Communication; +using OpenCNCPilot.GCode; using System; using System.Windows; @@ -23,6 +24,9 @@ private void OpenFileDialogGCode_FileOk(object sender, System.ComponentModel.Can if (machine.Mode == Machine.OperatingMode.SendFile) return; + CurrentFileName = ""; + ToolPath = GCodeFile.Empty; + try { machine.SetFile(System.IO.File.ReadAllLines(openFileDialogGCode.FileName)); diff --git a/OpenCNCPilot/MainWindow.xaml.MachineStatus.cs b/OpenCNCPilot/MainWindow.xaml.MachineStatus.cs index 230f412..be1a2a8 100644 --- a/OpenCNCPilot/MainWindow.xaml.MachineStatus.cs +++ b/OpenCNCPilot/MainWindow.xaml.MachineStatus.cs @@ -229,7 +229,15 @@ private void Machine_FileChanged() } catch (Exception ex) { - MessageBox.Show("Could not parse GCode File, no preview/editing available\nrun this file at your own risk\n" + ex.Message); + MessageBox.Show("Could not parse GCode File, no preview/editing available\nrun this file at your own risk\n" + ex.Message + "\n\n\ninternal:\n" + ex.StackTrace); + } + + if (ToolPath.Warnings.Count > 0) + { + MessageBox.Show(@"Warning! There were some errors while parsing this file! +Do not use OpenCNCPilot's edit functions unless you are sure that these warnings can be ignored! +If you use edit functions, check the output file for errors before running the gcode! +Be aware that the affected lines will likely move when using edit functions" + "\n\n >" + string.Join("\n >", ToolPath.Warnings)); } if (Properties.Settings.Default.EnableCodePreview)