xwm.envs¶
A Franka Emika FR3 arm in Newton, observed as pixels or as a 20-D proprioceptive state, with a dense reach reward. Needs the newton extra.
Simulated environments with real dynamics.
Distinct from xwm.data, which generates synthetic arrays in pure JAX.
Everything here wraps an external simulator, carries optional heavy
dependencies, and lives outside the jit boundary.
Modules:
| Name | Description |
|---|---|
discretize |
Turning a continuous action space into a discrete one. |
newton_franka |
A Franka arm in Newton, as a source of action-labelled video. |
render |
Two rendering paths, for two different jobs. |
Classes:
| Name | Description |
|---|---|
FrankaConfig |
Simulation and rendering settings. |
FrankaEnv |
A Franka FR3 arm with RGB observations and joint-space actions. |
HighQualityRenderer |
Render or export a trajectory with Newton's high-quality viewers. |
Functions:
| Name | Description |
|---|---|
discrete_action_table |
|
franka_sequences |
Collect an action-labelled video dataset from |
smooth_actions |
|
look_at_angles |
|
supersample |
Box-downsample a |
which_backends |
Which rendering backends are usable here. |
FrankaConfig
¶
FrankaConfig(image_size: int = 64, action_scale: float = 0.25, fps: int = 30, substeps: int = 16, joint_armature: float = 0.1, target_ke: float = 800.0, target_kd: float = 40.0, pose_noise: float = 0.35, goal: tuple[float, float, float] = (0.3, 0.15, 0.55), action_penalty: float = 0.01, camera_distance: float = 1.15, camera_height: float = 0.65, camera_target_height: float = 0.45, camera_fov_degrees: float = 60.0, enable_shadows: bool = False, enable_textures: bool = False, solver: str = 'auto', asset_name: str = 'franka_emika_panda', urdf_relative_path: str = 'urdf/fr3_franka_hand.urdf')
Simulation and rendering settings.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
image_size
|
int
|
square observation resolution. CPU raytracing cost grows with the pixel count, so 64 is a sensible default for training. |
64
|
action_scale
|
float
|
radians of joint-target change per unit action. Large enough that one step is visible in the image, which matters: if a single step barely changes the observation, "predict no change" becomes a near-perfect baseline and the benchmark is vacuous. |
0.25
|
fps
|
int
|
control rate. |
30
|
substeps
|
int
|
physics substeps per control step. What matters is the
resulting |
16
|
joint_armature
|
float
|
added rotor inertia. The single most important stabiliser here -- without it the solver produces NaNs. |
0.1
|
target_ke, target_kd
|
joint position-servo gains. The defaults were chosen so the arm holds its commanded pose (~0.007 rad of drift over 12 idle steps) while a commanded sweep still moves the tool ~0.65 m. Both halves matter: a servo too weak and the model learns gravity instead of the action; too stiff and the solver diverges. |
required | |
pose_noise
|
float
|
radians of uniform noise on the initial pose at reset, which is what gives the dataset its variety. |
0.35
|
enable_shadows, enable_textures
|
raytracing quality. Both cost render time, which is why they are off by default on CPU; on a GPU they are close to free and they add real information to the image -- shading disambiguates depth, and texture distinguishes links that are otherwise identically white. |
required | |
solver
|
str
|
|
'auto'
|
FrankaEnv
¶
FrankaEnv(config: FrankaConfig | None = None, *, urdf_path: str | Path | None = None)
A Franka FR3 arm with RGB observations and joint-space actions.
Example
Attributes:
| Name | Type | Description |
|---|---|---|
config |
the |
|
model |
the underlying |
Methods:
| Name | Description |
|---|---|
reset |
Reset to a randomly perturbed home pose. Returns the observation. |
step |
Apply one control step. Returns the resulting observation. |
observe |
Render the current state to |
render |
Render at any resolution, |
joint_positions |
|
body_positions |
|
tool_position |
|
state_observation |
|
is_finite |
Whether the simulation is still numerically healthy. |
high_quality_renderer |
A |
goal_distance |
Metres from the tool to the goal. Ground truth, for evaluation. |
reward |
Dense reach reward in roughly |
rollout |
Execute an action sequence from a fresh reset. |
Source code in xwm/envs/newton_franka.py
camera_framing
¶
(eye, target) in world metres, shared by every renderer.
One definition so that a path-traced figure and the observations the model trains on show the same view from the same place.
reset
¶
Reset to a randomly perturbed home pose. Returns the observation.
Source code in xwm/envs/newton_franka.py
step
¶
Apply one control step. Returns the resulting observation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
action
|
ndarray
|
|
required |
Source code in xwm/envs/newton_franka.py
observe
¶
Render the current state to (3, H, W) float32 in [0, 1].
Uses config.image_size -- the resolution the model is trained on.
render
¶
Render at any resolution, (3, size, size) float32 in [0, 1].
Pass a larger size for figures: upscaling a training frame turns
every pixel into a block and adds no detail, while the raytracer will
render at whatever resolution you ask for.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
size
|
int | None
|
output resolution. Defaults to |
None
|
samples
|
int
|
supersampling factor. The Warp raytracer casts one ray per
pixel, so silhouettes and shadow boundaries come out as hard
staircases; rendering at |
1
|
For photorealistic output -- soft shadows, ambient occlusion, materials --
see xwm.envs.HighQualityRenderer, which drives Newton's OVRTX
path tracer or exports a USD stage.
Source code in xwm/envs/newton_franka.py
joint_positions
¶
(7,) arm joint angles. For evaluation -- the model never sees these.
body_positions
¶
tool_position
¶
state_observation
¶
(20,) proprioceptive observation: joints, velocities, tool, goal delta.
The cheap alternative to pixels. TD-MPC2 and MuZero on state converge in minutes rather than hours, which makes them testable; swap in an image encoder once the pipeline is known to work.
Source code in xwm/envs/newton_franka.py
is_finite
¶
high_quality_renderer
¶
A xwm.envs.HighQualityRenderer bound to this environment's model.
Feed it simulation states as the episode runs::
with env.high_quality_renderer(backend="usd",
output_path="episode.usd") as renderer:
env.reset(seed=0)
for action in actions:
env.step(action)
renderer.add(env.state)
Source code in xwm/envs/newton_franka.py
goal_distance
¶
reward
¶
Dense reach reward in roughly [-1, 0], minus an action penalty.
-tanh(distance) rather than -distance: a bounded reward keeps the
value function inside the categorical head's bin range without per-task
tuning, and its gradient does not vanish far from the goal the way a
squared distance's does.
Source code in xwm/envs/newton_franka.py
rollout
¶
Execute an action sequence from a fresh reset.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
actions
|
ndarray
|
|
required |
Returns:
| Type | Description |
|---|---|
dict[str, ndarray]
|
``{"video": (T + 1, 3, H, W), "joint_q": (T + 1, 7), |
dict[str, ndarray]
|
"tool": (T + 1, 3)}`` -- one more observation than actions, since |
dict[str, ndarray]
|
the initial frame precedes the first action. |
Source code in xwm/envs/newton_franka.py
HighQualityRenderer
¶
HighQualityRenderer(model, *, backend: Backend = 'usd', size: tuple[int, int] = (1280, 720), output_path: str | Path | None = None, environment: str = 'studio', fps: int = 30, up_axis: str = 'Z')
Render or export a trajectory with Newton's high-quality viewers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
the |
required | |
backend
|
Backend
|
|
'usd'
|
size
|
tuple[int, int]
|
output resolution ( |
(1280, 720)
|
output_path
|
str | Path | None
|
destination stage ( |
None
|
environment
|
str
|
OVRTX lighting environment -- |
'studio'
|
fps
|
int
|
playback rate recorded in the output. |
30
|
Example
Methods:
| Name | Description |
|---|---|
set_camera |
Forwarded to the viewer, where supported. |
look_at |
Aim the camera from |
add |
Record one simulation state as a frame. |
close |
Finish the output. Returns the written path for |
Attributes:
| Name | Type | Description |
|---|---|---|
frames |
ndarray
|
Captured frames as |
Source code in xwm/envs/render.py
frames
¶
Captured frames as (T, 3, H, W) float32 -- the "rtx" path only.
Feeds xwm.plots.save_gif and xwm.plots.plot_frames
directly, so a path-traced episode is written exactly like a Warp one.
set_camera
¶
look_at
¶
Aim the camera from eye at target, both in world metres.
Without this the path-traced view points at the horizon while the
training camera looks at the arm, and the two renders are not of the
same scene. See look_at_angles for the conversion.
Source code in xwm/envs/render.py
add
¶
Record one simulation state as a frame.
Source code in xwm/envs/render.py
discrete_action_table
¶
discrete_action_table(action_dim: int, *, magnitude: float = 1.0, include_noop: bool = True) -> ndarray
(n_actions, action_dim) table of axis-aligned moves.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
action_dim
|
int
|
number of continuous action dimensions. |
required |
magnitude
|
float
|
how far each move pushes its dimension. |
1.0
|
include_noop
|
bool
|
add an all-zeros action. Worth keeping: without it the agent cannot choose to stay put, which on a reach task means it can never stop once it arrives. |
True
|
Returns:
| Type | Description |
|---|---|
ndarray
|
|
Source code in xwm/envs/discretize.py
franka_sequences
¶
franka_sequences(env: FrankaEnv, n_sequences: int, length: int, *, seed: int = 0, smoothness: float = 0.7, progress_every: int = 0) -> dict[str, ndarray]
Collect an action-labelled video dataset from env.
The returned dict matches what xwm.action.ActionWorldModel expects,
so it is a drop-in replacement for xwm.data.sprite_sequences:
video:(n, length, 3, H, W)action:(n, length - 1, 7)--action[i, t]joins framestandt + 1joint_q:(n, length, 7)ground truth, for probestool:(n, length, 3)ground-truth hand position, for probes
Diverged rollouts (NaN from the solver) are discarded and resampled, so the dataset never contains a corrupt sequence.
Source code in xwm/envs/newton_franka.py
smooth_actions
¶
smooth_actions(rng: Generator, n_sequences: int, length: int, action_dim: int, *, smoothness: float = 0.7) -> ndarray
(n, length, action_dim) temporally correlated actions in [-1, 1].
White noise makes an arm jitter in place and go nowhere; an AR(1) process produces trajectories that actually sweep through the workspace.
Source code in xwm/envs/newton_franka.py
look_at_angles
¶
(pitch, yaw) in degrees for a viewer camera at eye facing target.
Newton's viewer camera is parameterised by position, pitch and yaw rather
than by a look-at target. For a Z-up scene its forward vector is
(cos yaw cos pitch, sin yaw cos pitch, sin pitch), which inverts to
pitch = asin(dz) and yaw = atan2(dy, dx); the other two up-axes
permute which components play those roles. Deriving the angles beats
guessing them -- a camera aimed at the horizon puts the robot in a handful
of pixels, which is a figure of nothing.
Source code in xwm/envs/render.py
supersample
¶
Box-downsample a (3, H*f, W*f) frame by factor.
Rendering above the target resolution and averaging down is the cheapest
anti-aliasing there is, and the Warp raytracer has no built-in
multisampling: one ray per pixel means every silhouette is a hard staircase.
At factor=3 each output pixel integrates nine rays, which is enough to
make edges and shadow boundaries read as smooth.
Source code in xwm/envs/render.py
which_backends
¶
Which rendering backends are usable here.
Worth calling before a long run: discovering that the high-quality path is unavailable after four hours of simulation is a poor use of a GPU.