Skip to content
Merged
Changes from all commits
Commits
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
73 changes: 73 additions & 0 deletions pylabrobot/liquid_handling/backends/hamilton/STAR_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -10091,6 +10091,79 @@ async def rotate_iswap_wrist(self, orientation: WristDriveOrientation):
tp=orientation.value,
)

# -----------------------------------------------------------------------
# iSWAP: Combined Rotation-Wrist Moves
# -----------------------------------------------------------------------

async def _iswap_rotate_increments(
self,
rotation_position: int, # units: increments
wrist_position: int, # units: increments
rotation_speed: int = 25_000, # units: increments/sec
wrist_speed: int = 20_000, # units: increments/sec
rotation_acceleration: int = 170, # units: 1000 increments/sec^2
wrist_acceleration: int = 145, # units: 1000 increments/sec^2
rotation_current_limit: int = 5,
wrist_current_limit: int = 5,
) -> None:
"""Absolute parallel move of rotation (Joint 1) + wrist (Joint 2) drives.

Args:
rotation_position [increments]: signed destination, range -30032..+30032.
wrist_position [increments]: signed destination, range -30000..+30000.
rotation_speed [increments/sec]: max velocity, range 20..75000.
wrist_speed [increments/sec]: max velocity, range 20..65000.
rotation_acceleration [1000 increments/sec^2]: range 5..200.
wrist_acceleration [1000 increments/sec^2]: range 5..200.
rotation_current_limit: current protection limiter, range 0..7.
wrist_current_limit: current protection limiter, range 0..7.
"""
if not self.extended_conf.left_x_drive.iswap_installed:
raise RuntimeError("iSWAP is not installed")

if abs(rotation_position) > STARBackend.iswap_rotation_drive_max_increment:
raise ValueError(
f"rotation_position must be between "
f"{-STARBackend.iswap_rotation_drive_max_increment} and "
f"{STARBackend.iswap_rotation_drive_max_increment}; got {rotation_position}"
)
if abs(wrist_position) > STARBackend.iswap_wrist_drive_max_increment:
raise ValueError(
f"wrist_position must be between "
f"{-STARBackend.iswap_wrist_drive_max_increment} and "
f"{STARBackend.iswap_wrist_drive_max_increment}; got {wrist_position}"
)

if not 20 <= rotation_speed <= 75000:
raise ValueError(f"rotation_speed must be between 20 and 75000; got {rotation_speed}")
if not 20 <= wrist_speed <= 65000:
raise ValueError(f"wrist_speed must be between 20 and 65000; got {wrist_speed}")
if not 5 <= rotation_acceleration <= 200:
raise ValueError(
f"rotation_acceleration must be between 5 and 200; got {rotation_acceleration}"
)
if not 5 <= wrist_acceleration <= 200:
raise ValueError(f"wrist_acceleration must be between 5 and 200; got {wrist_acceleration}")
if not 0 <= rotation_current_limit <= 7:
raise ValueError(
f"rotation_current_limit must be between 0 and 7; got {rotation_current_limit}"
)
if not 0 <= wrist_current_limit <= 7:
raise ValueError(f"wrist_current_limit must be between 0 and 7; got {wrist_current_limit}")

await self.send_command(
module="R0",
command="PA",
wa=f"{rotation_position:+06}",
wv=f"{rotation_speed:05}",
wr=f"{rotation_acceleration:03}",
ww=f"{rotation_current_limit}",
ta=f"{wrist_position:+06}",
tv=f"{wrist_speed:05}",
tr=f"{wrist_acceleration:03}",
tw=f"{wrist_current_limit}",
)
Comment on lines +10154 to +10165
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new command-building logic (range checks + string formatting for wa/ta/wv/etc.) isn’t covered by unit tests. The repo already uses STAR_tests.py to assert exact firmware command strings for iSWAP-related operations; please add a focused test that calls _iswap_rotate_both_joints_in_increments (via a command-catcher/mocked backend) and asserts the assembled R0PA... command, including sign/zero-padding and boundary conditions.

Copilot uses AI. Check for mistakes.

# -----------------------------------------------------------------------
# iSWAP: Gripper
# -----------------------------------------------------------------------
Expand Down
Loading