Skip to content
Merged
Show file tree
Hide file tree
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
5 changes: 4 additions & 1 deletion docs/.vitepress/config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default defineConfig({
{ text: 'Get Started', link: '/getting-started/installation' },
{ text: 'SDK', link: '/sdk/' },
{ text: 'Examples', link: '/examples/' },
{ text: 'Releases', link: '/releases/v1.0' },
{ text: 'Releases', link: '/releases/v1.1' },
{ text: 'i2rt.com', link: 'https://i2rt.com', target: '_blank' },
],

Expand Down Expand Up @@ -93,13 +93,16 @@ export default defineConfig({
{ text: 'Record & Replay', link: '/examples/record-replay' },
{ text: 'Motor Control', link: '/examples/motor-control' },
{ text: 'MuJoCo Control', link: '/examples/control-with-mujoco' },
{ text: 'Viser Control', link: '/examples/control-with-viser' },
{ text: 'Minimum Gello', link: '/examples/minimum-gello' },
],
},
],
'/releases/': [
{
text: 'Release Notes',
items: [
{ text: 'v1.1', link: '/releases/v1.1' },
{ text: 'v1.0', link: '/releases/v1.0' },
],
},
Expand Down
18 changes: 14 additions & 4 deletions docs/examples/control-with-mujoco.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

Interactive MuJoCo viewer for i2rt robots. Visualises the robot in real time and lets you move it by dragging a target marker via inverse kinematics — no hardware required in simulation mode.

The control loop runs in a background thread, performs self-collision detection (commands that would self-collide are blocked), and applies gravity compensation when running on real hardware. Pass `--log` to print joint state and torques every loop iteration.

## Hardware Required

- None for simulation (`--sim` flag)
Expand Down Expand Up @@ -34,6 +36,12 @@ python examples/control_with_mujoco/control_with_mujoco.py --arm big_yam --gripp

# Arm only, no gripper
python examples/control_with_mujoco/control_with_mujoco.py --arm yam --gripper no_gripper --sim

# Soft-tip gripper, no arm (gripper-only test rig)
python examples/control_with_mujoco/control_with_mujoco.py --arm no_arm --gripper flexible_4310 --sim

# Stream joint state + torques to the terminal each loop iteration
python examples/control_with_mujoco/control_with_mujoco.py --sim --log
```

### Real Hardware
Expand All @@ -47,12 +55,13 @@ python examples/control_with_mujoco/control_with_mujoco.py --arm big_yam --gripp

| Argument | Default | Description |
|----------|---------|-------------|
| `--arm` | `yam` | Arm type: `yam`, `yam_pro`, `yam_ultra`, `big_yam` |
| `--gripper` | `linear_4310` | Gripper: `linear_4310`, `linear_3507`, `crank_4310`, `yam_teaching_handle`, `no_gripper` |
| `--arm` | `yam` | Arm type: `yam`, `yam_pro`, `yam_ultra`, `big_yam`, `no_arm` |
| `--gripper` | `linear_4310` | Gripper: `linear_4310`, `linear_3507`, `crank_4310`, `flexible_4310`, `yam_teaching_handle`, `no_gripper` |
| `--channel` | `can0` | CAN interface name (real hardware only) |
| `--sim` | off | Use simulation instead of real hardware |
| `--dt` | `0.02` | Control loop timestep in seconds |
| `--site` | `grasp_site` | MuJoCo site name used as end-effector |
| `--site` | auto | MuJoCo site name used as end-effector. Auto-detects `grasp_site` (or `tcp_site` for `yam_teaching_handle`) when omitted. |
| `--log` | off | Log joint state and torques each loop iteration |

## Viewer Controls

Expand All @@ -68,7 +77,8 @@ All YAM-family arm × gripper combinations are supported:

| Arm | Grippers |
|-----|---------|
| `yam` | `linear_4310`, `linear_3507`, `crank_4310`, `yam_teaching_handle`, `no_gripper` |
| `yam` | `linear_4310`, `linear_3507`, `crank_4310`, `flexible_4310`, `yam_teaching_handle`, `no_gripper` |
| `yam_pro` | same as yam |
| `yam_ultra` | same as yam |
| `big_yam` | same as yam |
| `no_arm` | any gripper except `no_gripper` (gripper-only test rig) |
96 changes: 96 additions & 0 deletions docs/examples/control-with-viser.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Viser Control Interface

**Location:** `examples/control_with_viser/`

Browser-based 3-D viewer and teleop interface for i2rt robots, powered by [viser](https://github.com/nerfstudio-project/viser). Open the viewer in any browser — no native viewer required, no display attached to the robot.

## Hardware Required

- None for simulation (`--sim` flag)
- 1× YAM / YAM Pro / YAM Ultra / big_yam arm + CANable adapter for real hardware

## Overview

The interface starts in **read-only mode**. The robot accepts no commands until the operator visually confirms alignment and clicks **Enable Robot**. Once enabled, three control modes are available:

```
VIS mode (default):
Robot joint states ──► Browser viewer (read-only mirror)

IK mode:
Drag transform gizmo ──► mink IK solver ──► Command arm

Joint-slider mode:
Per-joint sliders (deg) ──► Command arm directly
```

A gripper slider (normalised 0–1) is always available, independent of the arm mode.

## Running

### Simulation

```bash
# YAM arm + linear_4310 gripper (default)
python examples/control_with_viser/control_with_viser.py --sim

# big_yam arm with the soft-tip gripper
python examples/control_with_viser/control_with_viser.py --arm big_yam --gripper flexible_4310 --sim

# Custom port (multiple instances on one machine)
python examples/control_with_viser/control_with_viser.py --sim --port 8090
```

### Real Hardware

```bash
python examples/control_with_viser/control_with_viser.py --channel can0
python examples/control_with_viser/control_with_viser.py --arm big_yam --gripper linear_4310 --channel can0
```

Open `http://localhost:8080` (or whichever `--port` you chose) in your browser.

## Arguments

| Argument | Default | Description |
|----------|---------|-------------|
| `--arm` | `yam` | Arm type: `yam`, `yam_pro`, `yam_ultra`, `big_yam`, `no_arm` |
| `--gripper` | `linear_4310` | Gripper: `linear_4310`, `linear_3507`, `crank_4310`, `flexible_4310`, `yam_teaching_handle`, `no_gripper` |
| `--channel` | `can0` | CAN interface name (real hardware only) |
| `--sim` | off | Use simulation instead of real hardware |
| `--dt` | `0.02` | Control loop timestep in seconds |
| `--port` | `8080` | Viser server port |
| `--site` | auto | EE site name. Auto-detects `grasp_site` (or `tcp_site` for `yam_teaching_handle`) when omitted. |

## Enabling the Robot

1. Open the viewer URL printed on launch.
2. Verify the rendered pose matches the physical robot.
3. Tick **Alignment Confirmed**.
4. Click **Enable Robot**.

The robot only starts responding to slider / IK input after step 4.

## Teaching-Handle Indicators

When running with `--gripper yam_teaching_handle`, two on-screen LEDs mirror the leader-arm buttons:

- **SYNC** — top button, latches arm-sync on/off.
- **RECORD** — second button, user-programmable (commonly bound to recording).

## MuJoCo vs Viser

| Feature | MuJoCo | Viser |
|---------|--------|-------|
| Display | Native window | Browser (any client) |
| Multi-user | Local only | Multiple browsers can connect to one server |
| IK target | Drag in 3-D scene | Drag transform gizmo |
| Per-joint sliders | Yes (CONTROL mode) | Yes (Joint-slider mode) |
| Safety gate | None | Read-only until "Enable Robot" |
| Best for | Local debugging | Remote / headless robot, browser-only setups |

## See Also

- [MuJoCo Control Interface](/examples/control-with-mujoco)
- [Minimum Gello](/examples/minimum-gello)
- [YAM Arm API](/sdk/yam-arm)
12 changes: 4 additions & 8 deletions docs/examples/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,12 @@ All examples live in the [`examples/`](https://github.com/i2rt-robotics/i2rt/tre

| Example | Hardware Needed | Complexity |
|---------|----------------|------------|
| [Bimanual Teleoperation](/examples/bimanual-teleoperation) | 4 YAM arms + 4 CANable | Intermediate |
| [Record & Replay Trajectory](/examples/record-replay) | 1+ YAM arm | Beginner |
| [Minimum Gello](/examples/minimum-gello) | 1+ YAM arm (or sim) | Beginner |
| [Single Motor PD Control](/examples/motor-control) | 1 DM motor | Beginner |
| [Record & Replay Trajectory](/examples/record-replay) | 1+ YAM arm | Beginner |
| [MuJoCo Control Interface](/examples/control-with-mujoco) | None (sim) / 1 YAM arm | Beginner |

::: tip More examples
Additional examples in the repository (not yet documented here):
- `examples/control_with_viser/` — Web-based robot visualization with Viser
- `examples/minimum_gello/` — Core leader-follower teleoperation script
:::
| [Viser Control Interface](/examples/control-with-viser) | None (sim) / 1 YAM arm | Beginner |
| [Bimanual Teleoperation](/examples/bimanual-teleoperation) | 4 YAM arms + 4 CANable | Intermediate |

## Running an Example

Expand Down
87 changes: 87 additions & 0 deletions docs/examples/minimum-gello.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Minimum Gello (Teleoperation)

**Location:** `examples/minimum_gello/`

The minimal leader–follower teleoperation script. Supports any YAM-family arm + gripper assembly, simulation mode, and local or remote visualization. This is the foundation that [Bimanual Teleoperation](/examples/bimanual-teleoperation) builds on.

## Hardware Required

- None for simulation (`--sim` flag, follower-only).
- Single-arm teleoperation: 1× YAM follower + 1× YAM leader (with `yam_teaching_handle`) + 2× CANable adapters.
- Visualizer-only: 1× YAM arm or sim.

## Modes

| Mode | What it does |
|------|--------------|
| `follower` *(default)* | Drives the local robot from commands received over a portal server. Used as the receiving side in a leader→follower pair. |
| `leader` | Reads a local teaching handle and sends commands to a remote follower. **Requires real hardware** — `--sim` is not supported in leader mode. |
| `visualizer_local` | MuJoCo viewer mirrors the local robot's live state. No motion is commanded. |
| `visualizer_remote` | MuJoCo viewer mirrors a remote robot's state via the portal server. |

## Quick Start

```bash
# Follower (default) on real hardware
python examples/minimum_gello/minimum_gello.py --can-channel can0

# Follower in simulation — no hardware required
python examples/minimum_gello/minimum_gello.py --sim

# Live MuJoCo viewer for the local robot
python examples/minimum_gello/minimum_gello.py --mode visualizer_local

# Try a different arm + gripper combination in sim
python examples/minimum_gello/minimum_gello.py --arm big_yam --gripper linear_4310 --sim
python examples/minimum_gello/minimum_gello.py --arm yam_pro --gripper flexible_4310 --sim
```

## Leader → Follower Setup

Run the follower on one terminal (or machine):

```bash
python examples/minimum_gello/minimum_gello.py \
--gripper linear_4310 --mode follower --can-channel can0
```

Run the leader on another (separate CAN bus, real hardware only):

```bash
python examples/minimum_gello/minimum_gello.py \
--gripper yam_teaching_handle --mode leader --can-channel can1 --bilateral-kp 0.2
```

Press **button 0** on the teaching handle to sync the leader to the follower. Press again to desync.

::: tip Bilateral force feedback
`--bilateral-kp` (default 0.0) controls how much the follower's load is reflected back to the leader. Try 0.1–0.3 to feel object weight; values >0.3 can feel sluggish.
:::

## Arguments

| Flag | Default | Description |
|------|---------|-------------|
| `--arm` | `yam` | Arm type: `yam`, `yam_pro`, `yam_ultra`, `big_yam`, `no_arm` |
| `--gripper` | `yam_teaching_handle` | Gripper: `crank_4310`, `linear_3507`, `linear_4310`, `flexible_4310`, `yam_teaching_handle`, `no_gripper` |
| `--mode` | `follower` | Operation mode (see table above) |
| `--sim` | off | Use `SimRobot` instead of real hardware (follower / visualizer only) |
| `--can-channel` | `can0` | CAN interface name |
| `--server-host` | `localhost` | Portal server host (used by leader / remote visualizer) |
| `--server-port` | `11333` | Portal server port |
| `--bilateral-kp` | `0.0` | Bilateral force feedback gain (leader mode) |
| `--ee-mass` | model default | Override end-effector mass (kg) for gravity comp |

## Overriding Handle Weight

3-D-printed teaching handles vary in mass. The default model assumes 0.258 kg. If your handle is heavier or lighter, pass `--ee-mass` so gravity compensation matches the real hardware:

```bash
python examples/minimum_gello/minimum_gello.py --ee-mass 0.350 --can-channel can0
```

## See Also

- [Bimanual Teleoperation](/examples/bimanual-teleoperation) — extends this script to four arms.
- [YAM Arm API](/sdk/yam-arm) — programmatic equivalent of `--arm` / `--gripper`.
- [Viser Control Interface](/examples/control-with-viser) — browser-based alternative to MuJoCo visualizer mode.
72 changes: 59 additions & 13 deletions docs/examples/motor-control.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,22 @@ The simplest possible example — command a single DM-series motor to a target p
## Running

```bash
python i2rt/scripts/single_motor_pd_pos_control.py --channel can0 --motor_id 1 --kd 5
python examples/single_motor_position_pd_control/single_motor_position_pd_control.py \
--channel can0 --motor_id 1 --motor_type DM4340 --kd 3
```

Common arguments:

| Argument | Default | Description |
|----------|---------|-------------|
| `--channel` | `can0` | CAN interface name |
| `--motor_id` | `1` | Motor ID on the bus (1–7 typical) |
| `--motor_type` | `DM4340` | Motor model: `DM4310`, `DM4340`, `DM6248`, `DM3507` |
| `--kp` | `80.0` | Proportional gain |
| `--kd` | `3.0` | Derivative gain |
| `--rate_hz` | `200.0` | Control loop rate |
| `--step` | `0.01` | Step size per arrow key press (rad) |

The interactive panel shows live motor state:

```
Expand Down Expand Up @@ -43,28 +56,61 @@ Controls: ←/→ move • r reset-to-current • SPACE hold • q quit

## Example Code

The example wraps a single motor in a `DMChainCanInterface` and runs a PD position loop:

```python
from i2rt.motor_drivers.dm_motor import DmMotor
from i2rt.motor_drivers.dm_driver import DMChainCanInterface

motor = DmMotor(channel="can0", motor_id=1)
motor.enable()
motor_list = [[1, "DM4340"]] # [(motor_id, motor_type), ...]
motor_directions = [1]
chain = DMChainCanInterface(
motor_list, [0], motor_directions, channel="can0", receive_mode="p16"
)

# Command position (radians) with PD gains
motor.set_position_pd(target=0.0, kp=10.0, kd=0.5)
states = chain.read_states() # current pos / vel / torque
chain.set_commands([{"pos": 0.0, "kp": 80.0, "kd": 3.0}])

import time
time.sleep(2.0)
motor.disable()
chain.close()
```

## Expected Output
## Motor Configuration Tools

One-time motor configuration utilities live in `i2rt/motor_config_tool/`. When `--motor_id` is omitted, all three commands operate on **motors 1–7** on the bus by default — pass an explicit `--motor_id N` to target a single motor.

### Ping motors

```bash
# Ping every motor on can0 (IDs 1–7)
python i2rt/motor_config_tool/ping_motors.py --channel can0

# Ping motor 3 only
python i2rt/motor_config_tool/ping_motors.py --channel can0 --motor_id 3
```
Motor 1: pos=0.0042 vel=0.0 torque=0.12
Motor 1: pos=0.0021 vel=-0.01 torque=0.08
Motor 1: pos=0.0003 vel=0.0 torque=0.02

### Zero motor offset

```bash
# Zero every motor on can0 (run with the arm in its mechanical zero pose)
python i2rt/motor_config_tool/set_zero.py --channel can0

# Zero motor 1 only
python i2rt/motor_config_tool/set_zero.py --channel can0 --motor_id 1
```

### Set safety timeout

```bash
# Disable the 400 ms motor safety timeout (default)
python i2rt/motor_config_tool/set_timeout.py --channel can0

# Re-enable the safety timeout
python i2rt/motor_config_tool/set_timeout.py --channel can0 --timeout
```

::: warning Power cycle required
After running `set_zero.py` or `set_timeout.py`, power-cycle the motor for the new configuration to take effect.
:::

## See Also

- [YAM Arm API](/sdk/yam-arm)
Expand Down
Loading
Loading