Interpreting gcode - fragmuffin/pygcode GitHub Wiki
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 simplym.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)