Skip to content

v1: OTDeck: bring static geometry and holder-based slot rendering forward from main#1154

Merged
BioCam merged 3 commits into
PyLabRobot:v1b1from
BioCam:v1b1-ot2-resource-alignment
Jul 7, 2026
Merged

v1: OTDeck: bring static geometry and holder-based slot rendering forward from main#1154
BioCam merged 3 commits into
PyLabRobot:v1b1from
BioCam:v1b1-ot2-resource-alignment

Conversation

@BioCam

@BioCam BioCam commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

v1b1's OT-2 resources predate #1130 and #1131 on main: there is no OT2RobotGeometry, and the deck is still the original slots-list OTDeck rather than the holder-based one. This brings the resource layer forward so v1b1's OT-2 deck matches main, and ports the matching visualizer rendering and backend coordinate handling.

Adds OT2RobotGeometry, a frozen dataclass of the OT-2's fixed gantry extents, per-mount nozzle offsets, and head8 channel offsets, and replaces the deck with the version whose 12 slots are ResourceHolder children. The base classes this depends on - Coordinate, ResourceHolder, Trash, OTModule - are byte-identical on v1b1, so the carry-over is near-verbatim; the one adaptation is the deck round-trip test, which uses v1b1's Cor_96_wellplate_360ul_Fb since that factory predates the main naming rename.

The holder-based deck positions labware from the deck plate corner rather than slot 1's corner, so the legacy OT-2 backend is updated to match: tip pickup and drop walk up to the deck through the slot holder, and a new _deck_to_robot_frame subtracts slot 1's corner from the aspirate and dispense coordinates so the wire commands stay in the robot frame the motion API expects. Without this the deck change shifts every generated coordinate by slot 1's inset.

The visualizer draws each slot from its holder and labels empty slots with their number, and looks the deck up by type via getDeck() instead of the hardcoded resources["deck"] key. The type lookup is required, not cosmetic: v1b1's Trash renderer reads the deck through that key and throws when it is absent, so without it the OT-2 scene fails to draw. The main-only deck-surface gradient is left out because v1b1 does not define its colour constants.

Validated by running a standard single-channel OT-2 protocol against the simulator on this branch - pick up, aspirate, dispense, return - by the legacy backend command tests, and by rendering the deck in a headless browser: slots, slot numbers, labware, and the trash all draw with no console errors, and the deck border and selection highlight bound the slots correctly.

One item is left out of scope: the browser drag-to-slot snapping still uses the old fixed site coordinates rather than the holders, so it is untouched here and interactive placement is unchanged for Python-assigned protocols. The workcell tree lists slots in column order because a deck's children are sorted by x; this is identical to main (verified by rendering the same scene on both) and is unrelated to this change.

🤖 Generated with Claude Code

BioCam added 2 commits July 7, 2026 18:01
Bring the main-branch resource layer forward: add `OT2RobotGeometry`
(static gantry extents, per-mount offsets, head8 channel offsets) and
replace the slots-list deck with the holder-based `OTDeck` whose slots
are `ResourceHolder` children. Resource-layer only; the base classes it
depends on (`Coordinate`, `ResourceHolder`, `Trash`, `OTModule`) are
API-identical on v1b1.
Draw each OT-2 slot from its `ResourceHolder` child and label empty
slots with their number, replacing the hardcoded site loop. Add
`getDeck()` and use it in place of the `resources["deck"]` lookups so
`Trash` and the snapping paths find the deck by type instead of a
hardcoded name, which otherwise throws when the deck is absent.
@BioCam BioCam changed the title v1b1: OTDeck: bring static geometry and holder-based slot rendering forward from main v1: OTDeck: bring static geometry and holder-based slot rendering forward from main Jul 7, 2026
The holder-based deck positions labware from the deck plate corner, so the
legacy OT-2 backend must subtract slot 1's corner to reach the robot frame
the motion API expects. Walk up to the deck through the slot holder during
tip pickup and drop, and route the aspirate and dispense locations through
a new `_deck_to_robot_frame`. Without this the deck change shifts every
generated wire coordinate by slot 1's inset.
@BioCam
BioCam merged commit 99920ec into PyLabRobot:v1b1 Jul 7, 2026
2 of 19 checks passed
@BioCam
BioCam deleted the v1b1-ot2-resource-alignment branch July 7, 2026 17:58
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.

1 participant