Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(hardware): add acceleration to pick up tip for 96 channel #12944

Merged
merged 28 commits into from
Jul 27, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
95d068b
add acceleration to tip_action
caila-marashaj Jun 15, 2023
b4d4bee
pick up tip move happens, but rumbly
caila-marashaj Jun 21, 2023
bdea049
linter stuff cleanup
caila-marashaj Jun 21, 2023
782a760
fixed position of acceleration in tipaction msg
caila-marashaj Jun 22, 2023
73d26bf
moving but delayed
caila-marashaj Jun 27, 2023
c3e044a
modify tip action, debugging code still in there
caila-marashaj Jun 28, 2023
a85074e
mostly working but returning position too early
caila-marashaj Jun 29, 2023
1952348
need to update tests
caila-marashaj Jul 6, 2023
fa194a3
updated unit test args for tip_action
caila-marashaj Jul 17, 2023
d2e7927
rebase
caila-marashaj Jul 17, 2023
2b20a20
rough final draft
caila-marashaj Jul 18, 2023
8cf3c15
cleanup
caila-marashaj Jul 18, 2023
7e5b7ef
format
caila-marashaj Jul 18, 2023
8ace0ef
remove redundant data check from gear motors
caila-marashaj Jul 18, 2023
155738b
hardware controller changes
caila-marashaj Jul 19, 2023
0aede03
increase backward distances
caila-marashaj Jul 20, 2023
97e12e9
changed helpers_ot3 function
caila-marashaj Jul 21, 2023
1550c9a
format
caila-marashaj Jul 21, 2023
735ebe7
helpers_ot3 function change
caila-marashaj Jul 21, 2023
af1eefa
got rid of copysign call
caila-marashaj Jul 21, 2023
e2280aa
check if speed exists
caila-marashaj Jul 21, 2023
5be4492
add deafult value to axis convert call
caila-marashaj Jul 24, 2023
93ef4ca
update gear motor position handling after move
caila-marashaj Jul 25, 2023
f1a42d1
test fix
caila-marashaj Jul 25, 2023
2b71f07
moved comments
caila-marashaj Jul 26, 2023
57bb955
remove updategearmotorpositionestimation msg
caila-marashaj Jul 26, 2023
e201a43
removed more unneeded code
caila-marashaj Jul 26, 2023
6eb76e6
address change reqs
caila-marashaj Jul 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
moving but delayed
  • Loading branch information
caila-marashaj committed Jul 26, 2023
commit 73d26bf4937e7782fc111e761856ace0271a3566
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 @@ -104,7 +104,7 @@
OT3AxisKind.Z: 150,
OT3AxisKind.P: 30,
OT3AxisKind.Z_G: 150,
OT3AxisKind.Q: 4,
OT3AxisKind.Q: 10,
},
low_throughput={
OT3AxisKind.X: 800,
Expand Down
15 changes: 11 additions & 4 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 @@ -67,6 +68,7 @@
from opentrons_hardware.hardware_control.motion_planning import (
Move,
Coordinates,
Block,
)
from opentrons_hardware.hardware_control.estop.detector import (
EstopDetector,
Expand All @@ -81,7 +83,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 @@ -260,6 +262,7 @@ def __init__(
self._estop_detector: Optional[EstopDetector] = None
self._estop_state_machine = EstopStateMachine(detector=None)
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 @@ -331,6 +334,10 @@ def _build_system_hardware(
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 Down Expand Up @@ -619,11 +626,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
29 changes: 28 additions & 1 deletion api/src/opentrons/hardware_control/backends/ot3utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,10 +333,15 @@ def create_move_group(
origin: Coordinates[Axis, CoordinateValue],
moves: List[Move[Axis]],
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 @@ -356,6 +361,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 Down Expand Up @@ -398,6 +404,27 @@ def create_tip_action_home_group(
return [home_group, backoff_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
51 changes: 34 additions & 17 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 @@ -1664,7 +1665,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 @@ -1679,26 +1680,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 @@ -1710,6 +1724,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 @@ -1719,7 +1734,7 @@ async def pick_up_tip(

await self._move_to_plunger_bottom(realmount, rate=1.0)
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 Down Expand Up @@ -1760,6 +1775,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 @@ -1813,6 +1829,7 @@ async def drop_tip(

_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 @@ -150,6 +150,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 @@ -271,6 +272,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 @@ -568,6 +568,12 @@ class TipActionResponsePayload(MoveCompletedPayload):
success: utils.UInt8Field
gear_motor_id: GearMotorIdField

seq_id: utils.UInt8Field
caila-marashaj marked this conversation as resolved.
Show resolved Hide resolved
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
41 changes: 27 additions & 14 deletions hardware/opentrons_hardware/hardware_control/motion.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""A collection of motions that define a single move."""
from typing import List, Dict, Iterable, Union
from typing import List, Dict, Iterable, Union, Optional, Tuple
from dataclasses import dataclass
import numpy as np
from logging import getLogger
Expand Down Expand Up @@ -107,6 +107,7 @@ def create_step(
duration: np.float64,
present_nodes: Iterable[NodeId],
stop_condition: MoveStopCondition = MoveStopCondition.none,
tip_action_step: Optional[PipetteTipActionType] = None,
) -> MoveGroupStep:
"""Create a move from a block.

Expand All @@ -119,23 +120,34 @@ def create_step(
A Move
"""
ordered_nodes = sorted(present_nodes, key=lambda node: node.value)
# Gripper G cannont process this type of move and this will
# Gripper G cannot process this type of move and this will
# result in numerous move set timeouts if the gripper is attached
# possible TODO if requested is to also add a move group step that
# adds a MoveGroupeSingleGripperStep
# adds a MoveGroupSingleGripperStep
ordered_nodes = list([n for n in present_nodes if n != NodeId.gripper_g])

step: MoveGroupStep = {}
for axis_node in ordered_nodes:
step[axis_node] = MoveGroupSingleAxisStep(
distance_mm=distance.get(axis_node, np.float64(0)),
acceleration_mm_sec_sq=acceleration.get(axis_node, np.float64(0)),
velocity_mm_sec=velocity.get(axis_node, np.float64(0)),
if tip_action_step is not None:

step[NodeId.pipette_left] = MoveGroupTipActionStep(
duration_sec=duration,
velocity_mm_sec=velocity.get(NodeId.pipette_left, np.float64(0)),
action=tip_action_step,
stop_condition=stop_condition,
move_type=MoveType.get_move_type(stop_condition),
acceleration_mm_sec_sq=acceleration.get(NodeId.pipette_left, np.float64(0)),
)
return step
return step

else:
for axis_node in ordered_nodes:
step[axis_node] = MoveGroupSingleAxisStep(
distance_mm=distance.get(axis_node, np.float64(0)),
acceleration_mm_sec_sq=acceleration.get(axis_node, np.float64(0)),
velocity_mm_sec=velocity.get(axis_node, np.float64(0)),
duration_sec=duration,
stop_condition=stop_condition,
move_type=MoveType.get_move_type(stop_condition),
)
return step


def create_backoff_step(velocity: Dict[NodeId, np.float64]) -> MoveGroupStep:
Expand Down Expand Up @@ -200,12 +212,13 @@ def create_tip_action_step(
)
for axis_node in present_nodes:
step[axis_node] = MoveGroupTipActionStep(
velocity_mm_sec=velocity[axis_node],
acceleration_mm_sec_sq=acceleration[axis_node],
duration_sec=abs(distance[axis_node] / velocity[axis_node]),
stop_condition=stop_condition,
velocity_mm_sec=velocity[axis_node],
action=action,
stop_condition=stop_condition,
acceleration_mm_sec_sq=acceleration[axis_node],
)
# breakpoint()
return step


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ def targets_to_moves(
for target in targets:
position = {k: np.float64(target.position.get(k, 0)) for k in all_axes}
unit_vector, distance = get_unit_vector(initial_checked, position)
# print(f"using unit vector = {unit_vector}")
# print(f"using max speed = {target.max_speed}")
speed = limit_max_speed(unit_vector, target.max_speed, constraints)
third_distance = np.float64(distance / 3)
m = Move(
Expand Down
Loading