> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cadenzalabs.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Gym adapter

> Step a robot through a reset/step loop with GymAdapter.

`GymAdapter` exposes the simulator as a Gym-style `reset()` / `step()` loop, the
natural interface for driving a robot from a policy. It speaks `ActionCall` in
and `Observation` out.

```mermaid theme={null}
flowchart LR
    RESET["reset()"] --> OBS0[Observation]
    OBS0 --> POLICY[your policy]
    POLICY -->|ActionCall| STEP["step(call)"]
    STEP --> SIM[Sim · physics]
    SIM --> OBS["(Observation, info)"]
    OBS --> POLICY
    POLICY -->|done| CLOSE["close()"]
```

```python theme={null}
import cadenza_lab as cadenza
from cadenza_lab import ActionCall

env = cadenza.GymAdapter(robot="go1", headless=True)
obs = env.reset()

for _ in range(20):
    obs, info = env.step(ActionCall("walk_forward", distance_m=0.5))
    if not env.is_open:           # property, not a method
        break

env.close()
```

## Constructor

```python theme={null}
GymAdapter(robot, *, xml_path=None, scene=None, headless=False,
           render_camera=False, cam_distance=0.0, cam_elevation=-15.0,
           cam_azimuth=270.0, max_action_seconds=30.0)
```

| Param                | Description                                              |
| -------------------- | -------------------------------------------------------- |
| `robot`              | `"go1"` or `"g1"`.                                       |
| `scene`              | An optional [`Scene`](/sdk/simulation-and-scenes#scene). |
| `headless`           | `True` to run without a viewer (CI-safe).                |
| `render_camera`      | Populate `Observation.camera` each step.                 |
| `max_action_seconds` | Per-action wall-clock cap.                               |

## Methods

| Method                                  | Returns                     | Description                                           |
| --------------------------------------- | --------------------------- | ----------------------------------------------------- |
| `reset()`                               | `Observation`               | Reset to the start state.                             |
| `step(call)`                            | `(Observation, info: dict)` | Execute one `ActionCall`.                             |
| `add_box / add_slope / add_sphere(...)` | `GymAdapter`                | Add geometry before `reset()` (same args as `Scene`). |
| `clear_scene()`                         | None                        | Remove added geometry.                                |
| `is_open`                               | `bool`                      | **Property.** Whether the viewer/sim is still open.   |
| `close()`                               | None                        | Shut down the sim/viewer.                             |

<Note>
  Scene geometry is baked at `reset()`. Add boxes/slopes/spheres **before** the
  first `reset()` (or call `reset()` again after changing the scene).
</Note>

<Warning>
  `GymAdapter.step()` returns `(Observation, info)`, **not** the 5-tuple Gym
  returns. For the standard `(obs, reward, terminated, truncated, info)` loop tied
  to a CLI mission, use [`CustomEnv`](/sdk/custom-environments).
</Warning>

## `ActionCall`

The action passed to `step()`. Parameterizes a named action.

```python theme={null}
ActionCall(action_name, speed=1.0, extension=1.0, repeat=1,
           distance_m=0.0, rotation_rad=0.0, duration_s=0.0,
           speed_override=0.0, height_override=0.0)
```

| Field                                             | Description                                                         |
| ------------------------------------------------- | ------------------------------------------------------------------- |
| `action_name`                                     | A base action, e.g. `"walk_forward"` (see [Actions](/sdk/actions)). |
| `distance_m`                                      | Target distance for locomotion actions.                             |
| `rotation_rad`                                    | Target rotation for turn actions.                                   |
| `speed`, `extension`, `repeat`                    | Gait/scale modifiers.                                               |
| `duration_s`, `speed_override`, `height_override` | Fine-grained overrides.                                             |

## `Observation`

Returned by `reset()` / `step()`.

| Attribute                          | Description                                                                          |
| ---------------------------------- | ------------------------------------------------------------------------------------ |
| `pos`, `rpy`, `body_height`        | Base pose (numpy arrays / float).                                                    |
| `qpos`, `qvel`                     | Full generalized position / velocity.                                                |
| `foot_contacts`                    | Tuple of per-foot ground contact bools.                                              |
| `terrain_ahead`, `obstacles_ahead` | Raycast sensing dicts (see [Simulation](/sdk/simulation-and-scenes#state--sensing)). |
| `camera`                           | RGB frame, shape `(224, 224, 3)` (when `render_camera=True`).                        |
| `depth`                            | Depth frame.                                                                         |
| `to_dict()`                        | Serialize the observation to a plain dict.                                           |

## Demo: drive a scene through a Gym loop

```python theme={null}
"""demo_gym.py: headless reset/step loop with obstacles + camera (CI-safe)."""
import cadenza_lab as cadenza
from cadenza_lab import ActionCall

env = cadenza.GymAdapter(robot="go1", headless=True, render_camera=True)
env.add_box(position=(-1.2, 0.0, 0.08), size=(0.15, 0.15, 0.08))
env.add_slope(position=(-2.5, 0.0, 0.0), size=(0.6, 0.6, 0.05), angle_deg=12)

obs = env.reset()
print("start:", obs.pos.round(2), "camera:", obs.camera.shape)

plan = [
    ActionCall("walk_forward", distance_m=0.6),
    ActionCall("turn_left", rotation_rad=0.8),
    ActionCall("walk_forward", distance_m=0.6),
    ActionCall("sit"),
]
for call in plan:
    obs, info = env.step(call)
    print(f"{call.action_name:<14} moved={info['moved_m']:.2f}  ok={info['ok']}")
    if not env.is_open:
        break

env.close()
```

```bash theme={null}
python demo_gym.py
```
