Skip to content

Commit

Permalink
Merge branch 'edge' into fix-hardware-testing-robot-assembly-qc-for-d…
Browse files Browse the repository at this point in the history
…vt-2
  • Loading branch information
andySigler committed May 22, 2023
2 parents f711bde + a58eb35 commit bd63fb0
Show file tree
Hide file tree
Showing 67 changed files with 1,520 additions and 557 deletions.
11 changes: 11 additions & 0 deletions api-client/src/protocols/getProtocolIds.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { GET, request } from '../request'

import type { ResponsePromise } from '../request'
import type { HostConfig } from '../types'
import type { ProtocolsIds } from './types'

export function getProtocolIds(
config: HostConfig
): ResponsePromise<ProtocolsIds> {
return request<ProtocolsIds>(GET, `/protocols/ids`, null, config)
}
1 change: 1 addition & 0 deletions api-client/src/protocols/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export { getProtocolAnalyses } from './getProtocolAnalyses'
export { deleteProtocol } from './deleteProtocol'
export { createProtocol } from './createProtocol'
export { getProtocols } from './getProtocols'
export { getProtocolIds } from './getProtocolIds'

export * from './types'
export * from './utils'
Expand Down
5 changes: 5 additions & 0 deletions api-client/src/protocols/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,8 @@ export interface Protocols {
links?: ResourceLinks
data: ProtocolResource[]
}

export interface ProtocolsIds {
links?: ResourceLinks
data: string[]
}
49 changes: 1 addition & 48 deletions api/release-notes-internal.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,37 +16,6 @@ Some things are known not to work, and are listed below. Specific compatibility

For more details about this release, please see the full [technical change log][].

# Internal Release 0.7.0

This is internal release 0.7.0 for the Opentrons Flex robot software, involving both robot control and the on-device display.

Some things are known not to work, and are listed below. Specific compatibility notes about peripheral hardware are also listed.

## Big New Things
### Robot Control
- Updated python api version to 2.15
- Added load Magnetic block as a module in python api and in PE. You can now load a magnetic block using `protocol_context.load_module("magneticBlockV1", <slot_name>)` with `apiLevel` of 2.15.

For more details about this release, please see the full [technical change log][].

[technical change log]: https://github.com/Opentrons/opentrons/releases

---

# Internal Release 0.6.0

This is internal release 0.6.0 for the Opentrons Flex robot software, involving both robot control and the on-device display.

Some things are known not to work, and are listed below. Specific compatibility notes about peripheral hardware are also listed.

## Hardware Revision Compatibility

- This release will work best on a DVT robot frame with a programmed rear-panel board. If that doesn't apply, edit `/data/feature_flags.json` and turn `rearPanelIntegration` to `false` or the robot server won't start.
- This release is compatible with EVT pipettes and gripper only if they have received the tool ID rework.
- This release is compatible with DVT pipettes and gripper.
- This release should be used with DVT module caddies. This might introduce a slight LPC offset change if the previous offsets for labware on modules were measured while using EVT caddies.
- This release should be used with pipette bootloaders of at least v7.

## Big Things That Don't Work Yet So Don't Report Bugs About Them

### ODD
Expand All @@ -56,27 +25,10 @@ Some things are known not to work, and are listed below. Specific compatibility
- It can take a while for the robot to start after installing an update (it's the firmware updates happening on boot). Allow 10 minutes after an update that has a firmware change.

### Robot Control
- USB connectivity
- Pipette/gripper firmware update on attach: if you need to attach a new instrument, attach it and then power-cycle the robot or restart the robot server
- Pipette pressure sensing both for liquid-level sensing purposes and for clog-detection purposes
- Labware pick up failure with gripper

## Big New Things
### Robot Control
- All python protocol API functions that take deck slot names (like load_labware) now support deck slot "coordinates", e.g. specifying a deck slot as "A1" rather than 1. This feature requires a Python protocol to request API version 2.15.

## Reasonably Sized New Things
### ODD
- Protocol result screens! No more do you have to stare at those big buttons forever

### Robot Control
- Python API `load_labware`, `load_module` and `move_labware` can accept location as deck coordinates (e.g. "A1", "D3") in addition to slot numbers
- The `.parent` property for Module and Labware objects (loaded on the deck) will return a coordinate style deck location (e.g. "B2", "C3") for protocols with robotType "OT-3 Standard" instead of the slot number
- Rerunning a protocol should no longer result in being on step ?
- DVT gripper sets its force more accurately now
- Fixed a couple more bugs with pipette calibration; it should no longer fail during the Z height calibration
- Fixed a problem where the change-pipette process would crash after removing a pipette because it tried to home the now-not-present pipette

## Big Things That Do Work Please Do Report Bugs About Them
### Robot Control
- Liquid handling protocols with 1 and 8 channel pipettes
Expand All @@ -86,6 +38,7 @@ Some things are known not to work, and are listed below. Specific compatibility
- Network connectivity and discoverability
- Firmware update for all devices attached when the robot turns on
- Cancelling a protocol run. We're even more sure we fixed this so definitely tell us if it's not.
- USB connectivity

### ODD
- Protocol execution including end-of-protocol screen
Expand Down
16 changes: 16 additions & 0 deletions api/src/opentrons/config/advanced_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,11 @@ class Setting(NamedTuple):
title="Enable robots with the new usb connected rear-panel board.",
description="This is an Opentrons-internal setting to test new rear-panel.",
),
SettingDefinition(
_id="disableStallDetection",
title="Disable stall detection on the Flex.",
description="This is an Opentrons-internal setting for hardware-testing.",
),
]

if ARCHITECTURE == SystemArchitecture.BUILDROOT:
Expand Down Expand Up @@ -547,6 +552,16 @@ def _migrate23to24(previous: SettingsMap) -> SettingsMap:
return newmap


def _migrate24to25(previous: SettingsMap) -> SettingsMap:
"""Migrate to version 25 of the feature flags file.
- Adds the disableStallDetection config element.
"""
newmap = {k: v for k, v in previous.items()}
newmap["disableStallDetection"] = None
return newmap


_MIGRATIONS = [
_migrate0to1,
_migrate1to2,
Expand All @@ -572,6 +587,7 @@ def _migrate23to24(previous: SettingsMap) -> SettingsMap:
_migrate21to22,
_migrate22to23,
_migrate23to24,
_migrate24to25,
]
"""
List of all migrations to apply, indexed by (version - 1). See _migrate below
Expand Down
4 changes: 4 additions & 0 deletions api/src/opentrons/config/feature_flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,7 @@ def rear_panel_integration() -> bool:
"""Whether to enable usb connected rear_panel for the OT-3."""

return advs.get_setting_with_env_overload("rearPanelIntegration")


def stall_detection_enabled() -> bool:
return not advs.get_setting_with_env_overload("disableStallDetection")
24 changes: 6 additions & 18 deletions api/src/opentrons/hardware_control/backends/ot3controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
Union,
)
from opentrons.config.types import OT3Config, GantryLoad
from opentrons.config import ot3_pipette_config, gripper_config
from opentrons.config import ot3_pipette_config, gripper_config, feature_flags as ff
from .ot3utils import (
UpdateProgress,
axis_convert,
Expand Down Expand Up @@ -124,7 +124,6 @@
OT3SubSystem,
)
from opentrons.hardware_control.errors import (
MustHomeError,
InvalidPipetteName,
InvalidPipetteModel,
FirmwareUpdateRequired,
Expand Down Expand Up @@ -414,12 +413,6 @@ async def update_motor_status(self) -> None:
async def update_motor_estimation(self, axes: Sequence[OT3Axis]) -> None:
"""Update motor position estimation for commanded nodes, and update cache of data."""
nodes = set([axis_to_node(a) for a in axes])
for node in nodes:
if not (
node in self._motor_status.keys()
and self._motor_status[node].encoder_ok
):
raise MustHomeError(f"Axis {node} has invalid encoder position")
response = await update_motor_position_estimation(self._messenger, nodes)
self._handle_motor_status_response(response)

Expand Down Expand Up @@ -501,16 +494,8 @@ def _handle_motor_status_response(
for axis, pos in response.items():
self._position.update({axis: pos[0]})
self._encoder_position.update({axis: pos[1]})
# if an axis has already been homed, we're not clearing the motor ok status flag
# TODO: (2023-01-10) This is just a temp fix so we're not blocking hardware testing,
# we should port the encoder position over to use as motor position if encoder status is ok
already_homed = (
self._motor_status[axis].motor_ok
if axis in self._motor_status.keys()
else False
)
self._motor_status.update(
{axis: MotorStatus(motor_ok=pos[2] or already_homed, encoder_ok=pos[3])}
{axis: MotorStatus(motor_ok=pos[2], encoder_ok=pos[3])}
)

@requires_update
Expand All @@ -532,7 +517,10 @@ async def move(
"""
group = create_move_group(origin, moves, self._motor_nodes(), stop_condition)
move_group, _ = group
runner = MoveGroupRunner(move_groups=[move_group])
runner = MoveGroupRunner(
move_groups=[move_group],
ignore_stalls=True if not ff.stall_detection_enabled() else False,
)
positions = await runner.run(can_messenger=self._messenger)
self._handle_motor_status_response(positions)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ class TipMotorPickUpTipSpec:
pick_up_distance: float
speed: float
currents: Dict[OT3Axis, float]
# FIXME we should throw this in a config
# file of some sort
home_buffer: float = 0


@dataclass(frozen=True)
Expand All @@ -100,6 +103,9 @@ class DropTipMove:
home_after_safety_margin: float = 0
home_axes: Sequence[OT3Axis] = tuple()
is_ht_tip_action: bool = False
# FIXME we should throw this in a config
# file of some sort
home_buffer: float = 0


@dataclass(frozen=True)
Expand Down Expand Up @@ -691,6 +697,7 @@ def build_presses() -> Iterator[Tuple[float, float]]:
pick_up_distance=instrument.pick_up_configurations.distance,
speed=instrument.pick_up_configurations.speed,
currents={OT3Axis.Q: instrument.pick_up_configurations.current},
home_buffer=10,
),
),
add_tip_to_instr,
Expand Down Expand Up @@ -769,6 +776,7 @@ def build() -> List[DropTipMove]:
home_after_safety_margin=abs(bottom_pos - droptip_pos),
home_axes=home_axes,
is_ht_tip_action=is_ht_pipette,
home_buffer=10 if is_ht_pipette else 0,
),
DropTipMove( # always finish drop-tip at a known safe plunger position
target_position=bottom_pos, current=plunger_currents, speed=None
Expand Down
28 changes: 25 additions & 3 deletions api/src/opentrons/hardware_control/ot3_calibration.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ class CalibrationMethod(Enum):
NONCONTACT_PASS = "noncontact pass"


class CalibrationTarget(Enum):
DECK_OBJECT = "deck_object"
GANTRY_INSTRUMENT = "gantry_instrument"


class CalibrationStructureNotFoundError(RuntimeError):
def __init__(self, structure_height: float, lower_limit: float) -> None:
super().__init__(
Expand Down Expand Up @@ -546,7 +551,11 @@ async def _calibrate_mount(
try:
# find the center of the calibration sqaure
offset = await find_calibration_structure_position(
hcapi, mount, nominal_center, method, raise_verify_error
hcapi,
mount,
nominal_center,
method=method,
raise_verify_error=raise_verify_error,
)
# update center with values obtained during calibration
LOG.info(f"Found calibration value {offset} for mount {mount.name}")
Expand All @@ -570,6 +579,7 @@ async def find_calibration_structure_position(
mount: OT3Mount,
nominal_center: Point,
method: CalibrationMethod = CalibrationMethod.BINARY_SEARCH,
target: CalibrationTarget = CalibrationTarget.GANTRY_INSTRUMENT,
raise_verify_error: bool = True,
) -> Point:
"""Find the calibration square offset given an arbitry postition on the deck."""
Expand All @@ -582,7 +592,15 @@ async def find_calibration_structure_position(
found_center = await find_calibration_structure_center(
hcapi, mount, initial_center, method, raise_verify_error
)
return nominal_center - found_center

offset = nominal_center - found_center
# NOTE: If the calibration target is a deck object the polarity of the calibrated
# offset needs to be reversed. This is because we are using the gantry instrument
# to calibrate a stationary object on the deck and need to find the offset of that
# deck object relative to the deck and not the instrument which sits above the deck.
if target == CalibrationTarget.DECK_OBJECT:
return offset * -1
return offset


async def find_slot_center_binary_from_nominal_center(
Expand Down Expand Up @@ -782,7 +800,11 @@ async def calibrate_module(
# from the nominal position so we dont have to alter any other part of the system.
nominal_position = nominal_position - PREP_OFFSET_DEPTH
offset = await find_calibration_structure_position(
hcapi, mount, nominal_position, method=CalibrationMethod.BINARY_SEARCH
hcapi,
mount,
nominal_position,
method=CalibrationMethod.BINARY_SEARCH,
target=CalibrationTarget.DECK_OBJECT,
)
await hcapi.save_module_offset(module_id, mount, slot, offset)
return offset
Expand Down
Loading

0 comments on commit bd63fb0

Please sign in to comment.