-
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(api): return location sequences from commands #17435
base: edge
Are you sure you want to change the base?
Conversation
These are like offset location sequences, but they involve instance IDs instead of geometry identifiers. They'll be returned from various commands.
Load labware now tells you the location sequence of the labware it just loaded.
MoveLabware is a little different than the other implementations. It needs an origin and a destination sequence, since it's a move - that's straightforward. But it also needs to drive a distinction between an immediate destination: where is the labware dropped off? and an eventual destination: where does the labware end up? so that the necessary information to figure out what happens when you move a labware to the trash is there. We need to identify the trash, and which trash; but we also need to indicate that the labware is going to get thrown out. So we have three total locations.
stackLocationSequence: LabwareLocationSequence | None = Field( | ||
None, description="The location sequence for this stack." | ||
) | ||
locationSequences: List[LabwareLocationSequence] | None = Field( | ||
None, | ||
description="The location sequences for the lids just loaded into the stack. These are in the same order as labwareIds.", |
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 am confused between these 2 props. can we maybe clarify it?
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 one of them is a "physical adapter" maybe it will clarify if we add it to the desc
eventualDestinationLocationSequence: LabwareLocationSequence | None = Field( | ||
None, | ||
description=( | ||
"The full location in which this labware will eventually reside. This will typically be the same as its " | ||
"immediate destination, but if this labware is going to the trash then this field will be off deck." | ||
), | ||
) | ||
immediateDestinationLocationSequence: LabwareLocationSequence | None = 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.
can you explain the diff between these two props?
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.
Yeah, this is for when you move stuff to the trash. We want to know that it's going to the trash, so we can render it; but it doesn't end up in the trash, it ends up off deck, and we want to know that too. So we have both
def labware_location_is_system( | ||
location: LabwareLocation, | ||
) -> TypeGuard[_SystemLocationType]: | ||
"""Check if a location is the system location.""" |
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.
might have missed this convo but what is a system location?
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.
SYSTEM
is a new location used for uh I forget. It's like off deck but not literally off deck, I think it's for deleted stuff
labware_location.moduleId | ||
) | ||
try: | ||
self._modules.get_flex_stacker_substate(labware_location.moduleId) |
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.
are we doing this get just for catching the exception?
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.
Yup
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.
overall looks good! had a few questions/clarifications.
These will probably need to change more.
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## edge #17435 +/- ##
==========================================
+ Coverage 17.34% 25.51% +8.16%
==========================================
Files 3128 3270 +142
Lines 226114 232069 +5955
Branches 6884 9323 +2439
==========================================
+ Hits 39225 59210 +19985
+ Misses 186889 172842 -14047
- Partials 0 17 +17
Flags with carried forward coverage won't be shown. Click here to find out more.
|
By adding all the locations of a labware used in a command that establishes or changes the position of a labware, we can free the client from having to accumulate all previous such commands to display a single such command.
These locations are shown as location sequences. These are lists of heterogenous unions keyed by
kind
. The kinds mostly correspond to the kinds of locations that the engine already uses - they're different types because they have thekind
key so you can tell them apart when serialized instead of just via python isinstance checks. All these sequences end in anOnAddressableAreaLocation
. This probably needs to be rethought in a subsequent pr, because it makes modules awkward. Labware on a module will have a location sequence containing that module and then anOnAddressableAreaLocation
. This probably needs to change to guarantee that sequences end in anOnCutoutLocation
or something that identify the addressable area and cutout fixture or something. It's a little awkward that the OT-2 and the flex work differently.There are some command implementations that are straightforward, and some that are charmingly quirky.
loadLabware
,reloadLabware
,loadLid
all just return the location of the newly added labware. Simple, clean, wondrousloadLidStack
creates a lid stack object and returns its location, and also creates N lid objects and returns all of their locations, which is done in its own array that is guaranteed to have the same ordering as all the lid ids so we can keep the types of the locations consistent across commands and also avoid altering already-existing result elementsmoveLabware
needs an origin and a destination location, so it has them. In fact, one destination location isn't enough. When we move labware to a trash location, we need to encode both (1) which trash location it was and (2) that it is a trash location. After the command, the position of the labware isOFF_DECK
(because it went into the trash), after all. So we get bothimmediateDestinationLocationSequence
(which in this scenario would be the addressable area of the trash) andeventualDestinationLocationSequence
(which in this scenario would be off deck). If the two are the same, then the two are the samestore
andretrieve
commands have info that isn't really actually useful right now, but it will be soon, so let's carve out some space for them. For now the labware just bounces back and forth between the module/off deck and the module/stacker staging slot.to come out of draft
[ ] add "what is the old and new state of the locations named in the command" to these valuesnot going to do that ^ in this pr just so we can get it merged