Skip to content

Commit

Permalink
feat(api): support get_max_travel_z for Flex and enable use_virtual_p…
Browse files Browse the repository at this point in the history
…ipettes (#12515)

* calculate max height for simulating ot3/flex

* fix incorrect max volume and channel count in shared data

* revert channel count for dummy shared_data 96 channel

* comment better explaining the source of the virtual height

* Comment rephrasing from in-person discussion.

---------

Co-authored-by: Max Marrone <[email protected]>
  • Loading branch information
jbleon95 and SyntaxColoring authored Apr 19, 2023
1 parent 066e13e commit ca7bbba
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 11 deletions.
22 changes: 18 additions & 4 deletions api/src/opentrons/protocol_engine/execution/gantry_mover.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@
MotorAxis.RIGHT_PLUNGER: HardwareAxis.C,
}

# The height of the bottom of the pipette nozzle at home position without any tips.
# We rely on this being the same for every OT-3 pipette.
#
# We found this number by peeking at the height that OT3Simulator returns for these pipettes:
# * Single- and 8-Channel P50 GEN3
# * Single-, 8-, and 96-channel P1000 GEN3
#
# That OT3Simulator return value is what Protocol Engine uses for simulation when Protocol Engine
# is configured to not virtualize pipettes, so this number should match it.
VIRTUAL_MAX_OT3_HEIGHT = 248.0


class GantryMover(TypingProtocol):
"""Abstract class for gantry movement handler."""
Expand Down Expand Up @@ -211,9 +222,12 @@ def get_max_travel_z(self, pipette_id: str) -> float:
Args:
pipette_id: Pipette ID to get instrument height and tip length for.
"""
instrument_height = self._state_view.pipettes.get_instrument_max_height_ot2(
pipette_id
)
if self._state_view.config.robot_type == "OT-2 Standard":
instrument_height = self._state_view.pipettes.get_instrument_max_height_ot2(
pipette_id
)
else:
instrument_height = VIRTUAL_MAX_OT3_HEIGHT
tip_length = self._state_view.tips.get_tip_length(pipette_id)
return instrument_height - tip_length

Expand Down Expand Up @@ -248,7 +262,7 @@ async def home(self, axes: Optional[List[MotorAxis]]) -> None:
def create_gantry_mover(
state_view: StateView, hardware_api: HardwareControlAPI
) -> GantryMover:
"""Create a tip handler."""
"""Create a gantry mover."""
return (
HardwareGantryMover(hardware_api=hardware_api, state_view=state_view)
if state_view.config.use_virtual_pipettes is False
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,7 @@ async def create_simulating_runner(
ignore_pause=True,
use_virtual_modules=True,
use_virtual_gripper=True,
use_virtual_pipettes=(
robot_type != "OT-3 Standard"
and not feature_flags.disable_fast_protocol_upload()
),
use_virtual_pipettes=(not feature_flags.disable_fast_protocol_upload()),
),
)

Expand Down
20 changes: 18 additions & 2 deletions api/tests/opentrons/protocol_engine/execution/test_gantry_mover.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
HardwareGantryMover,
VirtualGantryMover,
create_gantry_mover,
VIRTUAL_MAX_OT3_HEIGHT,
)


Expand Down Expand Up @@ -379,12 +380,13 @@ async def test_virtual_get_position_default(
assert result == Point(x=0, y=0, z=0)


def test_virtual_get_max_travel_z(
def test_virtual_get_max_travel_z_ot2(
decoy: Decoy,
mock_state_view: StateView,
virtual_subject: VirtualGantryMover,
) -> None:
"""It should get the max travel z height with the state store."""
"""It should get the max travel z height with the state store for an OT-2."""
decoy.when(mock_state_view.config.robot_type).then_return("OT-2 Standard")
decoy.when(
mock_state_view.pipettes.get_instrument_max_height_ot2("pipette-id")
).then_return(42)
Expand All @@ -395,6 +397,20 @@ def test_virtual_get_max_travel_z(
assert result == 22.0


def test_virtual_get_max_travel_z_ot3(
decoy: Decoy,
mock_state_view: StateView,
virtual_subject: VirtualGantryMover,
) -> None:
"""It should get the max travel z height with the state store."""
decoy.when(mock_state_view.config.robot_type).then_return("OT-3 Standard")
decoy.when(mock_state_view.tips.get_tip_length("pipette-id")).then_return(48)

result = virtual_subject.get_max_travel_z("pipette-id")

assert result == VIRTUAL_MAX_OT3_HEIGHT - 48.0


async def test_virtual_move_relative(
decoy: Decoy,
mock_state_view: StateView,
Expand Down
2 changes: 1 addition & 1 deletion shared-data/pipette/definitions/1/pipetteNameSpecs.json
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,7 @@
},
"channels": 8,
"minVolume": 1,
"maxVolume": 50,
"maxVolume": 1000,
"smoothieConfigs": {
"stepsPerMM": 2133.33,
"homePosition": 230.15,
Expand Down

0 comments on commit ca7bbba

Please sign in to comment.