Skip to content


Our G-Code API provides a way to use G-Codes to control Zaber devices. The library interprets the codes and outputs Zaber ASCII protocol stream commands. You can review the usage of Streams in this article and the stream commands in the protocol manual. This article assumes a basic understanding of G-Code.

Basic Usage

Starting with basic G-Code translation is easy.

# from zaber_motion.gcode import Translator

stream = device.get_stream(1)
stream.setup_live(1, 2)

translator = Translator.setup(stream)

translator.translate("G0 X100")
translator.translate("G0 Y100")
translator.translate("G0 X0 Y0")


First, you need to set up a live stream over the designated axes. Then, set up an instance of the @class Translator class over the stream. Afterward, you can start translating G-Code by calling the @method Translate method. The device may not start moving immediately after calling @method Translate because the instructions are buffered in the library for optimization. Additionally, the movements are also queued in the device to allow for smooth motion. To ensure that the library sends all the movements, call the @method Flush method. The method also waits for the device to finish all the queued movements. At the end, we should call the @method Disabled method to release the axes from the stream.

The @method Translate method also returns a the @class TranslateResult data class instance. The instance contains generated commands as well as warnings produced during translation. The warnings can be useful in determining ignored or unknown instructions.

result = translator.translate("G28 G999")
# {'_commands': ['on a b line abs 0 0'],
# '_warnings': [{'_message': 'Unknown command G999.', '_from_block': 4, '_to_block': 8}]}

Additionally the translation can throw the @class GCodeSyntaxException and the @class GCodeExecutionException exceptions containing details of what went wrong.


The translator's @method Setup method takes additional argument for configuring the translator.

translator = Translator.setup(stream, TranslatorConfig(
    AxisMapping('X', axis_index=1),
    AxisMapping('Y', axis_index=0)
    AxisTransformation("X", scaling=-1),
    AxisTransformation("Y", translation=Measurement(20, Units.LENGTH_MILLIMETRES)),

You can use the configuration to remap translator axes or transform the coordinates of an axis. For example, you can invert the axis by specifying scaling=-1 or offset it by 20 mm by specifying translation.

Coordinate Systems

The translator support 9 coordinate system: G54-G59 and G59.1-G59.3. You can set coordinate system offset by programming G10 L2 P? where P? is the coordinate system number (G54 is P1). You can also retrieve currently used coordinate system or an offset of axis in a given coordinate system. See the example below.

translator.translate("G10 L2 P3 X200 Y50") # set up offset for G56
translator.translate("G56") # select G56
# prints G56
offset = translator.get_axis_coordinate_system_offset("G56", "X", Units.LENGTH_MILLIMETRES)
# prints 200

Interaction with Other Hardware

It's often useful to interact with other hardware on top of Zaber devices. You can, for example, use M-code M3 to turn on a spindle of a milling machine with digital input on Zaber controller. The example below demonstrates exactly that.

with open("C:\\prototype.tap") as file:
  while True:
    line = file.readline()
    if not line:
      break # EOF
    else if line == "M3":
      translator.flush() # finish all queued movements
      stream.set_digital_output(1, True) # turn on digital output
      time.sleep(30) # wait 30 seconds for the spindle to reach full speed
      translator.translate(line) # all the other instructions

It is crucial to always call the @method Flush method before interacting with other hardware. By calling the method, you ensure that the device has reached the final position in the submitted G-Code.

If you also perform some movement outside of G-Code, make sure to call the @method ResetPosition method afterwards. The method queries the device and updates translator's internal position to match the device. Alternatively, you can use the @method SetPosition method to update the position manually.

Using patterns like the one above, you can interact with any external hardware like PLC, laser, pumps, etc.

Stream Command Passthrough

We provide a special M-Code M700 that allows to pass stream commands directly to the underlying stream. The commands are provided in G-Code comments with parentheses.

result = translator.translate("M700 (wait io ai 1 >= 0.5) (wait 200)")
# {'_commands': ['wait io ai 1 >= 0.5', 'wait 200'],
# '_warnings': []}

The example above passes two commands to the stream. The first one waits for analog input 1 to get above 0.5 V. The second one then waits additional 200 ms.

Path Control Mode

The translator supports continuous path mode (G64) where it rounds corners of line segments to maintain speed. The current implementation has certain limitations. Firstly, the corners are only rounded up to a specified path deviation from a corner (in contrast to milling machines' ability to maintain constant milling speed). You can specify the deviation with P parameter; otherwise, the default value of 0.1 mm applies. Secondly, the translator only looks ahead at two consequent linear movements and always reaches each segment at worst case as a tangent.

G64 is a default path control mode.

In addition to G64 the translator also supports exact path mode G61 and exact stop mode G61.1. Use these modes to enforce the exact travel of the specified path. You may also use G9 exact stop instruction to enforce stopping after a single block.

Offline Translation

In addition to streaming G-Code directly to the device, we also provide a way to translate instructions without sending the commands. You can, for example, use this for simulation purposes or processing of the generated commands.

# from zaber_motion.gcode import OfflineTranslator

translator = OfflineTranslator.setup(DeviceDefinition(device_id=30331, axes=[
  AxisDefinition(peripheral_id=70245, microstep_resolution=64),
  AxisDefinition(peripheral_id=70245, microstep_resolution=64),
  AxisDefinition(peripheral_id=70245, microstep_resolution=64),
], max_speed=Measurement(100, Units.VELOCITY_MILLIMETRES_PER_SECOND)))

result = translator.translate("G28")
# {'_commands': ['on a b c line abs 0 0 0'], '_warnings': [] }

In order to create an offline translator, you have to specify information about the device. You can find this information by accessing device settings in Zaber Launcher.

The interface of the @class OfflineTranslator class is nearly identical the one of the @class Translator class with notable exception of @method Translate and @method Flush methods being synchronous.

Supported Codes

The translator supports a wide range of semi-standard G-Codes and M-Codes.

  • G0 - traverse line
  • G1 - line
  • G2, G3 - arc, without support for parameters R and P
  • G4 - dwell (P in seconds)
  • G10 - set coordinate system (L2 only)
  • G17, G18, G19 - plane selection
  • G21 - millimeter system selection
  • G28, G28.1 - return to home, set home to the current position
  • G30, G30.1 - return to secondary home, set secondary home to the current position
  • G53 - machine coordinate system
  • G54-G59, G59.1-G59.3 - coordinate system selection
  • G61, G61.1, G64 - path control mode
  • G90, G91 - absolute/relative mode (G91 is default)
  • G90.1, G91.1 - absolute/relative arc distance mode (G91.1 is default)
  • G92, G92.1 - temporary work offset (not recommended)
  • M2, M30 - program stop and end
  • M64, M65 - set digital output
  • M66 - wait on input (E not supported; L0,L1,L2 not supported; Q not supported; use M700 when possible)
  • M68 - set analog output

If you require support of some additional codes for your application, please let us know.

Non-supported Codes

There are some codes that we explicitly don't support at this moment.

  • G20 - inch system selection
  • G40, G41, G42 - tool radius compensation
  • G43, G44, G49 - tool length compensation
  • G93 - inverse time feed rate mode
  • G95 - feed rate per revolution

Custom Codes

Here you find all non-standard codes specific to our implementation.

  • M700 - stream command passthrough