-
Notifications
You must be signed in to change notification settings - Fork 184
feat(api): save gripper jaw width to robot fs #18532
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
base: edge
Are you sure you want to change the base?
Conversation
7d73c67
to
cd7a2c9
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## edge #18532 +/- ##
==========================================
+ Coverage 24.83% 25.48% +0.65%
==========================================
Files 3274 3275 +1
Lines 281044 280870 -174
Branches 33831 33744 -87
==========================================
+ Hits 69786 71580 +1794
+ Misses 211237 209268 -1969
- Partials 21 22 +1
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
@@ -56,6 +56,7 @@ def reset_gripper(self) -> None: | |||
self._gripper = new_gripper | |||
|
|||
async def reset(self) -> None: | |||
# TODO(cm): do we want to reset the gripper jaw width here as well? |
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.
Review Request
do we want to reset the gripper jaw width where we do the calibration data?
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.
yes but that's not here - it's in reset_instrument_offset
. this reset
is part of the instrument load mechanics
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.
To clarify, Are you asking if we should clear what's on the filesystem, or just what's in-memory? What are the implications of clearing what's in memory?
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.
I'd say maybe we clean out old gripper jaw width files during instrument calibration. Would we ever want to keep more than one of these files at a time anyways? It would kind of be beneficial to keep some old ones so that if a previously used gripper gets re-installed it's old jaw width data gets reloaded, but maybe that should "always be remeasured" anyways when doing 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.
just what's on the filesystem
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.
Looks good and like a nice speedup. Let's make sure that it all works during gripper calibration, both when the calibration is the first thing you're doing after adding a new gripper (i.e. you just unboxed the gripper and have never used it on this machine before) and during a rerun.
@@ -56,6 +56,7 @@ def reset_gripper(self) -> None: | |||
self._gripper = new_gripper | |||
|
|||
async def reset(self) -> None: | |||
# TODO(cm): do we want to reset the gripper jaw width here as well? |
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.
yes but that's not here - it's in reset_instrument_offset
. this reset
is part of the instrument load mechanics
@@ -191,6 +195,10 @@ def update_jaw_open_position_from_closed_position( | |||
is closed, and then altering the logical open position so that it is whatever it needs | |||
to be for the logical closed position to be the same as the config. | |||
""" | |||
if jaw_at_closed is None: |
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.
is not None?
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.
no, calling this with None
is intended to allow you to reset those values
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.
Neat idea!
Changes requested for the combination of a couple of things:
- We're reusing jaw width across grippers?
- After jaw width is saved once, it's reused forever and never cleared or overwritten?
I just skimmed through this, so let me know if I'm misunderstanding.
@@ -56,6 +56,7 @@ def reset_gripper(self) -> None: | |||
self._gripper = new_gripper | |||
|
|||
async def reset(self) -> None: | |||
# TODO(cm): do we want to reset the gripper jaw width here as well? |
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.
To clarify, Are you asking if we should clear what's on the filesystem, or just what's in-memory? What are the implications of clearing what's in memory?
# Save Gripper Jaw Width Data | ||
|
||
|
||
def save_gripper_jaw_width_data( |
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.
As far as I can tell, because we're putting this in a new directory (gripper_jaw_width_data
) instead of the existing one (gripper
), we need to manually wire this up to the HTTP endpoints that clear calibration. See e.g. clear_gripper_calibration_offsets()
.
It seems fine to reuse the existing gripper offset reset setting for that, even though jaw width is technically a different thing from 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.
looking good, left small comment
Mistaken about model needing a serial number field
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.
Really cool! Left a few comments regarding file management and stuff.
source=local_types.SourceType.user, | ||
status=cal_status_model, | ||
) | ||
io.save_to_file(gripper_jaw_width_dir, gripper_id, gripper_jaw_width) |
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.
Since gripper_id
is the file name here, will we start creating many copies of this file if there are multiple grippers swapped on a robot? Might want a clean up step that removes stale or irrelevant gripper files, just for cleanliness.
@@ -56,6 +56,7 @@ def reset_gripper(self) -> None: | |||
self._gripper = new_gripper | |||
|
|||
async def reset(self) -> None: | |||
# TODO(cm): do we want to reset the gripper jaw width here as well? |
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.
I'd say maybe we clean out old gripper jaw width files during instrument calibration. Would we ever want to keep more than one of these files at a time anyways? It would kind of be beneficial to keep some old ones so that if a previously used gripper gets re-installed it's old jaw width data gets reloaded, but maybe that should "always be remeasured" anyways when doing calibration?
Overview
Gripper speedup alert 💀 🚨 🚧⚠️
Due to mechanical tolerances in the 'grip' axis on the robot, each individual gripper needs to run a calibration routine in order to determine its max width and be able to establish position tracking. This routine has the gripper jaw open all the way until the limit switch is triggered, and then close all the way. The software assumes that the distance between the two gripper paddles is 60mm when closed. It then uses the encoder value at the position the gripper is found to be closed to calculate the max jaw width of the specific gripper that's on the robot.
The problem is that this value lives in the hardware controller, and therefore is wiped from existence any time
OT3API
is reset. We can reduce the number of times this routine happens by storing the gripper jaw calibration result to the robot file system and looking it up, if the gripper doesn't already have it.Changelog
gripper_jaw_width_data
. This will store the encoder value at the gripper's closed positionGripper::has_jaw_width_calibration
, look for data in this file, and return true + update theGripper
instance at hand if it's there