Skip to content

Commit

Permalink
feat(gripper): specify whether or not a gripper move should stay enga…
Browse files Browse the repository at this point in the history
…ged after an error (#13214)

* update hardware message to add stay engaged param

* stay engaged when grip

* use stay engaged in hardware controller
  • Loading branch information
ahiuchingau authored Aug 2, 2023
1 parent e8a656b commit 35edf78
Show file tree
Hide file tree
Showing 13 changed files with 34 additions and 8 deletions.
5 changes: 4 additions & 1 deletion api/src/opentrons/hardware_control/backends/ot3controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -660,8 +660,11 @@ async def gripper_grip_jaw(
self,
duty_cycle: float,
stop_condition: MoveStopCondition = MoveStopCondition.none,
stay_engaged: bool = True,
) -> None:
move_group = create_gripper_jaw_grip_group(duty_cycle, stop_condition)
move_group = create_gripper_jaw_grip_group(
duty_cycle, stop_condition, stay_engaged
)
runner = MoveGroupRunner(move_groups=[move_group])
positions = await runner.run(can_messenger=self._messenger)
self._handle_motor_status_response(positions)
Expand Down
3 changes: 2 additions & 1 deletion api/src/opentrons/hardware_control/backends/ot3simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,9 +353,10 @@ async def gripper_grip_jaw(
self,
duty_cycle: float,
stop_condition: MoveStopCondition = MoveStopCondition.none,
stay_engaged: bool = True,
) -> None:
"""Move gripper inward."""
_ = create_gripper_jaw_grip_group(duty_cycle, stop_condition)
_ = create_gripper_jaw_grip_group(duty_cycle, stop_condition, stay_engaged)

@ensure_yield
async def gripper_home_jaw(self, duty_cycle: float) -> None:
Expand Down
2 changes: 2 additions & 0 deletions api/src/opentrons/hardware_control/backends/ot3utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -428,12 +428,14 @@ def create_gear_motor_home_group(
def create_gripper_jaw_grip_group(
duty_cycle: float,
stop_condition: MoveStopCondition = MoveStopCondition.none,
stay_engaged: bool = True,
) -> MoveGroup:
step = create_gripper_jaw_step(
duration=np.float64(GRIPPER_JAW_GRIP_TIME),
duty_cycle=np.float32(round(duty_cycle)),
stop_condition=stop_condition,
move_type=MoveType.grip,
stay_engaged=stay_engaged,
)
move_group: MoveGroup = [step]
return move_group
Expand Down
12 changes: 8 additions & 4 deletions api/src/opentrons/hardware_control/ot3api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1395,10 +1395,12 @@ async def update_config(self, **kwargs: Any) -> None:
self._config = replace(self._config, **kwargs)

@ExecutionManagerProvider.wait_for_running
async def _grip(self, duty_cycle: float) -> None:
async def _grip(self, duty_cycle: float, stay_engaged: bool = True) -> None:
"""Move the gripper jaw inward to close."""
try:
await self._backend.gripper_grip_jaw(duty_cycle=duty_cycle)
await self._backend.gripper_grip_jaw(
duty_cycle=duty_cycle, stay_engaged=stay_engaged
)
await self._cache_encoder_position()
except Exception:
self._log.exception(
Expand Down Expand Up @@ -1431,12 +1433,14 @@ async def _hold_jaw_width(self, jaw_width_mm: float) -> None:
self._log.exception("Gripper set width failed")
raise

async def grip(self, force_newtons: Optional[float] = None) -> None:
async def grip(
self, force_newtons: Optional[float] = None, stay_engaged: bool = True
) -> None:
self._gripper_handler.check_ready_for_jaw_move()
dc = self._gripper_handler.get_duty_cycle_by_grip_force(
force_newtons or self._gripper_handler.get_gripper().default_grip_force
)
await self._grip(duty_cycle=dc)
await self._grip(duty_cycle=dc, stay_engaged=stay_engaged)
self._gripper_handler.set_jaw_state(GripperJawState.GRIPPING)

async def ungrip(self, force_newtons: Optional[float] = None) -> None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ async def move_labware_with_gripper(

# Keep the gripper in idly gripped position to avoid colliding with
# things like the thermocycler latches
await ot3api.grip(force_newtons=IDLE_STATE_GRIP_FORCE)
await ot3api.grip(force_newtons=IDLE_STATE_GRIP_FORCE, stay_engaged=False)

async def ensure_movement_not_obstructed_by_module(
self, labware_id: str, new_location: LabwareLocation
Expand Down
1 change: 1 addition & 0 deletions api/tests/opentrons/hardware_control/test_ot3_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,7 @@ async def test_gripper_action_works_with_gripper(
await ot3_hardware.grip(5.0)
mock_grip.assert_called_once_with(
gc.duty_cycle_by_force(5.0, gripper_config.grip_force_profile),
stay_engaged=True,
)

await ot3_hardware.ungrip()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,9 @@ async def test_move_labware_with_gripper(
await ot3_hardware_api.move_to(
mount=gripper, abs_position=expected_waypoints[5]
),
await ot3_hardware_api.grip(force_newtons=IDLE_STATE_GRIP_FORCE),
await ot3_hardware_api.grip(
force_newtons=IDLE_STATE_GRIP_FORCE, stay_engaged=False
),
)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,7 @@ class GripperMoveRequestPayload(AddToMoveGroupRequestPayload):

duty_cycle: utils.UInt32Field
encoder_position_um: utils.Int32Field
stay_engaged: utils.UInt8Field


@dataclass(eq=False)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ async def grip(
seq_id: int,
duration_sec: float,
duty_cycle: int,
stay_engaged: bool = False,
) -> None:
"""Start grip motion."""
await can_messenger.send(
Expand All @@ -141,6 +142,7 @@ async def grip(
),
duty_cycle=UInt32Field(duty_cycle),
encoder_position_um=Int32Field(0),
stay_engaged=UInt8Field(int(stay_engaged)),
)
),
)
Expand All @@ -162,6 +164,7 @@ async def home(
duration=UInt32Field(0),
duty_cycle=UInt32Field(duty_cycle),
encoder_position_um=Int32Field(0),
stay_engaged=UInt8Field(0),
)
),
)
Expand All @@ -173,6 +176,7 @@ async def move(
seq_id: int,
duty_cycle: int,
encoder_position_um: int,
stay_engaged: bool = False,
) -> None:
"""Start linear motion."""
await can_messenger.send(
Expand All @@ -184,6 +188,7 @@ async def move(
duration=UInt32Field(0),
duty_cycle=UInt32Field(duty_cycle),
encoder_position_um=Int32Field(encoder_position_um),
stay_engaged=UInt8Field(int(stay_engaged)),
)
),
)
3 changes: 3 additions & 0 deletions hardware/opentrons_hardware/hardware_control/motion.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class MoveGroupSingleGripperStep:
pwm_duty_cycle: np.float32
encoder_position_um: np.int32
pwm_frequency: np.float32 = np.float32(320000)
stay_engaged: bool = False
stop_condition: MoveStopCondition = MoveStopCondition.gripper_force
move_type: MoveType = MoveType.grip

Expand Down Expand Up @@ -214,6 +215,7 @@ def create_gripper_jaw_step(
duty_cycle: np.float32,
encoder_position_um: np.int32 = np.int32(0),
frequency: np.float32 = np.float32(320000),
stay_engaged: bool = False,
stop_condition: MoveStopCondition = MoveStopCondition.gripper_force,
move_type: MoveType = MoveType.grip,
) -> MoveGroupStep:
Expand All @@ -223,6 +225,7 @@ def create_gripper_jaw_step(
duration_sec=duration,
pwm_frequency=frequency,
pwm_duty_cycle=duty_cycle,
stay_engaged=stay_engaged,
stop_condition=stop_condition,
move_type=move_type,
encoder_position_um=encoder_position_um,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ def _get_brushed_motor_message(
),
duty_cycle=UInt32Field(int(step.pwm_duty_cycle)),
encoder_position_um=Int32Field(int(step.encoder_position_um)),
stay_engaged=UInt8Field(int(step.stay_engaged)),
)
if step.move_type == MoveType.home:
return GripperHomeRequest(payload=payload)
Expand Down
1 change: 1 addition & 0 deletions hardware/opentrons_hardware/scripts/gripper_lifetime.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ async def run(args: argparse.Namespace) -> None:
pwm_frequency=float32(pwm_freq),
pwm_duty_cycle=float32(pwm_duty),
encoder_position_um=int32(0),
stay_engaged=True,
)
}
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ def move_group_gripper_multiple() -> MoveGroups:
duration_sec=float64(1),
pwm_duty_cycle=float32(50),
encoder_position_um=int32(0),
stay_engaged=True,
stop_condition=MoveStopCondition.gripper_force,
move_type=MoveType.grip,
),
Expand All @@ -203,6 +204,7 @@ def move_group_gripper_multiple() -> MoveGroups:
duration_sec=float64(1),
pwm_duty_cycle=float32(50),
encoder_position_um=int32(80000),
stay_engaged=False,
stop_condition=MoveStopCondition.encoder_position,
move_type=MoveType.linear,
),
Expand Down

0 comments on commit 35edf78

Please sign in to comment.