# Manipulator Bring Ball

Bring Ball is a classic Manipulator task from the DeepMind Control Suite. A planar hand with a thumb and finger must grasp a ball and move it to a target ball position. MotrixLab currently provides one Bring Ball environment:

-   `dm-manipulator-bring-ball`: grasp the ball and move it to the target position

```{video} /_static/videos/bring-ball.mp4
:poster: _static/images/poster/bring-ball.jpg
:nocontrols:
:autoplay:
:playsinline:
:muted:
:loop:
:width: 100%
```

---

## Task Description

Bring Ball is a planar (x-z) grasp-and-transport task:

-   The hand has 4 arm joints (`arm_root`, `arm_shoulder`, `arm_elbow`, `arm_wrist`) plus thumb/finger joints
-   Grasping is driven by the `grasp` tendon, coupling the `thumb` and `finger` joints
-   The ball can slide in the plane (`ball_x`, `ball_z`) and rotate about the y-axis (`ball_y`)
-   The target ball is a mocap body, sampled at reset

---

## Action Space

| Item          | Details                         |
| ------------- | ------------------------------- |
| **Type**      | `Box(-1.0, 1.0, (5,), float32)` |
| **Dimension** | 5                               |

Actions correspond to the following actuators:

| Index | Action Meaning                     | Min Control | Max Control |  XML Name  |
| ----: | ---------------------------------- | :---------: | :---------: | :--------: |
|     0 | Root joint drive                   |     -1      |      1      |   `root`   |
|     1 | Shoulder joint drive               |     -1      |      1      | `shoulder` |
|     2 | Elbow joint drive                  |     -1      |      1      |  `elbow`   |
|     3 | Wrist joint drive                  |     -1      |      1      |  `wrist`   |
|     4 | Grasp drive (thumb/finger coupled) |     -1      |      1      |  `grasp`   |

---

## Observation Space

| Item          | Details                          |
| ------------- | -------------------------------- |
| **Type**      | `Box(-inf, inf, (41,), float32)` |
| **Dimension** | 41                               |

The observation vector is composed of the following parts (in order):

| Part           | Content Description           | Dim | Notes                                |
| -------------- | ----------------------------- | --- | ------------------------------------ |
| **arm_pos**    | `sin`/`cos` of 8 joint angles | 16  | Joint order listed below             |
| **arm_vel**    | 8 joint velocities            | 8   | Same order as arm_pos                |
| **touch**      | `log(1 + touch)` sensors      | 5   | palm/finger/thumb/fingertip/thumbtip |
| **hand_pos**   | Grasp site world position     | 3   | x, y, z                              |
| **object_pos** | Ball position                 | 3   | x, y, z                              |
| **target_pos** | Target ball position          | 3   | x, y, z                              |
| **rel**        | `object_pos - target_pos`     | 3   | Relative position                    |

| Index | Observation Range                               | Dim | Notes                             |
| ----- | ----------------------------------------------- | --- | --------------------------------- |
| 0-15  | `sin`/`cos` of 8 joint angles                   | 16  | Joint order: arm_root -> thumbtip |
| 16-23 | 8 joint velocities                              | 8   | Same order as above               |
| 24-28 | Touch: palm, finger, thumb, fingertip, thumbtip | 5   | `log(1 + touch)`                  |
| 29-31 | Grasp position (x, y, z)                        | 3   | hand_pos                          |
| 32-34 | Ball position (x, y, z)                         | 3   | object_pos                        |
| 35-37 | Target ball position (x, y, z)                  | 3   | target_pos                        |
| 38-40 | Ball relative position (x, y, z)                | 3   | rel                               |

Joint order: `arm_root`, `arm_shoulder`, `arm_elbow`, `arm_wrist`, `finger`, `fingertip`, `thumb`, `thumbtip`.

---

## Reward Function Design

Bring Ball uses shaped rewards with multiple components and penalties:

```python
# R1: Reach - fingertips approach the ball
r_reach = tolerance(avg_tip_dist)

# R2: Orient - palm points toward the ball
r_orient = clip(1 - orient_bound + dot(hand_dir, unit_vec_to_ball), 0..1)

# R3: Pause - reduce arm jitter when close to the ball
r_pause = tolerance(arm_speed_step) * is_close_to_ball

# R4: Close - grasp intent and contact together
r_close = r_close_intent * (approach_or_grasp)

# R5: Lift & Transport - height and target distance
r_lift_height = tolerance(ball_z)
r_transport = tolerance(move_dist_to_target)
r_lift = mix(r_lift_height, r_transport)

# Precision/Progress
r_precision = tolerance(move_dist_to_target, gaussian)
r_progress = (prev_dist - curr_dist) * scale

# Penalties
penalty_side + penalty_hover
```

Default weights (from `BringBallCfg`):

-   reach 1.0, orient 1.5, pause 0.5, close 2.0, lift 6.0, precision 1.0
-   lift mixes `lift_height_weight` and `transport_weight`
-   progress reward is controlled by `transport_progress_scale`

---

## Initial State

-   **Arm initialization**: uses the default model pose (`randomize_arm=False`), thumb/finger are symmetric
-   **Target position**: `x in [-0.4, 0.4]`, `z in [0.1, 0.4]`, `y = 0.001`
-   **Ball position**: `x in [-0.4, 0.4]`, `z in [0.2, 0.7]`, with a minimum hand distance
-   **Physics settling**: performs settle steps after reset (`settle_steps=300`)

---

## Episode Termination Conditions

-   Terminate if any `NaN` appears in observations

---

## Usage Guide

### 1. Environment Preview (random actions)

```bash
uv run scripts/view.py --env dm-manipulator-bring-ball
```

### 2. Start Training

```bash
uv run scripts/train.py --env dm-manipulator-bring-ball --train-backend torch
```

### 3. View Training Progress

```bash
uv run tensorboard --logdir runs/dm-manipulator-bring-ball
```

### 4. Test Training Results

```bash
uv run scripts/play.py --env dm-manipulator-bring-ball
```

---

## Expected Training Results

1. The hand consistently reaches and grasps the ball
2. The ball is lifted off the ground and held at a stable height
3. The ball is reliably moved close to the target ball position
