Using the Gripper (RoMa)
>=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, orLEFT— defaults to the arm's current direction.pick_up_offset: aVector(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 (default6).
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
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.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