Skip to content
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(api): add internal xy belt calibration method #12204

Merged
merged 8 commits into from
Mar 20, 2023

Conversation

pmoegenburg
Copy link
Member

@pmoegenburg pmoegenburg commented Feb 28, 2023

Overview

Run automatic calibration for the gantry x and y belts attached to the specified mount. Returned linear transform matrix is determined via the actual and nominal center points of the back right (A), front right (B), and back left (C) slots.

Test Plan

  • Run calibrate_belts method on OT3 via repl.py to verify linear transform matrix is as expected
    • Robot SZ DVT 7 transform matrix: [[0.9984, -0.0004, 0.0], [0.0007, 1.0001, 0.0], [0.0, 0.0, 1.0]]
  • Verify utilizing linear transform matrix results in move to desired defined point. This will be done by Test Engineering in future

Changelog

Review requests

Risk assessment

@pmoegenburg pmoegenburg self-assigned this Feb 28, 2023
@pmoegenburg pmoegenburg requested a review from a team as a code owner February 28, 2023 02:09
@codecov
Copy link

codecov bot commented Feb 28, 2023

Codecov Report

Merging #12204 (9ec13cc) into edge (b618e9b) will not change coverage.
The diff coverage is n/a.

Impacted file tree graph

@@           Coverage Diff           @@
##             edge   #12204   +/-   ##
=======================================
  Coverage   73.79%   73.79%           
=======================================
  Files        2203     2203           
  Lines       60602    60602           
  Branches     6245     6245           
=======================================
  Hits        44724    44724           
  Misses      14441    14441           
  Partials     1437     1437           
Flag Coverage Δ
notify-server 89.13% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
api/src/opentrons/hardware_control/scripts/repl.py 0.00% <ø> (ø)

Copy link
Member

@sfoster1 sfoster1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think we've got a couple math issues here, put it inline.

We should also maybe make calibrate_belts use opentrons.util.linal.solve_attitude, but this implementation once fixed will also work. However, if we want to keep this implementation, we should refactor lines 882-889 into their own function that takes a list of actual points and a list of nominal points and returns the attitude and test it... which is basically linal.solve_attitude


return (
((point_c.x - point_a.x) / nominal_x),
((point_b.x - point_a.x) / nominal_y),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look correct, right? It doesn't make sense to divide an x distance by a y distance, or a y distance by an x distance.

return (
((point_c.x - point_a.x) / nominal_x),
((point_b.x - point_a.x) / nominal_y),
), (((point_c.y - point_a.y) / nominal_x), ((point_b.y - point_a.y) / nominal_y))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

Copy link
Member

@sfoster1 sfoster1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, this looks good to me once tested!

Copy link
Contributor

@Laura-Danielle Laura-Danielle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, I think the math looks good. However, if you want to utilize the capacitive probe to perform these functions, you'll actually need to add the probe length before doing that.

Take a look at calibrate_pipette for reference. Also @sfoster1 , I am assume we'll want to make sure we're not baking in any offsets from instrument calibration?

If this is the case, we should also make sure to reset the instrument offset (which again can be found in the calibrate_pipette function.

The actual and nominal centers of the specified slot.
"""
nominal_center = _get_calibration_square_position_in_slot(slot)
z_height = await find_deck_height(hcapi, mount, nominal_center)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we using a pipette to find the deck height? As this stands now, the probe length is not taken into account in this function.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That should be handled by the machine->deck transformation right? Or is this an old comment

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is specifically regarding probing the deck w/ a capacitive probe.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And yes it's taken care of now in calibrate_belts

@Laura-Danielle
Copy link
Contributor

If this test should only be performed using the pipette mounts, we should also throw an error if a gripper mount is passed in.

Copy link
Member

@sfoster1 sfoster1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good, couple more things though.

"""
if mount == OT3Mount.GRIPPER:
raise RuntimeError("Must use pipette mount, not gripper")
try:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rather than have a whole bunch of stuff inside a try block, let's put all that stuff in a function and just call the function in a try block

if mount == OT3Mount.GRIPPER:
raise RuntimeError("Must use pipette mount, not gripper")
try:
await hcapi.reset_instrument_offset(mount)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have three problems with this:

First, if we want to reset instrument offset to default, we need to pass to_default=True here; otherwise, this will just reload the current saved instrument offset.
Second, if we want to reset the instrument offset to default before calibration, we need to reload it from disk afterwards with an await hcapi.reset_instrument_offset(mount) in the finally-block.
Finally, we don't actually need to do reset the instrument offset here because we're calculating a linear transform, so any offset applied equally to all points will fall out.

I think on balance we should just remove this call, but if we want to keep it we need to fix the to_default and not resetting it afterwards thing.

Copy link
Member

@sfoster1 sfoster1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, this looks good to me!

Copy link
Contributor

@Laura-Danielle Laura-Danielle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Agree w / Seth re: instrument cal stuff not being necessary :)

@sfoster1 sfoster1 removed the WIP label Mar 17, 2023
@pmoegenburg pmoegenburg merged commit 3bf370c into edge Mar 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants