Gifan Thadathil
G-code is a low-level numerical control language. It interfaces between software and hardware in Computerized Numerical Control (CNC) machines. The g-code-tools module provides a structure for G-code as well as reading and writing functions. Furthermore, it provides a handful of functions for manipulating G-code.
The ad hoc nature of G-code motivates this library’s existence. G-code is often machine specific. Not every machine will interpret commands in the same way, and not every machine will mechanically support every defined command in G-code. One of the author’s machines didn’t use the Cartesian coordinate system G-code assumes — not to mention there are multiple competing standards for G-code. Since many CNC machines make use of automatically generated G-code, it is likely the generated G-code will not work for your machine.
This package provides tools for programmatically modifying G-code. You can use it to create programs that convert generated G-code into machine-specific G-code.
Note:
g-code-tools is intended for use with G-code generated with another program. It provides only limited support for manual G-coders.
We try to be standard-agnostic with our assumptions, but loosely follow the LinuxCNC standard.
A G-code program is very similar to assembly. A program is a list of commands organized into lines: one command on each line. A command is made up of codes, separated by spaces. It has two components, the name of the command and its parameters. Each of these are codes. A code is a letter and a number. The structures we provide reflect exactly this organization.
procedure
( g-code-sym? val)→boolean?
val:any/c
sym:g-code-sym?num:number?
;G0;X150.574;F500;Throws exn:fail;Throws exn:fail
name:code?
;G0 X100 Y100;G4 P1000;S255;G0 X100 Y100 G1 X0 Y0 is okay, but it is invalid G-code since;there are 2 actual commands.
Since structures are annoying to write, we provide some convenient macros for writing G-code in Racket.
;(code 'G 0)(cdG0);(code 'X 120.45)(cdX120.45);Error!(cdX120.45)
;(command (code 'G 0) (list (code 'X 10) (code 'Y 10)))(cmdG0X10Y10)
;(list (command (code 'G 0) (list (code 'X 10) (code 'Y 10)));(command (code 'G 0) (list (code 'X 20) (code 'Y 20)));(command (code 'M 5) '()))(cmds(G0X10Y10)(G0X20Y20)(M5))
procedure
( read-g-code [in])→(listof command? )
Note that we do not yet provide useful error messages on syntactically malformed input! Furthermore, semantically invalid input will be successfully read in.
procedure
( write-g-code cmds[out]num-decs)→void?
As for style, each command is written to a new line, and that is all. No comments or anything else is added to minimize file sizes. Before writing, every number is rounded to num-decs decimal places.
cd:code?cd:code?cd:code?cd:code?cd:code?cd:code?cd:code?cd:code?cd:code?cd:code?cd:code?cd:code?
procedures
( g-command? cmd)→boolean?
cmd:command?cmd:command?cmd:command?cmd:command?cmd:command?cmd:command?cmd:command?cmd:command?cmd:command?cmd:command?cmd:command?cmd:command?
procedure
( param-in-command? cdcmd)→boolean?
cd:code?cmd:command?
procedure
( param-by-sym symcmd)→(or/c code? #f)
sym:g-code-sym?cmd:command?
Some commands operate on coordinates, which are specified with a certain group of codes. For example "G0 X20 Y20 Z20" tells the machine to move quickly to coordinate (20, 20, 20). The X, Y, and Z codes together specify the coordinate.
Within Racket, a coordinate is a list with one, two, or three elements depending on the number of dimensions. Each element should be a coordinate code.
procedure
( coord-code? cd)→boolean?
cd:code?
> (coord? 20)
procedures
( empty-coord? coord)→boolean?
coord:coord?coord:coord?coord:coord?coord:coord?coord:coord?coord:coord?coord:coord?coord:coord?coord:coord?coord:coord?coord:coord?coord:coord?coord:coord?
The number of codes should match the expected number of dimensions.
The order of codes should match the name of the function. For example a list of a X, Y, and Z code matches xyz-code?, but a list of a Y, X, and Z code would not.
procedure
cmd:command?
procedure
( update-commands cmdsupdater)→(listof command? )
procedure
( update-program-coords cmdsupdater)→(listof command? )
(map (lambda (a-cmd)(update-coords a-cmdupdater))cmds)
The following lists (in no particular order) new functionality/changes that are planned. We make no guarantees, but we will try. Anyone is free to send a pull request!
Better support for more codes. For example, a function for changing all F codes, which represent feed rates.
Semantic validation of G-code. This means ensuring multiple commands aren’t on the same line, checking for proper parameters to commands, etc.
Tool-path simulations.
Sorting functions for minimizing non-work movement.
G-code to pict and pict to G-code conversion. Other converters?
Multi-threaded functions.
First release.