Skip to content

Commit

Permalink
Merge branch 'edge' into feat-hardware-testing-acceleration-in-liquid…
Browse files Browse the repository at this point in the history
…-class
  • Loading branch information
andySigler committed Jul 11, 2023
2 parents 20a38ac + 40d81f2 commit 5bd6465
Show file tree
Hide file tree
Showing 82 changed files with 2,836 additions and 803 deletions.
Binary file modified api/docs/img/tutorial/diluent.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added api/docs/img/tutorial/initial-deck-map-flex.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified api/docs/img/tutorial/row-loop.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified api/docs/img/tutorial/row-tracking.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified api/docs/img/tutorial/solution.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified api/docs/img/tutorial/stepwise-transfer.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
184 changes: 131 additions & 53 deletions api/docs/v2/tutorial.rst

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions api/src/opentrons/drivers/rpi_drivers/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def find_hub(
if (board_revision == BoardRevision.FLEX_B2) and (
hub == FLEX_B2_USB_PORT_GROUP_FRONT
):
port = 1
port = 9
hub_port = int(port_info[2])
else:
port = int(port_info[2])
Expand All @@ -120,7 +120,7 @@ def find_hub(
if board_revision == BoardRevision.FLEX_B2:
port_info = port_nodes[0].split(".")
hub = int(port_info[1])
port = 1
port = 9
hub_port = None
name = port_nodes[0]
else:
Expand Down
4 changes: 2 additions & 2 deletions api/src/opentrons/hardware_control/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from opentrons import types as top_types
from opentrons.config import robot_configs
from opentrons.config.types import RobotConfig, OT3Config
from opentrons.drivers.rpi_drivers.types import USBPort
from opentrons.drivers.rpi_drivers.types import USBPort, PortGroup

from .util import use_or_initialize_loop, check_motion_bounds
from .instruments.ot2.pipette import (
Expand Down Expand Up @@ -1117,7 +1117,7 @@ async def create_simulating_module(

return await self._backend.module_controls.build_module(
port="",
usb_port=USBPort(name="", port_number=0),
usb_port=USBPort(name="", port_number=1, port_group=PortGroup.MAIN),
type=modules.ModuleType.from_model(model),
sim_model=model.value,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,7 @@ def _next_index() -> int:
ModuleAtPort(
port=c.url,
name=c.module_type,
usb_port=USBPort(
name=c.identifier, port_number=0, hub=True, hub_port=_next_index()
),
usb_port=USBPort(name=c.identifier, port_number=_next_index()),
)
for c in message.connections
]
Expand Down
10 changes: 4 additions & 6 deletions api/src/opentrons/hardware_control/ot3api.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
CapacitivePassSettings,
LiquidProbeSettings,
)
from opentrons.drivers.rpi_drivers.types import USBPort
from opentrons.drivers.rpi_drivers.types import USBPort, PortGroup
from opentrons_hardware.hardware_control.motion_planning import (
Move,
MoveManager,
Expand Down Expand Up @@ -142,9 +142,7 @@
InstrumentDict,
GripperDict,
)
from opentrons_hardware.hardware_control.motion_planning.move_utils import (
MoveConditionNotMet,
)


from .status_bar_state import StatusBarStateController

Expand Down Expand Up @@ -485,7 +483,7 @@ async def create_simulating_module(

return await self._backend.module_controls.build_module(
port="",
usb_port=USBPort(name="", port_number=0),
usb_port=USBPort(name="", port_number=1, port_group=PortGroup.LEFT),
type=modules.ModuleType.from_model(model),
sim_model=model.value,
)
Expand Down Expand Up @@ -1227,7 +1225,7 @@ async def _home(self, axes: Sequence[OT3Axis]) -> None:
except ZeroLengthMoveError:
self._log.info(f"{axis} already at home position, skip homing")
continue
except (MoveConditionNotMet, Exception) as e:
except BaseException as e:
self._log.exception(f"Homing failed: {e}")
self._current_position.clear()
raise
Expand Down
6 changes: 6 additions & 0 deletions api/src/opentrons/protocol_api/core/engine/labware.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
LabwareDefinition as LabwareDefinitionDict,
)

from opentrons_shared_data.labware.labware_definition import LabwareRole

from opentrons.protocol_engine.errors import LabwareNotOnDeckError, ModuleNotOnDeckError
from opentrons.protocol_engine.clients import SyncClient as ProtocolEngineClient
from opentrons.types import DeckSlotName, Point
Expand Down Expand Up @@ -98,6 +100,10 @@ def is_tip_rack(self) -> bool:
"""Whether the labware is a tip rack."""
return self._definition.parameters.isTiprack

def is_adapter(self) -> bool:
"""Whether the labware is an adapter."""
return LabwareRole.adapter in self._definition.allowedRoles

def is_fixed_trash(self) -> bool:
"""Whether the labware is a fixed trash."""
return self._engine_client.state.labware.is_fixed_trash(
Expand Down
87 changes: 82 additions & 5 deletions api/src/opentrons/protocol_api/core/engine/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from opentrons.protocol_engine import (
DeckSlotLocation,
ModuleLocation,
OnLabwareLocation,
ModuleModel as EngineModuleModel,
LabwareMovementStrategy,
LabwareOffsetVector,
Expand All @@ -30,10 +31,12 @@
ModuleModel as ProtocolEngineModuleModel,
OFF_DECK_LOCATION,
LabwareLocation,
NonStackedLocation,
)
from opentrons.protocol_engine.clients import SyncClient as ProtocolEngineClient
from opentrons.protocol_engine.errors import (
LabwareNotLoadedOnModuleError,
LabwareNotLoadedOnLabwareError,
)

from ... import validation
Expand Down Expand Up @@ -134,7 +137,9 @@ def add_labware_definition(
def load_labware(
self,
load_name: str,
location: Union[DeckSlotName, ModuleCore, NonConnectedModuleCore, OffDeckType],
location: Union[
DeckSlotName, LabwareCore, ModuleCore, NonConnectedModuleCore, OffDeckType
],
label: Optional[str],
namespace: Optional[str],
version: Optional[int],
Expand Down Expand Up @@ -193,12 +198,59 @@ def load_labware(

return labware_core

def load_adapter(
self,
load_name: str,
location: Union[DeckSlotName, ModuleCore, NonConnectedModuleCore, OffDeckType],
namespace: Optional[str],
version: Optional[int],
) -> LabwareCore:
"""Load an adapter using its identifying parameters"""
load_location = self._get_non_stacked_location(location=location)

custom_labware_params = (
self._engine_client.state.labware.find_custom_labware_load_params()
)
namespace, version = load_labware_params.resolve(
load_name, namespace, version, custom_labware_params
)

load_result = self._engine_client.load_adapter(
load_name=load_name,
location=load_location,
namespace=namespace,
version=version,
)

# FIXME(jbl, 2023-06-23) read fixme above:
deck_conflict.check(
engine_state=self._engine_client.state,
new_labware_id=load_result.adapterId,
# It's important that we don't fetch these IDs from Protocol Engine, and
# use our own bookkeeping instead. If we fetched these IDs from Protocol
# Engine, it would have leaked state from Labware Position Check in the
# same HTTP run.
#
# Wrapping .keys() in list() is just to make Decoy verification easier.
existing_labware_ids=list(self._labware_cores_by_id.keys()),
existing_module_ids=list(self._module_cores_by_id.keys()),
)

labware_core = LabwareCore(
labware_id=load_result.adapterId,
engine_client=self._engine_client,
)

self._labware_cores_by_id[labware_core.labware_id] = labware_core

return labware_core

# TODO (spp, 2022-12-14): https://opentrons.atlassian.net/browse/RLAB-237
def move_labware(
self,
labware_core: LabwareCore,
new_location: Union[
DeckSlotName, ModuleCore, NonConnectedModuleCore, OffDeckType
DeckSlotName, LabwareCore, ModuleCore, NonConnectedModuleCore, OffDeckType
],
use_gripper: bool,
use_pick_up_location_lpc_offset: bool,
Expand Down Expand Up @@ -455,6 +507,18 @@ def get_labware_on_module(
except LabwareNotLoadedOnModuleError:
return None

def get_labware_on_labware(
self, labware_core: LabwareCore
) -> Optional[LabwareCore]:
"""Get the item on top of a given labware, if any."""
try:
labware_id = self._engine_client.state.labware.get_id_by_labware(
labware_core.labware_id
)
return self._labware_cores_by_id[labware_id]
except LabwareNotLoadedOnLabwareError:
return None

def get_slot_center(self, slot_name: DeckSlotName) -> Point:
"""Get the absolute coordinate of a slot's center."""
return self._engine_client.state.labware.get_slot_center_position(slot_name)
Expand Down Expand Up @@ -493,7 +557,7 @@ def define_liquid(

def get_labware_location(
self, labware_core: LabwareCore
) -> Union[str, ModuleCore, NonConnectedModuleCore, OffDeckType]:
) -> Union[str, LabwareCore, ModuleCore, NonConnectedModuleCore, OffDeckType]:
"""Get labware parent location."""
labware_location = self._engine_client.state.labware.get_location(
labware_core.labware_id
Expand All @@ -504,13 +568,26 @@ def get_labware_location(
)
elif isinstance(labware_location, ModuleLocation):
return self._module_cores_by_id[labware_location.moduleId]
elif isinstance(labware_location, OnLabwareLocation):
return self._labware_cores_by_id[labware_location.labwareId]

return OffDeckType.OFF_DECK

@staticmethod
def _convert_labware_location(
location: Union[DeckSlotName, ModuleCore, NonConnectedModuleCore, OffDeckType]
self,
location: Union[
DeckSlotName, LabwareCore, ModuleCore, NonConnectedModuleCore, OffDeckType
],
) -> LabwareLocation:
if isinstance(location, LabwareCore):
return OnLabwareLocation(labwareId=location.labware_id)
else:
return self._get_non_stacked_location(location)

@staticmethod
def _get_non_stacked_location(
location: Union[DeckSlotName, ModuleCore, NonConnectedModuleCore, OffDeckType]
) -> NonStackedLocation:
if isinstance(location, (ModuleCore, NonConnectedModuleCore)):
return ModuleLocation(moduleId=location.module_id)
elif location is OffDeckType.OFF_DECK:
Expand Down
8 changes: 6 additions & 2 deletions api/src/opentrons/protocol_api/core/labware.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,15 @@ def get_calibrated_offset(self) -> Point:

@abstractmethod
def is_tip_rack(self) -> bool:
"Whether the labware is a tip rack."
"""Whether the labware is a tip rack."""

@abstractmethod
def is_adapter(self) -> bool:
"""Whether the labware is an adapter."""

@abstractmethod
def is_fixed_trash(self) -> bool:
"Whether the labware is a fixed trash."
"""Whether the labware is a fixed trash."""

@abstractmethod
def get_tip_length(self) -> float:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ def get_calibrated_offset(self) -> Point:
def is_tip_rack(self) -> bool:
return self._parameters["isTiprack"]

def is_adapter(self) -> bool:
return False # Adapters were introduced in v2.15 and not supported in legacy protocols

def is_fixed_trash(self) -> bool:
"""Whether the labware is fixed trash."""
return "fixedTrash" in self.get_quirks()
Expand Down
35 changes: 32 additions & 3 deletions api/src/opentrons/protocol_api/core/legacy/legacy_protocol_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,12 @@ def add_labware_definition(
def load_labware(
self,
load_name: str,
location: Union[DeckSlotName, legacy_module_core.LegacyModuleCore, OffDeckType],
location: Union[
DeckSlotName,
LegacyLabwareCore,
legacy_module_core.LegacyModuleCore,
OffDeckType,
],
label: Optional[str],
namespace: Optional[str],
version: Optional[int],
Expand All @@ -157,6 +162,10 @@ def load_labware(
raise APIVersionError(
"Loading a labware off deck is only supported with apiLevel 2.15 and newer."
)
elif isinstance(location, LegacyLabwareCore):
raise APIVersionError(
"Loading a labware onto another labware or adapter is only supported with api version 2.15 and above"
)

deck_slot = (
location if isinstance(location, DeckSlotName) else location.get_deck_slot()
Expand Down Expand Up @@ -224,12 +233,25 @@ def load_labware(

return labware_core

def load_adapter(
self,
load_name: str,
location: Union[DeckSlotName, legacy_module_core.LegacyModuleCore, OffDeckType],
namespace: Optional[str],
version: Optional[int],
) -> LegacyLabwareCore:
"""Load an adapter using its identifying parameters"""
raise APIVersionError("Loading adapter is not supported in this API version.")

# TODO (spp, 2022-12-14): https://opentrons.atlassian.net/browse/RLAB-237
def move_labware(
self,
labware_core: LegacyLabwareCore,
new_location: Union[
DeckSlotName, legacy_module_core.LegacyModuleCore, OffDeckType
DeckSlotName,
LegacyLabwareCore,
legacy_module_core.LegacyModuleCore,
OffDeckType,
],
use_gripper: bool,
use_pick_up_location_lpc_offset: bool,
Expand Down Expand Up @@ -424,6 +446,11 @@ def get_labware_on_module(
labware = module_core.geometry.labware
return cast(LegacyLabwareCore, labware._core) if labware is not None else None

def get_labware_on_labware(
self, labware_core: LegacyLabwareCore
) -> Optional[LegacyLabwareCore]:
assert False, "get_labware_on_labware only supported on engine core"

def get_deck_definition(self) -> DeckDefinitionV3:
"""Get the geometry definition of the robot's deck."""
assert False, "get_deck_definition only supported on engine core"
Expand All @@ -450,6 +477,8 @@ def define_liquid(

def get_labware_location(
self, labware_core: LegacyLabwareCore
) -> Union[str, legacy_module_core.LegacyModuleCore, OffDeckType]:
) -> Union[
str, LegacyLabwareCore, legacy_module_core.LegacyModuleCore, OffDeckType
]:
"""Get labware parent location."""
assert False, "get_labware_location only supported on engine core"
Loading

0 comments on commit 5bd6465

Please sign in to comment.