Skip to content

Commit

Permalink
moving but delayed
Browse files Browse the repository at this point in the history
  • Loading branch information
caila-marashaj committed Jun 27, 2023
1 parent 05cebc1 commit 9070819
Show file tree
Hide file tree
Showing 10 changed files with 262 additions and 106 deletions.
2 changes: 1 addition & 1 deletion api/src/opentrons/config/defaults_ot3.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@
OT3AxisKind.Z: 120,
OT3AxisKind.P: 30,
OT3AxisKind.Z_G: 150,
OT3AxisKind.Q: 4,
OT3AxisKind.Q: 10,
},
low_throughput={
OT3AxisKind.X: 600,
Expand Down
53 changes: 45 additions & 8 deletions api/src/opentrons/hardware_control/backends/ot3controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from contextlib import asynccontextmanager
from functools import wraps
import logging
import time
from copy import deepcopy
from typing import (
Any,
Expand Down Expand Up @@ -40,6 +41,7 @@
create_gripper_jaw_home_group,
create_gripper_jaw_hold_group,
create_tip_action_group,
create_fast_tip_action_group,
PipetteAction,
motor_nodes,
LIMIT_SWITCH_OVERTRAVEL_DISTANCE,
Expand All @@ -62,6 +64,7 @@
from opentrons_hardware.hardware_control.motion_planning import (
Move,
Coordinates,
Block,
)

from opentrons_hardware.hardware_control.motor_enable_disable import (
Expand All @@ -71,7 +74,7 @@
from opentrons_hardware.hardware_control.motor_position_status import (
get_motor_position,
update_motor_position_estimation,
update_gear_motor_position_estimation,
# update_gear_motor_position_estimation,
)
from opentrons_hardware.hardware_control.limit_switches import get_limit_switches
from opentrons_hardware.hardware_control.tip_presence import get_tip_ejector_state
Expand Down Expand Up @@ -242,6 +245,7 @@ def __init__(
FirmwareUpdate(),
)
self._position = self._get_home_position()
self._gear_motor_position = None
self._encoder_position = self._get_home_position()
self._motor_status = {}
self._check_updates = check_updates
Expand Down Expand Up @@ -292,6 +296,10 @@ def _build_system_hardware(
usb_messenger.start()
return RemoteOT3GPIO(usb_messenger), usb_messenger

@property
def gear_motor_position(self) -> float:
return self._gear_motor_position

def _motor_nodes(self) -> Set[NodeId]:
"""Get a list of the motor controller nodes of all attached and ok devices."""
return motor_nodes(self._subsystem_manager.targets)
Expand All @@ -318,10 +326,16 @@ async def update_motor_status(self) -> None:
response = await get_motor_position(self._messenger, motor_nodes)
self._handle_motor_status_response(response)

async def gear_motor_position_estimation(self) -> Tuple[float, bool]:
response = await update_gear_motor_position_estimation(self._messenger)

return response
# async def gear_motor_position_estimation(self) -> Tuple[float, bool]:
# motor_response = await update_gear_motor_position_estimation(self._messenger)
# updated_successfully = motor_response[1]
# if updated_successfully:
# self._gear_motor_position = motor_response[0]
# return self._gear_motor_position, True
# else:
# # if the gear motor didn't update successfully, return the most recent
# # position estimate
# return self._gear_motor_position, False

async def update_motor_estimation(self, axes: Sequence[OT3Axis]) -> None:
"""Update motor position estimation for commanded nodes, and update cache of data."""
Expand Down Expand Up @@ -593,6 +607,29 @@ def _filter_move_group(self, move_group: MoveGroup) -> MoveGroup:
)
return new_group

async def fast_tip_action(
self,
origin: Dict[OT3Axis, float],
moves: List[Move],
tip_action: str = "clamp",
) -> None:
if tip_action == "home":
stop_condition = MoveStopCondition.limit_switch
else:
stop_condition = MoveStopCondition.none
breakpoint()
group = create_move_group(origin, moves, [NodeId.pipette_left], stop_condition, tip_action)
move_group, _ = group
runner = MoveGroupRunner(
move_groups=[move_group],
ignore_stalls=True if not ff.stall_detection_enabled() else False,
)
positions = await runner.run(can_messenger=self._messenger)
# print(f"done w move group runner: {positions} at {time.time()}")
if NodeId.pipette_left in positions:
self._gear_motor_position = positions[NodeId.pipette_left][0]
# print(f"gear position is now {self._gear_motor_position}")

async def tip_action(
self,
axes: Sequence[OT3Axis],
Expand All @@ -606,11 +643,11 @@ async def tip_action(
move_group = create_tip_action_group(
axes, distance, speed, acceleration, cast(PipetteAction, tip_action)
)
# print(f"about to create runner at {time.time()}")
runner = MoveGroupRunner(move_groups=[move_group])
positions = await runner.run(can_messenger=self._messenger)
for axis, point in positions.items():
self._position.update({axis: point[0]})
self._encoder_position.update({axis: point[1]})
# print(f"positions returned {positions}, at {time.time()}")
# await update_gear_motor_position_estimation(self._messenger)

@requires_update
async def gripper_grip_jaw(
Expand Down
31 changes: 29 additions & 2 deletions api/src/opentrons/hardware_control/backends/ot3utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""Shared utilities for ot3 hardware control."""
from typing import Dict, Iterable, List, Set, Tuple, TypeVar, Sequence
from typing import Dict, Iterable, List, Set, Tuple, TypeVar, Sequence, Optional
from typing_extensions import Literal
from opentrons.config.types import OT3MotionSettings, OT3CurrentSettings, GantryLoad
from opentrons.hardware_control.types import (
Expand Down Expand Up @@ -303,10 +303,15 @@ def create_move_group(
origin: Coordinates[OT3Axis, CoordinateValue],
moves: List[Move[OT3Axis]],
present_nodes: Iterable[NodeId],
stop_condition: MoveStopCondition = MoveStopCondition.none,
stop_condition: MoveStopCondition,
tip_action_type: Optional[PipetteTipActionType] = None,
) -> Tuple[MoveGroup, Dict[NodeId, float]]:
pos = _convert_to_node_id_dict(origin)
move_group: MoveGroup = []
if tip_action_type is not None:
tip_action_step = PipetteTipActionType[tip_action_type]
else:
tip_action_step = None
for move in moves:
unit_vector = move.unit_vector
for block in move.blocks:
Expand All @@ -321,6 +326,7 @@ def create_move_group(
duration=block.time,
present_nodes=present_nodes,
stop_condition=stop_condition,
tip_action_step=tip_action_step,
)
for ax in pos.keys():
pos[ax] += node_id_distances.get(ax, 0)
Expand All @@ -345,6 +351,27 @@ def create_home_group(
return move_group


def create_fast_tip_action_group(
axes: Sequence[OT3Axis],
move: Move,
action: str = "clamp",
) -> MoveGroup:
current_nodes = [axis_to_node(ax) for ax in axes]
tip_action_group = []
for block in move.blocks:
if block.initial_speed == 0:
continue
step = create_tip_action_step(
velocity={node_id: np.float64(block.initial_speed) for node_id in current_nodes},
distance={node_id: np.float64(block.distance) for node_id in current_nodes},
acceleration={node_id: np.float64(block.acceleration) for node_id in current_nodes},
present_nodes=current_nodes,
action=PipetteTipActionType[action],
)
tip_action_group.append(step)
return tip_action_group


def create_tip_action_group(
axes: Sequence[OT3Axis],
distance: float,
Expand Down
60 changes: 40 additions & 20 deletions api/src/opentrons/hardware_control/ot3api.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import asyncio
import contextlib
import time
from functools import partial, lru_cache
from dataclasses import replace
import logging
Expand Down Expand Up @@ -1606,7 +1607,7 @@ async def _force_pick_up_tip(
await self._move(target_up)

async def _motor_pick_up_tip(
self, mount: OT3Mount, pipette_spec: TipMotorPickUpTipSpec
self, mount: OT3Mount, pipette_spec: TipMotorPickUpTipSpec, accelerate_during_pickup: bool = False,
) -> None:
async with self._backend.restore_current():
await self._backend.set_active_current(
Expand All @@ -1621,26 +1622,39 @@ async def _motor_pick_up_tip(
await self._move(target_down)
# perform pick up tip

gear_motor_origin = await self._backend.gear_motor_position_estimation()
gear_origin_dict = {OT3Axis.Q: gear_motor_origin[0]}
# if accelerate_during_pickup:
# gear_motor_origin = await self._backend.gear_motor_position_estimation()
# gear_origin_dict = {OT3Axis.Q: gear_motor_origin[0]}
gear_origin_dict = {OT3Axis.Q: 0}
gear_motor_target = pipette_spec.pick_up_distance
gear_target_dict = {OT3Axis.Q: gear_motor_target}
moves = self._build_moves(gear_origin_dict, gear_target_dict)
blocks = moves[0][0].blocks
clamp_moves = self._build_moves(gear_origin_dict, gear_target_dict)

await self._backend.fast_tip_action(gear_origin_dict, clamp_moves[0], "clamp")

# else:
# await self._backend.tip_action(
# [OT3Axis.of_main_tool_actuator(mount)],
# float(pipette_spec.pick_up_distance),
# float(pipette_spec.speed),
# float(0),
# "clamp",
# )

gear_motor_position = {OT3Axis.Q: self._backend.gear_motor_position}
# print(f"gear motor pos = {gear_motor_position}")
home_target = {OT3Axis.Q: 5}
# print(f"passing in gear motor position = {gear_motor_position}")
home_moves = self._build_moves(gear_motor_position, home_target)
# print(f"home moves = {home_moves[0]}")
await self._backend.fast_tip_action(gear_motor_position, home_moves[0], "clamp")
print(f"done almost homing at {time.time()}")

for block in blocks:
await self._backend.tip_action(
[OT3Axis.of_main_tool_actuator(mount)],
float(block.distance),
float(block.initial_speed),
float(block.acceleration),
"clamp",
)
# back clamps off the adapter posts
await self._backend.tip_action(
[OT3Axis.of_main_tool_actuator(mount)],
float(pipette_spec.pick_up_distance + pipette_spec.home_buffer),
float(pipette_spec.speed),
# float(pipette_spec.pick_up_distance + pipette_spec.home_buffer),
float(5.5),
float(pipette_spec.speed - 1),
float(0),
"home",
)
Expand All @@ -1652,6 +1666,7 @@ async def pick_up_tip(
presses: Optional[int] = None,
increment: Optional[float] = None,
prep_after: bool = True,
accelerate_during_pickup: bool = True,
) -> None:
"""Pick up tip from current location."""
realmount = OT3Mount.from_mount(mount)
Expand All @@ -1660,7 +1675,7 @@ async def pick_up_tip(
)

if spec.pick_up_motor_actions:
await self._motor_pick_up_tip(realmount, spec.pick_up_motor_actions)
await self._motor_pick_up_tip(realmount, spec.pick_up_motor_actions, accelerate_during_pickup)
else:
await self._force_pick_up_tip(realmount, spec)

Expand All @@ -1670,7 +1685,7 @@ async def pick_up_tip(
for rel_point, speed in spec.shake_off_list:
await self.move_rel(realmount, rel_point, speed=speed)

await self._backend.get_tip_present(realmount, TipStateType.PRESENT)
# await self._backend.get_tip_present(realmount, TipStateType.PRESENT)

_add_tip_to_instrs()

Expand All @@ -1697,6 +1712,7 @@ def set_working_volume(
)
instrument.working_volume = tip_volume


async def drop_tip(
self, mount: Union[top_types.Mount, OT3Mount], home_after: bool = False
) -> None:
Expand Down Expand Up @@ -1739,7 +1755,8 @@ async def drop_tip(
speed=move.speed,
home_flagged_axes=False,
)
if move.home_after:
if move.home_after:
await self._home([OT3Axis.from_axis(ax) for ax in move.home_axes])

for shake in spec.shake_moves:
await self.move_rel(mount, shake[0], speed=shake[1])
Expand All @@ -1751,9 +1768,12 @@ async def drop_tip(
}
)

await self._backend.get_tip_present(realmount, TipStateType.ABSENT)
# TODO: implement tip-detection sequence during drop-tip for 96ch
if self.gantry_load != GantryLoad.HIGH_THROUGHPUT:
await self._backend.get_tip_present(realmount, TipStateType.ABSENT)
_remove()


async def clean_up(self) -> None:
"""Get the API ready to stop cleanly."""
await self._backend.clean_up()
Expand Down
2 changes: 2 additions & 0 deletions hardware/opentrons_hardware/drivers/can_bus/can_messenger.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ async def send_and_verify_recieved(self) -> ErrorCode:
max(1.0, self._timeout),
)
except asyncio.TimeoutError:
print(f"\n\n no ack received\n\n")
log.error(
f"Message did not receive ack for message index {self._message.payload.message_index}"
)
Expand Down Expand Up @@ -277,6 +278,7 @@ async def _ensure_send(
exclusive: bool = False,
) -> ErrorCode:
if len(expected_nodes) == 0:
print(f"no expected nodes")
log.warning("Expected Nodes should have been specified")
if node_id == NodeId.broadcast:
expected_nodes = _Basic_Nodes.copy()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,12 @@ class TipActionResponsePayload(MoveCompletedPayload):
success: utils.UInt8Field
gear_motor_id: GearMotorIdField

seq_id: utils.UInt8Field
current_position_um: utils.UInt32Field
encoder_position_um: utils.Int32Field
position_flags: MotorPositionFlagsField
ack_id: utils.UInt8Field


@dataclass(eq=False)
class PeripheralStatusResponsePayload(SensorPayload):
Expand Down
Loading

0 comments on commit 9070819

Please sign in to comment.