MolmoSpaces Adapter¶
Wraps MolmoSpaces as llenvs MDP environments. MolmoSpaces is a large-scale robot manipulation and navigation research platform built on MuJoCo. It provides 8 benchmark tasks (pick, place, navigate, open/close, etc.) with multi-view cameras, proprioceptive sensors, and continuous robot control.
The adapter provides temporal abstraction: each llenvs step() = one high-level VLM decision, executed over many physics steps by MolmoSpaces' IK solver and low-level controller.
Installation¶
MolmoSpaces requires MuJoCo. See the MolmoSpaces repository for full installation instructions.
Quick Start¶
from llenvs.adapters.molmospaces import MolmoSpacesAdapter
adapter = MolmoSpacesAdapter()
env = adapter.get_environment("molmospaces:pick", max_steps=30)
state, info = env.reset(options={"task_index": 0})
print(state.observation.prompt) # Task instruction + proprioception
print(len(state.observation.images)) # 2 (front + wrist cameras)
print([t.name for t in state.observation.available_tools])
# ['move_end_effector', 'grasp', 'release']
from llenvs.core import Action
from llenvs.core.tools import ToolCall
# Move the end-effector to the object
call = ToolCall(id="c1", name="move_end_effector", arguments={"x": 0.5, "y": 0.1, "z": 0.3})
result = env.step(state, Action(tool_calls=(call,)))
# Grasp the object
call = ToolCall(id="c2", name="grasp", arguments={})
result = env.step(result.next_state, Action(tool_calls=(call,)))
With Evaluation Runner¶
from llenvs.evaluation.runner import run_tool_evaluation
result = run_tool_evaluation(
environment=env,
backend=backend,
task_indices=list(range(50)),
)
print(f"Success rate: {result.success_rate}")
Robot Control Tools¶
The VLM interacts with the robot through function-calling tools. Each tool call triggers many internal physics steps.
| Tool | Parameters | Description |
|---|---|---|
move_end_effector |
x, y, z, qw?, qx?, qy?, qz? | Move end-effector via IK solver |
grasp |
(none) | Close gripper |
release |
(none) | Open gripper |
navigate_to |
x, y | Move robot base (mobile robots only) |
set_joints |
positions (array) | Direct joint control (joint controller only) |
navigate_to is only available for mobile robots (e.g., RBY1). set_joints is only available when controller_type="joint".
Tool Execution¶
Each tool call is executed through MolmoSpaces' IK solver and controller:
move_end_effector→ IK solver computes joint targets → controller steps physics until convergencegrasp/release→ gripper actuated directlynavigate_to→ base controller steps physics to target positionset_joints→ controller steps physics to target joint positions
The max_physics_steps_per_action parameter (default: 200) limits the physics budget per tool call.
Observation Space¶
Each observation includes:
- Multi-view camera images: RGB images from configurable cameras (default: front + wrist)
- Depth images (optional): Depth maps from each camera
- Proprioception (optional): End-effector position/orientation, gripper state, joint positions as text
- Task instruction: Natural language description of the task
# Configure observations
env = adapter.get_environment(
"molmospaces:pick",
cameras=("front", "wrist", "overhead"),
image_format="jpeg",
image_quality=80,
include_proprioception=True,
include_depth=True,
)
Camera Configuration¶
| Parameter | Type | Default | Description |
|---|---|---|---|
cameras |
tuple[str, ...] |
("front", "wrist") |
Camera views to render |
image_format |
str |
"jpeg" |
"jpeg" or "png" |
image_quality |
int |
80 |
JPEG quality (1-100) |
include_depth |
bool |
False |
Include depth maps as additional images |
JPEG is the default since robot camera images are natural photos where JPEG compression is efficient.
Task Presets¶
| Task | Max Steps | Description |
|---|---|---|
navigate-to |
20 | Navigate the robot base to a target location |
pick |
30 | Pick up a specified object |
pick-and-place |
40 | Pick up an object and place it at a target |
pick-and-place-next-to |
40 | Pick up an object and place it next to another |
pick-and-place-color |
40 | Pick up a color-specified object and place it |
open |
30 | Open a container or drawer |
close |
30 | Close a container or drawer |
open-door |
30 | Open a door by manipulating its handle |
Rewards¶
Native Reward¶
MolmoSpacesReward wraps task.get_reward(). Uses STEP type for intermediate dense rewards and OUTCOME type at terminal steps.
Success Reward (opt-in)¶
MolmoSpacesSuccessReward provides binary 0/1 from task.judge_success(). OUTCOME type, only at terminal. Available via extra_rewards:
from llenvs.adapters.molmospaces import MolmoSpacesSuccessReward
env = adapter.get_environment(
"molmospaces:pick",
extra_rewards=(MolmoSpacesSuccessReward(),),
)
Controller Configuration¶
| Parameter | Type | Default | Description |
|---|---|---|---|
controller_type |
str |
"ik" |
"ik" or "joint" |
robot_type |
str |
"franka" |
"franka" (stationary) or "rby1" (mobile) |
max_physics_steps_per_action |
int |
200 |
Physics step budget per tool call |
is_mobile |
bool |
False |
Auto-set from robot_type |
# Mobile robot with joint control
env = adapter.get_environment(
"molmospaces:navigate-to",
robot_type="rby1", # auto-enables is_mobile
controller_type="joint", # enables set_joints tool
)
Container Deployment¶
MolmoSpaces requires MuJoCo and GPU rendering. For isolated deployment:
from llenvs.container import create_container_environment, ContainerConfig
config = ContainerConfig(
runtime="docker",
image="molmospaces-env:latest", # custom image with MuJoCo + GPU support
port=8080,
)
env = create_container_environment(env_config, container_config=config)
Parameters¶
MolmoSpacesAdapter.get_environment()¶
| Parameter | Type | Description |
|---|---|---|
name |
str |
"molmospaces:<task>" (e.g., "molmospaces:pick") |
molmospaces_env |
Any \| None |
Pre-created MolmoSpaces environment |
tasks |
list \| None |
Pre-loaded task list |
robot |
Any \| None |
Pre-created robot instance |
ik_solver |
Any \| None |
Pre-created IK solver |
controller |
Any \| None |
Pre-created controller |
cameras |
tuple[str, ...] |
Camera names to render |
image_format |
str |
Image format ("jpeg" or "png") |
image_quality |
int |
JPEG quality |
include_proprioception |
bool |
Include robot state as text |
include_depth |
bool |
Include depth images |
max_steps |
int \| None |
Max high-level steps |
max_physics_steps_per_action |
int |
Physics budget per tool call |
robot_type |
str |
"franka" or "rby1" |
controller_type |
str |
"ik" or "joint" |
extra_rewards |
tuple[RewardFunction, ...] |
Additional reward functions |
Environment Capabilities¶
| Feature | Supported |
|---|---|
__len__ |
Yes |
task_index |
Yes |
seed |
Yes |
compute_rewards |
Yes (dense + success) |
pure_step |
No (MuJoCo state) |
| Tool calling | Yes (IK + controller) |
| Multi-image | Yes (configurable cameras) |
| Depth images | Yes (optional) |
| Proprioception | Yes (optional text) |
Scorer / DatasetProvider |
No (multi-turn) |
Hidden State¶
MolmoSpacesHidden contains:
| Field | Type | Description |
|---|---|---|
task_index |
int |
Task index |
task_name |
str |
Task name |
episode_step |
int |
High-level step count |
physics_steps |
int |
Total physics steps this episode |
last_action |
str \| None |
Last tool action name |
ee_position |
tuple[float, ...] |
End-effector position |
ee_orientation |
tuple[float, ...] |
End-effector orientation (quaternion) |
gripper_state |
str |
"open" or "closed" |
joint_positions |
tuple[float, ...] |
Current joint angles |
cumulative_reward |
float |
Cumulative episode reward |
task_instruction |
str |
Natural language instruction |
success |
bool |
Task completion status |
Limitations¶
- Requires MuJoCo: MolmoSpaces depends on MuJoCo for physics simulation
- GPU rendering: Camera rendering benefits from GPU acceleration
- Non-pure step: MuJoCo state is mutable; environments use
_StateContinuityTracker - Temporal abstraction: Each high-level step may execute hundreds of physics steps; IK failures result in tool errors
- No native answer extraction: Robot manipulation uses tool-action evaluation