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.
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
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. |
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. |
Scene geometry is baked at reset(). Add boxes/slopes/spheres before the
first reset() (or call reset() again after changing the scene).
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.
ActionCall
The action passed to step(). Parameterizes a named action.
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). |
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). |
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
"""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()