Skip to content

Commit

Permalink
fix(api,hardware-testing): Fix wrong polarity in module offsets + ref…
Browse files Browse the repository at this point in the history
…actor module calibration test script and add verification step. (#12733)

* fix(api,hardware-testing): Fix the wrong polarity in module offsets + refactor module calibration test script and add verification step.

- Fixed issue with module calibration offset getting generated with the wrong polarity
- Fixed issue with module calibration where get_nominal_module_offset was applying the calibrated module offset
- Added calibration_target arg and enums to find_calibration_structure_position method so we can reverse the calibration offset based on whether we are calibrating a deck object (module) or gantry instrument (pipette, gripper, etc)
- Refactor the module calibration test script and added OpentronsHTTPAPI HTTP wrapper class to consolidate functionality
- Added a verification step to the module calibration test script so we can confirm the center square with/without offsets.
- Added urllib3, certifi, and charset-normalizer to Pipfile.lock for hardware_testing module
  • Loading branch information
vegano1 authored May 22, 2023
1 parent bdb2bce commit a58eb35
Show file tree
Hide file tree
Showing 5 changed files with 551 additions and 179 deletions.
28 changes: 25 additions & 3 deletions api/src/opentrons/hardware_control/ot3_calibration.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ class CalibrationMethod(Enum):
NONCONTACT_PASS = "noncontact pass"


class CalibrationTarget(Enum):
DECK_OBJECT = "deck_object"
GANTRY_INSTRUMENT = "gantry_instrument"


class CalibrationStructureNotFoundError(RuntimeError):
def __init__(self, structure_height: float, lower_limit: float) -> None:
super().__init__(
Expand Down Expand Up @@ -546,7 +551,11 @@ async def _calibrate_mount(
try:
# find the center of the calibration sqaure
offset = await find_calibration_structure_position(
hcapi, mount, nominal_center, method, raise_verify_error
hcapi,
mount,
nominal_center,
method=method,
raise_verify_error=raise_verify_error,
)
# update center with values obtained during calibration
LOG.info(f"Found calibration value {offset} for mount {mount.name}")
Expand All @@ -570,6 +579,7 @@ async def find_calibration_structure_position(
mount: OT3Mount,
nominal_center: Point,
method: CalibrationMethod = CalibrationMethod.BINARY_SEARCH,
target: CalibrationTarget = CalibrationTarget.GANTRY_INSTRUMENT,
raise_verify_error: bool = True,
) -> Point:
"""Find the calibration square offset given an arbitry postition on the deck."""
Expand All @@ -582,7 +592,15 @@ async def find_calibration_structure_position(
found_center = await find_calibration_structure_center(
hcapi, mount, initial_center, method, raise_verify_error
)
return nominal_center - found_center

offset = nominal_center - found_center
# NOTE: If the calibration target is a deck object the polarity of the calibrated
# offset needs to be reversed. This is because we are using the gantry instrument
# to calibrate a stationary object on the deck and need to find the offset of that
# deck object relative to the deck and not the instrument which sits above the deck.
if target == CalibrationTarget.DECK_OBJECT:
return offset * -1
return offset


async def find_slot_center_binary_from_nominal_center(
Expand Down Expand Up @@ -782,7 +800,11 @@ async def calibrate_module(
# from the nominal position so we dont have to alter any other part of the system.
nominal_position = nominal_position - PREP_OFFSET_DEPTH
offset = await find_calibration_structure_position(
hcapi, mount, nominal_position, method=CalibrationMethod.BINARY_SEARCH
hcapi,
mount,
nominal_position,
method=CalibrationMethod.BINARY_SEARCH,
target=CalibrationTarget.DECK_OBJECT,
)
await hcapi.save_module_offset(module_id, mount, slot, offset)
return offset
Expand Down
12 changes: 1 addition & 11 deletions api/src/opentrons/protocol_engine/state/modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
Union,
overload,
)
from numpy import array, dot, add
from numpy import array, dot

from opentrons.hardware_control.modules.magdeck import (
OFFSET_TO_LABWARE_BOTTOM as MAGNETIC_MODULE_OFFSET_TO_LABWARE_BOTTOM,
Expand Down Expand Up @@ -669,16 +669,6 @@ def get_nominal_module_offset(
# Apply the slot transform, if any
xform = array(xforms_ser_offset)
xformed = dot(xform, pre_transform) # type: ignore[no-untyped-call]

# add the calibrated module offset if there is one
module = self.get(module_id)
offset: Optional[ModuleOffsetVector] = None
if module.serialNumber is not None:
offset = self._state.module_offset_by_serial.get(module.serialNumber)

if offset is not None:
module_offset = array((offset.x, offset.y, offset.z, 1))
xformed = add(xformed, module_offset)
return LabwareOffsetVector(
x=xformed[0],
y=xformed[1],
Expand Down
97 changes: 97 additions & 0 deletions hardware-testing/Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit a58eb35

Please sign in to comment.