UniteLabs

Using the Gripper (RoMa)

Moving labware around the deck with the Tecan Freedom EVO's Robotic Manipulator Arm.
The Freedom EVO is supported in liquid handling SDK versions >=0.35.0.

The Freedom EVO's Robotic Manipulator (RoMa) is a plate gripper that moves labware between deck sites. It is mounted on a separate arm that is independent from the pipetting head and approaches labware from one of four cardinal directions.

Prerequisites

  • A switched on Tecan Freedom EVO device with a Robotic Manipulator Arm
  • A plate carrier with a plate
  • A running Tecan Freedom EVO connector
  • Basic understanding of the liquid handler class (See Deck & Carriers)

Connect and Initialize

from unitelabs.sdk import AsyncApiClient
from unitelabs.liquid_handling.tecan import TecanFreedomEvo

client = AsyncApiClient()

evo = TecanFreedomEvo(name="Tecan Freedom EVO", client=client)
await evo.configure()
await evo.initialize()
await evo.activate()
gripper is a vendor-neutral alias for roma — both refer to the same RoboticManipulatorArm instance.

Arrange the Deck

from unitelabs.labware.plates import Standard96Plate
from unitelabs.labware.tecan import MP_3Pos_flat

plate_carrier = MP_3Pos_flat()
plate = Standard96Plate(identifier="Plate_96Well")
plate_carrier[0] = plate
evo.deck.add(plate_carrier, track=1)

Pick Up Labware

Pass the labware object directly to pick_up(). The RoMa approaches from its current facing direction unless approach_direction is given explicitly.

from unitelabs.liquid_handling.tecan import ApproachDirection

await evo.roma.pick_up(plate, approach_direction=ApproachDirection.FRONT)
assert evo.roma.get() == plate
assert await evo.roma.has_labware() is True

pick_up() accepts optional parameters to fine-tune the grip:

  • approach_direction: FRONT, RIGHT, BACK, or LEFT — defaults to the arm's current direction.
  • pick_up_offset: a Vector(dx, dy) in mm to adjust the pick-up location.
  • width_offset: an offset in mm to adjust the assumed size of the labware.
  • grip_gap: the initial gap between the gripper and the labware before closing, in mm (default 6).
Offset alignment: if you use pick_up_offset when picking up, pass the same value as drop_offset to put_down. A mismatch can misalign the gripper on the drop.

Put Down Labware

Pass the target carrier site to put_down() — indexing a carrier returns its CarrierSite objects, not the deck. plate_carrier[1] is the second (empty) site of the 3-position carrier used above.

await evo.roma.put_down(plate_carrier[1], approach_direction=ApproachDirection.FRONT)
assert evo.roma.get() is None
assert plate_carrier[1].get() == plate
Rotated placement: dropping from a different approach_direction than the labware was picked up with lands it physically rotated on the deck. The labware's own rotation attribute is updated to match, so downstream resource-graph state stays accurate.

Pick Up From / Transfer

pick_up_from references a carrier site directly instead of the labware object:

await evo.roma.pick_up_from(plate_carrier[1])
await evo.roma.put_down(plate_carrier[1])

transfer() combines pick up and put down into a single call:

await evo.roma.transfer(plate, target=plate_carrier[2])

transfer_from() moves labware between two sites without needing a reference to the labware object:

await evo.roma.transfer_from(
    source=plate_carrier[2],
    target=plate_carrier[0],
)

Gripper Fingers

Open or close the fingers directly, independent of a pick up/put down operation.

# Open to a specific width (mm, finger to finger)
await evo.roma.open_to(width=100)

# Close onto a plate; searches for it under the configured current limit
await evo.roma.close_to(width=80)

# Current opening width
width = await evo.roma.current_grip_width()

# Reachable travel limits (finger to finger), in mm
lower, upper = await evo.roma.get_gripper_machine_range()
close_to()/close_by() raise a RuntimeError if the gripper is already holding labware — release it with open_to() first.
Calling open_to() while the gripper is holding labware unassigns the labware from the gripper — it's no longer attached to any carrier site either, so you must manually reassign it by calling assign() on the target site (e.g. plate_carrier[1].assign(plate)). Prefer put_down() over open_to() for placing labware, since it does this internally; using open_to() to release labware is mainly for error recovery.

Configure the grip search parameters:

await evo.roma.set_gripper_parameters(
    speed=50,          # search speed while closing, in mm/s (0.1-150)
    pwm_limit=100,     # gripper PWM limit (0-249)
    current_limit=2,   # grip strength as current limit (0-3)
)

Arm Movement

Move the RoMa body directly by absolute location or relative offset.

from unitelabs.labware import Vector

await evo.roma.move_to(location=Vector(x=200, y=150, z=100), rotation=0)
await evo.roma.move_by(offset=Vector(z=-10), rotation_offset=90)
location = await evo.roma.current_location()
rotation = await evo.roma.current_rotation()
direction = await evo.roma.current_direction()  # nearest ApproachDirection within 90°

Initialization Variants

If a standard initialize() fails due to an obstruction at the rear, bring the arm to the front first with two_step_initialize().

await evo.roma.two_step_initialize()
errors = await evo.roma.get_extended_error()  # per-axis (X, Y, Z, R, G) error codes

Troubleshooting