Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
830b2aa
restructured hardware folder
mustafab0 Oct 22, 2025
819c3c7
Added spec for armdriver
mustafab0 Oct 22, 2025
2b352bd
added direnv dir to gitignore
mustafab0 Oct 23, 2025
c9ba547
xarm_driver initial design and message setup
mustafab0 Oct 23, 2025
5a69033
added custom messages for robot state and joint commands
mustafab0 Oct 24, 2025
0b1ac16
simple rt xarm driver running
mustafab0 Oct 24, 2025
f97b495
added a simple interactive position and velocity trajectory generative
mustafab0 Oct 24, 2025
50fc3e2
updated readme and spec.py based on the current implementation of the…
mustafab0 Oct 24, 2025
306826f
refactored xarm driver with mixins
mustafab0 Oct 24, 2025
1e328f1
reduced velocity controller timeout
mustafab0 Oct 24, 2025
c9258b7
fixed race issue when changing modes
mustafab0 Oct 24, 2025
1d8a1a4
disabled debug logging
mustafab0 Oct 24, 2025
8170a78
disabled position command publsihing and enabled velocity command pub…
mustafab0 Oct 24, 2025
036ec3b
extended robot state variables
mustafab0 Oct 25, 2025
b66ddb7
addded error code interpreter
mustafab0 Oct 25, 2025
6d13205
added all api calls as rpc calls
mustafab0 Oct 25, 2025
8fa51be
udated readme
mustafab0 Oct 25, 2025
16c2ef1
with error recovery
mustafab0 Oct 25, 2025
46af817
test files to test w/ hw and w/o hw
mustafab0 Oct 27, 2025
cce7f72
addressed PR comments
mustafab0 Nov 18, 2025
1c0f9f5
replaced num of joints to arm type
mustafab0 Nov 16, 2025
fcdcd45
modified readme for adding multicast
mustafab0 Nov 16, 2025
1b2b56c
CI code cleanup
mustafab0 Nov 18, 2025
9d2c9e5
Made the xArm SDK import lazy to fix CI test failures and Updated all…
mustafab0 Nov 19, 2025
a940ff0
Use xarm_driver from aa108b14 with base from 11b7c9b0, reverted to 2 …
mustafab0 Nov 19, 2025
4b3d60a
removed subscription management as module already does it
mustafab0 Nov 19, 2025
3862c16
removed running booolean onlu using thread safe threading event
mustafab0 Nov 20, 2025
dab26e8
fix imports
paul-nechifor Nov 19, 2025
e7392b8
ruff/mypy fixes
paul-nechifor Nov 19, 2025
4fbc086
fixed conflict markers after rebase
mustafab0 Dec 2, 2025
af203e1
Fix typing.List derecation
mustafab0 Dec 2, 2025
fc81c91
added xarm sdk to pyproject.toml
mustafab0 Dec 2, 2025
4b13f18
Merge remote-tracking branch 'origin/dev' into xarm-rt-driver
mustafab0 Dec 2, 2025
839d98a
Fix xArm SDK returning 7 joints for xarm6 (including gripper)
mustafab0 Dec 2, 2025
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ __pycache__/
*venv*/
.venv*/
.ssh/
.direnv/

# Ignore python tooling dirs
*.egg-info/
Expand Down
149 changes: 149 additions & 0 deletions dimos/hardware/manipulators/xarm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# xArm Driver for dimos

Real-time driver for UFACTORY xArm5/6/7 manipulators integrated with the dimos framework.

## Quick Start

### 1. Specify Robot IP

**On boot** (Important)
```bash
sudo ifconfig lo multicast
sudo route add -net 224.0.0.0 netmask 240.0.0.0 dev lo
```

**Option A: Command-line argument** (recommended)
```bash
python test_xarm_driver.py --ip 192.168.1.235
python interactive_control.py --ip 192.168.1.235
Comment on lines +17 to +18
Copy link
Contributor

Choose a reason for hiding this comment

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

It would be nice to have a blueprint for these commands. Picking up arguments from environment variables or CLI is supported.

```

**Option B: Environment variable**
```bash
export XARM_IP=192.168.1.235
python test_xarm_driver.py
```

**Option C: Use default** (192.168.1.235)
```bash
python test_xarm_driver.py # Uses default
```

**Note:** Command-line `--ip` takes precedence over `XARM_IP` environment variable.

### 2. Basic Usage

```python
from dimos import core
from dimos.hardware.manipulators.xarm.xarm_driver import XArmDriver
from dimos.msgs.sensor_msgs import JointState, JointCommand

# Start dimos and deploy driver
dimos = core.start(1)
xarm = dimos.deploy(XArmDriver, ip_address="192.168.1.235", xarm_type="xarm6")

# Configure LCM transports
xarm.joint_state.transport = core.LCMTransport("/xarm/joint_states", JointState)
xarm.joint_position_command.transport = core.LCMTransport("/xarm/joint_commands", JointCommand)

# Start and enable servo mode
xarm.start()
xarm.enable_servo_mode()

# Control via RPC
xarm.set_joint_angles([0, 0, 0, 0, 0, 0], speed=50, mvacc=100, mvtime=0)

# Cleanup
xarm.stop()
dimos.stop()
```

## Key Features

- **100Hz control loop** for real-time position/velocity control
- **LCM pub/sub** for distributed system integration
- **RPC methods** for direct hardware control
- **Position mode** (radians) and **velocity mode** (deg/s)
- **Component-based API**: motion, kinematics, system, gripper control

## Topics

**Subscribed:**
- `/xarm/joint_position_command` - JointCommand (positions in radians)
- `/xarm/joint_velocity_command` - JointCommand (velocities in deg/s)

**Published:**
- `/xarm/joint_states` - JointState (100Hz)
- `/xarm/robot_state` - RobotState (10Hz)
- `/xarm/ft_ext`, `/xarm/ft_raw` - WrenchStamped (force/torque)

## Common RPC Methods

```python
# System control
xarm.enable_servo_mode() # Enable position control (mode 1)
xarm.enable_velocity_control_mode() # Enable velocity control (mode 4)
xarm.motion_enable(True) # Enable motors
xarm.clean_error() # Clear errors

# Motion control
xarm.set_joint_angles([...], speed=50, mvacc=100, mvtime=0)
xarm.set_servo_angle(joint_id=5, angle=0.5, speed=50)

# State queries
state = xarm.get_joint_state()
position = xarm.get_position()
```

## Configuration

Key parameters for `XArmDriver`:
- `ip_address`: Robot IP (default: "192.168.1.235")
- `xarm_type`: Robot model - "xarm5", "xarm6", or "xarm7" (default: "xarm6")
- `control_frequency`: Control loop rate in Hz (default: 100.0)
- `is_radian`: Use radians vs degrees (default: True)
- `enable_on_start`: Auto-enable servo mode (default: True)
- `velocity_control`: Use velocity vs position mode (default: False)

## Testing

### With Mock Hardware (No Physical Robot)

```bash
# Unit tests with mocked xArm hardware
python tests/test_xarm_rt_driver.py
```

### With Real Hardware

**⚠️ Note:** Interactive control and hardware tests require a physical xArm connected to the network. Interactive control, and sample_trajectory_generator are part of test suite, and will be deprecated.

**Using Alfred Embodiment:**

To test with real hardware using the current Alfred embodiment:

1. **Turn on the Flowbase** (xArm controller)
2. **SSH into dimensional-cpu-2:**
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a bit overly specific to us. We should probably have internal docs somewhere else.

```
3. **Verify PC is connected to the controller:**
```bash
ping 192.168.1.235 # Should respond
```
4. **Run the interactive control:**
```bash
# Interactive control (recommended)
venv/bin/python dimos/hardware/manipulators/xarm/interactive_control.py --ip 192.168.1.235

# Run driver standalone
venv/bin/python dimos/hardware/manipulators/xarm/test_xarm_driver.py --ip 192.168.1.235

# Run automated test suite
venv/bin/python dimos/hardware/manipulators/xarm/test_xarm_driver.py --ip 192.168.1.235 --run-tests

# Specify xArm model type (if using xArm7)
venv/bin/python dimos/hardware/manipulators/xarm/interactive_control.py --ip 192.168.1.235 --type xarm7
```

## License

Copyright 2025 Dimensional Inc. - Apache License 2.0
15 changes: 15 additions & 0 deletions dimos/hardware/manipulators/xarm/components/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
"""Component classes for XArmDriver."""

from .gripper_control import GripperControlComponent
from .kinematics import KinematicsComponent
from .motion_control import MotionControlComponent
from .state_queries import StateQueryComponent
from .system_control import SystemControlComponent

__all__ = [
"GripperControlComponent",
"KinematicsComponent",
"MotionControlComponent",
"StateQueryComponent",
"SystemControlComponent",
]
Loading
Loading