From 0d222b0231ae76443d1ac12a326f0e0bd783fab3 Mon Sep 17 00:00:00 2001 From: Eric Taylor Date: Fri, 10 Apr 2026 09:19:32 -0400 Subject: [PATCH] Add Remove Small Moves script --- Remove Small Moves/README.md | 80 ++++++++++++++ Remove Small Moves/Remove-SmallMoves.ps1 | 132 +++++++++++++++++++++++ 2 files changed, 212 insertions(+) create mode 100644 Remove Small Moves/README.md create mode 100644 Remove Small Moves/Remove-SmallMoves.ps1 diff --git a/Remove Small Moves/README.md b/Remove Small Moves/README.md new file mode 100644 index 0000000..7343135 --- /dev/null +++ b/Remove Small Moves/README.md @@ -0,0 +1,80 @@ +# GCode Small-Move Remover + +PowerShell script that removes gcode cutting moves where X and Y coordinates differ from the previous kept position by less than or equal to a configurable threshold (default 0.0006). These near-zero moves cause Komo CNC machines to throw `ERROR: CRC Fault`. + +## Problem + +Komo controllers reject cutting moves where the actual displacement in X and Y is negligibly small. For example: + +``` +N7633 G1 X23.1756 Y27.9265 Z0.7700 F150. +N7634 G1 X23.1757 Y27.9268 Z0.7700 F150. <-- dX=0.0001, dY=0.0003 (CRC Fault) +N7635 G1 X23.1962 Y27.9797 Z0.7700 F150. +N7636 G1 X23.1963 Y27.9799 Z0.7700 F150. <-- dX=0.0001, dY=0.0002 (CRC Fault) +N7637 G1 X23.2163 Y28.0330 Z0.7700 F150. +``` + +Lines N7634 and N7636 move less than 0.0006 in both X and Y from the previous position, which Komo sees as invalid and halts with a CRC Fault error. + +## Solution + +The script parses `.OUT` gcode files and removes cutting move lines (G1, G2, G3) where **both** X and Y differ from the last kept position by less than or equal to the threshold, **and** there is no Z change. This eliminates the CRC Fault triggers while preserving all meaningful toolpath data. + +### What gets removed + +- G1/G2/G3 lines where dX <= threshold AND dY <= threshold AND Z is unchanged + +### What is always kept + +- **Z moves** - any line where Z changed is never removed +- **G0 (rapid)** positioning lines +- **G28** (home return) lines +- **G52** (coordinate offset) lines +- **M-codes**, comments, tool changes, and all other non-cutting lines + +## Usage + +```powershell +# Basic - creates *_cleaned.OUT next to the original +.\Remove-SmallMoves.ps1 -InputFile "C:\path\to\file.OUT" + +# Specify output file +.\Remove-SmallMoves.ps1 -InputFile "file.OUT" -OutputFile "file_fixed.OUT" + +# Custom threshold +.\Remove-SmallMoves.ps1 -InputFile "file.OUT" -Threshold 0.001 +``` + +## Parameters + +| Parameter | Required | Default | Description | +|-------------|----------|---------|-------------| +| `InputFile` | Yes | - | Path to the input gcode file | +| `OutputFile`| No | `*_cleaned.OUT` | Path for the cleaned output file | +| `Threshold` | No | `0.0006`| Max X or Y difference for removal | + +## Example Output + +``` +GCode Small-Move Remover +======================== +Threshold: <= 0.0006 in both X and Y +Input: file.OUT (8864 lines) +Output: file_cleaned.OUT (8310 lines) +Removed: 554 lines + +Sample removed lines (first 20): + Line 36 removed: X=28.0339 Y=25.8585 Z=0.77 (dX=0.0002, dY=0.0003, dZ=0) + Line 47 removed: X=27.7644 Y=27.1713 Z=0.77 (dX=0, dY=0, dZ=0) + ... +``` + +## How It Works + +1. Reads the input file line by line +2. Extracts X, Y, Z coordinates using regex +3. For cutting moves (G1/G2/G3) only: + - If Z changed significantly (> 0.0001), the line is always kept + - If Z is the same, compares X and Y against the last kept position + - If both dX and dY are within threshold, the line is removed +4. Updates the last known X/Y/Z position from kept lines only (removed lines don't update position tracking) \ No newline at end of file diff --git a/Remove Small Moves/Remove-SmallMoves.ps1 b/Remove Small Moves/Remove-SmallMoves.ps1 new file mode 100644 index 0000000..7330884 --- /dev/null +++ b/Remove Small Moves/Remove-SmallMoves.ps1 @@ -0,0 +1,132 @@ +<# +.SYNOPSIS + Removes gcode lines where X and Y coordinates differ from the previous + kept line by <= Threshold (default 0.0006), which causes Komo CRC Fault errors. + +.DESCRIPTION + Parses a gcode .OUT file and removes movement lines where both the X and Y + differences from the last kept position are within the threshold AND there + is no significant Z change. Lines with Z moves are always kept. + This eliminates near-zero XY moves that trigger Komo ERROR: CRC Fault. + + Only cutting moves (G1, G2, G3) are candidates for removal. All other lines + including G0 (rapid), G28 (home), G52 (offset), M-codes, and comments are + always kept unchanged. + +.PARAMETER InputFile + Path to the input gcode file. + +.PARAMETER OutputFile + Path for the cleaned output file. Defaults to input filename with "_cleaned" + appended before the extension. + +.PARAMETER Threshold + Maximum X or Y difference to consider a line for removal. Default 0.0006. + +.EXAMPLE + .\Remove-SmallMoves.ps1 "C:\path\to\file.OUT" + .\Remove-SmallMoves.ps1 -InputFile "file.OUT" -OutputFile "file_fixed.OUT" -Threshold 0.001 +#> + +param( + [Parameter(Mandatory = $true)] + [string]$InputFile, + + [string]$OutputFile, + + [double]$Threshold = 0.0006 +) + +if (-not $OutputFile) { + $OutputFile = [System.IO.Path]::Combine( + [System.IO.Path]::GetDirectoryName($InputFile), + [System.IO.Path]::GetFileNameWithoutExtension($InputFile) + '_cleaned' + [System.IO.Path]::GetExtension($InputFile) + ) +} + +$lines = Get-Content $InputFile + +$lastX = $null +$lastY = $null +$lastZ = $null +$removedLines = [System.Collections.ArrayList]::new() +$result = [System.Collections.ArrayList]::new() +$removedCount = 0 +$lineNum = 0 + +foreach ($line in $lines) { + $lineNum++ + + $xMatch = [regex]::Match($line, 'X(-?\d+\.?\d*)') + $yMatch = [regex]::Match($line, 'Y(-?\d+\.?\d*)') + $zMatch = [regex]::Match($line, 'Z(-?\d+\.?\d*)') + + $hasX = $xMatch.Success + $hasY = $yMatch.Success + $hasZ = $zMatch.Success + + if (-not ($hasX -or $hasY -or $hasZ)) { + [void]$result.Add($line) + continue + } + + $isCuttingMove = $line -match '\bG[123]\b' + + if (-not $isCuttingMove) { + if ($hasX) { $lastX = $x } + if ($hasY) { $lastY = $y } + if ($hasZ) { $lastZ = $z } + [void]$result.Add($line) + continue + } + + $x = if ($hasX) { [double]::Parse($xMatch.Groups[1].Value, [System.Globalization.CultureInfo]::InvariantCulture) } else { $lastX } + $y = if ($hasY) { [double]::Parse($yMatch.Groups[1].Value, [System.Globalization.CultureInfo]::InvariantCulture) } else { $lastY } + $z = if ($hasZ) { [double]::Parse($zMatch.Groups[1].Value, [System.Globalization.CultureInfo]::InvariantCulture) } else { $lastZ } + + if ($null -ne $lastZ -and $null -ne $z) { + $diffZ = [math]::Abs($z - $lastZ) + } else { + $diffZ = [double]::MaxValue + } + + if ($diffZ -lt 0.0001) { + if ($null -ne $lastX -and $null -ne $lastY -and $null -ne $x -and $null -ne $y) { + $diffX = [math]::Abs($x - $lastX) + $diffY = [math]::Abs($y - $lastY) + + if ($diffX -le $Threshold -and $diffY -le $Threshold) { + [void]$removedLines.Add("Line $lineNum removed: X=${x} Y=${y} Z=${z} (dX=$diffX, dY=$diffY, dZ=$diffZ)") + $removedCount++ + continue + } + } + } + + if ($hasX) { $lastX = $x } + if ($hasY) { $lastY = $y } + if ($hasZ) { $lastZ = $z } + [void]$result.Add($line) +} + +$result | Set-Content $OutputFile + +Write-Host "" +Write-Host "GCode Small-Move Remover" +Write-Host "========================" +Write-Host "Threshold: <= $Threshold in both X and Y" +Write-Host "Input: $InputFile ($($lines.Count) lines)" +Write-Host "Output: $OutputFile ($($result.Count) lines)" +Write-Host "Removed: $removedCount lines" +Write-Host "" + +if ($removedLines.Count -gt 0) { + Write-Host "Sample removed lines (first 20):" + $sample = if ($removedLines.Count -gt 20) { $removedLines[0..19] } else { $removedLines } + foreach ($r in $sample) { + Write-Host " $r" + } + if ($removedLines.Count -gt 20) { + Write-Host " ... and $($removedLines.Count - 20) more" + } +} \ No newline at end of file