-
Notifications
You must be signed in to change notification settings - Fork 179
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(engine): add mmToEdge parameter to touchTip #17107
base: edge
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,11 @@ | |
|
||
from opentrons.types import Point | ||
|
||
from ..errors import TouchTipDisabledError, LabwareIsTipRackError | ||
from ..errors import ( | ||
TouchTipDisabledError, | ||
TouchTipIncompatibleArgumentsError, | ||
LabwareIsTipRackError, | ||
) | ||
from ..types import DeckPoint | ||
from .command import ( | ||
AbstractCommandImpl, | ||
|
@@ -45,6 +49,12 @@ class TouchTipParams(PipetteIdMixin, WellLocationMixin): | |
), | ||
) | ||
|
||
mmToEdge: Optional[float] = Field( | ||
None, | ||
description="Offset away from the the well edge, in millimeters." | ||
"Incompatible when a radius is included as a non 1.0 value.", | ||
) | ||
|
||
speed: Optional[float] = Field( | ||
None, | ||
description=( | ||
|
@@ -89,6 +99,11 @@ async def execute( | |
labware_id = params.labwareId | ||
well_name = params.wellName | ||
|
||
if params.radius != 1.0 and params.mmToEdge is not None: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the radius of 1.0 a ratio, or is it a value in millimeters? |
||
raise TouchTipIncompatibleArgumentsError( | ||
"Cannot use mmToEdge with a radius that is not 1.0" | ||
) | ||
|
||
if self._state_view.labware.get_has_quirk(labware_id, "touchTipDisabled"): | ||
raise TouchTipDisabledError( | ||
f"Touch tip not allowed on labware {labware_id}" | ||
|
@@ -112,11 +127,13 @@ async def execute( | |
pipette_id, params.speed | ||
) | ||
|
||
mm_to_edge = params.mmToEdge if params.mmToEdge is not None else 0 | ||
touch_waypoints = self._state_view.motion.get_touch_tip_waypoints( | ||
pipette_id=pipette_id, | ||
labware_id=labware_id, | ||
well_name=well_name, | ||
radius=params.radius, | ||
mm_to_edge=mm_to_edge, | ||
center_point=Point( | ||
center_result.public.position.x, | ||
center_result.public.position.y, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -53,15 +53,19 @@ def get_move_type_to_well( | |
|
||
|
||
def get_edge_point_list( | ||
center: Point, x_radius: float, y_radius: float, edge_path_type: EdgePathType | ||
center: Point, | ||
x_radius: float, | ||
y_radius: float, | ||
mm_to_edge: float, | ||
edge_path_type: EdgePathType, | ||
) -> List[Point]: | ||
"""Get list of edge points dependent on edge path type.""" | ||
edges = EdgeList( | ||
right=center + Point(x=x_radius, y=0, z=0), | ||
left=center + Point(x=-x_radius, y=0, z=0), | ||
right=center + Point(x=x_radius - mm_to_edge, y=0, z=0), | ||
left=center + Point(x=-x_radius + mm_to_edge, y=0, z=0), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
? |
||
center=center, | ||
forward=center + Point(x=0, y=y_radius, z=0), | ||
back=center + Point(x=0, y=-y_radius, z=0), | ||
forward=center + Point(x=0, y=y_radius - mm_to_edge, z=0), | ||
back=center + Point(x=0, y=-y_radius + mm_to_edge, z=0), | ||
) | ||
|
||
if edge_path_type == EdgePathType.LEFT: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -327,6 +327,7 @@ def get_touch_tip_waypoints( | |
labware_id: str, | ||
well_name: str, | ||
center_point: Point, | ||
mm_to_edge: float, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why isn't this defaulted to 0.0 here? |
||
radius: float = 1.0, | ||
) -> List[motion_planning.Waypoint]: | ||
"""Get a list of touch points for a touch tip operation.""" | ||
|
@@ -346,7 +347,11 @@ def get_touch_tip_waypoints( | |
) | ||
|
||
positions = _move_types.get_edge_point_list( | ||
center_point, x_offset, y_offset, edge_path_type | ||
center=center_point, | ||
x_radius=x_offset, | ||
y_radius=y_offset, | ||
mm_to_edge=mm_to_edge, | ||
edge_path_type=edge_path_type, | ||
) | ||
critical_point: Optional[CriticalPoint] = None | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -102,8 +102,99 @@ async def test_touch_tip_implementation( | |
pipette_id="abc", | ||
labware_id="123", | ||
well_name="A3", | ||
center_point=Point(x=1, y=2, z=3), | ||
radius=0.456, | ||
mm_to_edge=0, | ||
center_point=Point(x=1, y=2, z=3), | ||
) | ||
).then_return( | ||
[ | ||
Waypoint( | ||
position=Point(x=11, y=22, z=33), | ||
critical_point=CriticalPoint.XY_CENTER, | ||
), | ||
Waypoint( | ||
position=Point(x=44, y=55, z=66), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are these dummy return values supposed to be consistent with the size and center of the well at all? |
||
critical_point=CriticalPoint.XY_CENTER, | ||
), | ||
] | ||
) | ||
|
||
decoy.when( | ||
await mock_gantry_mover.move_to( | ||
pipette_id="abc", | ||
waypoints=[ | ||
Waypoint( | ||
position=Point(x=11, y=22, z=33), | ||
critical_point=CriticalPoint.XY_CENTER, | ||
), | ||
Waypoint( | ||
position=Point(x=44, y=55, z=66), | ||
critical_point=CriticalPoint.XY_CENTER, | ||
), | ||
], | ||
speed=9001, | ||
) | ||
).then_return(Point(x=4, y=5, z=6)) | ||
|
||
result = await subject.execute(params) | ||
|
||
assert result == SuccessData( | ||
public=TouchTipResult(position=DeckPoint(x=4, y=5, z=6)), | ||
state_update=update_types.StateUpdate( | ||
pipette_location=update_types.PipetteLocationUpdate( | ||
pipette_id="abc", | ||
new_location=update_types.Well(labware_id="123", well_name="A3"), | ||
new_deck_point=DeckPoint(x=4, y=5, z=6), | ||
) | ||
), | ||
) | ||
|
||
|
||
async def test_touch_tip_implementation_with_mm_to_edge( | ||
decoy: Decoy, | ||
mock_state_view: StateView, | ||
mock_movement_handler: MovementHandler, | ||
mock_gantry_mover: GantryMover, | ||
subject: TouchTipImplementation, | ||
) -> None: | ||
"""A TouchTip command should use mmToEdge if provided.""" | ||
params = TouchTipParams( | ||
pipetteId="abc", | ||
labwareId="123", | ||
wellName="A3", | ||
wellLocation=WellLocation(offset=WellOffset(x=1, y=2, z=3)), | ||
mmToEdge=0.789, | ||
speed=42.0, | ||
) | ||
|
||
decoy.when( | ||
await mock_movement_handler.move_to_well( | ||
pipette_id="abc", | ||
labware_id="123", | ||
well_name="A3", | ||
well_location=WellLocation(offset=WellOffset(x=1, y=2, z=3)), | ||
current_well=None, | ||
force_direct=False, | ||
minimum_z_height=None, | ||
speed=None, | ||
operation_volume=None, | ||
) | ||
).then_return(Point(x=1, y=2, z=3)) | ||
|
||
decoy.when( | ||
mock_state_view.pipettes.get_movement_speed( | ||
pipette_id="abc", requested_speed=42.0 | ||
) | ||
).then_return(9001) | ||
|
||
decoy.when( | ||
mock_state_view.motion.get_touch_tip_waypoints( | ||
pipette_id="abc", | ||
labware_id="123", | ||
well_name="A3", | ||
radius=1.0, | ||
mm_to_edge=0.789, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm confused what this is testing. Where in these tests do they demonstrate the I was going to call you out for using non-fraction-of-2 values in the test :) expecting that your test would fail because |
||
center_point=Point(x=1, y=2, z=3), | ||
) | ||
).then_return( | ||
[ | ||
|
@@ -183,3 +274,20 @@ async def test_touch_tip_no_tip_racks( | |
|
||
with pytest.raises(errors.LabwareIsTipRackError): | ||
await subject.execute(params) | ||
|
||
|
||
async def test_touch_tip_incompatible_arguments( | ||
decoy: Decoy, mock_state_view: StateView, subject: TouchTipImplementation | ||
) -> None: | ||
"""It should disallow touch tip if radius and mmToEdge is provided.""" | ||
params = TouchTipParams( | ||
pipetteId="abc", | ||
labwareId="123", | ||
wellName="A3", | ||
wellLocation=WellLocation(), | ||
radius=1.23, | ||
mmToEdge=4.56, | ||
) | ||
|
||
with pytest.raises(errors.TouchTipIncompatibleArgumentsError): | ||
await subject.execute(params) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you describe this value as the offset "from the the well edge," do you want to call it
mmFromEdge
?