Work in Progress: GCode Optimization in WebControl

I started working on adding a routine to webcontrol to perform gcode optimization. I stumbled upon a python implementation of travelling salesperson problem (TSP) that used genetic algorithm that I think will work with some adaptation since this isn’t precisely a TSP:

I made some modifications to it and I think it will work. But the real difficulty with gcode optimization turns out to be the parsing of the gcode and its re-assembly after the code is optimized. So I started this thread in hope knowledgeable people could provide some feedback and answer questions.

*Note:I’m putting aside optimizing gcode with tool changes, lasers, spindle control, relative positioning etc. until I can get gcode without any of them optimized.

In a CAM program, you typically set a traverse height that’s used for G0 moves. I can parse through gcode and determine what that value is and then use that to rebuild the G0 moves.

My first question: is there any reason to assume a gcode would have different traverse heights in G0 commands? That is, one G0 command uses 5 mm whereas another would use 7 mm? My thought is to just use the max Z value in a G0 command as the traverse height… this assumes that some silly CAM program would not just start off with a G0 Z25 but then use G0 Z5 when preparing to do a G0 XY? I wouldn’t want to use 25 for all the traverses when 5 is what the user wanted.

Right now I am breaking the gcode up into segments bracketed by G0/G00 commands… this leads to the following questions:

My second question: is there any reason to expect a CAM program to use a G0 Z command to move downward into a work piece? I would expect anything into a work piece to be a G1 Z command.

My third question: is there any reason to expect a CAM program to use a G0 Z command to move upward but not out completely out of a work piece? For example, during a move to cut a tab, might a gcode program use G0 Z+ to lift the bit to clear the tab? Since it’s not cutting material, maybe some CAM program might use max feed rate…

5 Likes

I wanted to add a huge thumbs up to this approach. I have a maslow system running development code, so I can help test alpha webcontrol versions to help. Anything that will help with optimization is desired. Having said that I’ll offer what limited perspective I have with the disclaimer that my experience is extremely limited.

  1. I think no. There is no reason to assume gcode would have different traverse heights on the maslow. The reasoning is that with maslow we are working on a planar surface, not a contour and we have no reference z map so if a different height was needed, the sled effectively makes it a relative height if it clears it… if that makes sense.

  2. G0 by definition (according to my friend google) is a fast move / traverse, not a cut, so I would echo that sentiment with a “No” it is not reasonable to expect a plunge with a G0 command. if anything it would only be a raise or lower to "travel height.

  3. Echoing the sentiment of #2, if cutting like in a carve operation, this should be expected to be a G1, not a G0. In my “vast and varied” (air quotes for sarcastic effect) experience, I’ve only ever seen a tab cut as if it were a complete skip and the cutter goes to g0 travelling height, the next position is located, bit lowers and cutting resumes. If an intermediate cut is desired, then it should be a G1, not a G0.

My question regarding optimization: There are a few different approaches to cutting successive depths that I have seen

  1. the entire shape at one depth, then the next depth…
  2. groups of shapes at one depth, then the next, then the next, then the next group of shapes.
  3. each line segment (or arc segment) at each depth, then the next segment until the entire shape is complete.

Depending on how you organize the gcode, in the optimization, you may need to/be forced to lock on a specific approach to be consistent. What does the TSP algorithm do with that and will that affect or be affected by the optimization algorithm of interest? I read something recently about an ant colony approach where you swap nodes until the overall path is shortest, but they didn’t offer code.

I wanted to add a huge thumbs up to this approach. I have a maslow system running development code, so I can help test alpha webcontrol versions to help. Anything that will help with optimization is desired. Having said that I’ll offer what limited perspective I have with the disclaimer that my experience is extremely limited.

  1. I think no. There is no reason to assume gcode would have different traverse heights on the maslow. The reasoning is that with maslow we are working on a planar surface, not a contour and we have no reference z map so if a different height was needed, the sled effectively makes it a relative height if it clears it… if that makes sense.

nothing prevents it, but I wouldn’t expect CAM to use different hights, but
someone manually manipulating gcode could do so.

  1. G0 by definition (according to my friend google) is a fast move / traverse, not a cut, so I would echo that sentiment with a “No” it is not reasonable to expect a plunge with a G0 command. if anything it would only be a raise or lower to "travel height.

I could see it if you are switching tools, rough out with one tool and then move
down close to that rapidly before going slowly and cutting

I’ve accidently done cuts with g0, the only difference between g0 and g1 is that
g0 is supposed to move at the max feed rate your machine supports while g1 goes
at the tate you specify.

  1. Echoing the sentiment of #2, if cutting like in a carve operation, this
    should be expected to be a G1, not a G0. In my “vast and varied” (air quotes
    for sarcastic effect) experience, I’ve only ever seen a tab cut as if it were
    a complete skip and the cutter goes to g0 travelling height, the next position
    is located, bit lowers and cutting resumes. If an intermediate cut is
    desired, then it should be a G1, not a G0.

agreed (with the emphisis on ‘should be’)

My question regarding optimization: There are a few different approaches to cutting successive depths that I have seen

  1. the entire shape at one depth, then the next depth…
  2. groups of shapes at one depth, then the next, then the next, then the next group of shapes.
  3. each line segment (or arc segment) at each depth, then the next segment until the entire shape is complete.

Depending on how you organize the gcode, in the optimization, you may need
to/be forced to lock on a specific approach to be consistent. What does the
TSP algorithm do with that and will that affect or be affected by the
optimization algorithm of interest? I read something recently about an ant
colony approach where you swap nodes until the overall path is shortest, but
they didn’t offer code.

I think the thing to do is

  1. minimize the G0 movement
  2. minimize the Z movement

any G1 movement can be re-ordered, but not eliminated.

David Lang

Don’t cam programs make the g-code according to the post-processor for the machine it will run on?
FreeCAD for example exports with LinuxCNC post-processor G0 for fast moves at clamping clearance height and safe height. Simple but does the job.
G1 G2 is for the cuts in material.
I might have got the question wrong, just wanted to say i missed you guys.

G0 Z6.000 (safe height)
G0 X18.947 Y21.547
G0 Z4.000 (clamping clearance)
G1 X18.947 Y21.547 Z-1.500 F1800.000
G2 X20.094 Y19.494 Z-1.500 I-3.047 J-3.047 F1800.000 (circular holes)
G2 X11.706 Y17.506 Z-1.500 I-4.194 J-0.994 F1800.000
G2 X18.947 Y21.547 Z-1.500 I4.194 J0.994 F1800.000
G1 X18.947 Y21.547 Z-3.000 F1800.000
G2 X20.094 Y19.494 Z-3.000 I-3.047 J-3.047 F1800.000
G2 X11.706 Y17.506 Z-3.000 I-4.194 J-0.994 F1800.000
G2 X18.947 Y21.547 Z-3.000 I4.194 J0.994 F1800.000

more or less, it’s more different flavor of machine.

LinuxCNC is one target, no matter what the machine details are
grbl in one target, no matter what the machine details are

the maslow is very close to grbl compatible

The simplicity of both is a nice target,

Estlcam is pretty darn spiffy… the author uses G0 Z moves from the traverse height to drop the bit to just above the worksurface and then issues the G1 command to penetrate rather than issuing a G1 command from the traverse height. To avoid eliminating that nicety, I now scan the file for the highest G0 Z move, use that as the traverse height and then treat all G0 Z moves that don’t reach that height as part of a path.

For example, here’s a snippet of an engraving of a line:

1)  ;Project linesDrawing1
2)  ;Created by Estlcam version 11 build 11.119
3)  ;Machining time about 00:04:02 hours
4)  G90
5)  M03 S24000
6)  G00 X0.0000 Y0.0000
7)  G00 Z5.0000
8)  ;No. 1: Engraving 1
9)  G00 Y76.2000
10) G00 Z0.5000
11) G01 Z-5.0000 F150
12) G01 Y0.0000 F480
13) G00 Z5.0000

The optimizer treats lines 1-5 as header lines because they precede any move and they get added to the beginning of the optimized gcode. Scanning through the code, both lines 7 and 13 are Z-axis moves to 5mm (the greatest Z height) and therefore the program will use 5mm as the traverse height. The program right now will create just one “path” from this file with start and end coordinates of (0, 76) and (0, 0), respectively with a start index of 10 and end index of 12 (the G0 line below traverse and all the G1 lines). The G00 moves at traverse are dumped since they new ones get created after optimization.

I seldom do full height tabs… most of the time I opt for half height… but regardless, based upon the above, it will treat any G0 or G1 Z-move that isn’t at traverse height as part of a cutting path.

The primary goal is to reduce the total distance traveled by G0 moves. That’s basically all that can be optimized from what I can tell without doing CAM itself.

1 Like

The method I use basically divides things up into groups of paths where the router bit is into the workpiece. So a multipass cut that drops 5 mm per pass is treated as one single path group and all the lines stay together. If your gcode does a single 100 mm circle, 5mm depth of cut per pass, to a depth of 25 mm, then there is nothing to optimize because its treated as one single path group (there wouldn’t be any G00 movements to optimize).

Now if the CAM program trying to generate two 100 mm circles produces code that does a 100 mm circle at 5 mm, moves over and does another 100 mm at 5 mm, then goes back and does the first circle at 10 mm, then the second circle at 10 mm, then back to the first at 15 mm… and so on, then the optimizer would optimize it and reorder it so it does the first circle then the second circle (if you follow). But, during each pass it would raise the Z axis to traverse height and then drop down again. I guess this could be a further optimization that might address @dlang’s comment regarding minimizing z-axis movement. But my concern is that drill operations raise and lower the bit to clear the hole… so I wouldn’t want to optimize that out. Lots to think about.

1 Like

And my last post for the night. I switched algorithms and ditched the genetic thing as it produced really, really bad results and was very slow. It probably needed tweaking, but I found other code using google’s OR tools and it was rather easy to implement… its fast and produced good results. This is a snippet of the gcode for a field of stars (part of the one of my kid’s American flag project I did a couple years ago) as it came out of Makercam:

Here’s it after maybe 15 seconds of optimization was completed… a lot of long, meaningless G0 moves were eliminated:

3 Likes

a drill operation would be a g1, not a g0 (IIRC, g2 and g3 are similar but
moving in arcs)

if you can re-order things to minimize the g0/g2 movement that is a fantastic
first step

but if movment up to the transverse height is g1, then you want to minimize
that.

a peck operation would be down/up/down/(up/down repeated)

a wasted move to the traverse height would be movement in any other
direction/up/down/movement in another direction

let the user set a flag to let you remove that so that if this is needed, they
can get the rest of the optimization, but by default look for this up/down and
eliminate it.

also, look for any G1 movement that’s above Z=0 and have an option that will
convert that to G0 movement.

define your blocks of movement as g-code that’s bounded by Z movement with no
x/y movement

In a later revision you can look at the entry point into a shape and direction
of cut type of thing, but a first pass that re-orders things to minimize G0 and
Z axis movement will give the biggest bang for the buck.

David Lang

what do the g-code simulators say about how much time is saved by the new
version?

As you are processing this g-code it may make sense to try to run a time
estimator

I think it’s either

  1. each line of G-code takes X ms
  2. calculate movement based on speed limit (and Z axis speed)

or each line of G-code takes a minimum of X ms, and if the movement is small
enough, that minimum applies

David Lang

I haven’t really tested it beyond seeing if it looks optimized… I just got it working late last night. Unfortunately, groundcontrol/webcontrol doesn’t have a run time estimator, but I agree it would be a good thing as that’s really the metric of how optimized it is.

I think I can do this and just replicate what estlcam does (i.e., drop to just above worksurface using g0 and penetrate using g1).

This is astounding. Awesome!!!

I would be very curious how optimal the paths are that are generated by Kiri:Moto by default for these complex parts. There were recent code improvements for cases just like this. If you enable “depth first” under “output” in CNC mode, it should optimize for local cuts and moves.

Post a sample.

Hey @madgrizzle that’s really awesome what you are doing!
I often wonders why the gcode is that overload with movements. Nice to see someone with knowhow working on it :muscle:

If people could send me sample gcode files at madgrizzlemaslow at gmail dot com, I’d appreciate it. I need a good sample from various cam programs to test with. I’m particularly interested in ones with tool changes and spindle control.

Big setback in that or-tools that I use for optimization isn’t supported on the RPI platform. I have to find something else.

1 Like

Hey @madgrizzle
I will send you some gcodes later!

How is it going?
This is the :fire: project that i am looking forward to :hugs:

Well, I haven’t found an alternate routine that works on the rpi, so this has taken a back seat for a while.