-
Notifications
You must be signed in to change notification settings - Fork 39
Interpreting gcode
To read gcode from a file, utilise the Line class. Each Line
instance contains a Block and an optional Comment. The Block
contains a list of gcodes you're after.
from pygcode import Line
with open('part.gcode', 'r') as fh:
for line_text in fh.readlines():
line = Line(line_text)
print(line) # will print the line (with cosmetic changes)
line.block.gcodes # is your list of gcodes
line.block.modal_params # are all parameters not assigned to a gcode, assumed to be motion modal parameters
if line.comment:
line.comment.text # your comment text
To elaborate, here are some line examples
>>> from pygcode import Line
>>> line = Line('G01 x1 y2 f100 s1000 ; blah')
>>> print(line)
G01 X1 Y2 F100 S1000 ; blah
>>> print(line.block)
G01 X1 Y2 F100 S1000
>>> sorted(line.block.gcodes)
[<GCodeFeedRate: F100>,
<GCodeSpindleSpeed: S1000>,
<GCodeLinearMove: G01{X1, Y2}>]
>>> print(line.comment)
; blah
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 pygcode-normalize.py
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)
Usage
Commands
Information