Expose iSWAPBackend.rotation_drive_request_position()#1011
Expose iSWAPBackend.rotation_drive_request_position()#1011
iSWAPBackend.rotation_drive_request_position()#1011Conversation
…crements` → `*_angle_increments`
| Previously measured to be 32.8 mm by contributor; | ||
| per-machine calibrated during service. Required for deriving the | ||
| iSWAP rotation drive's deck X coordinate from the X-arm carriage center. | ||
| """ | ||
| resp = await self.driver.send_command(module="C0", command="RA", ra="kg", fmt="kg###") | ||
| return cast(int, resp["kg"]) / 10.0 | ||
|
|
||
| # Vertical drop from the iSWAP rotation drive plane to the gripper | ||
| # finger plane, per VENUS Programmer Guide §15.1.1. | ||
| rotation_drive_z_offset_above_finger = 13.0 | ||
|
|
||
| async def rotation_drive_request_position(self) -> Coordinate: | ||
| """Position of the iSWAP rotation drive (joint 0) in deck coordinates, mm.""" | ||
| if not self.driver.extended_conf.left_x_drive.iswap_installed: # type: ignore[union-attr] | ||
| raise RuntimeError("iSWAP is not installed") | ||
|
|
||
| x_arm_center = await self.driver.left_x_arm.request_position() # type: ignore[union-attr] | ||
| iswap_x_offset = await self.rotation_drive_request_x_offset() | ||
| rotation_drive_y = await self.rotation_drive_request_y() | ||
| finger_loc = (await self.request_gripper_location()).location | ||
|
|
||
| return Coordinate( | ||
| x=x_arm_center - iswap_x_offset, | ||
| y=rotation_drive_y, | ||
| z=finger_loc.z + self.rotation_drive_z_offset_above_finger, | ||
| ) |
There was a problem hiding this comment.
I think it is worth considering making rotation_drive_request_position private, just loading it in _on_setup and then storing it locally so we don't have to call this firmware command every time.
There was a problem hiding this comment.
I'm not sure I understand what you mean:
Every time the STAR's X-arm moves this position is different, same for when the iSWAP performs any action, or channels require the iSWAP to move out of the way?
There was a problem hiding this comment.
the offset should be constant right?
There was a problem hiding this comment.
ohhh you don't mean making rotation_drive_request_position private,
but instead you mean making rotation_drive_request_x_offset private and cached during setup?
yes, that makes sense - will implement
…ding invalid C0 RA pn= (#1012)
…crements` → `*_angle_increments`
…//github.com/PyLabRobot/pylabrobot into expose-request_iswap_rotation_drive_position
…RG read, GA move)
|
can I or you merge this? |
It is time to re-start "Epic: Tame the iSWAP" ... a series of tasks/PRs aimed at making this unpredictable beast more reliable, predictable and ready for our agents.
This is PR 0 of many to come...
Adds
iSWAPBackend.rotation_drive_request_position()- returns the iSWAP rotation drive position as aCoordinatein deck space - plus the supportingrotation_drive_request_x_offset()read of EEPROMkgviaC0:RA.Also renames a few drive methods so naming reflects what they actually return.
Problem
The iSWAP arm is a 2-link planar manipulator (L1 = L2 = 138 mm) whose base — the rotation drive — sits at a fixed offset from the X-arm carriage.
Every kinematic calculation on the iSWAP — forward kinematics from joint angles to gripper pose, inverse kinematics from a target plate pose to joint angles, reachable-workspace and collision checks — starts from that base point in deck coordinates.
Without it, there is no anchor to put the arm geometry on the deck.
Today the rotation drive's deck position has to be reconstructed by hand from three separate reads:
kg(set during service, currently exposed nowhere in PLR),request_gripper_y_position, and the 13 mm vertical drop from the rotation-drive plane to the gripper finger plane to recover Z.This is the foundational primitive for moving iSWAP path planning out of C0's firmware macros (
PG,PP) and into PLR — the larger "tame the iSWAP" goal.Until joint 0 is queryable as a
Coordinate, none of the downstream kinematic work can land cleanly.Separately, the existing
request_{rotation,wrist}_drive_position_incrementsmethods return an angle in motor increments, not a spatial position — the name was misleading and now actively collides with the newrotation_drive_request_position(), which really does return aCoordinate.PR content / solution
New on
iSWAPBackend:rotation_drive_request_x_offset() -> float— reads EEPROMkgviaC0:RA(mm, /10). Per-machine, set at service.rotation_drive_z_offset_above_finger = 13.0— class constant for the rotation-drive-to-finger vertical offset.rotation_drive_request_position() -> Coordinate— composes X-arm center −kg, rotation-drive Y, finger Z + 13 mm.Raises
RuntimeErrorif no iSWAP is installed.Renames (angle ≠ position):
request_rotation_drive_position_increments→rotation_drive_request_angle_incrementsrequest_rotation_drive_orientation→rotation_drive_request_orientationrequest_wrist_drive_position_increments→request_wrist_drive_angle_incrementsrotate_rotation_drive→rotation_drive_rotateLegacy backend (
legacy/.../STAR_backend.py):"""Deprecated: use ..."""docstrings left untouched (no new deprecation messaging introduced).