-
Notifications
You must be signed in to change notification settings - Fork 183
feat(api): return location sequences from commands #17435
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
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
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 think it's where lid stacks go when they become empty - is that right @CaseyBatten?
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% 24.66% +7.31%
==========================================
Files 3128 3271 +143
Lines 226114 232920 +6806
Branches 6884 9713 +2829
==========================================
+ Hits 39225 57440 +18215
+ Misses 186889 175465 -11424
- Partials 0 15 +15
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.
LGTM! thank you for you explanations and your fixes!
A PR has been opened to address analyses snapshot changes. Please review the changes here: #17464 |
A PR has been opened to address analyses snapshot changes. Please review the changes here: #17464 |
…snapshots (#17464) This PR was requested on the PR #17435 Co-authored-by: sfoster1 <[email protected]>
A PR has been opened to address analyses snapshot changes. Please review the changes here: #17467 |
…snapshots (#17467) This PR was requested on the PR #17435 Co-authored-by: sfoster1 <[email protected]>
A PR has been opened to address analyses snapshot changes. Please review the changes here: #17468 |
A PR has been opened to address analyses snapshot changes. Please review the changes here: #17468 |
A PR has been opened to address analyses snapshot changes. Please review the changes here: #17468 |
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.
Thanks! LGTM when tests are passing and comments are resolved to your satisfaction.
# These legacy json protocols don't get location sequences because | ||
# to do so we'd have to go back and look up where the module gets loaded |
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.
What are the implications of this? Doesn't this mean...something?...in the app will break when running "old" JSON and PAPI protocols?
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.
All it means is that we have to carry the backwards-compat code in consuming clients until we remove support for those older kinds of protocols. The types establish pretty firmly that these location sequences are not guaranteed to be present for this reason.
shared-data/command/types/setup.ts
Outdated
|
||
export interface OnLabwareLocationSequenceComponent { | ||
kind: 'onLabware' | ||
labwareId: string | ||
lidId: string | null | ||
} | ||
|
||
export interface OnModuleLocationSequenceComponent { | ||
kind: 'onModule' | ||
moduleId: string | ||
} | ||
|
||
export interface OnAddressableAreaLocationSequenceComponent { | ||
kind: 'onAddressableArea' | ||
addressableAreaName: string | ||
slotName: string | null | ||
} | ||
|
||
export interface NotOnDeckLocationSequenceCompoennt { | ||
kind: 'notOnDeck' | ||
logicalLocationName: 'offDeck' | 'systemLocation' | ||
} | ||
|
||
export type LocationSequenceComponent = | ||
| OnLabwareLocationSequenceComponent | ||
| OnModuleLocationSequenceComponent | ||
| OnAddressableAreaLocationSequenceComponent | ||
| NotOnDeckLocationSequenceCompoennt | ||
|
||
export type LabwareLocationSequence = LocationSequenceComponent[] | ||
|
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.
Does the eventualDestinationLocationSequence
/immediateDestinationLocationSequence
thing get cleaner if we stop using a shared offDeck
/systemLocation
constant for trashed labware, and instead have a LocationSequenceComponent
with kind: 'inTrash'
?
Roughly like:
{
"kind": "inTrash",
"addressableAreaName": "gripperWasteChute"
}
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.
It would, but I would only want to do that if we added that notion to the engine internal (and labware key external) representation of locations; I really want to keep elements of the location sequence as things that would show up in static representations of the loaded-labware state
command=LoadLabware( | ||
id="load-labware-1", | ||
createdAt=datetime.now(), | ||
key="load-labware-1", | ||
status=CommandStatus.SUCCEEDED, | ||
result=LoadLabwareResult( | ||
labwareId="labware-id-1", | ||
definition=nice_labware_definition, | ||
offsetId=None, | ||
), | ||
params=LoadLabwareParams( | ||
location=DeckSlotLocation(slotName=DeckSlotName.SLOT_C2), | ||
loadName=nice_labware_definition.parameters.loadName, | ||
namespace=nice_labware_definition.namespace, | ||
version=nice_labware_definition.version, | ||
), | ||
), | ||
state_update=StateUpdate( | ||
loaded_labware=LoadedLabwareUpdate( | ||
labware_id="labware-id-1", | ||
definition=nice_labware_definition, | ||
offset_id=None, | ||
new_location=DeckSlotLocation(slotName=DeckSlotName.SLOT_C2), | ||
display_name=None, | ||
), | ||
addressable_area_used=AddressableAreaUsedUpdate(addressable_area_name="C2"), | ||
), |
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 it makes things cleaner, I think all of these command instantiations except for the LoadModule
ones can be replaced with dummies like Comment
, since the state stores only care about state_update
now, not the command. (With the exception of ModuleStore
, which still cares about the command because we haven't gotten to it yet.) In the future, I hope to delete command
from SucceedCommandAction
so all of these tests can be rid of this boilerplate.
api/tests/opentrons/protocol_engine/state/test_geometry_view.py
Outdated
Show resolved
Hide resolved
A PR has been opened to address analyses snapshot changes. Please review the changes here: #17468 |
…snapshots (#17468) This PR was requested on the PR #17435 Co-authored-by: sfoster1 <[email protected]>
A PR has been opened to address analyses snapshot changes. Please review the changes here: #17484 |
A PR has been opened to address analyses snapshot changes. Please review the changes here: #17484 |
…snapshots (#17484) This PR was requested on the PR #17435 Co-authored-by: sfoster1 <[email protected]>
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 the `kind` key so you can tell them apart when serialized instead of just via python isinstance checks. All these sequences end in either an `OnCutoutFixtureLocation` which lists a cutout id and possible cutout fixtures; or a `NotOnDeckLocation` that specifies `OFF_DECK` or system. Different robots have different kinds of sequences; on the OT-2, modules are loaded on deck slots, and so a labware on a module would have `[OnModule, OnAddressableArea, OnCutoutFixture]` while on the Flex, modules are loaded on cutout fixtures and a labware on a module would have `[OnAdressableArea, OnModule, OnCutoutFixture]` (having the `OnModule` there lets us have the module ID; it is not technically necessary). 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, wondrous - `loadLidStack` 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 elements - `moveLabware` 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 is `OFF_DECK` (because it went into the trash), after all. So we get both `immediateDestinationLocationSequence` (which in this scenario would be the addressable area of the trash) and `eventualDestinationLocationSequence` (which in this scenario would be off deck). If the two are the same, then the two are the same - the stacker `store` and `retrieve` 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 - [x] ts bindings - [x] stacker store and retrieve - ~[ ] add "what is the old and new state of the locations named in the command" to these values~ not going to do that ^ in this pr just so we can get it merged --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: sfoster1 <[email protected]>
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 either anOnCutoutFixtureLocation
which lists a cutout id and possible cutout fixtures; or aNotOnDeckLocation
that specifiesOFF_DECK
or system.Different robots have different kinds of sequences; on the OT-2, modules are loaded on deck slots, and so a labware on a module would have
[OnModule, OnAddressableArea, OnCutoutFixture]
while on the Flex, modules are loaded on cutout fixtures and a labware on a module would have[OnAdressableArea, OnModule, OnCutoutFixture]
(having theOnModule
there lets us have the module ID; it is not technically necessary).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