Skip to content

Commit 7620f90

Browse files
committed
feat(api): add latch_clearance param to the store_labware and dispense_labware commands.
1 parent 838194b commit 7620f90

File tree

8 files changed

+298
-380
lines changed

8 files changed

+298
-380
lines changed

api/src/opentrons/hardware_control/modules/flex_stacker.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,9 @@ async def move_axis(
428428
max_speed=speed, acceleration=acceleration
429429
)
430430
distance = direction.distance(distance)
431+
log.warning(
432+
f"MOVE: Axis {axis} {distance} mm in the {direction} direction speed={speed} accel={acceleration}"
433+
)
431434
res = await self._driver.move_in_mm(axis, distance, params=motion_params)
432435
if res == MoveResult.STALL_ERROR:
433436
self._stall_detected = True
@@ -458,6 +461,9 @@ async def home_axis(
458461
motion_params = default.move_params.update(
459462
max_speed=speed, acceleration=acceleration
460463
)
464+
log.warning(
465+
f"HOME: Axis {axis} in the {direction} direction speed={speed} accel={acceleration}"
466+
)
461467
success = await self._driver.move_to_limit_switch(
462468
axis=axis, direction=direction, params=motion_params
463469
)
@@ -513,8 +519,10 @@ async def dispense_labware(
513519
labware_height: float,
514520
enforce_hopper_lw_sensing: bool = True,
515521
enforce_shuttle_lw_sensing: bool = True,
522+
latch_clearance: Optional[float] = None,
516523
) -> None:
517524
"""Dispenses the next labware in the stacker."""
525+
log.warning(f"DISPENSE: {labware_height}")
518526
self.verify_labware_height(labware_height)
519527
await self._prepare_for_action()
520528
if enforce_hopper_lw_sensing:
@@ -526,7 +534,8 @@ async def dispense_labware(
526534

527535
# Transfer
528536
await self.open_latch()
529-
latch_clear_distance = labware_height + PLATFORM_OFFSET - LATCH_CLEARANCE
537+
latch_clearance = latch_clearance or LATCH_CLEARANCE
538+
latch_clear_distance = labware_height + PLATFORM_OFFSET - latch_clearance
530539
await self.move_axis(StackerAxis.Z, Direction.RETRACT, latch_clear_distance)
531540
await self.close_latch()
532541

@@ -543,8 +552,10 @@ async def store_labware(
543552
self,
544553
labware_height: float,
545554
enforce_shuttle_lw_sensing: bool = True,
555+
latch_clearance: Optional[float] = None,
546556
) -> None:
547557
"""Stores a labware in the stacker."""
558+
log.warning(f"STORE: {labware_height}")
548559
self.verify_labware_height(labware_height)
549560
await self._prepare_for_action()
550561

@@ -554,7 +565,8 @@ async def store_labware(
554565
await self.verify_shuttle_labware_presence(Direction.RETRACT, True)
555566

556567
# Move the Z so the labware sits right under any labware already stored
557-
latch_clear_distance = labware_height + PLATFORM_OFFSET + LATCH_CLEARANCE
568+
latch_clearance = latch_clearance or LATCH_CLEARANCE
569+
latch_clear_distance = labware_height + PLATFORM_OFFSET + latch_clearance
558570
distance = MAX_TRAVEL[StackerAxis.Z] - latch_clear_distance
559571
await self.move_axis(StackerAxis.Z, Direction.EXTEND, distance)
560572

api/src/opentrons/protocol_api/core/engine/module_core.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -724,14 +724,15 @@ class FlexStackerCore(ModuleCore, AbstractFlexStackerCore[LabwareCore]):
724724

725725
_sync_module_hardware: SynchronousAdapter[hw_modules.FlexStacker]
726726

727-
def retrieve(self) -> LabwareCore:
727+
def retrieve(self, latch_clearance: Optional[float] = None) -> LabwareCore:
728728
"""Retrieve a labware from the Flex Stacker's hopper.
729729
730730
Returns the primary labware.
731731
"""
732732
self._engine_client.execute_command(
733733
cmd.flex_stacker.RetrieveParams(
734734
moduleId=self.module_id,
735+
latchClearance=latch_clearance,
735736
)
736737
)
737738
base = self._protocol_core.get_labware_on_module(self)
@@ -742,11 +743,12 @@ def retrieve(self) -> LabwareCore:
742743
return primary
743744
return base
744745

745-
def store(self) -> None:
746+
def store(self, latch_clearance: Optional[float] = None) -> None:
746747
"""Store a labware into Flex Stacker's hopper."""
747748
self._engine_client.execute_command(
748749
cmd.flex_stacker.StoreParams(
749750
moduleId=self.module_id,
751+
latchClearance=latch_clearance,
750752
)
751753
)
752754

api/src/opentrons/protocol_api/core/module.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -407,14 +407,14 @@ def get_serial_number(self) -> str:
407407
"""Get the module's unique hardware serial number."""
408408

409409
@abstractmethod
410-
def retrieve(self) -> AbstractLabware[Any]:
410+
def retrieve(self, latch_clearance: Optional[float] = None) -> AbstractLabware[Any]:
411411
"""Release a labware from the hopper to the staging slot.
412412
413413
Returns the retreived primary labware.
414414
"""
415415

416416
@abstractmethod
417-
def store(self) -> None:
417+
def store(self, latch_clearance: Optional[float] = None) -> None:
418418
"""Store a labware in the stacker hopper."""
419419

420420
@abstractmethod

api/src/opentrons/protocol_api/module_contexts.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,15 +1130,15 @@ def serial_number(self) -> str:
11301130
return self._core.get_serial_number()
11311131

11321132
@requires_version(2, 25)
1133-
def retrieve(self) -> Labware:
1133+
def retrieve(self, latch_clearance: Optional[float] = None) -> Labware:
11341134
"""Retrieve a labware from the Flex Stacker and place it on the shuttle.
11351135
11361136
:returns: The retrieved :py:class:`Labware` object. This will always be the main labware,
11371137
even if the Flex Stacker contains labware on an adapter. To get the adapter object,
11381138
call :py:class:`Labware.parent` on the returned labware.
11391139
11401140
"""
1141-
labware_core = self._core.retrieve()
1141+
labware_core = self._core.retrieve(latch_clearance=latch_clearance)
11421142

11431143
return self._core_map.get_or_add(
11441144
labware_core,
@@ -1148,9 +1148,9 @@ def retrieve(self) -> Labware:
11481148
)
11491149

11501150
@requires_version(2, 25)
1151-
def store(self) -> None:
1151+
def store(self, latch_clearance: Optional[float] = None) -> None:
11521152
"""Move the labware currently on the Flex Stacker shuttle into the Flex Stacker."""
1153-
self._core.store()
1153+
self._core.store(latch_clearance=latch_clearance)
11541154

11551155
def _labware_to_cores(self, labware: Sequence[Labware]) -> list[LabwareCore]:
11561156
return [labware._core for labware in labware]

api/src/opentrons/protocol_engine/commands/flex_stacker/retrieve.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ class RetrieveParams(BaseModel):
9191
description="Do not use. Present for internal backward compatibility.",
9292
json_schema_extra=_remove_default,
9393
)
94+
latchClearance: float | SkipJsonSchema[None] = Field(
95+
None,
96+
description="optional latch clearance",
97+
)
9498

9599

96100
class RetrieveResult(BaseModel):
@@ -269,7 +273,8 @@ async def execute(self, params: RetrieveParams) -> _ExecuteReturn:
269273
try:
270274
stacker_hw.set_stacker_identify(True)
271275
await stacker_hw.dispense_labware(
272-
labware_height=stacker_state.get_pool_height_minus_overlap()
276+
labware_height=stacker_state.get_pool_height_minus_overlap(),
277+
latch_clearance=params.latchClearance,
273278
)
274279
except (
275280
FlexStackerStallError,

api/src/opentrons/protocol_engine/commands/flex_stacker/store.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ class StoreParams(BaseModel):
5959
...,
6060
description="Unique ID of the flex stacker.",
6161
)
62+
latchClearance: float | SkipJsonSchema[None] = Field(
63+
None,
64+
description="optional latch clearance",
65+
)
6266

6367

6468
class StoreResult(BaseModel):
@@ -205,7 +209,8 @@ async def execute(self, params: StoreParams) -> _ExecuteReturn:
205209
if stacker_hw is not None:
206210
stacker_hw.set_stacker_identify(True)
207211
await stacker_hw.store_labware(
208-
labware_height=stacker_state.get_pool_height_minus_overlap()
212+
labware_height=stacker_state.get_pool_height_minus_overlap(),
213+
latch_clearance=params.latchClearance,
209214
)
210215
except FlexStackerStallError as e:
211216
return DefinedErrorData(

0 commit comments

Comments
 (0)