Variable Morphology
jax-evogym supports two mechanisms for varying robot morphology:
robot_override— swap the robot’s body within a fixed template frame- Dense grid pipeline — build simulation data from scratch in pure JAX, vmap-able across populations
robot_override
Section titled “robot_override”Compile a template once, then instantiate it with different morphologies:
import numpy as npfrom jax_evogym import ( EvoWorld, FIXED, H_ACT, SOFT, V_ACT, CONTRACTILE, EMPTY, RIGID, compile_world_template, instantiate_world,)
# Compile onceworld = EvoWorld()world.add_from_array("ground", np.array([[FIXED, FIXED, FIXED, FIXED]]), 0, 0)world.add_from_array("robot", np.array([[H_ACT, SOFT, V_ACT]]), 1, 2)template = compile_world_template(world, robot_name="robot")
# Instantiate with different bodiesdense = np.array([[H_ACT, SOFT, V_ACT]])sparse = np.array([[H_ACT, EMPTY, V_ACT]])
dense_built = instantiate_world(template, robot_override=dense)sparse_built = instantiate_world(template, robot_override=sparse)- Override shape must match the robot template grid exactly
- Same array orientation as
add_from_array EMPTYdisables cells within the frame- Any dynamic voxel type is allowed (
RIGID,SOFT,H_ACT,V_ACT,CONTRACTILE) - Slope values are rejected
- Terrain objects are never affected
With mirroring
Section titled “With mirroring”instantiate_world does not auto-mirror robot_override. Pass the override explicitly to each template:
from jax_evogym import compile_world_templates
template_set = compile_world_templates(world, robot_name="robot", mirror_mode="paired")
built_primary = instantiate_world(template_set.primary, robot_override=body)built_mirror = instantiate_world(template_set.mirror, robot_override=body)If you want a truly mirrored body, construct the mirrored array yourself.
Dense grid pipeline
Section titled “Dense grid pipeline”For evolutionary search where you need to evaluate thousands of morphologies in parallel, the dense grid pipeline provides pure JAX, vmap-able construction:
from jax_evogym import precompute_grid, jax_build_sim_state, jax_build_collision_data
# 1. Precompute grid infrastructure (once per grid size)grid_data = precompute_grid(H=5, W=5)
# 2. Build simulation data (pure JAX, vmap-able)sim_state = jax_build_sim_state(body_array, grid_data)collision_data = jax_build_collision_data(body_array, grid_data)See Dense Grid Pipeline for the full guide.
When to use which
Section titled “When to use which”| Scenario | Use |
|---|---|
| Standard environment usage | Built-in environments (handle everything internally) |
| Fixed terrain, varying robot body | robot_override on a compiled template |
| Terrain with multiple objects | Object-separated build (compile_world_template) |
| Population-level morphology search with vmap | Dense grid pipeline |
| Custom terrain + custom morphology | Build the EvoWorld programmatically, compile, instantiate |