Two Dimensional Gantry

A common configuration of zaber devices is to create a 2D gantry by making a base of lock-stepped LC40s moving in the x direction, with a single LC40 atop them moving perpendicularly in the y direction. This can be nicely represented as a pair of moveables. To create a pair of axes, using millimeters as their default units:

Python
C#
C++
JavaScript
Java
default_units = DefaultMotionUnits(
    position=Units.LENGTH_MILLIMETRES,
    speed=Units.VELOCITY_MILLIMETRES_PER_SECOND,
    acceleration=Units.ACCELERATION_MILLIMETRES_PER_SECOND_SQUARED,
)
x_axis = Moveable.from_lockstep(device.get_lockstep(1), default_units)
y_axis = Moveable.from_axis(device.get_axis(3), default_units)
const defaultUnits = {
  position: Length.MILLIMETRES,
  speed: Velocity.MILLIMETRES_PER_SECOND,
  acceleration: Acceleration.MILLIMETRES_PER_SECOND_SQUARED,
};
const xAxis = await Moveable.fromLockstep(device.getLockstep(1), { units: defaultUnits });
const yAxis = await Moveable.fromAxis(device.getAxis(3), { units: defaultUnits });
var defaultUnits = new DefaultMotionUnits {
    Position = Units.Length_Millimetres,
    Speed = Units.Velocity_MillimetresPerSecond,
    Acceleration = Units.Acceleration_MillimetresPerSecondSquared
};
var xAxis = Moveable.FromLockstep(device.GetLockstep(1), defaultUnits);
var yAxis = Moveable.FromAxis(device.GetAxis(3), defaultUnits);
DefaultMotionUnits defaultUnits = new DefaultMotionUnits(
    Units.LENGTH_MILLIMETRES,
    Units.VELOCITY_MILLIMETRES_PER_SECOND,
    Units.ACCELERATION_MILLIMETRES_PER_SECOND_SQUARED,
    null
);
Moveable xAxis = Moveable.fromLockstep(device.getLockstep(1), defaultUnits);
Moveable yAxis = Moveable.fromAxis(device.getAxis(3), defaultUnits);
DefaultMotionUnits defaultUnits(
    Units::LENGTH_MILLIMETRES,
    Units::VELOCITY_MILLIMETRES_PER_SECOND,
    Units::ACCELERATION_MILLIMETRES_PER_SECOND_SQUARED,
    {}
);
Moveable xAxis = Moveable::fromLockstep(device.getLockstep(1), defaultUnits);
Moveable yAxis = Moveable::fromAxis(device.getAxis(3), defaultUnits);

These can then be controlled and queried with all the methods of the Moveable API.

Moving together

There are two basic ways of moving both axes to a point at once

With an async function

In this case, use your languages async functionality to run two move commands at once. This will ensure that all commands are complete before continuing:

Python
C#
C++
JavaScript
Java
await asyncio.gather(x_axis.move_absolute_async(100), y_axis.move_absolute_async(100))
await Promise.all([xAxis.moveAbsolute(100), yAxis.moveAbsolute(100)]);
Task.WaitAll(
    xAxis.MoveAbsoluteAsync(100),
    yAxis.MoveAbsoluteAsync(100)
);
CompletableFuture.allOf(
    xAxis.moveAbsoluteAsync(new MeasurementOrValue(100.0)),
    yAxis.moveAbsoluteAsync(new MeasurementOrValue(100.0))
).join();
auto xMove100 = std::async(std::launch::async, [&]{ xAxis.moveAbsolute(100.0); });
auto yMove100 = std::async(std::launch::async, [&]{ yAxis.moveAbsolute(100.0); });
xMove100.get();
yMove100.get();

With wait until idle

This is the better method to use if you don't want to write async code. By setting wait until idle to false, you tell the method to start the action, and then continue on to the next line of code before the move is complete. However, after sending the move commands you must call the Wait Until Idle method on every moving axis. Otherwise, the gantry may start acting on its next instructions before all moves are complete and result in unpredictable behavior:

Python
C#
C++
JavaScript
Java
x_axis.move_absolute(200, wait_until_idle=False)
y_axis.move_absolute(200, wait_until_idle=False)
x_axis.wait_until_idle()
y_axis.wait_until_idle()
xAxis.moveAbsolute(200, { waitUntilIdle: false });
yAxis.moveAbsolute(200, { waitUntilIdle: false });
await xAxis.waitUntilIdle();
await yAxis.waitUntilIdle();
xAxis.MoveAbsolute(200, waitUntilIdle: false);
yAxis.MoveAbsolute(200, waitUntilIdle: false);
xAxis.WaitUntilIdle();
yAxis.WaitUntilIdle();
xAxis.moveAbsolute(new MeasurementOrValue(200.0), null, null, false);
yAxis.moveAbsolute(new MeasurementOrValue(200.0), null, null, false);
xAxis.waitUntilIdle();
yAxis.waitUntilIdle();
xAxis.moveAbsolute(200.0, {}, {}, false);
yAxis.moveAbsolute(200.0, {}, {}, false);
xAxis.waitUntilIdle();
yAxis.waitUntilIdle();