It’s been a few years since the last time I did any serious gcode optimizer searching, but I found at least one abandoned github project and several big dollar commercial CAM software that claimed to optimize gcode. Estlcam has some built-in toolpath reordering and the almost ready to be released V12 claims it does better. Vectric also claims they’ll optimize but it doesn’t seem to be that impressive. I should dig up a bigger project (I’m working on chip carvings that take all afternoon to design and maybe a minute to run these days) and give the new GCC a whirl. Of course that means getting up off the sofa and off the internet
One consideration is that grbl doesn’t handle tool changes and the gcode senders I’ve tried don’t allow UI commands when paused, so a single file with multiple bits is problematic. I’ve always used one file per bit change, and tried to arrange toolpaths to prevent needing to use the same bit twice
Sorry for the delay. Here are the files, the gcode clean one and then the split/merged one.
1-8-gcc.nc (537.7 KB)
1-8-gcc-ts.nc (537.7 KB)
Thanks - I did find some other files that were multiple depths of cut. But they were a bit ‘boring’ (i.e. too simple) - so not good for testing.
@TimS And then I realised - I probably need the original file more than the others
But I went with the first file anyway, and I think I have some useful data
Throwing your names in here, so you can all follow along.
I’ve now ‘poked’ at a few files that do some flavour of multiple passes at differing depths of cut, and keeping a track of the cutting path statistics - minimum depth of cut (closest to 0), maximum, mean and standard deviation of cutting depths.
There are two types of cutting paths:
- zero, or near zero (relatively), standard deviation - these are clearing out material, but not necessarily ‘roughing’ paths.
- everything else - these could start their cut at
Z0
, but they have a significant size to their standard deviation of cutting depths. These usually (but not always) turn up later in a GCode file.
My thoughts for how to prioritise these for feeding into the merge
function.
- Get the breakdowns of the various depths of cut for the first type of cutting paths. This will be a ‘guide’ that implies the ‘layers’ (loosely like 3d printer slices).
- Get anything from the second type of cutting paths that is ‘above’ the first ‘layer’ of type 1. For this I’m thinking of a cutting path where its mean + 1 std dev is ‘above’.
- Throw the first ‘layer’ of type 1, and the results of step 2 above into the merge algorithm.
- Pretty much rinse and repeat steps 2 and 3 for each subsequent ‘layer’ of type 1.
- Any leftovers of type 2 now get processed by the merge algorithm.
when identifying the layers, I think you want to combine as much movement in a
layer before stacking them
for example, if cutting a square, you want to combine the sides, cutting all the
way around, before going deeper.
It’s common to say that finishing passes are a different ‘tool’ than earlier
passes, either with an actual tool swap, or by declaring the bit to be slightly
larger than it actually is for the earlier portion. I think it’s reasonable for
you to require a tool change for finishing passes, at least in the short run.
finishing passes also tend to be full depth, single pass cuts, so if you stack
cuts by depth, that should put them last anyway.
David Lang
Disclaimer…I know almost nothing about this stuff.
The layering could contradict what you are trying to do with reducing traveling. Even though the depths were not always in order it fully pocketed X area around my letters before moving to the next area.
I think the best way to keep minimal movement and cut properly would be to start with what you get from split/merge then reorg same paths in order of depth. It seemed on my brief skim of my gcode that the paths were all the same coordit wise just need to be prioritized on depth.
Something that would search for duplicate paths between z movements. Then reorg the paths based on those z movements.
A risk may be that the positive z movements for traveling may be misinterpreted. And stacked ahead of cuts.
To alleviate this, the program may have to identify Cut movements as starting with a negative z and end in a positive and travel movements start with a positive and end in a negative z.
Don’t know if I make sense or have provided any useful information.
The layering is an aspect of the problem that requires solving. There’s a reason why the ‘travelling salesman’ problem is considered so difficult to solve.
Something that GCodeClean deliberately does not do is keep track of the paths. This is kinda by design. So, to figure out split
and merge
I just have the clean
function add a comment at the end of each cutting path that identifies the ‘entry’ and ‘exit’ point (+ve Z) of that cutting path. With this approach any +ve Z movements that precede a specific cutting path stay in that place in the GCode.
So, split
and merge
can tell if entry and exit points line up, but not whether the cutting paths in between are the same.
And now we’re at v1.3.3 - with improved ‘depth of cut’-aware merge
Release Improved merge
, now ‘depth of cut’ aware · md8n/GCodeClean (github.com)
Note that this is a ‘breaking change’, previously clean
ed files will not feed into the new split
command. Redo each file starting with clean
to work around this.
So, after rummaging around a variety of tests looking for an ‘optimal’ solution (sorta like what I suggested above) it turned out to be.
- Call each tool change a new ‘sequence’.
- Take the total range of cutting depths, divide these into 10 ranges (arbitrary, but seems good enough), and assign each cutting path to one of those ranges depending on its maximum cutting depth, and call this a ‘sub-sequence’ (close to @TimS suggestion).
When it comes time to merge, each ‘sequence’:‘sub-sequence’ is processed in order, and the resulting ‘merges’ are simply concatenated together into the final file.
It took a couple tries to get the right steps, but I ran my latest chip carve file through gcodeclean’s clean, split, and merge and then cut it. The results were interesting. Cut time decreased a small amount (I didn’t record the unmodified time but remember it as about 7 1/2 minutes, the second was 7:07) but the cut order definitely improved, no more hopping all over the design. There was one funny, some of the vcuts (4 petals that were between two joined semicircles) went to half depth, then went elsewhere and then came back and finished instead of making the last few cuts in the center. The result looks the same as the first uncleaned version, so not a problem. I’d post a pic but I don’t seem to have the ability, both file upload and copy/paste upload to 100% and then get “Sorry, an error has occurred.”. I did it several times, then resized in M$ paint and tried again with the same result. I saw that on my chromebook and decided it was a chromeos weirdity, but this is with W10. I frequently upload pictures in other forums so I doubt it’s on this end. The GCodeClean log is below.
Processing sub-sequence 0:0
Pass 0: Primary Edges
Pass 1: Secondary Edges
Pass 2: Peer Seeding
Pass 3: Peer Seeding
Pass 4: Peer Seeding
Pass 5: Peer Seeding
Pass 6: Peer Seeding
Pass 7: Residual pairs
Pass 8: Residual pairs
Processing sub-sequence 0:1
Pass 0: Primary Edges
Pass 1: Secondary Edges
Pass 2: Peer Seeding
Pass 3: Peer Seeding
Pass 4: Peer Seeding
Processing sub-sequence 0:2
Pass 0: Primary Edges
Pass 1: Secondary Edges
Pass 2: Peer Seeding
Pass 3: Peer Seeding
Pass 4: Peer Seeding
Pass 5: Peer Seeding
Pass 6: Residual pairs
Processing sub-sequence 0:3
Pass 0: Primary Edges
Pass 1: Secondary Edges
Pass 2: Peer Seeding
Pass 3: Peer Seeding
Pass 4: Peer Seeding
Pass 5: Peer Seeding
Processing sub-sequence 0:4
Pass 0: Primary Edges
Pass 1: Secondary Edges
Pass 2: Peer Seeding
Pass 3: Peer Seeding
Pass 4: Peer Seeding
Total distinct tools: 1
Total nodes: 52
Total edges: 51
Starting node Id: 37
Ending node Id: 39
Current travelling distance: 918.62817637731743
New travelling distance: 889.77048439587636
Merge completed
So I read that output as 5 different ranges of depth of cut. And yeah it will organise by depth of cut first, and then try optimising the paths.
That explains it. Thanks!
Do you strip out the spindle commands? My original file had an S15000M3 but the cleaned, split, and merged version doesn’t. Not an issue for me since the current machine has a trim router spindle, but that cuts out anybody expecting a grbl controlled spindle including my dinky 3018.
That may be a bug, because I wrote the software, so you know…
If you could share the original file (feel free to PM it over) that would help track it down.
The other thing is that GCodeClean will split lines that have multiple commands, and then order those lines according to what the NIST spec says is the processing priority. So S15000M3
should end up as
S15000
M3
I’ve been busy and didn’t see this sooner. I’ll leave a note on the CNC PC to pm it to you the next time I turn it on.
@bar I’m unable to upload pictures, zipped files, or dot nc files, every attempt gets “Sorry, an error has occurred.” . I was able to post pics in the past, is it me or something else?
It happens in Chrome on both Windows and ChromeOS, so it’s not specific to one of my computers
In the interim here’s the first few lines of the original file, down to the first travel move. Nothing looks unusual to me. My postprocessor was modified to output 4 digits chasing down a problem that turned out to be a legit soft limit failure on a G2 (come on grbl, “Reset to continue” isn’t an informative soft limit trip message). I spent part of a day assuming it was related to an issue with not quite enough digits in arcs, which is an issue with Carveco that pops up periodically in another forum. It wasn’t, it was a problem with the keyboard typer not realizing his new moving gantry router couldn’t cut that far up the table , but I haven’t put my post back to 3 digits.
(VECTRIC POST REVISION)
(76EEA9F27885879E64C76150E75E20A8)
T1
G17
G21
G90
G0Z20.0000
G0X0.0000Y0.0000
S15000M3
G0X-14.8868Y-16.6196Z2.0000
G0Z1.0000
G1Z-2.4483F300.0
G1X-14.1175Y-18.3053Z-1.6757F500.0
G1X-13.3116Y-19.9197Z-0.8666
G1X-12.5967Y-21.2245Z-0.1492
G1X-12.4480Y-21.4837Z0.0000
G1X-12.8937Y-20.6974Z-0.4472
G1X-13.3116Y-19.9197Z-0.8666
G1X-14.1175Y-18.3053Z-1.6757
G1X-14.8868Y-16.6196Z-2.4483
G1X-13.7386Y-15.0255Z-1.3032
G1X-13.0487Y-14.0163Z-0.6153
G1X-12.4316Y-13.0772Z0.0000
G1X-13.0638Y-14.0389Z-0.6303
G1X-13.7386Y-15.0255Z-1.3032
G1X-14.8868Y-16.6196Z-2.4483
G1X-16.3359Y-16.2631Z-1.7067
G1X-17.5791Y-15.9020Z-1.0645
G1X-18.6275Y-15.5608Z-0.5230
G1X-19.6409Y-15.1989Z0.0000
G1X-18.4621Y-15.6168Z-0.6103
G1X-17.3596Y-15.9692Z-1.1799
G1X-16.3359Y-16.2631Z-1.7067
G1X-14.8868Y-16.6196Z-2.4483
G0Z2.0000
G0X-9.5385Y-15.8074
G0Z1.0000
G1Z-2.7994F300.0
G1X-8.8454Y-16.0308Z-2.1593F500.0
So the original clean
step changed the starting lines as follows
(VECTRIC POST REVISION)
(76EEA9F27885879E64C76150E75E20A8)
T1
(Preamble completion by GCodeClean)
G21
G90
G94
G17
G40
G49
G54
M3
(Preamble completed by GCodeClean)
G0 Z0.5
G0 X0 Y0
S15000
G0 X-14.887 Y-16.62
F300
G1 X-14.887 Y-16.62 Z-2.448
F500
G1 X-14.118 Y-18.305 Z-1.676
You’ll note that the M3
appears in the preamble, which was a simplification on my part, to ensure it got set somewhere. And then the S15000
appears where it was, and because the M3
had already been set, the next M3
(i.e. the orginal one from your GCode) gets eliminated as redundant.