Skip to content

Unify gripper API: move_gripper(width, force_sensing) + class hierarchy refactor#1044

Open
rickwierenga wants to merge 2 commits into
v1b1from
gripper-move-api
Open

Unify gripper API: move_gripper(width, force_sensing) + class hierarchy refactor#1044
rickwierenga wants to merge 2 commits into
v1b1from
gripper-move-api

Conversation

@rickwierenga
Copy link
Copy Markdown
Member

Summary

  • Collapses open_gripper(width) / close_gripper(width) into a single backend primitive move_gripper(width, force_sensing=False) and adds required min_gripper_width / max_gripper_width (Optional[float]) properties on CanGrip. Widths are always in mm.

  • Frontend open_gripper() / close_gripper() become no-width wrappers that read max/min from the backend and raise NotImplementedError when the corresponding limit is None. They still accept backend_params.

  • Splits the arm class hierarchy so GripperArm is the abstract base that owns gripper-width controls, with three concrete subclasses:

    _BaseArm
      └── GripperArm (abstract; owns gripper-width controls)
            ├── FixedAxisGripperArm  (was GripperArm; grip_axis="x"|"y")
            ├── OrientableGripperArm (was OrientableArm)
            └── ArticulatedGripperArm (was ArticulatedArm)
    
  • Concrete backends migrated:

    • iSWAP: GF/GC commands flow through move_gripper; CloseGripperParams renamed to GripParams; placeholder min=50 / max=145 mm.
    • CoreGripper: min=9, max=None; move_gripper(_, force_sensing=False) still fires ZO, force-sensing raises.
    • PreciseFlex PF400: placeholder min=60 / max=145 mm; routes to firmware gripper 1 / gripper 2.
    • xArm6: min/max_gripper_width delegate to existing gripper_min_mm / gripper_max_mm.
  • Deletes the legacy pylabrobot.arms shim package entirely.

  • Updates tests, notebooks, and architecture / user-guide docs.

Notes for review

  • iSWAP / PF400 min/max are placeholders — please overwrite with verified hardware limits.
  • PF400's GripOpenPos / GripClosePos firmware commands may want a closed_gripper_position-anchored mm→units helper (called out in the CanGrip docstring); current behaviour pass-through preserved.
  • xArm6 backend tests have 3 pre-existing failures on v1b1 that this branch does not fix or worsen (test_custom_mm_per_gripper_unit, test_pick_up_at_joint_position, test_pick_up_at_location_move_then_close).

Test plan

  • python -m pytest pylabrobot/capabilities/arms pylabrobot/hamilton/liquid_handlers/star/tests pylabrobot/ufactory/xarm6/backend_tests.py (58 pass; 3 pre-existing xArm6 failures unchanged)
  • Manually exercise iSWAP open_gripper() / close_gripper() / move_gripper(..., force_sensing=True, backend_params=GripParams(...)) on real hardware
  • Manually exercise PF400 open/close and verify firmware accepts mm widths (otherwise wire the mm→units helper)
  • Rebuild docs and skim updated arms.md / iswap.ipynb / xarm6 hello-world / precise_flex hello-world

🤖 Generated with Claude Code

rickwierenga and others added 2 commits May 16, 2026 19:06
…hy refactor

CanGrip backend mixin now exposes a single `move_gripper(width, force_sensing=False)`
plus required `min_gripper_width` / `max_gripper_width` (Optional[float]) properties,
replacing the old `open_gripper(gripper_width)` / `close_gripper(gripper_width)` pair.
Widths are always in mm; backends with non-mm hardware convert internally.

Frontend `open_gripper()` / `close_gripper()` are no-width wrappers that read
max/min from the backend and raise NotImplementedError when the corresponding
limit is None. They still accept `backend_params`.

Arm capability hierarchy split for clarity:

  _BaseArm
    └── GripperArm (abstract; owns gripper-width controls)
          ├── FixedAxisGripperArm (was GripperArm; grip_axis="x"|"y")
          ├── OrientableGripperArm (was OrientableArm)
          └── ArticulatedGripperArm (was ArticulatedArm)

Concrete backends migrated:
- iSWAP: GF/GC commands now flow through move_gripper; CloseGripperParams
  renamed to GripParams; min=50, max=145 mm (placeholders).
- CoreGripper: min=9, max=None (no commandable open width); ZO still fires
  on move_gripper(_, force_sensing=False); force_sensing=True raises.
- PreciseFlex PF400: min=60, max=145 mm (placeholders); routes to
  gripper 1 / gripper 2 firmware commands.
- xArm6: min/max_gripper_width delegate to existing gripper_min_mm/gripper_max_mm.

The legacy pylabrobot.arms shim package is deleted entirely.

Tests, notebooks, and the architecture / user-guide docs are updated to the
new API and class names.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…lers

- Frontend GripperArm.move_gripper raises ValueError when width is outside
  the backend's advertised [min_gripper_width, max_gripper_width] (None
  bounds skip the check on that side).
- iSWAP move_gripper raises ValueError when backend_params is passed with
  force_sensing=False (GripParams only applies to the GC branch).
- PreciseFlex backend gains a required closed_gripper_position constructor
  param and a _mm_to_firmware_units helper; move_gripper now converts mm to
  firmware units (linear, slope 1) before issuing GripOpenPos / GripClosePos.
- Fix xArm6 pick_up_at_joint_position calling the nonexistent
  close_gripper; rewrite stale tests (mm/unit defaults, removed kwarg).
- Fix legacy STAR_backend.iswap_open_gripper and liquid_handler.py OrientableArm
  import / instantiation after the v1b1 renames.
- Migrate pf400_test.ipynb and precise_flex/hello-world.ipynb to the new API;
  drop dead docs/api/pylabrobot.arms.rst; fix architecture.md, arms.md,
  hamilton.rst, iswap.ipynb references.
- Add docstrings on frontend wrappers, abstract GripperArm, and CanGrip
  force_sensing contract; reword "interface compatibility" docstring framing.
- Tests: new precise_flex_tests.py (move_gripper wire bytes + helper anchor),
  abstract GripperArm cannot be instantiated, iSWAP backend_params rejection,
  width-bounds validation on the frontend.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant