opentrons 8.6.0__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.
Potentially problematic release.
This version of opentrons might be problematic. Click here for more details.
- opentrons/__init__.py +150 -0
- opentrons/_version.py +34 -0
- opentrons/calibration_storage/__init__.py +54 -0
- opentrons/calibration_storage/deck_configuration.py +62 -0
- opentrons/calibration_storage/encoder_decoder.py +31 -0
- opentrons/calibration_storage/file_operators.py +142 -0
- opentrons/calibration_storage/helpers.py +103 -0
- opentrons/calibration_storage/ot2/__init__.py +34 -0
- opentrons/calibration_storage/ot2/deck_attitude.py +85 -0
- opentrons/calibration_storage/ot2/mark_bad_calibration.py +27 -0
- opentrons/calibration_storage/ot2/models/__init__.py +0 -0
- opentrons/calibration_storage/ot2/models/v1.py +149 -0
- opentrons/calibration_storage/ot2/pipette_offset.py +129 -0
- opentrons/calibration_storage/ot2/tip_length.py +281 -0
- opentrons/calibration_storage/ot3/__init__.py +31 -0
- opentrons/calibration_storage/ot3/deck_attitude.py +83 -0
- opentrons/calibration_storage/ot3/gripper_offset.py +156 -0
- opentrons/calibration_storage/ot3/models/__init__.py +0 -0
- opentrons/calibration_storage/ot3/models/v1.py +122 -0
- opentrons/calibration_storage/ot3/module_offset.py +138 -0
- opentrons/calibration_storage/ot3/pipette_offset.py +95 -0
- opentrons/calibration_storage/types.py +45 -0
- opentrons/cli/__init__.py +21 -0
- opentrons/cli/__main__.py +5 -0
- opentrons/cli/analyze.py +557 -0
- opentrons/config/__init__.py +631 -0
- opentrons/config/advanced_settings.py +871 -0
- opentrons/config/defaults_ot2.py +214 -0
- opentrons/config/defaults_ot3.py +499 -0
- opentrons/config/feature_flags.py +86 -0
- opentrons/config/gripper_config.py +55 -0
- opentrons/config/reset.py +203 -0
- opentrons/config/robot_configs.py +187 -0
- opentrons/config/types.py +183 -0
- opentrons/drivers/__init__.py +0 -0
- opentrons/drivers/absorbance_reader/__init__.py +11 -0
- opentrons/drivers/absorbance_reader/abstract.py +72 -0
- opentrons/drivers/absorbance_reader/async_byonoy.py +352 -0
- opentrons/drivers/absorbance_reader/driver.py +81 -0
- opentrons/drivers/absorbance_reader/hid_protocol.py +161 -0
- opentrons/drivers/absorbance_reader/simulator.py +84 -0
- opentrons/drivers/asyncio/__init__.py +0 -0
- opentrons/drivers/asyncio/communication/__init__.py +22 -0
- opentrons/drivers/asyncio/communication/async_serial.py +187 -0
- opentrons/drivers/asyncio/communication/errors.py +88 -0
- opentrons/drivers/asyncio/communication/serial_connection.py +557 -0
- opentrons/drivers/command_builder.py +102 -0
- opentrons/drivers/flex_stacker/__init__.py +13 -0
- opentrons/drivers/flex_stacker/abstract.py +214 -0
- opentrons/drivers/flex_stacker/driver.py +768 -0
- opentrons/drivers/flex_stacker/errors.py +68 -0
- opentrons/drivers/flex_stacker/simulator.py +309 -0
- opentrons/drivers/flex_stacker/types.py +367 -0
- opentrons/drivers/flex_stacker/utils.py +19 -0
- opentrons/drivers/heater_shaker/__init__.py +5 -0
- opentrons/drivers/heater_shaker/abstract.py +76 -0
- opentrons/drivers/heater_shaker/driver.py +204 -0
- opentrons/drivers/heater_shaker/simulator.py +94 -0
- opentrons/drivers/mag_deck/__init__.py +6 -0
- opentrons/drivers/mag_deck/abstract.py +44 -0
- opentrons/drivers/mag_deck/driver.py +208 -0
- opentrons/drivers/mag_deck/simulator.py +63 -0
- opentrons/drivers/rpi_drivers/__init__.py +33 -0
- opentrons/drivers/rpi_drivers/dev_types.py +94 -0
- opentrons/drivers/rpi_drivers/gpio.py +282 -0
- opentrons/drivers/rpi_drivers/gpio_simulator.py +127 -0
- opentrons/drivers/rpi_drivers/interfaces.py +15 -0
- opentrons/drivers/rpi_drivers/types.py +364 -0
- opentrons/drivers/rpi_drivers/usb.py +102 -0
- opentrons/drivers/rpi_drivers/usb_simulator.py +22 -0
- opentrons/drivers/serial_communication.py +151 -0
- opentrons/drivers/smoothie_drivers/__init__.py +4 -0
- opentrons/drivers/smoothie_drivers/connection.py +51 -0
- opentrons/drivers/smoothie_drivers/constants.py +121 -0
- opentrons/drivers/smoothie_drivers/driver_3_0.py +1933 -0
- opentrons/drivers/smoothie_drivers/errors.py +49 -0
- opentrons/drivers/smoothie_drivers/parse_utils.py +143 -0
- opentrons/drivers/smoothie_drivers/simulator.py +99 -0
- opentrons/drivers/smoothie_drivers/types.py +16 -0
- opentrons/drivers/temp_deck/__init__.py +10 -0
- opentrons/drivers/temp_deck/abstract.py +54 -0
- opentrons/drivers/temp_deck/driver.py +197 -0
- opentrons/drivers/temp_deck/simulator.py +57 -0
- opentrons/drivers/thermocycler/__init__.py +12 -0
- opentrons/drivers/thermocycler/abstract.py +99 -0
- opentrons/drivers/thermocycler/driver.py +395 -0
- opentrons/drivers/thermocycler/simulator.py +126 -0
- opentrons/drivers/types.py +107 -0
- opentrons/drivers/utils.py +222 -0
- opentrons/execute.py +742 -0
- opentrons/hardware_control/__init__.py +65 -0
- opentrons/hardware_control/__main__.py +77 -0
- opentrons/hardware_control/adapters.py +98 -0
- opentrons/hardware_control/api.py +1347 -0
- opentrons/hardware_control/backends/__init__.py +7 -0
- opentrons/hardware_control/backends/controller.py +400 -0
- opentrons/hardware_control/backends/errors.py +9 -0
- opentrons/hardware_control/backends/estop_state.py +164 -0
- opentrons/hardware_control/backends/flex_protocol.py +497 -0
- opentrons/hardware_control/backends/ot3controller.py +1930 -0
- opentrons/hardware_control/backends/ot3simulator.py +900 -0
- opentrons/hardware_control/backends/ot3utils.py +664 -0
- opentrons/hardware_control/backends/simulator.py +442 -0
- opentrons/hardware_control/backends/status_bar_state.py +240 -0
- opentrons/hardware_control/backends/subsystem_manager.py +431 -0
- opentrons/hardware_control/backends/tip_presence_manager.py +173 -0
- opentrons/hardware_control/backends/types.py +14 -0
- opentrons/hardware_control/constants.py +6 -0
- opentrons/hardware_control/dev_types.py +125 -0
- opentrons/hardware_control/emulation/__init__.py +0 -0
- opentrons/hardware_control/emulation/abstract_emulator.py +21 -0
- opentrons/hardware_control/emulation/app.py +56 -0
- opentrons/hardware_control/emulation/connection_handler.py +38 -0
- opentrons/hardware_control/emulation/heater_shaker.py +150 -0
- opentrons/hardware_control/emulation/magdeck.py +60 -0
- opentrons/hardware_control/emulation/module_server/__init__.py +8 -0
- opentrons/hardware_control/emulation/module_server/client.py +78 -0
- opentrons/hardware_control/emulation/module_server/helpers.py +130 -0
- opentrons/hardware_control/emulation/module_server/models.py +31 -0
- opentrons/hardware_control/emulation/module_server/server.py +110 -0
- opentrons/hardware_control/emulation/parser.py +74 -0
- opentrons/hardware_control/emulation/proxy.py +241 -0
- opentrons/hardware_control/emulation/run_emulator.py +68 -0
- opentrons/hardware_control/emulation/scripts/__init__.py +0 -0
- opentrons/hardware_control/emulation/scripts/run_app.py +54 -0
- opentrons/hardware_control/emulation/scripts/run_module_emulator.py +72 -0
- opentrons/hardware_control/emulation/scripts/run_smoothie.py +37 -0
- opentrons/hardware_control/emulation/settings.py +119 -0
- opentrons/hardware_control/emulation/simulations.py +133 -0
- opentrons/hardware_control/emulation/smoothie.py +192 -0
- opentrons/hardware_control/emulation/tempdeck.py +69 -0
- opentrons/hardware_control/emulation/thermocycler.py +128 -0
- opentrons/hardware_control/emulation/types.py +10 -0
- opentrons/hardware_control/emulation/util.py +38 -0
- opentrons/hardware_control/errors.py +43 -0
- opentrons/hardware_control/execution_manager.py +164 -0
- opentrons/hardware_control/instruments/__init__.py +5 -0
- opentrons/hardware_control/instruments/instrument_abc.py +39 -0
- opentrons/hardware_control/instruments/ot2/__init__.py +0 -0
- opentrons/hardware_control/instruments/ot2/instrument_calibration.py +152 -0
- opentrons/hardware_control/instruments/ot2/pipette.py +777 -0
- opentrons/hardware_control/instruments/ot2/pipette_handler.py +995 -0
- opentrons/hardware_control/instruments/ot3/__init__.py +0 -0
- opentrons/hardware_control/instruments/ot3/gripper.py +420 -0
- opentrons/hardware_control/instruments/ot3/gripper_handler.py +173 -0
- opentrons/hardware_control/instruments/ot3/instrument_calibration.py +214 -0
- opentrons/hardware_control/instruments/ot3/pipette.py +858 -0
- opentrons/hardware_control/instruments/ot3/pipette_handler.py +1030 -0
- opentrons/hardware_control/module_control.py +332 -0
- opentrons/hardware_control/modules/__init__.py +69 -0
- opentrons/hardware_control/modules/absorbance_reader.py +373 -0
- opentrons/hardware_control/modules/errors.py +7 -0
- opentrons/hardware_control/modules/flex_stacker.py +948 -0
- opentrons/hardware_control/modules/heater_shaker.py +426 -0
- opentrons/hardware_control/modules/lid_temp_status.py +35 -0
- opentrons/hardware_control/modules/magdeck.py +233 -0
- opentrons/hardware_control/modules/mod_abc.py +245 -0
- opentrons/hardware_control/modules/module_calibration.py +93 -0
- opentrons/hardware_control/modules/plate_temp_status.py +61 -0
- opentrons/hardware_control/modules/tempdeck.py +299 -0
- opentrons/hardware_control/modules/thermocycler.py +731 -0
- opentrons/hardware_control/modules/types.py +417 -0
- opentrons/hardware_control/modules/update.py +255 -0
- opentrons/hardware_control/modules/utils.py +73 -0
- opentrons/hardware_control/motion_utilities.py +318 -0
- opentrons/hardware_control/nozzle_manager.py +422 -0
- opentrons/hardware_control/ot3_calibration.py +1171 -0
- opentrons/hardware_control/ot3api.py +3227 -0
- opentrons/hardware_control/pause_manager.py +31 -0
- opentrons/hardware_control/poller.py +112 -0
- opentrons/hardware_control/protocols/__init__.py +106 -0
- opentrons/hardware_control/protocols/asyncio_configurable.py +11 -0
- opentrons/hardware_control/protocols/calibratable.py +45 -0
- opentrons/hardware_control/protocols/chassis_accessory_manager.py +90 -0
- opentrons/hardware_control/protocols/configurable.py +48 -0
- opentrons/hardware_control/protocols/event_sourcer.py +18 -0
- opentrons/hardware_control/protocols/execution_controllable.py +33 -0
- opentrons/hardware_control/protocols/flex_calibratable.py +96 -0
- opentrons/hardware_control/protocols/flex_instrument_configurer.py +52 -0
- opentrons/hardware_control/protocols/gripper_controller.py +55 -0
- opentrons/hardware_control/protocols/hardware_manager.py +51 -0
- opentrons/hardware_control/protocols/identifiable.py +16 -0
- opentrons/hardware_control/protocols/instrument_configurer.py +206 -0
- opentrons/hardware_control/protocols/liquid_handler.py +266 -0
- opentrons/hardware_control/protocols/module_provider.py +16 -0
- opentrons/hardware_control/protocols/motion_controller.py +243 -0
- opentrons/hardware_control/protocols/position_estimator.py +45 -0
- opentrons/hardware_control/protocols/simulatable.py +10 -0
- opentrons/hardware_control/protocols/stoppable.py +9 -0
- opentrons/hardware_control/protocols/types.py +27 -0
- opentrons/hardware_control/robot_calibration.py +224 -0
- opentrons/hardware_control/scripts/README.md +28 -0
- opentrons/hardware_control/scripts/__init__.py +1 -0
- opentrons/hardware_control/scripts/gripper_control.py +208 -0
- opentrons/hardware_control/scripts/ot3gripper +7 -0
- opentrons/hardware_control/scripts/ot3repl +7 -0
- opentrons/hardware_control/scripts/repl.py +187 -0
- opentrons/hardware_control/scripts/tc_control.py +97 -0
- opentrons/hardware_control/scripts/update_module_fw.py +274 -0
- opentrons/hardware_control/simulator_setup.py +260 -0
- opentrons/hardware_control/thread_manager.py +431 -0
- opentrons/hardware_control/threaded_async_lock.py +97 -0
- opentrons/hardware_control/types.py +792 -0
- opentrons/hardware_control/util.py +234 -0
- opentrons/legacy_broker.py +53 -0
- opentrons/legacy_commands/__init__.py +1 -0
- opentrons/legacy_commands/commands.py +483 -0
- opentrons/legacy_commands/helpers.py +153 -0
- opentrons/legacy_commands/module_commands.py +276 -0
- opentrons/legacy_commands/protocol_commands.py +54 -0
- opentrons/legacy_commands/publisher.py +155 -0
- opentrons/legacy_commands/robot_commands.py +51 -0
- opentrons/legacy_commands/types.py +1186 -0
- opentrons/motion_planning/__init__.py +32 -0
- opentrons/motion_planning/adjacent_slots_getters.py +168 -0
- opentrons/motion_planning/deck_conflict.py +501 -0
- opentrons/motion_planning/errors.py +35 -0
- opentrons/motion_planning/types.py +42 -0
- opentrons/motion_planning/waypoints.py +218 -0
- opentrons/ordered_set.py +138 -0
- opentrons/protocol_api/__init__.py +105 -0
- opentrons/protocol_api/_liquid.py +157 -0
- opentrons/protocol_api/_liquid_properties.py +814 -0
- opentrons/protocol_api/_nozzle_layout.py +31 -0
- opentrons/protocol_api/_parameter_context.py +300 -0
- opentrons/protocol_api/_parameters.py +31 -0
- opentrons/protocol_api/_transfer_liquid_validation.py +108 -0
- opentrons/protocol_api/_types.py +43 -0
- opentrons/protocol_api/config.py +23 -0
- opentrons/protocol_api/core/__init__.py +23 -0
- opentrons/protocol_api/core/common.py +33 -0
- opentrons/protocol_api/core/core_map.py +74 -0
- opentrons/protocol_api/core/engine/__init__.py +22 -0
- opentrons/protocol_api/core/engine/_default_labware_versions.py +179 -0
- opentrons/protocol_api/core/engine/deck_conflict.py +400 -0
- opentrons/protocol_api/core/engine/exceptions.py +19 -0
- opentrons/protocol_api/core/engine/instrument.py +2391 -0
- opentrons/protocol_api/core/engine/labware.py +238 -0
- opentrons/protocol_api/core/engine/load_labware_params.py +73 -0
- opentrons/protocol_api/core/engine/module_core.py +1027 -0
- opentrons/protocol_api/core/engine/overlap_versions.py +20 -0
- opentrons/protocol_api/core/engine/pipette_movement_conflict.py +358 -0
- opentrons/protocol_api/core/engine/point_calculations.py +64 -0
- opentrons/protocol_api/core/engine/protocol.py +1153 -0
- opentrons/protocol_api/core/engine/robot.py +139 -0
- opentrons/protocol_api/core/engine/stringify.py +74 -0
- opentrons/protocol_api/core/engine/transfer_components_executor.py +1006 -0
- opentrons/protocol_api/core/engine/well.py +241 -0
- opentrons/protocol_api/core/instrument.py +459 -0
- opentrons/protocol_api/core/labware.py +151 -0
- opentrons/protocol_api/core/legacy/__init__.py +11 -0
- opentrons/protocol_api/core/legacy/_labware_geometry.py +37 -0
- opentrons/protocol_api/core/legacy/deck.py +369 -0
- opentrons/protocol_api/core/legacy/labware_offset_provider.py +108 -0
- opentrons/protocol_api/core/legacy/legacy_instrument_core.py +709 -0
- opentrons/protocol_api/core/legacy/legacy_labware_core.py +235 -0
- opentrons/protocol_api/core/legacy/legacy_module_core.py +592 -0
- opentrons/protocol_api/core/legacy/legacy_protocol_core.py +612 -0
- opentrons/protocol_api/core/legacy/legacy_well_core.py +162 -0
- opentrons/protocol_api/core/legacy/load_info.py +67 -0
- opentrons/protocol_api/core/legacy/module_geometry.py +547 -0
- opentrons/protocol_api/core/legacy/well_geometry.py +148 -0
- opentrons/protocol_api/core/legacy_simulator/__init__.py +16 -0
- opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +624 -0
- opentrons/protocol_api/core/legacy_simulator/legacy_protocol_core.py +85 -0
- opentrons/protocol_api/core/module.py +484 -0
- opentrons/protocol_api/core/protocol.py +311 -0
- opentrons/protocol_api/core/robot.py +51 -0
- opentrons/protocol_api/core/well.py +116 -0
- opentrons/protocol_api/core/well_grid.py +45 -0
- opentrons/protocol_api/create_protocol_context.py +177 -0
- opentrons/protocol_api/deck.py +223 -0
- opentrons/protocol_api/disposal_locations.py +244 -0
- opentrons/protocol_api/instrument_context.py +3272 -0
- opentrons/protocol_api/labware.py +1579 -0
- opentrons/protocol_api/module_contexts.py +1447 -0
- opentrons/protocol_api/module_validation_and_errors.py +61 -0
- opentrons/protocol_api/protocol_context.py +1688 -0
- opentrons/protocol_api/robot_context.py +303 -0
- opentrons/protocol_api/validation.py +761 -0
- opentrons/protocol_engine/__init__.py +155 -0
- opentrons/protocol_engine/actions/__init__.py +65 -0
- opentrons/protocol_engine/actions/action_dispatcher.py +30 -0
- opentrons/protocol_engine/actions/action_handler.py +13 -0
- opentrons/protocol_engine/actions/actions.py +302 -0
- opentrons/protocol_engine/actions/get_state_update.py +38 -0
- opentrons/protocol_engine/clients/__init__.py +5 -0
- opentrons/protocol_engine/clients/sync_client.py +174 -0
- opentrons/protocol_engine/clients/transports.py +197 -0
- opentrons/protocol_engine/commands/__init__.py +757 -0
- opentrons/protocol_engine/commands/absorbance_reader/__init__.py +61 -0
- opentrons/protocol_engine/commands/absorbance_reader/close_lid.py +154 -0
- opentrons/protocol_engine/commands/absorbance_reader/common.py +6 -0
- opentrons/protocol_engine/commands/absorbance_reader/initialize.py +151 -0
- opentrons/protocol_engine/commands/absorbance_reader/open_lid.py +154 -0
- opentrons/protocol_engine/commands/absorbance_reader/read.py +226 -0
- opentrons/protocol_engine/commands/air_gap_in_place.py +162 -0
- opentrons/protocol_engine/commands/aspirate.py +244 -0
- opentrons/protocol_engine/commands/aspirate_in_place.py +184 -0
- opentrons/protocol_engine/commands/aspirate_while_tracking.py +211 -0
- opentrons/protocol_engine/commands/blow_out.py +146 -0
- opentrons/protocol_engine/commands/blow_out_in_place.py +119 -0
- opentrons/protocol_engine/commands/calibration/__init__.py +60 -0
- opentrons/protocol_engine/commands/calibration/calibrate_gripper.py +166 -0
- opentrons/protocol_engine/commands/calibration/calibrate_module.py +117 -0
- opentrons/protocol_engine/commands/calibration/calibrate_pipette.py +96 -0
- opentrons/protocol_engine/commands/calibration/move_to_maintenance_position.py +156 -0
- opentrons/protocol_engine/commands/command.py +308 -0
- opentrons/protocol_engine/commands/command_unions.py +974 -0
- opentrons/protocol_engine/commands/comment.py +57 -0
- opentrons/protocol_engine/commands/configure_for_volume.py +108 -0
- opentrons/protocol_engine/commands/configure_nozzle_layout.py +115 -0
- opentrons/protocol_engine/commands/custom.py +67 -0
- opentrons/protocol_engine/commands/dispense.py +194 -0
- opentrons/protocol_engine/commands/dispense_in_place.py +179 -0
- opentrons/protocol_engine/commands/dispense_while_tracking.py +204 -0
- opentrons/protocol_engine/commands/drop_tip.py +232 -0
- opentrons/protocol_engine/commands/drop_tip_in_place.py +205 -0
- opentrons/protocol_engine/commands/flex_stacker/__init__.py +64 -0
- opentrons/protocol_engine/commands/flex_stacker/common.py +900 -0
- opentrons/protocol_engine/commands/flex_stacker/empty.py +293 -0
- opentrons/protocol_engine/commands/flex_stacker/fill.py +281 -0
- opentrons/protocol_engine/commands/flex_stacker/retrieve.py +339 -0
- opentrons/protocol_engine/commands/flex_stacker/set_stored_labware.py +328 -0
- opentrons/protocol_engine/commands/flex_stacker/store.py +339 -0
- opentrons/protocol_engine/commands/generate_command_schema.py +61 -0
- opentrons/protocol_engine/commands/get_next_tip.py +134 -0
- opentrons/protocol_engine/commands/get_tip_presence.py +87 -0
- opentrons/protocol_engine/commands/hash_command_params.py +38 -0
- opentrons/protocol_engine/commands/heater_shaker/__init__.py +102 -0
- opentrons/protocol_engine/commands/heater_shaker/close_labware_latch.py +83 -0
- opentrons/protocol_engine/commands/heater_shaker/deactivate_heater.py +82 -0
- opentrons/protocol_engine/commands/heater_shaker/deactivate_shaker.py +84 -0
- opentrons/protocol_engine/commands/heater_shaker/open_labware_latch.py +110 -0
- opentrons/protocol_engine/commands/heater_shaker/set_and_wait_for_shake_speed.py +125 -0
- opentrons/protocol_engine/commands/heater_shaker/set_target_temperature.py +90 -0
- opentrons/protocol_engine/commands/heater_shaker/wait_for_temperature.py +102 -0
- opentrons/protocol_engine/commands/home.py +100 -0
- opentrons/protocol_engine/commands/identify_module.py +86 -0
- opentrons/protocol_engine/commands/labware_handling_common.py +29 -0
- opentrons/protocol_engine/commands/liquid_probe.py +464 -0
- opentrons/protocol_engine/commands/load_labware.py +210 -0
- opentrons/protocol_engine/commands/load_lid.py +154 -0
- opentrons/protocol_engine/commands/load_lid_stack.py +272 -0
- opentrons/protocol_engine/commands/load_liquid.py +95 -0
- opentrons/protocol_engine/commands/load_liquid_class.py +144 -0
- opentrons/protocol_engine/commands/load_module.py +223 -0
- opentrons/protocol_engine/commands/load_pipette.py +167 -0
- opentrons/protocol_engine/commands/magnetic_module/__init__.py +32 -0
- opentrons/protocol_engine/commands/magnetic_module/disengage.py +97 -0
- opentrons/protocol_engine/commands/magnetic_module/engage.py +119 -0
- opentrons/protocol_engine/commands/move_labware.py +546 -0
- opentrons/protocol_engine/commands/move_relative.py +102 -0
- opentrons/protocol_engine/commands/move_to_addressable_area.py +176 -0
- opentrons/protocol_engine/commands/move_to_addressable_area_for_drop_tip.py +198 -0
- opentrons/protocol_engine/commands/move_to_coordinates.py +107 -0
- opentrons/protocol_engine/commands/move_to_well.py +119 -0
- opentrons/protocol_engine/commands/movement_common.py +338 -0
- opentrons/protocol_engine/commands/pick_up_tip.py +241 -0
- opentrons/protocol_engine/commands/pipetting_common.py +443 -0
- opentrons/protocol_engine/commands/prepare_to_aspirate.py +121 -0
- opentrons/protocol_engine/commands/pressure_dispense.py +155 -0
- opentrons/protocol_engine/commands/reload_labware.py +90 -0
- opentrons/protocol_engine/commands/retract_axis.py +75 -0
- opentrons/protocol_engine/commands/robot/__init__.py +70 -0
- opentrons/protocol_engine/commands/robot/close_gripper_jaw.py +96 -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 +86 -0
- opentrons/protocol_engine/commands/save_position.py +109 -0
- opentrons/protocol_engine/commands/seal_pipette_to_tip.py +353 -0
- opentrons/protocol_engine/commands/set_rail_lights.py +67 -0
- opentrons/protocol_engine/commands/set_status_bar.py +89 -0
- opentrons/protocol_engine/commands/temperature_module/__init__.py +46 -0
- opentrons/protocol_engine/commands/temperature_module/deactivate.py +86 -0
- opentrons/protocol_engine/commands/temperature_module/set_target_temperature.py +97 -0
- opentrons/protocol_engine/commands/temperature_module/wait_for_temperature.py +104 -0
- opentrons/protocol_engine/commands/thermocycler/__init__.py +152 -0
- opentrons/protocol_engine/commands/thermocycler/close_lid.py +87 -0
- opentrons/protocol_engine/commands/thermocycler/deactivate_block.py +80 -0
- opentrons/protocol_engine/commands/thermocycler/deactivate_lid.py +80 -0
- opentrons/protocol_engine/commands/thermocycler/open_lid.py +87 -0
- opentrons/protocol_engine/commands/thermocycler/run_extended_profile.py +171 -0
- opentrons/protocol_engine/commands/thermocycler/run_profile.py +124 -0
- opentrons/protocol_engine/commands/thermocycler/set_target_block_temperature.py +140 -0
- opentrons/protocol_engine/commands/thermocycler/set_target_lid_temperature.py +100 -0
- opentrons/protocol_engine/commands/thermocycler/wait_for_block_temperature.py +93 -0
- opentrons/protocol_engine/commands/thermocycler/wait_for_lid_temperature.py +89 -0
- opentrons/protocol_engine/commands/touch_tip.py +189 -0
- opentrons/protocol_engine/commands/unsafe/__init__.py +161 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_blow_out_in_place.py +100 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_drop_tip_in_place.py +121 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_engage_axes.py +82 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_place_labware.py +208 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_stacker_close_latch.py +94 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_stacker_manual_retrieve.py +295 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_stacker_open_latch.py +91 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_stacker_prepare_shuttle.py +136 -0
- opentrons/protocol_engine/commands/unsafe/unsafe_ungrip_labware.py +77 -0
- opentrons/protocol_engine/commands/unsafe/update_position_estimators.py +90 -0
- opentrons/protocol_engine/commands/unseal_pipette_from_tip.py +153 -0
- opentrons/protocol_engine/commands/verify_tip_presence.py +100 -0
- opentrons/protocol_engine/commands/wait_for_duration.py +76 -0
- opentrons/protocol_engine/commands/wait_for_resume.py +75 -0
- opentrons/protocol_engine/create_protocol_engine.py +193 -0
- opentrons/protocol_engine/engine_support.py +28 -0
- opentrons/protocol_engine/error_recovery_policy.py +81 -0
- opentrons/protocol_engine/errors/__init__.py +191 -0
- opentrons/protocol_engine/errors/error_occurrence.py +182 -0
- opentrons/protocol_engine/errors/exceptions.py +1308 -0
- opentrons/protocol_engine/execution/__init__.py +50 -0
- opentrons/protocol_engine/execution/command_executor.py +216 -0
- opentrons/protocol_engine/execution/create_queue_worker.py +102 -0
- opentrons/protocol_engine/execution/door_watcher.py +119 -0
- opentrons/protocol_engine/execution/equipment.py +819 -0
- opentrons/protocol_engine/execution/error_recovery_hardware_state_synchronizer.py +101 -0
- opentrons/protocol_engine/execution/gantry_mover.py +686 -0
- opentrons/protocol_engine/execution/hardware_stopper.py +147 -0
- opentrons/protocol_engine/execution/heater_shaker_movement_flagger.py +207 -0
- opentrons/protocol_engine/execution/labware_movement.py +297 -0
- opentrons/protocol_engine/execution/movement.py +350 -0
- opentrons/protocol_engine/execution/pipetting.py +607 -0
- opentrons/protocol_engine/execution/queue_worker.py +86 -0
- opentrons/protocol_engine/execution/rail_lights.py +25 -0
- opentrons/protocol_engine/execution/run_control.py +33 -0
- opentrons/protocol_engine/execution/status_bar.py +34 -0
- opentrons/protocol_engine/execution/thermocycler_movement_flagger.py +188 -0
- opentrons/protocol_engine/execution/thermocycler_plate_lifter.py +81 -0
- opentrons/protocol_engine/execution/tip_handler.py +550 -0
- opentrons/protocol_engine/labware_offset_standardization.py +194 -0
- opentrons/protocol_engine/notes/__init__.py +17 -0
- opentrons/protocol_engine/notes/notes.py +59 -0
- opentrons/protocol_engine/plugins.py +104 -0
- opentrons/protocol_engine/protocol_engine.py +683 -0
- opentrons/protocol_engine/resources/__init__.py +26 -0
- opentrons/protocol_engine/resources/deck_configuration_provider.py +232 -0
- opentrons/protocol_engine/resources/deck_data_provider.py +94 -0
- opentrons/protocol_engine/resources/file_provider.py +161 -0
- opentrons/protocol_engine/resources/fixture_validation.py +68 -0
- opentrons/protocol_engine/resources/labware_data_provider.py +106 -0
- opentrons/protocol_engine/resources/labware_validation.py +73 -0
- opentrons/protocol_engine/resources/model_utils.py +32 -0
- opentrons/protocol_engine/resources/module_data_provider.py +44 -0
- opentrons/protocol_engine/resources/ot3_validation.py +21 -0
- opentrons/protocol_engine/resources/pipette_data_provider.py +379 -0
- opentrons/protocol_engine/slot_standardization.py +128 -0
- opentrons/protocol_engine/state/__init__.py +1 -0
- opentrons/protocol_engine/state/_abstract_store.py +27 -0
- opentrons/protocol_engine/state/_axis_aligned_bounding_box.py +50 -0
- opentrons/protocol_engine/state/_labware_origin_math.py +636 -0
- opentrons/protocol_engine/state/_move_types.py +83 -0
- opentrons/protocol_engine/state/_well_math.py +193 -0
- opentrons/protocol_engine/state/addressable_areas.py +699 -0
- opentrons/protocol_engine/state/command_history.py +309 -0
- opentrons/protocol_engine/state/commands.py +1164 -0
- opentrons/protocol_engine/state/config.py +39 -0
- opentrons/protocol_engine/state/files.py +57 -0
- opentrons/protocol_engine/state/fluid_stack.py +138 -0
- opentrons/protocol_engine/state/geometry.py +2408 -0
- opentrons/protocol_engine/state/inner_well_math_utils.py +548 -0
- opentrons/protocol_engine/state/labware.py +1432 -0
- opentrons/protocol_engine/state/liquid_classes.py +82 -0
- opentrons/protocol_engine/state/liquids.py +73 -0
- opentrons/protocol_engine/state/module_substates/__init__.py +45 -0
- opentrons/protocol_engine/state/module_substates/absorbance_reader_substate.py +35 -0
- opentrons/protocol_engine/state/module_substates/flex_stacker_substate.py +112 -0
- opentrons/protocol_engine/state/module_substates/heater_shaker_module_substate.py +115 -0
- opentrons/protocol_engine/state/module_substates/magnetic_block_substate.py +17 -0
- opentrons/protocol_engine/state/module_substates/magnetic_module_substate.py +65 -0
- opentrons/protocol_engine/state/module_substates/temperature_module_substate.py +67 -0
- opentrons/protocol_engine/state/module_substates/thermocycler_module_substate.py +163 -0
- opentrons/protocol_engine/state/modules.py +1515 -0
- opentrons/protocol_engine/state/motion.py +373 -0
- opentrons/protocol_engine/state/pipettes.py +905 -0
- opentrons/protocol_engine/state/state.py +421 -0
- opentrons/protocol_engine/state/state_summary.py +36 -0
- opentrons/protocol_engine/state/tips.py +420 -0
- opentrons/protocol_engine/state/update_types.py +904 -0
- opentrons/protocol_engine/state/wells.py +290 -0
- opentrons/protocol_engine/types/__init__.py +310 -0
- opentrons/protocol_engine/types/automatic_tip_selection.py +39 -0
- opentrons/protocol_engine/types/command_annotations.py +53 -0
- opentrons/protocol_engine/types/deck_configuration.py +81 -0
- opentrons/protocol_engine/types/execution.py +96 -0
- opentrons/protocol_engine/types/hardware_passthrough.py +25 -0
- opentrons/protocol_engine/types/instrument.py +47 -0
- opentrons/protocol_engine/types/instrument_sensors.py +47 -0
- opentrons/protocol_engine/types/labware.py +131 -0
- opentrons/protocol_engine/types/labware_movement.py +22 -0
- opentrons/protocol_engine/types/labware_offset_location.py +111 -0
- opentrons/protocol_engine/types/labware_offset_vector.py +16 -0
- opentrons/protocol_engine/types/liquid.py +40 -0
- opentrons/protocol_engine/types/liquid_class.py +59 -0
- opentrons/protocol_engine/types/liquid_handling.py +13 -0
- opentrons/protocol_engine/types/liquid_level_detection.py +191 -0
- opentrons/protocol_engine/types/location.py +194 -0
- opentrons/protocol_engine/types/module.py +310 -0
- opentrons/protocol_engine/types/partial_tip_configuration.py +76 -0
- opentrons/protocol_engine/types/run_time_parameters.py +133 -0
- opentrons/protocol_engine/types/tip.py +18 -0
- opentrons/protocol_engine/types/util.py +21 -0
- opentrons/protocol_engine/types/well_position.py +124 -0
- opentrons/protocol_reader/__init__.py +37 -0
- opentrons/protocol_reader/extract_labware_definitions.py +66 -0
- opentrons/protocol_reader/file_format_validator.py +152 -0
- opentrons/protocol_reader/file_hasher.py +27 -0
- opentrons/protocol_reader/file_identifier.py +284 -0
- opentrons/protocol_reader/file_reader_writer.py +90 -0
- opentrons/protocol_reader/input_file.py +16 -0
- opentrons/protocol_reader/protocol_files_invalid_error.py +6 -0
- opentrons/protocol_reader/protocol_reader.py +188 -0
- opentrons/protocol_reader/protocol_source.py +124 -0
- opentrons/protocol_reader/role_analyzer.py +86 -0
- opentrons/protocol_runner/__init__.py +26 -0
- opentrons/protocol_runner/create_simulating_orchestrator.py +118 -0
- opentrons/protocol_runner/json_file_reader.py +55 -0
- opentrons/protocol_runner/json_translator.py +314 -0
- opentrons/protocol_runner/legacy_command_mapper.py +852 -0
- opentrons/protocol_runner/legacy_context_plugin.py +116 -0
- opentrons/protocol_runner/protocol_runner.py +530 -0
- opentrons/protocol_runner/python_protocol_wrappers.py +179 -0
- opentrons/protocol_runner/run_orchestrator.py +496 -0
- opentrons/protocol_runner/task_queue.py +95 -0
- opentrons/protocols/__init__.py +6 -0
- opentrons/protocols/advanced_control/__init__.py +0 -0
- opentrons/protocols/advanced_control/common.py +38 -0
- opentrons/protocols/advanced_control/mix.py +60 -0
- opentrons/protocols/advanced_control/transfers/__init__.py +0 -0
- opentrons/protocols/advanced_control/transfers/common.py +180 -0
- opentrons/protocols/advanced_control/transfers/transfer.py +972 -0
- opentrons/protocols/advanced_control/transfers/transfer_liquid_utils.py +231 -0
- opentrons/protocols/api_support/__init__.py +0 -0
- opentrons/protocols/api_support/constants.py +8 -0
- opentrons/protocols/api_support/deck_type.py +110 -0
- opentrons/protocols/api_support/definitions.py +18 -0
- opentrons/protocols/api_support/instrument.py +151 -0
- opentrons/protocols/api_support/labware_like.py +233 -0
- opentrons/protocols/api_support/tip_tracker.py +175 -0
- opentrons/protocols/api_support/types.py +32 -0
- opentrons/protocols/api_support/util.py +403 -0
- opentrons/protocols/bundle.py +89 -0
- opentrons/protocols/duration/__init__.py +4 -0
- opentrons/protocols/duration/errors.py +5 -0
- opentrons/protocols/duration/estimator.py +628 -0
- opentrons/protocols/execution/__init__.py +0 -0
- opentrons/protocols/execution/dev_types.py +181 -0
- opentrons/protocols/execution/errors.py +40 -0
- opentrons/protocols/execution/execute.py +84 -0
- opentrons/protocols/execution/execute_json_v3.py +275 -0
- opentrons/protocols/execution/execute_json_v4.py +359 -0
- opentrons/protocols/execution/execute_json_v5.py +28 -0
- opentrons/protocols/execution/execute_python.py +169 -0
- opentrons/protocols/execution/json_dispatchers.py +87 -0
- opentrons/protocols/execution/types.py +7 -0
- opentrons/protocols/geometry/__init__.py +0 -0
- opentrons/protocols/geometry/planning.py +297 -0
- opentrons/protocols/labware.py +312 -0
- opentrons/protocols/models/__init__.py +0 -0
- opentrons/protocols/models/json_protocol.py +679 -0
- opentrons/protocols/parameters/__init__.py +0 -0
- opentrons/protocols/parameters/csv_parameter_definition.py +77 -0
- opentrons/protocols/parameters/csv_parameter_interface.py +96 -0
- opentrons/protocols/parameters/exceptions.py +34 -0
- opentrons/protocols/parameters/parameter_definition.py +272 -0
- opentrons/protocols/parameters/types.py +17 -0
- opentrons/protocols/parameters/validation.py +267 -0
- opentrons/protocols/parse.py +671 -0
- opentrons/protocols/types.py +159 -0
- opentrons/py.typed +0 -0
- opentrons/resources/scripts/lpc21isp +0 -0
- opentrons/resources/smoothie-edge-8414642.hex +23010 -0
- opentrons/simulate.py +1065 -0
- opentrons/system/__init__.py +6 -0
- opentrons/system/camera.py +51 -0
- opentrons/system/log_control.py +59 -0
- opentrons/system/nmcli.py +856 -0
- opentrons/system/resin.py +24 -0
- opentrons/system/smoothie_update.py +15 -0
- opentrons/system/wifi.py +204 -0
- opentrons/tools/__init__.py +0 -0
- opentrons/tools/args_handler.py +22 -0
- opentrons/tools/write_pipette_memory.py +157 -0
- opentrons/types.py +618 -0
- opentrons/util/__init__.py +1 -0
- opentrons/util/async_helpers.py +166 -0
- opentrons/util/broker.py +84 -0
- opentrons/util/change_notifier.py +47 -0
- opentrons/util/entrypoint_util.py +278 -0
- opentrons/util/get_union_elements.py +26 -0
- opentrons/util/helpers.py +6 -0
- opentrons/util/linal.py +178 -0
- opentrons/util/logging_config.py +265 -0
- opentrons/util/logging_queue_handler.py +61 -0
- opentrons/util/performance_helpers.py +157 -0
- opentrons-8.6.0.dist-info/METADATA +37 -0
- opentrons-8.6.0.dist-info/RECORD +601 -0
- opentrons-8.6.0.dist-info/WHEEL +4 -0
- opentrons-8.6.0.dist-info/entry_points.txt +3 -0
- opentrons-8.6.0.dist-info/licenses/LICENSE +202 -0
|
File without changes
|
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
""" Classes and functions for gripper state tracking
|
|
4
|
+
"""
|
|
5
|
+
import logging
|
|
6
|
+
from typing import Any, Optional, Set, Dict, Tuple, Final
|
|
7
|
+
|
|
8
|
+
from opentrons.types import Point
|
|
9
|
+
from opentrons.config import gripper_config
|
|
10
|
+
from opentrons.hardware_control.types import (
|
|
11
|
+
GripperProbe,
|
|
12
|
+
CriticalPoint,
|
|
13
|
+
GripperJawState,
|
|
14
|
+
)
|
|
15
|
+
from opentrons.hardware_control.errors import (
|
|
16
|
+
InvalidCriticalPoint,
|
|
17
|
+
)
|
|
18
|
+
from .instrument_calibration import (
|
|
19
|
+
GripperCalibrationOffset,
|
|
20
|
+
load_gripper_calibration_offset,
|
|
21
|
+
save_gripper_calibration_offset,
|
|
22
|
+
save_gripper_jaw_width_data,
|
|
23
|
+
load_gripper_jaw_width,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
from ..instrument_abc import AbstractInstrument
|
|
27
|
+
from opentrons.hardware_control.dev_types import AttachedGripper, GripperDict
|
|
28
|
+
from opentrons_shared_data.errors.exceptions import (
|
|
29
|
+
CommandPreconditionViolated,
|
|
30
|
+
MotionFailedError,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
from opentrons_shared_data.gripper import (
|
|
34
|
+
GripperDefinition,
|
|
35
|
+
GripForceProfile,
|
|
36
|
+
Geometry,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
RECONFIG_KEYS = {"quirks", "grip_force_profile"}
|
|
40
|
+
|
|
41
|
+
MAX_ACCEPTABLE_JAW_DISPLACEMENT: Final = 20
|
|
42
|
+
|
|
43
|
+
mod_log = logging.getLogger(__name__)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class Gripper(AbstractInstrument[GripperDefinition]):
|
|
47
|
+
"""A class to gather and track gripper state and configs.
|
|
48
|
+
|
|
49
|
+
This class should not touch hardware or call back out to the hardware
|
|
50
|
+
control API. Its only purpose is to gather state.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
def __init__(
|
|
54
|
+
self,
|
|
55
|
+
config: GripperDefinition,
|
|
56
|
+
gripper_cal_offset: GripperCalibrationOffset,
|
|
57
|
+
gripper_id: str,
|
|
58
|
+
) -> None:
|
|
59
|
+
self._config = config
|
|
60
|
+
self._model = config.model
|
|
61
|
+
|
|
62
|
+
self._geometry = self._config.geometry
|
|
63
|
+
base_offset = Point(*self._geometry.base_offset_from_mount)
|
|
64
|
+
self._jaw_center_offset = (
|
|
65
|
+
Point(*self._geometry.jaw_center_offset_from_base) + base_offset
|
|
66
|
+
)
|
|
67
|
+
#: the distance between the gripper mount and the jaw center at home
|
|
68
|
+
self._front_calibration_pin_offset = (
|
|
69
|
+
Point(*self._geometry.pin_one_offset_from_base) + base_offset
|
|
70
|
+
)
|
|
71
|
+
#: the distance between the gripper mount and the front calibration pin
|
|
72
|
+
#: at home
|
|
73
|
+
self._rear_calibration_pin_offset = (
|
|
74
|
+
Point(*self._geometry.pin_two_offset_from_base) + base_offset
|
|
75
|
+
)
|
|
76
|
+
#: the distance between the gripper mount and the rear calibration pin
|
|
77
|
+
#: at home
|
|
78
|
+
self._calibration_offset = gripper_cal_offset
|
|
79
|
+
#: The output value of calibration - the additional vector added into
|
|
80
|
+
#: the critical point geometry based on gripper mount calibration
|
|
81
|
+
self._gripper_id = gripper_id
|
|
82
|
+
self._state = GripperJawState.UNHOMED
|
|
83
|
+
self._current_jaw_displacement = 0.0
|
|
84
|
+
self._attached_probe: Optional[GripperProbe] = None
|
|
85
|
+
self._log = mod_log.getChild(self._gripper_id)
|
|
86
|
+
self._log.info(
|
|
87
|
+
f"loaded: {self._model}, gripper offset: {self._calibration_offset}"
|
|
88
|
+
)
|
|
89
|
+
self._encoder_position_at_jaw_closed: Optional[float] = None
|
|
90
|
+
|
|
91
|
+
@property
|
|
92
|
+
def grip_force_profile(self) -> GripForceProfile:
|
|
93
|
+
return self._config.grip_force_profile
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
def geometry(self) -> Geometry:
|
|
97
|
+
return self._geometry
|
|
98
|
+
|
|
99
|
+
@property
|
|
100
|
+
def attached_probe(self) -> Optional[GripperProbe]:
|
|
101
|
+
return self._attached_probe
|
|
102
|
+
|
|
103
|
+
def add_probe(self, probe: GripperProbe) -> None:
|
|
104
|
+
"""This is used for finding the critical point during calibration."""
|
|
105
|
+
assert not self.attached_probe
|
|
106
|
+
self._attached_probe = probe
|
|
107
|
+
|
|
108
|
+
def remove_probe(self) -> None:
|
|
109
|
+
assert self.attached_probe
|
|
110
|
+
self._attached_probe = None
|
|
111
|
+
|
|
112
|
+
@property
|
|
113
|
+
def max_allowed_grip_error(self) -> float:
|
|
114
|
+
return self._geometry.max_allowed_grip_error
|
|
115
|
+
|
|
116
|
+
@property
|
|
117
|
+
def _jaw_min(self) -> float:
|
|
118
|
+
return self._config.geometry.jaw_width["min"]
|
|
119
|
+
|
|
120
|
+
@property
|
|
121
|
+
def _jaw_nominal_max(self) -> float:
|
|
122
|
+
return self._config.geometry.jaw_width["max"]
|
|
123
|
+
|
|
124
|
+
@property
|
|
125
|
+
def _jaw_max_offset(self) -> float | None:
|
|
126
|
+
if self._encoder_position_at_jaw_closed is None:
|
|
127
|
+
return None
|
|
128
|
+
return self._jaw_min - (
|
|
129
|
+
self._jaw_nominal_max - (self._encoder_position_at_jaw_closed * 2)
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
@property
|
|
133
|
+
def max_jaw_width(self) -> float:
|
|
134
|
+
return self._config.geometry.jaw_width["max"] + (self._jaw_max_offset or 0)
|
|
135
|
+
|
|
136
|
+
@property
|
|
137
|
+
def min_jaw_width(self) -> float:
|
|
138
|
+
return self._config.geometry.jaw_width["min"]
|
|
139
|
+
|
|
140
|
+
@property
|
|
141
|
+
def jaw_width(self) -> float:
|
|
142
|
+
return self.max_jaw_width - (self.current_jaw_displacement * 2.0)
|
|
143
|
+
|
|
144
|
+
@property
|
|
145
|
+
def current_jaw_displacement(self) -> float:
|
|
146
|
+
"""The distance one side of the jaw has traveled from home."""
|
|
147
|
+
return self._current_jaw_displacement
|
|
148
|
+
|
|
149
|
+
@current_jaw_displacement.setter
|
|
150
|
+
def current_jaw_displacement(self, mm: float) -> None:
|
|
151
|
+
max_mm = self.max_jaw_displacement() + 2.0
|
|
152
|
+
if mm > max_mm:
|
|
153
|
+
self._log.warning(
|
|
154
|
+
f"jaw displacement {round(mm, 1)} mm exceeds max expected value: "
|
|
155
|
+
f"{max_mm} mm, setting value to max value instead."
|
|
156
|
+
)
|
|
157
|
+
self._current_jaw_displacement = min(mm, max_mm)
|
|
158
|
+
|
|
159
|
+
@property
|
|
160
|
+
def default_grip_force(self) -> float:
|
|
161
|
+
return self.grip_force_profile.default_grip_force
|
|
162
|
+
|
|
163
|
+
@property
|
|
164
|
+
def default_idle_force(self) -> float:
|
|
165
|
+
return self.grip_force_profile.default_idle_force
|
|
166
|
+
|
|
167
|
+
@property
|
|
168
|
+
def default_home_force(self) -> float:
|
|
169
|
+
return self.grip_force_profile.default_home_force
|
|
170
|
+
|
|
171
|
+
def max_jaw_displacement(self) -> float:
|
|
172
|
+
geometry = self._config.geometry
|
|
173
|
+
return (self.max_jaw_width - geometry.jaw_width["min"]) / 2
|
|
174
|
+
|
|
175
|
+
@property
|
|
176
|
+
def state(self) -> GripperJawState:
|
|
177
|
+
return self._state
|
|
178
|
+
|
|
179
|
+
@state.setter
|
|
180
|
+
def state(self, s: GripperJawState) -> None:
|
|
181
|
+
self._state = s
|
|
182
|
+
|
|
183
|
+
@property
|
|
184
|
+
def config(self) -> GripperDefinition:
|
|
185
|
+
return self._config
|
|
186
|
+
|
|
187
|
+
def update_config_item(self, elements: Dict[str, Any]) -> None:
|
|
188
|
+
raise NotImplementedError("Update config is not supported at this time.")
|
|
189
|
+
|
|
190
|
+
@property
|
|
191
|
+
def model(self) -> str:
|
|
192
|
+
return repr(self._model)
|
|
193
|
+
|
|
194
|
+
@property
|
|
195
|
+
def gripper_id(self) -> str:
|
|
196
|
+
return self._gripper_id
|
|
197
|
+
|
|
198
|
+
def reload_configurations(self) -> None:
|
|
199
|
+
return None
|
|
200
|
+
|
|
201
|
+
def update_jaw_open_position_from_closed_position(
|
|
202
|
+
self, jaw_at_closed: float | None
|
|
203
|
+
) -> None:
|
|
204
|
+
"""Update the estimation of the jaw position at open based on reading it at closed.
|
|
205
|
+
|
|
206
|
+
This is necessary because the gripper jaw has a well-defined positional hard stop
|
|
207
|
+
when fully closed and empty but _not_ when open. The open position can vary unit to
|
|
208
|
+
unit. You can calibrate this out by reading the position of the encoder when the jaw
|
|
209
|
+
is closed, and then altering the logical open position so that it is whatever it needs
|
|
210
|
+
to be for the logical closed position to be the same as the config.
|
|
211
|
+
"""
|
|
212
|
+
if jaw_at_closed is None:
|
|
213
|
+
self._encoder_position_at_jaw_closed = jaw_at_closed
|
|
214
|
+
return
|
|
215
|
+
if (
|
|
216
|
+
abs((jaw_at_closed * 2) - (self._jaw_nominal_max - self._jaw_min))
|
|
217
|
+
> MAX_ACCEPTABLE_JAW_DISPLACEMENT
|
|
218
|
+
):
|
|
219
|
+
raise MotionFailedError(
|
|
220
|
+
message="Gripper jaw calibration out of bounds",
|
|
221
|
+
detail={
|
|
222
|
+
"type": "gripper-jaw-calibration-out-of-bounds",
|
|
223
|
+
"actual-displacement": str(jaw_at_closed * 2),
|
|
224
|
+
"nominal-displacement": str(self._jaw_nominal_max - self._jaw_min),
|
|
225
|
+
},
|
|
226
|
+
)
|
|
227
|
+
save_gripper_jaw_width_data(
|
|
228
|
+
gripper_id=self._gripper_id,
|
|
229
|
+
encoder_position_at_closed=jaw_at_closed,
|
|
230
|
+
)
|
|
231
|
+
self._encoder_position_at_jaw_closed = jaw_at_closed
|
|
232
|
+
self._log.info(
|
|
233
|
+
f"Gripper max jaw offset is now {self._jaw_max_offset} from input position {jaw_at_closed}"
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
@property
|
|
237
|
+
def has_jaw_width_calibration(self) -> bool:
|
|
238
|
+
if self._encoder_position_at_jaw_closed is not None:
|
|
239
|
+
return True
|
|
240
|
+
else:
|
|
241
|
+
load_gripper_jaw_width_data = load_gripper_jaw_width(
|
|
242
|
+
gripper_id=self._gripper_id
|
|
243
|
+
)
|
|
244
|
+
if load_gripper_jaw_width_data.encoder_position_at_jaw_closed is not None:
|
|
245
|
+
# update class members with data from the robot
|
|
246
|
+
self.update_jaw_open_position_from_closed_position(
|
|
247
|
+
jaw_at_closed=load_gripper_jaw_width_data.encoder_position_at_jaw_closed
|
|
248
|
+
)
|
|
249
|
+
return True
|
|
250
|
+
return False
|
|
251
|
+
|
|
252
|
+
def reset_offset(self, to_default: bool) -> None:
|
|
253
|
+
"""Tempoarily reset the gripper offsets to default values."""
|
|
254
|
+
if to_default:
|
|
255
|
+
self._calibration_offset = load_gripper_calibration_offset(gripper_id=None)
|
|
256
|
+
else:
|
|
257
|
+
self._calibration_offset = load_gripper_calibration_offset(
|
|
258
|
+
gripper_id=self._gripper_id
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
def reset_jaw_width_calibration(self, to_default: bool) -> None:
|
|
262
|
+
"""Reset the gripper jaw width measurement in the protocol engine."""
|
|
263
|
+
if to_default:
|
|
264
|
+
loaded_jaw_width_data = load_gripper_jaw_width(gripper_id=None)
|
|
265
|
+
else:
|
|
266
|
+
loaded_jaw_width_data = load_gripper_jaw_width(gripper_id=self._gripper_id)
|
|
267
|
+
self.update_jaw_open_position_from_closed_position(
|
|
268
|
+
jaw_at_closed=loaded_jaw_width_data.encoder_position_at_jaw_closed
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
def save_offset(self, delta: Point) -> GripperCalibrationOffset:
|
|
272
|
+
"""Save a new gripper offset."""
|
|
273
|
+
save_gripper_calibration_offset(self.gripper_id, delta)
|
|
274
|
+
self._calibration_offset = load_gripper_calibration_offset(self.gripper_id)
|
|
275
|
+
return self._calibration_offset
|
|
276
|
+
|
|
277
|
+
def check_calibration_pin_location_is_accurate(self) -> None:
|
|
278
|
+
if not self.attached_probe:
|
|
279
|
+
raise CommandPreconditionViolated(
|
|
280
|
+
"Cannot calibrate gripper without attaching a calibration probe",
|
|
281
|
+
detail={
|
|
282
|
+
"probe": str(self._attached_probe),
|
|
283
|
+
"jaw_state": str(self.state),
|
|
284
|
+
},
|
|
285
|
+
)
|
|
286
|
+
if self.state != GripperJawState.GRIPPING:
|
|
287
|
+
raise CommandPreconditionViolated(
|
|
288
|
+
"Cannot calibrate gripper if jaw is not in gripping state",
|
|
289
|
+
detail={
|
|
290
|
+
"probe": str(self._attached_probe),
|
|
291
|
+
"jaw_state": str(self.state),
|
|
292
|
+
},
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
def critical_point(self, cp_override: Optional[CriticalPoint] = None) -> Point:
|
|
296
|
+
"""
|
|
297
|
+
The vector from the gripper mount to the critical point, which is selectable
|
|
298
|
+
between the center of the gripper engagement volume and the calibration pins.
|
|
299
|
+
"""
|
|
300
|
+
if cp_override in [CriticalPoint.NOZZLE, CriticalPoint.TIP]:
|
|
301
|
+
raise InvalidCriticalPoint(cp_override.name, "gripper")
|
|
302
|
+
|
|
303
|
+
if not self._attached_probe:
|
|
304
|
+
cp = cp_override or CriticalPoint.GRIPPER_JAW_CENTER
|
|
305
|
+
else:
|
|
306
|
+
if self._attached_probe is GripperProbe.REAR:
|
|
307
|
+
cp = cp_override or CriticalPoint.GRIPPER_REAR_CALIBRATION_PIN
|
|
308
|
+
else:
|
|
309
|
+
cp = cp_override or CriticalPoint.GRIPPER_FRONT_CALIBRATION_PIN
|
|
310
|
+
|
|
311
|
+
if cp in [CriticalPoint.GRIPPER_JAW_CENTER, CriticalPoint.XY_CENTER]:
|
|
312
|
+
return self._jaw_center_offset + Point(*self._calibration_offset.offset)
|
|
313
|
+
elif cp == CriticalPoint.GRIPPER_FRONT_CALIBRATION_PIN:
|
|
314
|
+
self.check_calibration_pin_location_is_accurate()
|
|
315
|
+
return (
|
|
316
|
+
self._front_calibration_pin_offset
|
|
317
|
+
+ Point(*self._calibration_offset.offset)
|
|
318
|
+
+ Point(y=self.current_jaw_displacement)
|
|
319
|
+
- Point(y=(self._jaw_max_offset or 0))
|
|
320
|
+
)
|
|
321
|
+
elif cp == CriticalPoint.GRIPPER_REAR_CALIBRATION_PIN:
|
|
322
|
+
self.check_calibration_pin_location_is_accurate()
|
|
323
|
+
return (
|
|
324
|
+
self._rear_calibration_pin_offset
|
|
325
|
+
+ Point(*self._calibration_offset.offset)
|
|
326
|
+
- Point(y=self.current_jaw_displacement)
|
|
327
|
+
+ Point(y=(self._jaw_max_offset or 0))
|
|
328
|
+
)
|
|
329
|
+
else:
|
|
330
|
+
raise InvalidCriticalPoint(cp.name, "gripper")
|
|
331
|
+
|
|
332
|
+
def duty_cycle_by_force(self, newton: float) -> float:
|
|
333
|
+
return gripper_config.duty_cycle_by_force(newton, self.grip_force_profile)
|
|
334
|
+
|
|
335
|
+
def __str__(self) -> str:
|
|
336
|
+
return f"{self._config.display_name}"
|
|
337
|
+
|
|
338
|
+
def __repr__(self) -> str:
|
|
339
|
+
return f"<{self.__class__.__name__}: {self._config.display_name} {id(self)}"
|
|
340
|
+
|
|
341
|
+
def as_dict(self) -> GripperDict:
|
|
342
|
+
d: GripperDict = {
|
|
343
|
+
"model": self._config.model,
|
|
344
|
+
"gripper_id": self._gripper_id,
|
|
345
|
+
"display_name": self._config.display_name,
|
|
346
|
+
"state": self._state,
|
|
347
|
+
"calibration_offset": self._calibration_offset,
|
|
348
|
+
}
|
|
349
|
+
return d
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
def _reload_gripper(
|
|
353
|
+
new_config: GripperDefinition,
|
|
354
|
+
attached_instr: Gripper,
|
|
355
|
+
cal_offset: GripperCalibrationOffset,
|
|
356
|
+
) -> Tuple[Gripper, bool]:
|
|
357
|
+
# Once we have determined that the new and attached grippers
|
|
358
|
+
# are similar enough that we might skip, see if the configs
|
|
359
|
+
# match closely enough.
|
|
360
|
+
# Returns a gripper object
|
|
361
|
+
if new_config == attached_instr.config:
|
|
362
|
+
# Same config, good enough
|
|
363
|
+
return attached_instr, True
|
|
364
|
+
else:
|
|
365
|
+
newdict = new_config.model_dump()
|
|
366
|
+
olddict = attached_instr.config.model_dump()
|
|
367
|
+
changed: Set[str] = set()
|
|
368
|
+
for k in newdict.keys():
|
|
369
|
+
if newdict[k] != olddict[k]:
|
|
370
|
+
changed.add(k)
|
|
371
|
+
if changed.intersection(RECONFIG_KEYS):
|
|
372
|
+
# Something has changed that requires reconfig
|
|
373
|
+
# we shoud recalibrate the jaw as well
|
|
374
|
+
return (
|
|
375
|
+
Gripper(
|
|
376
|
+
new_config,
|
|
377
|
+
cal_offset,
|
|
378
|
+
attached_instr._gripper_id,
|
|
379
|
+
),
|
|
380
|
+
False,
|
|
381
|
+
)
|
|
382
|
+
else:
|
|
383
|
+
# update just the cal offset and update info
|
|
384
|
+
attached_instr._calibration_offset = cal_offset
|
|
385
|
+
return attached_instr, True
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
def compare_gripper_config_and_check_skip(
|
|
389
|
+
freshly_detected: AttachedGripper,
|
|
390
|
+
attached: Optional[Gripper],
|
|
391
|
+
cal_offset: GripperCalibrationOffset,
|
|
392
|
+
) -> Tuple[Optional[Gripper], bool]:
|
|
393
|
+
"""
|
|
394
|
+
Given the gripper config for an attached gripper (if any) freshly read
|
|
395
|
+
from disk, and any attached instruments,
|
|
396
|
+
|
|
397
|
+
- Compare the new and configured gripper configs
|
|
398
|
+
- Load the new configs if they differ
|
|
399
|
+
- Return a bool indicating whether hardware reconfiguration may be
|
|
400
|
+
skipped
|
|
401
|
+
"""
|
|
402
|
+
config = freshly_detected.get("config")
|
|
403
|
+
serial = freshly_detected.get("id") or ""
|
|
404
|
+
|
|
405
|
+
if not config and not attached:
|
|
406
|
+
# nothing attached now, nothing used to be attached, nothing
|
|
407
|
+
# to reconfigure
|
|
408
|
+
return attached, True
|
|
409
|
+
|
|
410
|
+
if config and attached:
|
|
411
|
+
# something was attached and something is attached. are they
|
|
412
|
+
# the same? we can tell by comparing serials
|
|
413
|
+
if serial == attached.gripper_id:
|
|
414
|
+
# similar enough to check
|
|
415
|
+
return _reload_gripper(config, attached, cal_offset)
|
|
416
|
+
|
|
417
|
+
if config:
|
|
418
|
+
return Gripper(config, cal_offset, serial), False
|
|
419
|
+
else:
|
|
420
|
+
return None, False
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
import logging
|
|
3
|
+
import math
|
|
4
|
+
|
|
5
|
+
from opentrons.types import Point
|
|
6
|
+
from .instrument_calibration import (
|
|
7
|
+
GripperCalibrationOffset,
|
|
8
|
+
load_gripper_calibration_offset,
|
|
9
|
+
)
|
|
10
|
+
from opentrons.hardware_control.dev_types import GripperDict
|
|
11
|
+
from opentrons.hardware_control.types import (
|
|
12
|
+
CriticalPoint,
|
|
13
|
+
GripperJawState,
|
|
14
|
+
GripperProbe,
|
|
15
|
+
)
|
|
16
|
+
from opentrons.hardware_control.errors import InvalidCriticalPoint
|
|
17
|
+
from opentrons_shared_data.errors.exceptions import (
|
|
18
|
+
GripperNotPresentError,
|
|
19
|
+
CommandPreconditionViolated,
|
|
20
|
+
)
|
|
21
|
+
from .gripper import Gripper
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
MOD_LOG = logging.getLogger(__name__)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class GripperHandler:
|
|
28
|
+
GH_LOG = MOD_LOG.getChild("GripperHandler")
|
|
29
|
+
|
|
30
|
+
def __init__(self, gripper: Optional[Gripper] = None):
|
|
31
|
+
self._gripper = gripper
|
|
32
|
+
self._log = self.GH_LOG.getChild(str(id(self)))
|
|
33
|
+
|
|
34
|
+
def has_gripper(self) -> bool:
|
|
35
|
+
return bool(self._gripper)
|
|
36
|
+
|
|
37
|
+
def get_gripper(self) -> Gripper:
|
|
38
|
+
gripper = self._gripper
|
|
39
|
+
if not gripper:
|
|
40
|
+
raise GripperNotPresentError(
|
|
41
|
+
message="Cannot perform action without gripper attached"
|
|
42
|
+
)
|
|
43
|
+
return gripper
|
|
44
|
+
|
|
45
|
+
def reset_gripper(self) -> None:
|
|
46
|
+
"""Reset the internal state of the gripper."""
|
|
47
|
+
og_gripper = self._gripper
|
|
48
|
+
if not og_gripper:
|
|
49
|
+
return
|
|
50
|
+
new_gripper = Gripper(
|
|
51
|
+
og_gripper.config,
|
|
52
|
+
load_gripper_calibration_offset(og_gripper.gripper_id),
|
|
53
|
+
og_gripper.gripper_id,
|
|
54
|
+
)
|
|
55
|
+
self._gripper = new_gripper
|
|
56
|
+
|
|
57
|
+
async def reset(self) -> None:
|
|
58
|
+
self._gripper = None
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def gripper(self) -> Optional[Gripper]:
|
|
62
|
+
return self._gripper
|
|
63
|
+
|
|
64
|
+
@gripper.setter
|
|
65
|
+
def gripper(self, gripper: Optional[Gripper] = None) -> None:
|
|
66
|
+
self._gripper = gripper
|
|
67
|
+
|
|
68
|
+
def reset_instrument_offset(self, to_default: bool) -> None:
|
|
69
|
+
"""
|
|
70
|
+
Temporarily reset the gripper offsets to default values.
|
|
71
|
+
"""
|
|
72
|
+
gripper = self.get_gripper()
|
|
73
|
+
gripper.reset_offset(to_default)
|
|
74
|
+
gripper.reset_jaw_width_calibration(to_default)
|
|
75
|
+
|
|
76
|
+
def save_instrument_offset(self, delta: Point) -> GripperCalibrationOffset:
|
|
77
|
+
"""
|
|
78
|
+
Save a new instrument offset.
|
|
79
|
+
:param delta: The offset to set for the pipette.
|
|
80
|
+
"""
|
|
81
|
+
gripper = self.get_gripper()
|
|
82
|
+
self._log.info(f"Saving gripper {gripper.gripper_id} offset: {delta}")
|
|
83
|
+
return gripper.save_offset(delta)
|
|
84
|
+
|
|
85
|
+
def get_critical_point(self, cp_override: Optional[CriticalPoint] = None) -> Point:
|
|
86
|
+
if not self._gripper:
|
|
87
|
+
raise GripperNotPresentError()
|
|
88
|
+
if cp_override == CriticalPoint.MOUNT:
|
|
89
|
+
raise InvalidCriticalPoint(
|
|
90
|
+
cp_override.name,
|
|
91
|
+
"gripper",
|
|
92
|
+
"The gripper mount may not be moved directly.",
|
|
93
|
+
)
|
|
94
|
+
return self._gripper.critical_point(cp_override)
|
|
95
|
+
|
|
96
|
+
def get_gripper_dict(self) -> Optional[GripperDict]:
|
|
97
|
+
if not self._gripper:
|
|
98
|
+
# TODO (spp, 2023-04-19): Should this raise an error if fetching info of
|
|
99
|
+
# gripper that's not attached, like we do with pipettes?
|
|
100
|
+
return None
|
|
101
|
+
else:
|
|
102
|
+
return self._gripper.as_dict()
|
|
103
|
+
|
|
104
|
+
def get_attached_probe(self) -> Optional[GripperProbe]:
|
|
105
|
+
return self.get_gripper().attached_probe
|
|
106
|
+
|
|
107
|
+
def add_probe(self, probe: GripperProbe) -> None:
|
|
108
|
+
"""This is used for finding the critical point during calibration."""
|
|
109
|
+
gripper = self.get_gripper()
|
|
110
|
+
current_probe = self.get_attached_probe()
|
|
111
|
+
if not current_probe:
|
|
112
|
+
gripper.add_probe(probe)
|
|
113
|
+
else:
|
|
114
|
+
self._log.warning("add probe called with a probe already attached.")
|
|
115
|
+
|
|
116
|
+
def remove_probe(self) -> None:
|
|
117
|
+
gripper = self.get_gripper()
|
|
118
|
+
current_probe = self.get_attached_probe()
|
|
119
|
+
if current_probe:
|
|
120
|
+
gripper.remove_probe()
|
|
121
|
+
else:
|
|
122
|
+
self._log.warning("remove probe called without a probe attached")
|
|
123
|
+
|
|
124
|
+
def check_ready_for_calibration(self) -> None:
|
|
125
|
+
"""Raise an exception if a probe is not attached before calibration."""
|
|
126
|
+
gripper = self.get_gripper()
|
|
127
|
+
gripper.check_calibration_pin_location_is_accurate()
|
|
128
|
+
|
|
129
|
+
def check_ready_for_jaw_move(self, command: str) -> None:
|
|
130
|
+
"""Raise an exception if it is not currently valid to move the jaw."""
|
|
131
|
+
gripper = self.get_gripper()
|
|
132
|
+
if gripper.state == GripperJawState.UNHOMED:
|
|
133
|
+
raise CommandPreconditionViolated(
|
|
134
|
+
message=f"Cannot {command} gripper jaw before homing",
|
|
135
|
+
detail={
|
|
136
|
+
"command": command,
|
|
137
|
+
"jaw_state": str(gripper.state),
|
|
138
|
+
},
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
def is_ready_for_idle(self) -> bool:
|
|
142
|
+
"""Gripper can idle when the jaw is not currently gripping."""
|
|
143
|
+
gripper = self.get_gripper()
|
|
144
|
+
if gripper.state == GripperJawState.UNHOMED:
|
|
145
|
+
self._log.warning(
|
|
146
|
+
"Gripper jaw is not homed and cannot move to idle position."
|
|
147
|
+
)
|
|
148
|
+
return False
|
|
149
|
+
return gripper.state != GripperJawState.GRIPPING
|
|
150
|
+
|
|
151
|
+
def is_ready_for_jaw_home(self) -> bool:
|
|
152
|
+
"""Raise an exception if it is not currently valid to home the jaw."""
|
|
153
|
+
gripper = self.get_gripper()
|
|
154
|
+
if gripper.state == GripperJawState.GRIPPING and not math.isclose(
|
|
155
|
+
gripper.jaw_width, gripper.geometry.jaw_width["min"], abs_tol=5.0
|
|
156
|
+
):
|
|
157
|
+
return False
|
|
158
|
+
return True
|
|
159
|
+
|
|
160
|
+
def set_jaw_state(self, state: GripperJawState) -> None:
|
|
161
|
+
self.get_gripper().state = state
|
|
162
|
+
|
|
163
|
+
def get_duty_cycle_by_grip_force(self, newton: float) -> float:
|
|
164
|
+
gripper = self.get_gripper()
|
|
165
|
+
return gripper.duty_cycle_by_force(newton)
|
|
166
|
+
|
|
167
|
+
def set_jaw_displacement(self, mm: float) -> None:
|
|
168
|
+
gripper = self.get_gripper()
|
|
169
|
+
gripper.current_jaw_displacement = mm
|
|
170
|
+
|
|
171
|
+
def is_valid_jaw_width(self, mm: float) -> bool:
|
|
172
|
+
conf = self.get_gripper().geometry
|
|
173
|
+
return conf.jaw_width["min"] <= mm <= conf.jaw_width["max"]
|