-
Notifications
You must be signed in to change notification settings - Fork 175
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
fix(api): Exclude existing module offsets when running subsequent module calibrations #12667
fix(api): Exclude existing module offsets when running subsequent module calibrations #12667
Conversation
Codecov Report
@@ Coverage Diff @@
## edge #12667 +/- ##
==========================================
+ Coverage 73.29% 73.56% +0.26%
==========================================
Files 1506 2260 +754
Lines 49424 62140 +12716
Branches 2998 6597 +3599
==========================================
+ Hits 36227 45714 +9487
- Misses 12741 14834 +2093
- Partials 456 1592 +1136
Flags with carried forward coverage won't be shown. Click here to find out more.
|
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.
The functionality looks good but I'm a little nervous doing this get_raw_module_offset
and then subtracting it thing. It makes the code in the calibration command depend on the internal behavior of other modules. We're now depending on the implicit contract that the only offset from nominal in the well position is whatever get_raw_module_offset
returns, which is a contract across two separate modules.
What if instead we have get_nominal_well_position
, which probably internally depends on a get_nominal_module_position
(and maybe raises NotImplementedError
if you ask it for the nominal position of a well that's not something on a labware)? Now we've made the contract explicit: if you ask for get_nominal_well_position()
, it must take into account nothing but the predefined geometry.
I think that would be a little more robust to regressions.
api/src/opentrons/protocol_engine/commands/calibration/calibrate_module.py
Outdated
Show resolved
Hide resolved
… function so we can get the module offset vector with or without calibrated module offsets added get_labware_parent_position which has the same functionality as the previous get_labware_position but without the calibrated module offsets get_labware_position now uses the new get_labware_parent_position method and adds the calibrated module offsets with the new get_labware_offset_vector function this lets us use get_nominal_well_position to just get the uncalibrated well position when calibrating modules updated the thermocycler calibration adapter definition to match the source dimensions
… function so we can get the module offset vector with or without calibrated module offsets added get_labware_parent_position which has the same functionality as the previous get_labware_position but without the calibrated module offsets get_labware_position now uses the new get_labware_parent_position method and adds the calibrated module offsets with the new get_labware_offset_vector function this lets us use get_nominal_well_position to just get the uncalibrated well position when calibrating modules updated the thermocycler calibration adapter definition to match the source dimensions
…tps:https://github.com/Opentrons/opentrons into RCORE-738_clear-offset-on-new-module-calibration
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.
This looks great to me aside from those couple nits! Nice work!
@@ -630,7 +630,16 @@ def get_dimensions(self, module_id: str) -> ModuleDimensions: | |||
"""Get the specified module's dimensions.""" | |||
return self.get_definition(module_id).dimensions | |||
|
|||
def get_module_offset( | |||
def get_module_offset_vector(self, module_id: str) -> ModuleOffsetVector: |
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.
nit: can we call this get_module_calibration_offset
? i'm getting confused by having both this and get_module_offset
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.
Agreed. The only reason get_labware_offset_vector()
is named like it is is because the official terminology is that Labware Position Check saves labware offsets, not labware calibrations. (🤷) But "calibration" is more specific than just "offset," so it's nice to say "calibration" when we can.
parent_pos = self.get_labware_parent_origin_position(labware_id) | ||
origin_offset = self._labware.get_definition(labware_id).cornerOffsetFromSlot | ||
well_def = self._labware.get_well_definition(labware_id, well_name) | ||
return Point( |
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.
nit: could do return parent_pos + origin_offset + well_def + Point(x=0, y=0, z=well_def.depth)
but it's up to you whether that's clearer or not
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.
Code makes sense to me. Thanks!
The overall approach also makes sense to me, but with a caveat: it only protects loadModule
commands. That means, in the module calibration flows, we'll have to be careful that the app doesn't issue any other commands that would visit this module.
For example, if the app did a moveToWell
command, that would still use the module's old calibration, right? The app does issue other commands like moveToWell
during Labware Position Check. So we should make sure it doesn't need to do that for module calibration.
@@ -630,7 +630,16 @@ def get_dimensions(self, module_id: str) -> ModuleDimensions: | |||
"""Get the specified module's dimensions.""" | |||
return self.get_definition(module_id).dimensions | |||
|
|||
def get_module_offset( | |||
def get_module_offset_vector(self, module_id: str) -> ModuleOffsetVector: |
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.
Agreed. The only reason get_labware_offset_vector()
is named like it is is because the official terminology is that Labware Position Check saves labware offsets, not labware calibrations. (🤷) But "calibration" is more specific than just "offset," so it's nice to say "calibration" when we can.
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.
LGTM!
Just the two naming suggestions similar to @sfoster1 's
) | ||
|
||
def get_labware_parent_position(self, labware_id: str) -> Point: |
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.
..and change this to get_labware_parent_calibrated_position
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.
kept it as is for consistency
Am I understanding your concern correctly that if a |
No—my concern is that if a For example, imagine if the app had a step where it did |
Overview
Module Calibrations were failing because the calibration starting position was being shifted by the previous module calibration value for the given module, which meant that eventually the starting position would be way off-center and would not be able to find the calibration square. This PR addresses this issue and fixes another issue with non-connected modules (magnetic block) where we would throw
ModuleNotConnectedError
when trying to get the labware well position.Closes: RCORE-738
Test Plan
ModuleNotConnectedError
when getting the position for labware on top of the magnetic block.Changelog
Review requests
Make sure we are comfortable with the get_module_changes which affect get_well_position
Risk assessment
medium, while this affects module calibration directly any changes to get_module_offset also affect get_well_position