Skip to content

Commit 3390b4d

Browse files
committed
Merge back 'chore_release-pd-8.7.0' into 'edge'
2 parents 8a97133 + 7f9cc6a commit 3390b4d

File tree

2 files changed

+91
-22
lines changed

2 files changed

+91
-22
lines changed

.github/workflows/pd-test-build-deploy.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ jobs:
113113
make -C protocol-designer NODE_ENV=${{ needs.determine-deploy-config.outputs.environment == 'production' && 'production' || 'development' }} OT_PD_PRERELEASE_MODE=${{ needs.determine-deploy-config.outputs.environment == 'sandbox' && '1' || '0' }}
114114
- name: 'upload sourcemaps to Sentry'
115115
# Only on production or staging releases (protocol-designer* or staging-protocol-designer*)
116-
if: github.ref_type == 'tag' && (startsWith(github.ref, 'refs/tags/protocol-designer') || startsWith(github.ref, 'refs/tags/staging-protocol-designer'))
116+
if: github.ref_type == 'tag' && (startsWith(github.ref, 'refs/tags/protocol-designer') || startsWith(github.ref, 'refs/tags/staging-protocol-designer')) && (needs.determine-deploy-config.outputs.environment == 'production' || needs.determine-deploy-config.outputs.environment == 'staging')
117117
uses: getsentry/action-release@v3
118118
env:
119119
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
@@ -125,7 +125,7 @@ jobs:
125125
set_commits: auto
126126
ignore_missing: true
127127
finalize: false
128-
environment: ${{ needs.determine-deploy-config.outputs.environment == 'production' && 'production' || 'staging' }}
128+
environment: ${{ needs.determine-deploy-config.outputs.environment }}
129129
- name: 'upload github artifact'
130130
uses: actions/upload-artifact@v4
131131
with:

step-generation/src/utils/safePipetteMovements.ts

Lines changed: 89 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
getAddressableAreaFromSlotId,
66
getDeckDefFromRobotType,
77
getFlexSurroundingSlots,
8+
getModuleDef,
89
getOt2SurroundingSlots,
910
getPositionFromSlotId,
1011
OT2_ROBOT_TYPE,
@@ -23,6 +24,7 @@ import type {
2324
NozzleConfigurationStyle,
2425
OT2AddressableAreaName,
2526
PipetteChannels,
27+
PipetteV2Specs,
2628
RobotType,
2729
} from '@opentrons/shared-data'
2830
import type {
@@ -91,7 +93,8 @@ const getPipetteBoundsAtSpecifiedMoveToPosition = (
9193
pipetteEntity: PipetteEntity,
9294
tipLength: number,
9395
wellTargetPoint: Point,
94-
primaryNozzle: string
96+
primaryNozzle: string,
97+
tipOverlapOnNozzle: number
9598
): Point[] => {
9699
const { nozzleMap, nozzleOffset, pipetteBoundingBoxOffsets } =
97100
pipetteEntity.spec
@@ -116,7 +119,6 @@ const getPipetteBoundsAtSpecifiedMoveToPosition = (
116119
const frontY =
117120
wellTargetPoint.y - (primaryNozzlePoint[1] - pipetteBoundingBoxFrontYOffset)
118121

119-
const tipOverlapOnNozzle = 0
120122
const zNozzles = (wellTargetPoint.z ?? 0) + tipLength - tipOverlapOnNozzle
121123

122124
const backLeftBound = { x: leftX, y: backY, z: zNozzles }
@@ -140,22 +142,28 @@ const getHasOverlappingRectangles = (
140142
}
141143

142144
const getModuleHeightFromDeckDefinition = (
143-
moduleModel: ModuleModel
145+
moduleModel: ModuleModel,
146+
robotType: RobotType
144147
): number => {
145-
const deckDef = getDeckDefFromRobotType(FLEX_ROBOT_TYPE)
146-
const { addressableAreas } = deckDef.locations
147-
const moduleAddressableArea = addressableAreas.find(addressableArea =>
148-
addressableArea.id.includes(moduleModel)
149-
)
150-
return moduleAddressableArea?.offsetFromCutoutFixture[2] ?? 0
148+
if (robotType === FLEX_ROBOT_TYPE) {
149+
const deckDef = getDeckDefFromRobotType(robotType)
150+
const { addressableAreas } = deckDef.locations
151+
const moduleAddressableArea = addressableAreas.find(addressableArea =>
152+
addressableArea.id.includes(moduleModel)
153+
)
154+
return moduleAddressableArea?.offsetFromCutoutFixture[2] ?? 0
155+
}
156+
// OT-2
157+
return getModuleDef(moduleModel).dimensions.bareOverallHeight
151158
}
152159

153160
// check the highest Z-point of all items stacked given a deck slot (including modules,
154161
// adapters, and modules on adapters)
155162
const getHighestZInSlot = (
156163
robotState: RobotState,
157164
invariantContext: InvariantContext,
158-
slotId: string
165+
slotId: string,
166+
robotType: RobotType
159167
): number => {
160168
const { modules, labware } = robotState
161169
const { moduleEntities, labwareEntities } = invariantContext
@@ -167,11 +175,12 @@ const getHighestZInSlot = (
167175
)
168176

169177
// if slot has labware, includes labware, adapters, and module
170-
if (largestLabwareStack != null) {
178+
if (largestLabwareStack.length > 0) {
171179
largestLabwareStack.forEach(item => {
172180
if (modules[item] != null) {
173181
totalHeight += getModuleHeightFromDeckDefinition(
174-
moduleEntities[item].model
182+
moduleEntities[item].model,
183+
robotType
175184
)
176185
}
177186
if (labware[item] != null) {
@@ -181,7 +190,8 @@ const getHighestZInSlot = (
181190
// if slot only has module
182191
} else if (moduleInSlot != null) {
183192
totalHeight += getModuleHeightFromDeckDefinition(
184-
moduleEntities[moduleInSlot].model
193+
moduleEntities[moduleInSlot].model,
194+
robotType
185195
)
186196
}
187197
return totalHeight
@@ -241,7 +251,8 @@ const getSlotHasPotentialCollidingObject = (
241251
? getHighestZInSlot(
242252
robotState,
243253
invariantContext,
244-
slot.addressableArea.id
254+
slot.addressableArea.id,
255+
robotType
245256
)
246257
: 0
247258
if (highestZInSurroundingSlot >= pipetteBounds[0]?.z) {
@@ -344,11 +355,9 @@ export const getIsSafePipetteMovement = (args: {
344355
return true
345356
}
346357

347-
const tiprackEntityId = tipState.pipettes[pipetteId]?.tiprackURI
348-
const tiprackTipLength =
349-
tiprackEntityId != null
350-
? labwareEntities[tiprackEntityId]?.def.parameters.tipLength
351-
: 0
358+
const tiprackId = tipState.pipettes[pipetteId]?.tiprackURI
359+
const tiprackEntity = tiprackId != null ? labwareEntities[tiprackId] : null
360+
const tiprackTipLength = tiprackEntity?.def.parameters.tipLength ?? 0
352361
const stagingAreaSlots = Object.values(stagingAreaEntities).map(
353362
stagingArea => stagingArea.location as string
354363
)
@@ -384,11 +393,20 @@ export const getIsSafePipetteMovement = (args: {
384393
if (!isWithinPipetteExtents) {
385394
return false
386395
}
396+
const tipOverlapOnNozzle =
397+
tiprackEntity != null
398+
? getTipOverlap({
399+
pipetteSpecs,
400+
tiprackUri: tiprackEntity.labwareDefURI,
401+
nozzles: nozzleConfiguration,
402+
})
403+
: 0
387404
const pipetteBoundsAtWellLocation = getPipetteBoundsAtSpecifiedMoveToPosition(
388405
pipetteEntity,
389406
tipLength,
390407
wellTargetPoint,
391-
primaryNozzle
408+
primaryNozzle,
409+
tipOverlapOnNozzle
392410
)
393411
const surroundingSlots =
394412
robotType === OT2_ROBOT_TYPE
@@ -582,3 +600,54 @@ export const getTargetTipsFromWellSets = (args: {
582600
return wellSet[0]
583601
})
584602
}
603+
604+
const getTipOverlap = (args: {
605+
pipetteSpecs: PipetteV2Specs
606+
tiprackUri: string
607+
nozzles: NozzleConfigurationStyle
608+
}): number => {
609+
const { pipetteSpecs, tiprackUri, nozzles } = args
610+
const { channels } = pipetteSpecs
611+
const overlapKey = getOverlapKeyForPipetteSpecs(channels, nozzles)
612+
const tipOverlaps =
613+
pipetteSpecs.pickUpTipConfigurations.pressFit.configurationsByNozzleMap[
614+
overlapKey
615+
]?.default.tipOverlaps
616+
617+
// protect in case we get a bad overlap key
618+
if (tipOverlaps == null) {
619+
console.error(
620+
`No tip overlaps found for ${nozzles} and ${overlapKey} overlap.`
621+
)
622+
return 0
623+
}
624+
const maxVersion = Math.max(
625+
...Object.keys(tipOverlaps).map(version => Number(version.slice(1)))
626+
)
627+
return (
628+
tipOverlaps[`v${maxVersion}`]?.[tiprackUri] ??
629+
tipOverlaps[`v${maxVersion}`]?.default ??
630+
0
631+
)
632+
}
633+
634+
const getOverlapKeyForPipetteSpecs = (
635+
channels: PipetteChannels,
636+
nozzles: NozzleConfigurationStyle
637+
): string => {
638+
if (channels === 1) {
639+
return 'SingleA1'
640+
}
641+
if (channels === 8) {
642+
return nozzles === SINGLE ? 'SingleH1' : 'Full'
643+
}
644+
if (channels === 96) {
645+
if (nozzles === SINGLE) {
646+
return 'SingleH12'
647+
} else if (nozzles === COLUMN) {
648+
return 'Column12'
649+
}
650+
}
651+
// default
652+
return 'Full'
653+
}

0 commit comments

Comments
 (0)