Skip to content

Interpreting gcode

Peter Boin edited this page Jul 30, 2017 · 4 revisions

Interpreting GCode

Interpreting what a line of gcode does depends on the machine it's running on, and also that machine's state (or 'mode')

The simple line of a rapid move to x=10, y=10 may be G00 X10 Y10. However, if the machine in question is in "Incremental Motion" mode G91 then the machine will only end up at x=10, y=10 if it started at x=0, y=0

So, GCode interpretation is done via a virtual machine:

>>> from pygcode import Machine, GCodeRapidMove

>>> m = Machine()
>>> m.pos
<Position: X0 Y0 Z0>
>>> g = GCodeRapidMove(X=10, Y=20)
>>> m.process_gcodes(g)
>>> m.pos
<Position: X10 Y20 Z0>
>>> m.process_gcodes(g)
>>> m.pos
<Position: X10 Y20 Z0>   # same position; machine in absolute mode
>>> m.mode.distance
<GCodeAbsoluteDistanceMode: G90>  # see

>>> m.process_gcodes(GCodeIncrementalDistanceMode())
>>> m.process_gcodes(g)  # same gcode as above
>>> m.pos
<Position: X20 Y40 Z0>

all valid m.mode attributes can be found with from pygcode.gcodes import MODAL_GROUP_MAP; MODAL_GROUP_MAP.keys()

Also note that the order codes are interpreted is important. For example, the following code is WRONG

from pygcode import Machine, Line
m = Machine()
line = Line('G0 x10 y10 G91')
m.process_gcodes(*line.block.gcodes)  # WRONG!

This will process the movement to x=10, y=10, and then it will change the distance mode to Incremental... there are 2 ways to do this correctly.

  • m.process_gcodes(*sorted(line.block.gcodes)), or simply
  • m.process_block(line.block)

sorting a list of gcodes will sort them in execution order (as specified by LinuxCNC's order of execution). process_block does this automatically.

If you need to process & change one type of gcode (usually a movement), you must split a list of gcodes into those executed before, and after the one in question.

from pygcode import GCodeRapidMove, GCodeLinearMove
from pygcode import Machine, Line, split_gcodes
m = Machine()
line = Line('M0 G0 x10 y10 G91')
(befores, (g,), afters) = split_gcodes(line.block.gcodes, (GCodeRapidMove, GCodeLinearMove))
m.process_gcodes(*sorted(befores))
if g.X is not None:
    g.X += 100  # shift linear movements (rapid or otherwise)
m.process_gcodes(g)
m.process_gcodes(*sorted(afters))

For a more practical use of machines & interpreting gcode, have a look at the pygcode-norm script

At the time of writing this, that script converts arcs to linear codes, and expands drilling cycles to basic movements (so my GRBL machine can understand them)

Clone this wiki locally