Skip to content

hylo-env-mujoco

Hylo MuJoCo environment adapter and task set

Repository hylo-bench, adapters/hylo-env-mujoco. Licence: Apache-2.0. Depends on: hylo-core, mujoco>=3.1.

Registered entry points
Group Name Object
benchmarks mujoco/reach-v0 hylo.envs.mujoco.planar_reach:mujoco_benchmark
benchmarks mujoco/table-v0 hylo.envs.mujoco.table_reach:table_benchmark
envs mujoco.planar_reach hylo.envs.mujoco.planar_reach:PlanarReachEnv
envs mujoco.table_reach hylo.envs.mujoco.table_reach:TableReachEnv
Module Summary
hylo.envs.mujoco MuJoCo environments for Hylo
hylo.envs.mujoco.planar_reach MuJoCo planar 2-link arm reaching task. Environment + Task logic are ours; MuJoCo is only the
hylo.envs.mujoco.table_reach MuJoCo table-top reaching with language, occlusion and disturbances

hylo.envs.mujoco

MuJoCo environments for Hylo.

META module-attribute

META = {'contracts': {'envs': 'hylo.env/v0.1', 'benchmarks': 'hylo.benchmark/v0.1'}, 'maturity': 'implemented'}

hylo.envs.mujoco.planar_reach

MuJoCo planar 2-link arm reaching task. Environment + Task logic are ours; MuJoCo is only the Simulator (it has no env/task/seed concepts of its own; see our research notes).

MAX_JOINT_STEP module-attribute

MAX_JOINT_STEP = 0.05

SUCCESS_RADIUS module-attribute

SUCCESS_RADIUS = 0.02

MJCF module-attribute

MJCF = f'\n<mujoco model="planar_reach">\n  <compiler angle="radian"/>  <!-- MJCF defaults to degrees for joint ranges -->\n  <option timestep="0.01" integrator="implicitfast"/>\n  <worldbody>\n    <body name="link1">\n      <joint name="j1" type="hinge" axis="0 0 1" damping="0.5"/>\n      <geom type="capsule" fromto="0 0 0 {L1} 0 0" size="0.02" mass="0.5"/>\n      <body name="link2" pos="{L1} 0 0">\n        <joint name="j2" type="hinge" axis="0 0 1" damping="0.5" limited="true" range="-2.8 2.8"/>\n        <geom type="capsule" fromto="0 0 0 {L2} 0 0" size="0.02" mass="0.3"/>\n        <site name="tip" pos="{L2} 0 0" size="0.01"/>\n      </body>\n    </body>\n    <site name="target" pos="0.3 0.2 0" size="0.02" rgba="1 0 0 1"/>\n  </worldbody>\n  <actuator>\n    <position name="a1" joint="j1" kp="20"/>\n    <position name="a2" joint="j2" kp="20" ctrllimited="true" ctrlrange="-2.8 2.8"/>\n  </actuator>\n</mujoco>\n'

RSI_SEED_OFFSET module-attribute

RSI_SEED_OFFSET = 30000

PlanarReachEnv

PlanarReachEnv(control_hz: float = 20.0)

model instance-attribute

model = mujoco.MjModel.from_xml_string(MJCF)

data instance-attribute

data = mujoco.MjData(self.model)

control_hz instance-attribute

control_hz = control_hz

n_substeps instance-attribute

n_substeps = max(1, round(1.0 / (control_hz * self.model.opt.timestep)))

spec

spec() -> EnvSpec

reset

reset(task: TaskInstance) -> Observation

step

step(action: Action) -> StepResult

privileged_state

privileged_state() -> dict

snapshot

snapshot() -> bytes

restore

restore(blob: bytes) -> None

close

close() -> None

mujoco_tasks

mujoco_tasks() -> tuple[TaskSpec, ...]

splits_for

splits_for(protocol: str, train: int, validation: int, heldout: int, rsi_states: int = 100, gate_looks: int = 1) -> dict[str, tuple[int, ...]]

protocol "standard": train / validation / heldout. protocol "rsi": search / search_val / gate / heldout (RFC-0002, 40 / 20 / 20 / 20 percent of rsi_states seeds) for improvement campaigns.

mujoco_benchmark

mujoco_benchmark(train: int = 5, validation: int = 10, heldout: int = 10, protocol: str = 'standard', rsi_states: int = 100, gate_looks: int = 1)

hylo.envs.mujoco.table_reach

MuJoCo table-top reaching with language, occlusion and disturbances.

A planar 2-link arm over a table with three coloured pads. Each episode samples pad colours and positions, a target pad, and a natural-language instruction (direct: "touch the red pad", or indirect: "touch the pad the colour of a ripe tomato"). Pads are only observable for the first visible_steps steps; afterwards the agent must rely on memory. Optionally the arm is pushed.

Task logic (init distribution, instruction, success / failure predicates) lives here; MuJoCo is the Simulator. Success = fingertip dwells on the target pad; touching another pad long enough fails.

MAX_JOINT_STEP module-attribute

MAX_JOINT_STEP = 0.05

N_PADS module-attribute

N_PADS = 3

PAD_RADIUS module-attribute

PAD_RADIUS = 0.035

CAMERA_SIZE module-attribute

CAMERA_SIZE = 384

PALETTE module-attribute

PALETTE: dict[str, tuple[float, float, float]] = {'red': (0.85, 0.1, 0.1), 'green': (0.1, 0.7, 0.2), 'blue': (0.15, 0.35, 0.9), 'yellow': (0.95, 0.85, 0.1), 'purple': (0.55, 0.2, 0.75), 'orange': (0.95, 0.5, 0.1)}

DIRECT module-attribute

DIRECT = ['touch the {c} pad', 'move your fingertip onto the {c} pad', 'go to the {c} marker']

INDIRECT module-attribute

INDIRECT = {'red': 'touch the pad that is the colour of a ripe tomato', 'green': 'touch the pad that is the colour of fresh grass', 'blue': 'touch the pad that is the colour of a clear daytime sky', 'yellow': 'touch the pad that is the colour of a ripe banana', 'purple': 'touch the pad that is the colour of an eggplant', 'orange': 'touch the pad that is the colour of a pumpkin'}

MJCF module-attribute

MJCF = f'\n<mujoco model="table_reach">\n  <compiler angle="radian"/>\n  <option timestep="0.01" integrator="implicitfast" gravity="0 0 0"/>\n  <visual>\n    <global offwidth="960" offheight="720"/>\n    <headlight ambient="0.3 0.3 0.3" diffuse="0.35 0.35 0.35" specular="0.05 0.05 0.05"/>\n    <quality shadowsize="4096"/>\n  </visual>\n  <asset>\n    <texture name="sky" type="skybox" builtin="gradient" rgb1="0.80 0.86 0.92" rgb2="0.30 0.36 0.44" width="512" height="3072"/>\n    <texture name="wood" type="2d" builtin="flat" rgb1="0.80 0.72 0.60" rgb2="0.74 0.66 0.54" mark="random" random="0.08" width="512" height="512"/>\n    <material name="table" texture="wood" texrepeat="3 3" reflectance="0.04" specular="0.1"/>\n    <material name="floor" rgba="0.55 0.57 0.60 1" reflectance="0.0"/>\n    <material name="arm" rgba="0.22 0.24 0.28 1" specular="0.6" shininess="0.6"/>\n  </asset>\n  <worldbody>\n    <light directional="true" pos="0.6 -0.8 2.5" dir="-0.25 0.35 -1" diffuse="0.55 0.55 0.55" specular="0.1 0.1 0.1" castshadow="true"/>\n    <light directional="true" pos="-0.8 0.6 2.0" dir="0.3 -0.2 -1" diffuse="0.2 0.2 0.22" castshadow="false"/>\n    <camera name="top" pos="0 0 1.45" xyaxes="1 0 0 0 1 0" fovy="50"/>\n    <camera name="front" pos="0 -0.92 1.0" xyaxes="1 0 0 0 0.74 0.67" fovy="48"/>\n    <geom name="floor" type="plane" size="3 3 0.1" pos="0 0 -0.75" material="floor" contype="0" conaffinity="0"/>\n    <geom name="table" type="box" size="0.65 0.65 0.02" pos="0 0 -0.022" material="table" contype="0" conaffinity="0"/>\n    <geom name="table_leg" type="box" size="0.55 0.55 0.36" pos="0 0 -0.4" rgba="0.35 0.30 0.25 1" contype="0" conaffinity="0"/>\n{_PADS_XML}\n    <body name="base" pos="0 0 0.03">\n      <geom type="cylinder" size="0.04 0.03" rgba="0.2 0.2 0.25 1" contype="0" conaffinity="0"/>\n      <body name="link1" pos="0 0 0.03">\n        <joint name="j1" type="hinge" axis="0 0 1" damping="0.5"/>\n        <geom type="capsule" fromto="0 0 0 {L1} 0 0" size="0.022" material="arm" mass="0.5"/>\n        <body name="link2" pos="{L1} 0 0">\n          <joint name="j2" type="hinge" axis="0 0 1" damping="0.5" limited="true" range="-2.8 2.8"/>\n          <geom type="capsule" fromto="0 0 0 {L2} 0 0" size="0.019" rgba="0.42 0.45 0.50 1" mass="0.3"/>\n          <geom type="sphere" pos="{L2} 0 0" size="0.022" rgba="0.95 0.95 0.95 1" contype="0" conaffinity="0" mass="0"/>  <!-- visual only: no inertia -->\n          <site name="tip" pos="{L2} 0 0" size="0.012" rgba="1 1 1 1"/>\n        </body>\n      </body>\n    </body>\n  </worldbody>\n  <actuator>\n    <position name="a1" joint="j1" kp="20"/>\n    <position name="a2" joint="j2" kp="20" ctrllimited="true" ctrlrange="-2.8 2.8"/>\n  </actuator>\n</mujoco>\n'

TableReachEnv

TableReachEnv(control_hz: float = 20.0)

model instance-attribute

model = mujoco.MjModel.from_xml_string(MJCF)

data instance-attribute

data = mujoco.MjData(self.model)

control_hz instance-attribute

control_hz = control_hz

n_substeps instance-attribute

n_substeps = max(1, round(1.0 / (control_hz * self.model.opt.timestep)))

visible property

visible: bool

spec

spec() -> EnvSpec

reset

reset(task: TaskInstance) -> Observation

camera_params

camera_params(camera: str, width: int, height: int) -> dict

Pinhole parameters so consumers can project world points into the image (MuJoCo cameras look along -z).

step

step(action: Action) -> StepResult

privileged_state

privileged_state() -> dict

render

render(camera: str = 'front', width: int = 640, height: int = 480) -> np.ndarray

Requires an OpenGL backend (MUJOCO_GL=egl or osmesa).

close

close() -> None

table_tasks

table_tasks() -> tuple[TaskSpec, ...]

table_benchmark

table_benchmark(tags: list[str] | None = None, train: int = 10, validation: int = 20, heldout: int = 20, vision: bool = False, protocol: str = 'standard', rsi_states: int = 100, gate_looks: int = 1)

vision=True adds a top-camera image to observations while pads are visible (needs MuJoCo rendering). Task ids stay the same so results pair with the state-only variant seed by seed.