opentrons 8.3.0a0__py2.py3-none-any.whl → 8.3.0a1__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- opentrons/calibration_storage/deck_configuration.py +3 -3
- opentrons/calibration_storage/file_operators.py +3 -3
- opentrons/calibration_storage/helpers.py +3 -1
- opentrons/calibration_storage/ot2/models/v1.py +16 -29
- opentrons/calibration_storage/ot2/tip_length.py +7 -4
- opentrons/calibration_storage/ot3/models/v1.py +14 -23
- opentrons/cli/analyze.py +18 -6
- opentrons/drivers/asyncio/communication/__init__.py +2 -0
- opentrons/drivers/asyncio/communication/errors.py +16 -3
- opentrons/drivers/asyncio/communication/serial_connection.py +24 -9
- opentrons/drivers/command_builder.py +2 -2
- opentrons/drivers/flex_stacker/__init__.py +9 -0
- opentrons/drivers/flex_stacker/abstract.py +89 -0
- opentrons/drivers/flex_stacker/driver.py +260 -0
- opentrons/drivers/flex_stacker/simulator.py +109 -0
- opentrons/drivers/flex_stacker/types.py +138 -0
- opentrons/drivers/heater_shaker/driver.py +18 -3
- opentrons/drivers/temp_deck/driver.py +13 -3
- opentrons/drivers/thermocycler/driver.py +17 -3
- opentrons/execute.py +3 -1
- opentrons/hardware_control/__init__.py +1 -2
- opentrons/hardware_control/api.py +28 -20
- opentrons/hardware_control/backends/flex_protocol.py +4 -6
- opentrons/hardware_control/backends/ot3controller.py +177 -59
- opentrons/hardware_control/backends/ot3simulator.py +10 -8
- opentrons/hardware_control/backends/ot3utils.py +3 -13
- opentrons/hardware_control/dev_types.py +2 -0
- opentrons/hardware_control/emulation/heater_shaker.py +4 -0
- opentrons/hardware_control/emulation/module_server/client.py +1 -1
- opentrons/hardware_control/emulation/module_server/server.py +5 -3
- opentrons/hardware_control/emulation/settings.py +3 -4
- opentrons/hardware_control/instruments/ot2/instrument_calibration.py +2 -1
- opentrons/hardware_control/instruments/ot2/pipette.py +9 -21
- opentrons/hardware_control/instruments/ot2/pipette_handler.py +8 -1
- opentrons/hardware_control/instruments/ot3/gripper.py +2 -2
- opentrons/hardware_control/instruments/ot3/pipette.py +13 -22
- opentrons/hardware_control/instruments/ot3/pipette_handler.py +10 -1
- opentrons/hardware_control/modules/mod_abc.py +2 -2
- opentrons/hardware_control/motion_utilities.py +68 -0
- opentrons/hardware_control/nozzle_manager.py +39 -41
- opentrons/hardware_control/ot3_calibration.py +1 -1
- opentrons/hardware_control/ot3api.py +34 -22
- opentrons/hardware_control/protocols/gripper_controller.py +3 -0
- opentrons/hardware_control/protocols/hardware_manager.py +5 -1
- opentrons/hardware_control/protocols/liquid_handler.py +18 -0
- opentrons/hardware_control/protocols/motion_controller.py +6 -0
- opentrons/hardware_control/robot_calibration.py +1 -1
- opentrons/hardware_control/types.py +61 -0
- opentrons/protocol_api/__init__.py +20 -1
- opentrons/protocol_api/_liquid.py +24 -49
- opentrons/protocol_api/_liquid_properties.py +754 -0
- opentrons/protocol_api/_types.py +24 -0
- opentrons/protocol_api/core/common.py +2 -0
- opentrons/protocol_api/core/engine/instrument.py +67 -10
- opentrons/protocol_api/core/engine/labware.py +29 -7
- opentrons/protocol_api/core/engine/protocol.py +130 -5
- opentrons/protocol_api/core/engine/robot.py +139 -0
- opentrons/protocol_api/core/engine/well.py +4 -1
- opentrons/protocol_api/core/instrument.py +42 -4
- opentrons/protocol_api/core/labware.py +13 -4
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +34 -3
- opentrons/protocol_api/core/legacy/legacy_labware_core.py +13 -4
- opentrons/protocol_api/core/legacy/legacy_protocol_core.py +32 -1
- opentrons/protocol_api/core/legacy/legacy_robot_core.py +0 -0
- opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +34 -3
- opentrons/protocol_api/core/protocol.py +34 -1
- opentrons/protocol_api/core/robot.py +51 -0
- opentrons/protocol_api/instrument_context.py +145 -43
- opentrons/protocol_api/labware.py +231 -7
- opentrons/protocol_api/module_contexts.py +21 -17
- opentrons/protocol_api/protocol_context.py +125 -4
- opentrons/protocol_api/robot_context.py +204 -32
- opentrons/protocol_api/validation.py +261 -3
- opentrons/protocol_engine/__init__.py +4 -0
- opentrons/protocol_engine/actions/actions.py +2 -3
- opentrons/protocol_engine/clients/sync_client.py +18 -0
- opentrons/protocol_engine/commands/__init__.py +81 -0
- opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +0 -2
- opentrons/protocol_engine/commands/absorbance_reader/initialize.py +19 -5
- opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +0 -1
- opentrons/protocol_engine/commands/absorbance_reader/read.py +32 -9
- opentrons/protocol_engine/commands/air_gap_in_place.py +160 -0
- opentrons/protocol_engine/commands/aspirate.py +103 -53
- opentrons/protocol_engine/commands/aspirate_in_place.py +55 -51
- opentrons/protocol_engine/commands/blow_out.py +44 -39
- opentrons/protocol_engine/commands/blow_out_in_place.py +21 -32
- opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +13 -6
- opentrons/protocol_engine/commands/calibration/calibrate_module.py +1 -1
- opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +3 -3
- opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +1 -1
- opentrons/protocol_engine/commands/command.py +73 -66
- opentrons/protocol_engine/commands/command_unions.py +101 -1
- opentrons/protocol_engine/commands/comment.py +1 -1
- opentrons/protocol_engine/commands/configure_for_volume.py +10 -3
- opentrons/protocol_engine/commands/configure_nozzle_layout.py +6 -4
- opentrons/protocol_engine/commands/custom.py +6 -12
- opentrons/protocol_engine/commands/dispense.py +82 -48
- opentrons/protocol_engine/commands/dispense_in_place.py +71 -51
- opentrons/protocol_engine/commands/drop_tip.py +52 -31
- opentrons/protocol_engine/commands/drop_tip_in_place.py +13 -3
- opentrons/protocol_engine/commands/generate_command_schema.py +4 -11
- opentrons/protocol_engine/commands/get_next_tip.py +134 -0
- opentrons/protocol_engine/commands/get_tip_presence.py +1 -1
- opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +1 -1
- opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +1 -1
- opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +1 -1
- opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +1 -1
- opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +1 -1
- opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +1 -1
- opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +10 -4
- opentrons/protocol_engine/commands/home.py +13 -4
- opentrons/protocol_engine/commands/liquid_probe.py +60 -25
- opentrons/protocol_engine/commands/load_labware.py +29 -7
- opentrons/protocol_engine/commands/load_lid.py +146 -0
- opentrons/protocol_engine/commands/load_lid_stack.py +189 -0
- opentrons/protocol_engine/commands/load_liquid.py +12 -4
- opentrons/protocol_engine/commands/load_liquid_class.py +144 -0
- opentrons/protocol_engine/commands/load_module.py +31 -10
- opentrons/protocol_engine/commands/load_pipette.py +19 -8
- opentrons/protocol_engine/commands/magnetic_module/disengage.py +1 -1
- opentrons/protocol_engine/commands/magnetic_module/engage.py +1 -1
- opentrons/protocol_engine/commands/move_labware.py +19 -6
- opentrons/protocol_engine/commands/move_relative.py +35 -25
- opentrons/protocol_engine/commands/move_to_addressable_area.py +40 -27
- opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +53 -32
- opentrons/protocol_engine/commands/move_to_coordinates.py +36 -22
- opentrons/protocol_engine/commands/move_to_well.py +40 -24
- opentrons/protocol_engine/commands/movement_common.py +338 -0
- opentrons/protocol_engine/commands/pick_up_tip.py +49 -27
- opentrons/protocol_engine/commands/pipetting_common.py +169 -87
- opentrons/protocol_engine/commands/prepare_to_aspirate.py +24 -33
- opentrons/protocol_engine/commands/reload_labware.py +1 -1
- opentrons/protocol_engine/commands/retract_axis.py +1 -1
- opentrons/protocol_engine/commands/robot/__init__.py +69 -0
- opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +86 -0
- opentrons/protocol_engine/commands/robot/common.py +18 -0
- opentrons/protocol_engine/commands/robot/move_axes_relative.py +101 -0
- opentrons/protocol_engine/commands/robot/move_axes_to.py +100 -0
- opentrons/protocol_engine/commands/robot/move_to.py +94 -0
- opentrons/protocol_engine/commands/robot/open_gripper_jaw.py +77 -0
- opentrons/protocol_engine/commands/save_position.py +14 -5
- opentrons/protocol_engine/commands/set_rail_lights.py +1 -1
- opentrons/protocol_engine/commands/set_status_bar.py +1 -1
- opentrons/protocol_engine/commands/temperature_module/deactivate.py +1 -1
- opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +1 -1
- opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +10 -4
- opentrons/protocol_engine/commands/thermocycler/close_lid.py +1 -1
- opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +1 -1
- opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +1 -1
- opentrons/protocol_engine/commands/thermocycler/open_lid.py +1 -1
- opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +8 -2
- opentrons/protocol_engine/commands/thermocycler/run_profile.py +9 -3
- opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +11 -4
- opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +1 -1
- opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +1 -1
- opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +1 -1
- opentrons/protocol_engine/commands/touch_tip.py +65 -16
- opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +4 -1
- opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +12 -3
- opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +1 -4
- opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +1 -4
- opentrons/protocol_engine/commands/verify_tip_presence.py +11 -4
- opentrons/protocol_engine/commands/wait_for_duration.py +10 -3
- opentrons/protocol_engine/commands/wait_for_resume.py +10 -3
- opentrons/protocol_engine/errors/__init__.py +8 -0
- opentrons/protocol_engine/errors/error_occurrence.py +19 -20
- opentrons/protocol_engine/errors/exceptions.py +50 -0
- opentrons/protocol_engine/execution/command_executor.py +1 -1
- opentrons/protocol_engine/execution/equipment.py +73 -5
- opentrons/protocol_engine/execution/gantry_mover.py +364 -8
- opentrons/protocol_engine/execution/movement.py +27 -0
- opentrons/protocol_engine/execution/pipetting.py +5 -1
- opentrons/protocol_engine/execution/tip_handler.py +4 -6
- opentrons/protocol_engine/notes/notes.py +1 -1
- opentrons/protocol_engine/protocol_engine.py +7 -6
- opentrons/protocol_engine/resources/labware_data_provider.py +1 -1
- opentrons/protocol_engine/resources/labware_validation.py +5 -0
- opentrons/protocol_engine/resources/module_data_provider.py +1 -1
- opentrons/protocol_engine/resources/pipette_data_provider.py +12 -0
- opentrons/protocol_engine/slot_standardization.py +9 -9
- opentrons/protocol_engine/state/_move_types.py +9 -5
- opentrons/protocol_engine/state/_well_math.py +193 -0
- opentrons/protocol_engine/state/addressable_areas.py +25 -61
- opentrons/protocol_engine/state/command_history.py +12 -0
- opentrons/protocol_engine/state/commands.py +17 -13
- opentrons/protocol_engine/state/files.py +10 -12
- opentrons/protocol_engine/state/fluid_stack.py +138 -0
- opentrons/protocol_engine/state/frustum_helpers.py +57 -32
- opentrons/protocol_engine/state/geometry.py +47 -1
- opentrons/protocol_engine/state/labware.py +79 -25
- opentrons/protocol_engine/state/liquid_classes.py +82 -0
- opentrons/protocol_engine/state/liquids.py +16 -4
- opentrons/protocol_engine/state/modules.py +52 -70
- opentrons/protocol_engine/state/motion.py +6 -1
- opentrons/protocol_engine/state/pipettes.py +135 -58
- opentrons/protocol_engine/state/state.py +21 -2
- opentrons/protocol_engine/state/state_summary.py +4 -2
- opentrons/protocol_engine/state/tips.py +11 -44
- opentrons/protocol_engine/state/update_types.py +343 -48
- opentrons/protocol_engine/state/wells.py +19 -11
- opentrons/protocol_engine/types.py +176 -28
- opentrons/protocol_reader/extract_labware_definitions.py +5 -2
- opentrons/protocol_reader/file_format_validator.py +5 -5
- opentrons/protocol_runner/json_file_reader.py +9 -3
- opentrons/protocol_runner/json_translator.py +51 -25
- opentrons/protocol_runner/legacy_command_mapper.py +66 -64
- opentrons/protocol_runner/protocol_runner.py +35 -4
- opentrons/protocol_runner/python_protocol_wrappers.py +1 -1
- opentrons/protocol_runner/run_orchestrator.py +13 -3
- opentrons/protocols/advanced_control/common.py +38 -0
- opentrons/protocols/advanced_control/mix.py +1 -1
- opentrons/protocols/advanced_control/transfers/__init__.py +0 -0
- opentrons/protocols/advanced_control/transfers/common.py +56 -0
- opentrons/protocols/advanced_control/{transfers.py → transfers/transfer.py} +10 -85
- opentrons/protocols/api_support/definitions.py +1 -1
- opentrons/protocols/api_support/instrument.py +1 -1
- opentrons/protocols/api_support/util.py +10 -0
- opentrons/protocols/labware.py +39 -6
- opentrons/protocols/models/json_protocol.py +5 -9
- opentrons/simulate.py +3 -1
- opentrons/types.py +162 -2
- opentrons/util/logging_config.py +1 -1
- {opentrons-8.3.0a0.dist-info → opentrons-8.3.0a1.dist-info}/METADATA +16 -15
- {opentrons-8.3.0a0.dist-info → opentrons-8.3.0a1.dist-info}/RECORD +228 -201
- {opentrons-8.3.0a0.dist-info → opentrons-8.3.0a1.dist-info}/WHEEL +1 -1
- {opentrons-8.3.0a0.dist-info → opentrons-8.3.0a1.dist-info}/LICENSE +0 -0
- {opentrons-8.3.0a0.dist-info → opentrons-8.3.0a1.dist-info}/entry_points.txt +0 -0
- {opentrons-8.3.0a0.dist-info → opentrons-8.3.0a1.dist-info}/top_level.txt +0 -0
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
"""Common pipetting command base models."""
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
from typing import Literal, Tuple, TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from typing_extensions import TypedDict
|
|
3
7
|
from pydantic import BaseModel, Field
|
|
4
|
-
from typing import Literal, Optional, Tuple, TypedDict
|
|
5
8
|
|
|
9
|
+
from opentrons_shared_data.errors import ErrorCodes
|
|
6
10
|
from opentrons.protocol_engine.errors.error_occurrence import ErrorOccurrence
|
|
11
|
+
from opentrons.protocol_engine.types import AspiratedFluid, FluidKind
|
|
12
|
+
from opentrons_shared_data.errors.exceptions import PipetteOverpressureError
|
|
13
|
+
from .command import DefinedErrorData, SuccessData
|
|
14
|
+
from opentrons.protocol_engine.state.update_types import StateUpdate
|
|
7
15
|
|
|
8
|
-
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from ..execution.pipetting import PipettingHandler
|
|
19
|
+
from ..resources import ModelUtils
|
|
20
|
+
from ..notes import CommandNoteAdder
|
|
9
21
|
|
|
10
22
|
|
|
11
23
|
class PipetteIdMixin(BaseModel):
|
|
@@ -51,72 +63,6 @@ class FlowRateMixin(BaseModel):
|
|
|
51
63
|
)
|
|
52
64
|
|
|
53
65
|
|
|
54
|
-
class WellLocationMixin(BaseModel):
|
|
55
|
-
"""Mixin for command requests that take a location that's somewhere in a well."""
|
|
56
|
-
|
|
57
|
-
labwareId: str = Field(
|
|
58
|
-
...,
|
|
59
|
-
description="Identifier of labware to use.",
|
|
60
|
-
)
|
|
61
|
-
wellName: str = Field(
|
|
62
|
-
...,
|
|
63
|
-
description="Name of well to use in labware.",
|
|
64
|
-
)
|
|
65
|
-
wellLocation: WellLocation = Field(
|
|
66
|
-
default_factory=WellLocation,
|
|
67
|
-
description="Relative well location at which to perform the operation",
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
class LiquidHandlingWellLocationMixin(BaseModel):
|
|
72
|
-
"""Mixin for command requests that take a location that's somewhere in a well."""
|
|
73
|
-
|
|
74
|
-
labwareId: str = Field(
|
|
75
|
-
...,
|
|
76
|
-
description="Identifier of labware to use.",
|
|
77
|
-
)
|
|
78
|
-
wellName: str = Field(
|
|
79
|
-
...,
|
|
80
|
-
description="Name of well to use in labware.",
|
|
81
|
-
)
|
|
82
|
-
wellLocation: LiquidHandlingWellLocation = Field(
|
|
83
|
-
default_factory=LiquidHandlingWellLocation,
|
|
84
|
-
description="Relative well location at which to perform the operation",
|
|
85
|
-
)
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
class MovementMixin(BaseModel):
|
|
89
|
-
"""Mixin for command requests that move a pipette."""
|
|
90
|
-
|
|
91
|
-
minimumZHeight: Optional[float] = Field(
|
|
92
|
-
None,
|
|
93
|
-
description=(
|
|
94
|
-
"Optional minimal Z margin in mm."
|
|
95
|
-
" If this is larger than the API's default safe Z margin,"
|
|
96
|
-
" it will make the arc higher. If it's smaller, it will have no effect."
|
|
97
|
-
),
|
|
98
|
-
)
|
|
99
|
-
|
|
100
|
-
forceDirect: bool = Field(
|
|
101
|
-
False,
|
|
102
|
-
description=(
|
|
103
|
-
"If true, moving from one labware/well to another"
|
|
104
|
-
" will not arc to the default safe z,"
|
|
105
|
-
" but instead will move directly to the specified location."
|
|
106
|
-
" This will also force the `minimumZHeight` param to be ignored."
|
|
107
|
-
" A 'direct' movement is in X/Y/Z simultaneously."
|
|
108
|
-
),
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
speed: Optional[float] = Field(
|
|
112
|
-
None,
|
|
113
|
-
description=(
|
|
114
|
-
"Override the travel speed in mm/s."
|
|
115
|
-
" This controls the straight linear speed of motion."
|
|
116
|
-
),
|
|
117
|
-
)
|
|
118
|
-
|
|
119
|
-
|
|
120
66
|
class BaseLiquidHandlingResult(BaseModel):
|
|
121
67
|
"""Base properties of a liquid handling result."""
|
|
122
68
|
|
|
@@ -127,24 +73,8 @@ class BaseLiquidHandlingResult(BaseModel):
|
|
|
127
73
|
)
|
|
128
74
|
|
|
129
75
|
|
|
130
|
-
class
|
|
131
|
-
"""
|
|
132
|
-
|
|
133
|
-
# todo(mm, 2024-08-02): Consider deprecating or redefining this.
|
|
134
|
-
#
|
|
135
|
-
# This is here because opentrons.protocol_engine needed it for internal bookkeeping
|
|
136
|
-
# and, at the time, we didn't have a way to do that without adding this to the
|
|
137
|
-
# public command results. Its usefulness to callers outside
|
|
138
|
-
# opentrons.protocol_engine is questionable because they would need to know which
|
|
139
|
-
# critical point is in play, and I think that can change depending on obscure
|
|
140
|
-
# things like labware quirks.
|
|
141
|
-
position: DeckPoint = Field(
|
|
142
|
-
DeckPoint(x=0, y=0, z=0),
|
|
143
|
-
description=(
|
|
144
|
-
"The (x,y,z) coordinates of the pipette's critical point in deck space"
|
|
145
|
-
" after the move was completed."
|
|
146
|
-
),
|
|
147
|
-
)
|
|
76
|
+
class EmptyResult(BaseModel):
|
|
77
|
+
"""A result with no data."""
|
|
148
78
|
|
|
149
79
|
|
|
150
80
|
class ErrorLocationInfo(TypedDict):
|
|
@@ -208,3 +138,155 @@ class TipPhysicallyAttachedError(ErrorOccurrence):
|
|
|
208
138
|
detail: str = ErrorCodes.TIP_DROP_FAILED.value.detail
|
|
209
139
|
|
|
210
140
|
errorInfo: ErrorLocationInfo
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
async def prepare_for_aspirate(
|
|
144
|
+
pipette_id: str,
|
|
145
|
+
pipetting: PipettingHandler,
|
|
146
|
+
model_utils: ModelUtils,
|
|
147
|
+
location_if_error: ErrorLocationInfo,
|
|
148
|
+
) -> SuccessData[EmptyResult] | DefinedErrorData[OverpressureError]:
|
|
149
|
+
"""Execute pipetting.prepare_for_aspirate, handle errors, and marshal success."""
|
|
150
|
+
try:
|
|
151
|
+
await pipetting.prepare_for_aspirate(pipette_id)
|
|
152
|
+
except PipetteOverpressureError as e:
|
|
153
|
+
return DefinedErrorData(
|
|
154
|
+
public=OverpressureError(
|
|
155
|
+
id=model_utils.generate_id(),
|
|
156
|
+
createdAt=model_utils.get_timestamp(),
|
|
157
|
+
wrappedErrors=[
|
|
158
|
+
ErrorOccurrence.from_failed(
|
|
159
|
+
id=model_utils.generate_id(),
|
|
160
|
+
createdAt=model_utils.get_timestamp(),
|
|
161
|
+
error=e,
|
|
162
|
+
)
|
|
163
|
+
],
|
|
164
|
+
errorInfo=location_if_error,
|
|
165
|
+
),
|
|
166
|
+
state_update=StateUpdate().set_fluid_unknown(pipette_id=pipette_id),
|
|
167
|
+
)
|
|
168
|
+
else:
|
|
169
|
+
return SuccessData(
|
|
170
|
+
public=EmptyResult(),
|
|
171
|
+
state_update=StateUpdate().set_fluid_empty(pipette_id=pipette_id),
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
async def aspirate_in_place(
|
|
176
|
+
pipette_id: str,
|
|
177
|
+
volume: float,
|
|
178
|
+
flow_rate: float,
|
|
179
|
+
location_if_error: ErrorLocationInfo,
|
|
180
|
+
command_note_adder: CommandNoteAdder,
|
|
181
|
+
pipetting: PipettingHandler,
|
|
182
|
+
model_utils: ModelUtils,
|
|
183
|
+
) -> SuccessData[BaseLiquidHandlingResult] | DefinedErrorData[OverpressureError]:
|
|
184
|
+
"""Execute an aspirate in place microoperation."""
|
|
185
|
+
try:
|
|
186
|
+
volume_aspirated = await pipetting.aspirate_in_place(
|
|
187
|
+
pipette_id=pipette_id,
|
|
188
|
+
volume=volume,
|
|
189
|
+
flow_rate=flow_rate,
|
|
190
|
+
command_note_adder=command_note_adder,
|
|
191
|
+
)
|
|
192
|
+
except PipetteOverpressureError as e:
|
|
193
|
+
return DefinedErrorData(
|
|
194
|
+
public=OverpressureError(
|
|
195
|
+
id=model_utils.generate_id(),
|
|
196
|
+
createdAt=model_utils.get_timestamp(),
|
|
197
|
+
wrappedErrors=[
|
|
198
|
+
ErrorOccurrence.from_failed(
|
|
199
|
+
id=model_utils.generate_id(),
|
|
200
|
+
createdAt=model_utils.get_timestamp(),
|
|
201
|
+
error=e,
|
|
202
|
+
)
|
|
203
|
+
],
|
|
204
|
+
errorInfo=location_if_error,
|
|
205
|
+
),
|
|
206
|
+
state_update=StateUpdate().set_fluid_unknown(pipette_id=pipette_id),
|
|
207
|
+
)
|
|
208
|
+
else:
|
|
209
|
+
return SuccessData(
|
|
210
|
+
public=BaseLiquidHandlingResult(
|
|
211
|
+
volume=volume_aspirated,
|
|
212
|
+
),
|
|
213
|
+
state_update=StateUpdate().set_fluid_aspirated(
|
|
214
|
+
pipette_id=pipette_id,
|
|
215
|
+
fluid=AspiratedFluid(kind=FluidKind.LIQUID, volume=volume_aspirated),
|
|
216
|
+
),
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
async def dispense_in_place(
|
|
221
|
+
pipette_id: str,
|
|
222
|
+
volume: float,
|
|
223
|
+
flow_rate: float,
|
|
224
|
+
push_out: float | None,
|
|
225
|
+
location_if_error: ErrorLocationInfo,
|
|
226
|
+
pipetting: PipettingHandler,
|
|
227
|
+
model_utils: ModelUtils,
|
|
228
|
+
) -> SuccessData[BaseLiquidHandlingResult] | DefinedErrorData[OverpressureError]:
|
|
229
|
+
"""Dispense-in-place as a microoperation."""
|
|
230
|
+
try:
|
|
231
|
+
volume = await pipetting.dispense_in_place(
|
|
232
|
+
pipette_id=pipette_id,
|
|
233
|
+
volume=volume,
|
|
234
|
+
flow_rate=flow_rate,
|
|
235
|
+
push_out=push_out,
|
|
236
|
+
)
|
|
237
|
+
except PipetteOverpressureError as e:
|
|
238
|
+
return DefinedErrorData(
|
|
239
|
+
public=OverpressureError(
|
|
240
|
+
id=model_utils.generate_id(),
|
|
241
|
+
createdAt=model_utils.get_timestamp(),
|
|
242
|
+
wrappedErrors=[
|
|
243
|
+
ErrorOccurrence.from_failed(
|
|
244
|
+
id=model_utils.generate_id(),
|
|
245
|
+
createdAt=model_utils.get_timestamp(),
|
|
246
|
+
error=e,
|
|
247
|
+
)
|
|
248
|
+
],
|
|
249
|
+
errorInfo=location_if_error,
|
|
250
|
+
),
|
|
251
|
+
state_update=StateUpdate().set_fluid_unknown(pipette_id=pipette_id),
|
|
252
|
+
)
|
|
253
|
+
else:
|
|
254
|
+
return SuccessData(
|
|
255
|
+
public=BaseLiquidHandlingResult(volume=volume),
|
|
256
|
+
state_update=StateUpdate().set_fluid_ejected(
|
|
257
|
+
pipette_id=pipette_id, volume=volume
|
|
258
|
+
),
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
async def blow_out_in_place(
|
|
263
|
+
pipette_id: str,
|
|
264
|
+
flow_rate: float,
|
|
265
|
+
location_if_error: ErrorLocationInfo,
|
|
266
|
+
pipetting: PipettingHandler,
|
|
267
|
+
model_utils: ModelUtils,
|
|
268
|
+
) -> SuccessData[EmptyResult] | DefinedErrorData[OverpressureError]:
|
|
269
|
+
"""Execute a blow-out-in-place micro-operation."""
|
|
270
|
+
try:
|
|
271
|
+
await pipetting.blow_out_in_place(pipette_id=pipette_id, flow_rate=flow_rate)
|
|
272
|
+
except PipetteOverpressureError as e:
|
|
273
|
+
return DefinedErrorData(
|
|
274
|
+
public=OverpressureError(
|
|
275
|
+
id=model_utils.generate_id(),
|
|
276
|
+
createdAt=model_utils.get_timestamp(),
|
|
277
|
+
wrappedErrors=[
|
|
278
|
+
ErrorOccurrence.from_failed(
|
|
279
|
+
id=model_utils.generate_id(),
|
|
280
|
+
createdAt=model_utils.get_timestamp(),
|
|
281
|
+
error=e,
|
|
282
|
+
)
|
|
283
|
+
],
|
|
284
|
+
errorInfo=location_if_error,
|
|
285
|
+
),
|
|
286
|
+
state_update=StateUpdate().set_fluid_unknown(pipette_id=pipette_id),
|
|
287
|
+
)
|
|
288
|
+
else:
|
|
289
|
+
return SuccessData(
|
|
290
|
+
public=EmptyResult(),
|
|
291
|
+
state_update=StateUpdate().set_fluid_empty(pipette_id=pipette_id),
|
|
292
|
+
)
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
"""Prepare to aspirate command request, result, and implementation models."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
|
-
from opentrons_shared_data.errors.exceptions import PipetteOverpressureError
|
|
5
4
|
from pydantic import BaseModel
|
|
6
5
|
from typing import TYPE_CHECKING, Optional, Type, Union
|
|
7
6
|
from typing_extensions import Literal
|
|
8
7
|
|
|
9
|
-
from .pipetting_common import
|
|
10
|
-
OverpressureError,
|
|
11
|
-
PipetteIdMixin,
|
|
12
|
-
)
|
|
8
|
+
from .pipetting_common import OverpressureError, PipetteIdMixin, prepare_for_aspirate
|
|
13
9
|
from .command import (
|
|
14
10
|
AbstractCommandImpl,
|
|
15
11
|
BaseCommand,
|
|
@@ -61,39 +57,34 @@ class PrepareToAspirateImplementation(
|
|
|
61
57
|
self._model_utils = model_utils
|
|
62
58
|
self._gantry_mover = gantry_mover
|
|
63
59
|
|
|
60
|
+
def _transform_result(
|
|
61
|
+
self, result: SuccessData[BaseModel]
|
|
62
|
+
) -> SuccessData[PrepareToAspirateResult]:
|
|
63
|
+
return SuccessData(
|
|
64
|
+
public=PrepareToAspirateResult(), state_update=result.state_update
|
|
65
|
+
)
|
|
66
|
+
|
|
64
67
|
async def execute(self, params: PrepareToAspirateParams) -> _ExecuteReturn:
|
|
65
68
|
"""Prepare the pipette to aspirate."""
|
|
66
69
|
current_position = await self._gantry_mover.get_position(params.pipetteId)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
)
|
|
82
|
-
],
|
|
83
|
-
errorInfo=(
|
|
84
|
-
{
|
|
85
|
-
"retryLocation": (
|
|
86
|
-
current_position.x,
|
|
87
|
-
current_position.y,
|
|
88
|
-
current_position.z,
|
|
89
|
-
)
|
|
90
|
-
}
|
|
91
|
-
),
|
|
92
|
-
),
|
|
93
|
-
)
|
|
70
|
+
prepare_result = await prepare_for_aspirate(
|
|
71
|
+
pipette_id=params.pipetteId,
|
|
72
|
+
pipetting=self._pipetting_handler,
|
|
73
|
+
model_utils=self._model_utils,
|
|
74
|
+
location_if_error={
|
|
75
|
+
"retryLocation": (
|
|
76
|
+
current_position.x,
|
|
77
|
+
current_position.y,
|
|
78
|
+
current_position.z,
|
|
79
|
+
)
|
|
80
|
+
},
|
|
81
|
+
)
|
|
82
|
+
if isinstance(prepare_result, DefinedErrorData):
|
|
83
|
+
return prepare_result
|
|
94
84
|
else:
|
|
95
85
|
return SuccessData(
|
|
96
86
|
public=PrepareToAspirateResult(),
|
|
87
|
+
state_update=prepare_result.state_update,
|
|
97
88
|
)
|
|
98
89
|
|
|
99
90
|
|
|
@@ -104,7 +95,7 @@ class PrepareToAspirate(
|
|
|
104
95
|
|
|
105
96
|
commandType: PrepareToAspirateCommandType = "prepareToAspirate"
|
|
106
97
|
params: PrepareToAspirateParams
|
|
107
|
-
result: Optional[PrepareToAspirateResult]
|
|
98
|
+
result: Optional[PrepareToAspirateResult] = None
|
|
108
99
|
|
|
109
100
|
_ImplementationCls: Type[
|
|
110
101
|
PrepareToAspirateImplementation
|
|
@@ -89,7 +89,7 @@ class ReloadLabware(
|
|
|
89
89
|
|
|
90
90
|
commandType: ReloadLabwareCommandType = "reloadLabware"
|
|
91
91
|
params: ReloadLabwareParams
|
|
92
|
-
result: Optional[ReloadLabwareResult]
|
|
92
|
+
result: Optional[ReloadLabwareResult] = None
|
|
93
93
|
|
|
94
94
|
_ImplementationCls: Type[ReloadLabwareImplementation] = ReloadLabwareImplementation
|
|
95
95
|
|
|
@@ -61,7 +61,7 @@ class RetractAxis(BaseCommand[RetractAxisParams, RetractAxisResult, ErrorOccurre
|
|
|
61
61
|
|
|
62
62
|
commandType: RetractAxisCommandType = "retractAxis"
|
|
63
63
|
params: RetractAxisParams
|
|
64
|
-
result: Optional[RetractAxisResult]
|
|
64
|
+
result: Optional[RetractAxisResult] = None
|
|
65
65
|
|
|
66
66
|
_ImplementationCls: Type[RetractAxisImplementation] = RetractAxisImplementation
|
|
67
67
|
|
|
@@ -1 +1,70 @@
|
|
|
1
1
|
"""Robot movement commands."""
|
|
2
|
+
|
|
3
|
+
from .move_to import (
|
|
4
|
+
MoveTo,
|
|
5
|
+
MoveToCreate,
|
|
6
|
+
MoveToParams,
|
|
7
|
+
MoveToResult,
|
|
8
|
+
MoveToCommandType,
|
|
9
|
+
)
|
|
10
|
+
from .move_axes_to import (
|
|
11
|
+
MoveAxesTo,
|
|
12
|
+
MoveAxesToCreate,
|
|
13
|
+
MoveAxesToParams,
|
|
14
|
+
MoveAxesToResult,
|
|
15
|
+
MoveAxesToCommandType,
|
|
16
|
+
)
|
|
17
|
+
from .move_axes_relative import (
|
|
18
|
+
MoveAxesRelative,
|
|
19
|
+
MoveAxesRelativeCreate,
|
|
20
|
+
MoveAxesRelativeParams,
|
|
21
|
+
MoveAxesRelativeResult,
|
|
22
|
+
MoveAxesRelativeCommandType,
|
|
23
|
+
)
|
|
24
|
+
from .open_gripper_jaw import (
|
|
25
|
+
openGripperJaw,
|
|
26
|
+
openGripperJawCreate,
|
|
27
|
+
openGripperJawParams,
|
|
28
|
+
openGripperJawResult,
|
|
29
|
+
openGripperJawCommandType,
|
|
30
|
+
)
|
|
31
|
+
from .close_gripper_jaw import (
|
|
32
|
+
closeGripperJaw,
|
|
33
|
+
closeGripperJawCreate,
|
|
34
|
+
closeGripperJawParams,
|
|
35
|
+
closeGripperJawResult,
|
|
36
|
+
closeGripperJawCommandType,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
__all__ = [
|
|
40
|
+
# robot/moveTo
|
|
41
|
+
"MoveTo",
|
|
42
|
+
"MoveToCreate",
|
|
43
|
+
"MoveToParams",
|
|
44
|
+
"MoveToResult",
|
|
45
|
+
"MoveToCommandType",
|
|
46
|
+
# robot/moveAxesTo
|
|
47
|
+
"MoveAxesTo",
|
|
48
|
+
"MoveAxesToCreate",
|
|
49
|
+
"MoveAxesToParams",
|
|
50
|
+
"MoveAxesToResult",
|
|
51
|
+
"MoveAxesToCommandType",
|
|
52
|
+
# robot/moveAxesRelative
|
|
53
|
+
"MoveAxesRelative",
|
|
54
|
+
"MoveAxesRelativeCreate",
|
|
55
|
+
"MoveAxesRelativeParams",
|
|
56
|
+
"MoveAxesRelativeResult",
|
|
57
|
+
"MoveAxesRelativeCommandType",
|
|
58
|
+
# robot/openGripperJaw
|
|
59
|
+
"openGripperJaw",
|
|
60
|
+
"openGripperJawCreate",
|
|
61
|
+
"openGripperJawParams",
|
|
62
|
+
"openGripperJawResult",
|
|
63
|
+
"openGripperJawCommandType",
|
|
64
|
+
# robot/closeGripperJaw
|
|
65
|
+
"closeGripperJaw",
|
|
66
|
+
"closeGripperJawCreate",
|
|
67
|
+
"closeGripperJawParams",
|
|
68
|
+
"closeGripperJawResult",
|
|
69
|
+
"closeGripperJawCommandType",
|
|
70
|
+
]
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""Command models for opening a gripper jaw."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
from typing import Literal, Type, Optional, Any
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, Field
|
|
6
|
+
from pydantic.json_schema import SkipJsonSchema
|
|
7
|
+
|
|
8
|
+
from opentrons.hardware_control import HardwareControlAPI
|
|
9
|
+
from opentrons.protocol_engine.resources import ensure_ot3_hardware
|
|
10
|
+
|
|
11
|
+
from ..command import (
|
|
12
|
+
AbstractCommandImpl,
|
|
13
|
+
BaseCommand,
|
|
14
|
+
BaseCommandCreate,
|
|
15
|
+
SuccessData,
|
|
16
|
+
)
|
|
17
|
+
from opentrons.protocol_engine.errors.error_occurrence import ErrorOccurrence
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
closeGripperJawCommandType = Literal["robot/closeGripperJaw"]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _remove_default(s: dict[str, Any]) -> None:
|
|
24
|
+
s.pop("default", None)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class closeGripperJawParams(BaseModel):
|
|
28
|
+
"""Payload required to close a gripper."""
|
|
29
|
+
|
|
30
|
+
force: float | SkipJsonSchema[None] = Field(
|
|
31
|
+
default=None,
|
|
32
|
+
description="The force the gripper should use to hold the jaws, falls to default if none is provided.",
|
|
33
|
+
json_schema_extra=_remove_default,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class closeGripperJawResult(BaseModel):
|
|
38
|
+
"""Result data from the execution of a closeGripperJaw command."""
|
|
39
|
+
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class closeGripperJawImplementation(
|
|
44
|
+
AbstractCommandImpl[closeGripperJawParams, SuccessData[closeGripperJawResult]]
|
|
45
|
+
):
|
|
46
|
+
"""closeGripperJaw command implementation."""
|
|
47
|
+
|
|
48
|
+
def __init__(
|
|
49
|
+
self,
|
|
50
|
+
hardware_api: HardwareControlAPI,
|
|
51
|
+
**kwargs: object,
|
|
52
|
+
) -> None:
|
|
53
|
+
self._hardware_api = hardware_api
|
|
54
|
+
|
|
55
|
+
async def execute(
|
|
56
|
+
self, params: closeGripperJawParams
|
|
57
|
+
) -> SuccessData[closeGripperJawResult]:
|
|
58
|
+
"""Release the gripper."""
|
|
59
|
+
ot3_hardware_api = ensure_ot3_hardware(self._hardware_api)
|
|
60
|
+
await ot3_hardware_api.grip(force_newtons=params.force)
|
|
61
|
+
return SuccessData(
|
|
62
|
+
public=closeGripperJawResult(),
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class closeGripperJaw(
|
|
67
|
+
BaseCommand[closeGripperJawParams, closeGripperJawResult, ErrorOccurrence]
|
|
68
|
+
):
|
|
69
|
+
"""closeGripperJaw command model."""
|
|
70
|
+
|
|
71
|
+
commandType: closeGripperJawCommandType = "robot/closeGripperJaw"
|
|
72
|
+
params: closeGripperJawParams
|
|
73
|
+
result: Optional[closeGripperJawResult]
|
|
74
|
+
|
|
75
|
+
_ImplementationCls: Type[
|
|
76
|
+
closeGripperJawImplementation
|
|
77
|
+
] = closeGripperJawImplementation
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class closeGripperJawCreate(BaseCommandCreate[closeGripperJawParams]):
|
|
81
|
+
"""closeGripperJaw command request model."""
|
|
82
|
+
|
|
83
|
+
commandType: closeGripperJawCommandType = "robot/closeGripperJaw"
|
|
84
|
+
params: closeGripperJawParams
|
|
85
|
+
|
|
86
|
+
_CommandCls: Type[closeGripperJaw] = closeGripperJaw
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""Shared result types for robot API commands."""
|
|
2
|
+
from pydantic import BaseModel, Field
|
|
3
|
+
|
|
4
|
+
from typing import Dict
|
|
5
|
+
from opentrons.protocol_engine.types import MotorAxis
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
MotorAxisMapType = Dict[MotorAxis, float]
|
|
9
|
+
default_position = {ax: 0.0 for ax in MotorAxis}
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class DestinationRobotPositionResult(BaseModel):
|
|
13
|
+
"""The result dictionary of `MotorAxis` type."""
|
|
14
|
+
|
|
15
|
+
position: MotorAxisMapType = Field(
|
|
16
|
+
default=default_position,
|
|
17
|
+
description="The position of all axes on the robot. If no mount was provided, the last moved mount is used to determine the location.",
|
|
18
|
+
)
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""Command models for moving any robot axis relative."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
from typing import Literal, Type, Optional, TYPE_CHECKING, Any
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
from pydantic.json_schema import SkipJsonSchema
|
|
8
|
+
from opentrons.hardware_control import HardwareControlAPI
|
|
9
|
+
from opentrons.protocol_engine.resources import ensure_ot3_hardware
|
|
10
|
+
|
|
11
|
+
from .common import MotorAxisMapType, DestinationRobotPositionResult
|
|
12
|
+
|
|
13
|
+
from ..command import (
|
|
14
|
+
AbstractCommandImpl,
|
|
15
|
+
BaseCommand,
|
|
16
|
+
BaseCommandCreate,
|
|
17
|
+
SuccessData,
|
|
18
|
+
)
|
|
19
|
+
from ...errors.error_occurrence import ErrorOccurrence
|
|
20
|
+
|
|
21
|
+
if TYPE_CHECKING:
|
|
22
|
+
from opentrons.protocol_engine.execution import GantryMover
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
MoveAxesRelativeCommandType = Literal["robot/moveAxesRelative"]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _remove_default(s: dict[str, Any]) -> None:
|
|
29
|
+
s.pop("default", None)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class MoveAxesRelativeParams(BaseModel):
|
|
33
|
+
"""Payload required to move axes relative to position."""
|
|
34
|
+
|
|
35
|
+
axis_map: MotorAxisMapType = Field(
|
|
36
|
+
..., description="A dictionary mapping axes to relative movements in mm."
|
|
37
|
+
)
|
|
38
|
+
speed: float | SkipJsonSchema[None] = Field(
|
|
39
|
+
default=None,
|
|
40
|
+
description="The max velocity to move the axes at. Will fall to hardware defaults if none provided.",
|
|
41
|
+
json_schema_extra=_remove_default,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class MoveAxesRelativeResult(DestinationRobotPositionResult):
|
|
46
|
+
"""Result data from the execution of a MoveAxesRelative command."""
|
|
47
|
+
|
|
48
|
+
pass
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class MoveAxesRelativeImplementation(
|
|
52
|
+
AbstractCommandImpl[MoveAxesRelativeParams, SuccessData[MoveAxesRelativeResult]]
|
|
53
|
+
):
|
|
54
|
+
"""MoveAxesRelative command implementation."""
|
|
55
|
+
|
|
56
|
+
def __init__(
|
|
57
|
+
self,
|
|
58
|
+
gantry_mover: GantryMover,
|
|
59
|
+
hardware_api: HardwareControlAPI,
|
|
60
|
+
**kwargs: object,
|
|
61
|
+
) -> None:
|
|
62
|
+
self._gantry_mover = gantry_mover
|
|
63
|
+
self._hardware_api = hardware_api
|
|
64
|
+
|
|
65
|
+
async def execute(
|
|
66
|
+
self, params: MoveAxesRelativeParams
|
|
67
|
+
) -> SuccessData[MoveAxesRelativeResult]:
|
|
68
|
+
"""Move the axes on a flex a relative distance."""
|
|
69
|
+
# TODO (lc 08-16-2024) implement `move_axes` for OT 2 hardware controller
|
|
70
|
+
# and then we can remove this validation.
|
|
71
|
+
ensure_ot3_hardware(self._hardware_api)
|
|
72
|
+
|
|
73
|
+
current_position = await self._gantry_mover.move_axes(
|
|
74
|
+
axis_map=params.axis_map, speed=params.speed, relative_move=True
|
|
75
|
+
)
|
|
76
|
+
return SuccessData(
|
|
77
|
+
public=MoveAxesRelativeResult(position=current_position),
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class MoveAxesRelative(
|
|
82
|
+
BaseCommand[MoveAxesRelativeParams, MoveAxesRelativeResult, ErrorOccurrence]
|
|
83
|
+
):
|
|
84
|
+
"""MoveAxesRelative command model."""
|
|
85
|
+
|
|
86
|
+
commandType: MoveAxesRelativeCommandType = "robot/moveAxesRelative"
|
|
87
|
+
params: MoveAxesRelativeParams
|
|
88
|
+
result: Optional[MoveAxesRelativeResult]
|
|
89
|
+
|
|
90
|
+
_ImplementationCls: Type[
|
|
91
|
+
MoveAxesRelativeImplementation
|
|
92
|
+
] = MoveAxesRelativeImplementation
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class MoveAxesRelativeCreate(BaseCommandCreate[MoveAxesRelativeParams]):
|
|
96
|
+
"""MoveAxesRelative command request model."""
|
|
97
|
+
|
|
98
|
+
commandType: MoveAxesRelativeCommandType = "robot/moveAxesRelative"
|
|
99
|
+
params: MoveAxesRelativeParams
|
|
100
|
+
|
|
101
|
+
_CommandCls: Type[MoveAxesRelative] = MoveAxesRelative
|