Skip to content

basic implementation of uFactory xArm - #965

Merged
rickwierenga merged 10 commits into
PyLabRobot:v1b1from
Robert-Keyser-Calico:keyser-xarm-testing
Apr 13, 2026
Merged

basic implementation of uFactory xArm#965
rickwierenga merged 10 commits into
PyLabRobot:v1b1from
Robert-Keyser-Calico:keyser-xarm-testing

Conversation

@Robert-Keyser-Calico

Copy link
Copy Markdown
Contributor

This pull request introduces a new abstraction for 6-axis robotic arms to the codebase, including a generic frontend and backend interface, as well as an initial implementation for the xArm 6 robot. It also provides comprehensive tests and an interactive example script for pick-and-place operations. These changes pave the way for supporting advanced robotic arms and make it easier to integrate different 6-axis robots in the future.

6-Axis Arm Abstraction and Implementation

  • Added a generic SixAxisArm frontend class in six_axis.py that defines high-level operations (movement, gripper control, pick/place, freedrive mode) for 6-axis robots, delegating to a backend.
  • Introduced an abstract SixAxisBackend interface in six_axis_backend.py specifying all required backend methods for 6-axis robot support.
  • Exposed new modules in the package initializer (__init__.py) for easy import. [1] [2]

xArm 6-Specific Additions

  • Added joint enumeration (XArm6Axis) and backend scaffolding for the xArm 6 robot, preparing for hardware-specific implementations. [1] [2]
  • Included an interactive pick-and-place example script (example_pick_place.py) that guides users through teaching positions, saving/loading them, and running a pick-and-place cycle with vertical access.
  • Provided a sample taught_positions.json file as an example of saved positions for the xArm 6.

Testing

  • Added a thorough asynchronous test suite (six_axis_tests.py) that mocks the backend and validates all major frontend behaviors, including freedrive mode handling and command delegation.

Robert-Keyser-Calico and others added 4 commits March 25, 2026 10:59
Introduces a parallel arm hierarchy for 6-axis articulated robots alongside
the existing SCARA classes. Includes SixAxisBackend abstract base,
SixAxisArm frontend, XArm6Backend wrapping the xArm Python SDK, vertical
and horizontal access pattern sequences, freedrive mode, error recovery,
and an interactive pick-and-place walkthrough script with JSON position
persistence.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add speed, mvacc, joint_speed, joint_mvacc properties to XArm6Backend
- Change gripper interface to use target position parameter instead of
  binary open/close, using set_gripper_position from the SDK
- Add gripper_open_pos and gripper_close_pos constructor params for
  pick/place sequence defaults
- Enable gripper during setup (set_gripper_mode, set_gripper_enable)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove unused `patch` import in xarm6_backend_tests.py
- Sort imports alphabetically (HorizontalAccess before VerticalAccess)
- Type `_arm` as `Any` to fix mypy attr-defined errors (xarm SDK has no stubs)
- Add type: ignore comments for untyped xarm import and test mocking
- Apply ruff formatting to all 6 files

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use import-not-found instead of import-untyped for xarm SDK ignore
- Add from __future__ import annotations to example_pick_place.py
  for X | Y union syntax compatibility

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@rickwierenga
rickwierenga changed the base branch from main to v1b1 April 11, 2026 00:40
rickwierenga and others added 4 commits April 10, 2026 17:46
Drops the generic SixAxisArm frontend and SixAxisBackend base class;
XArm6Backend is now a standalone class. Relocates xarm6 to
pylabrobot/ufactory/xarm6 to match the existing top-level vendor layout.
Renames XArm6Axis enum members to semantic names (BASE_ROTATION, etc.).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Splits the old monolithic XArm6Backend into an XArm6Driver (SDK lifecycle,
retry-aware _call_sdk) and an XArm6ArmBackend implementing
ArticulatedGripperArmBackend + HasJoints + CanFreedrive. Motion profile
defaults live on per-call CartesianMoveParams/JointMoveParams dataclasses.
Adds the xarm optional dependency group.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Walks through setup, gripper control, Cartesian and joint movement,
position queries, pick/place, freedrive teaching, and park/halt/clear_errors
using the new ArticulatedArm capability API.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@rickwierenga

Copy link
Copy Markdown
Member

hey Rob, i moved it over to the v1b1 architecture and ported the example to a notebook in docs/user_guide/ufactory/xarm6/hello-world.ipynb. Would you mind giving this a test?

rickwierenga and others added 2 commits April 10, 2026 18:22
Apply ruff format to driver/backend/tests and silence a mypy no-any-return
on the xarm SDK mock helper.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Set gripper mode 1 (position/speed/force) instead of mode 0 (open/close),
  which is required for set_gripper_position to work
- Re-assert set_mode(0) + set_state(0) after gripper init to ensure arm
  is in position control mode (gripper mode change can reset arm state)
- Fix gripper unit conversion: account for 71-150mm physical range with
  proper linear mapping instead of assuming 0-based 0.1mm/unit
- Fix notebook: use keyword args for pick_up_at_location rotation parameter,
  remove invalid resource_width from drop_at_location, update gripper widths

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@rickwierenga
rickwierenga merged commit 72ef784 into PyLabRobot:v1b1 Apr 13, 2026
1 of 19 checks passed
@rickwierenga

Copy link
Copy Markdown
Member

thanks @Robert-Keyser-Calico !

@Robert-Keyser-Calico

Copy link
Copy Markdown
Contributor Author

A couple of comments that have been in the back of my head:

  1. I'm not sure about the enum names for the joints. I've always found elbow, wrist, etc confusing and especially the wrist_roll/pitch/yaw - those only make sense in the tool coordinate frame and even then I'm not sure about it. And this gets more confusing for 5 or 7 jointed arms. I personally prefer just sticking with the J1 - J6 naming scheme.
  2. The uFactory arms are a little simplistic and don't include the concept of "figure" or "pose" in the cartesian movements. (ie like the lefty/righty pose in the PF400). It just tries to maintain the same pose, which works pretty well for small known movements. We may want to add to the multiaxis arm backend an optional parameter for the figure that other arms from other vendors could use.

@rickwierenga

Copy link
Copy Markdown
Member
  1. ok will rename joints back, thanks for feedback!
  2. I think that would be through a backend param, which is how I am doing it for the kx2/pf400. I think it's difficult to describe a general pattern since the ambiguity in cartesian->joint conversion is arm specific.

@rickwierenga

Copy link
Copy Markdown
Member

does the arm have something like a for sensing mode / plate detection? where if you close the gripper it hits resistance and raises an error if no resistance is hit? similar to iswap

@Robert-Keyser-Calico

Robert-Keyser-Calico commented May 18, 2026 via email

Copy link
Copy Markdown
Contributor Author

@Robert-Keyser-Calico

Robert-Keyser-Calico commented May 19, 2026 via email

Copy link
Copy Markdown
Contributor Author

@Robert-Keyser-Calico

Robert-Keyser-Calico commented May 19, 2026 via email

Copy link
Copy Markdown
Contributor Author

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.

2 participants