Make Environment#

An IR-SIM simulation is created from a YAML scenario file with irsim.make() and driven by a short Python loop (env.step()env.render()env.done()). This page covers building the environment, the core loop, status control, dynamic object management, and running multiple environments.

Python script and YAML configuration file#

To start the simulation, you need to create an environment. The environment is a container for all the objects in the simulation. It is also responsible for updating the state of the simulation at each time step.

Create your environment with a simple Python script:

import irsim

env = irsim.make('empty_world.yaml')

The make function creates an environment from a configuration file. Supported parameters include:

  • world_name (str, optional): Path to the world YAML configuration file

  • projection (str, optional): Projection type (“3d” for 3D environment, None for 2D)

  • display (bool): Whether to display the environment visualization (default: True)

  • save_ani (bool): Whether to save the simulation as an animation (default: False)

  • log_level (str): Logging level for the environment (default: “INFO”)

  • seed (int, optional): Seed for IR-SIM’s project RNG. If provided, random elements produced by IR-SIM become reproducible. If omitted/None, a new unseeded generator is used (non-reproducible). Custom extensions using np.random or Python random should either switch to IR-SIM’s RNG or be seeded separately.

For more details, see the EnvBase class documentation.

Define your world properties in a YAML file (empty_world.yaml):

world:
  height: 10  # the height of the world (meters)
  width: 10   # the width of the world (meters)
  step_time: 0.1  # simulation time step (seconds) - 10Hz
  sample_time: 0.1  # rendering frequency (seconds) - 10Hz
  offset: [0, 0] # the offset of the world origin [x, y]
  control_mode: 'auto' # control mode: 'auto', 'keyboard'
  collision_mode: 'stop' # collision behavior: 'stop', 'unobstructed', 'unobstructed_obstacles'
  obstacle_map: null # path to obstacle map file (optional)

The configuration file is a YAML file that specifies the properties of the environment. The empty_world.yaml file is a simple configuration file that creates an empty environment.

Important Parameters Explanation#

World Configuration#

  • world: Main section that defines the simulation environment properties

  • height and width: Specify the size of the simulation world in meters

  • step_time: Controls simulation accuracy and speed (smaller = more accurate, slower)

  • sample_time: Controls rendering frequency (larger = faster simulation, less smooth visualization)

  • offset: Shifts the world coordinate system origin [x, y] in meters

  • control_mode: Determines how the simulation is controlled

    • 'auto': Automatic simulation execution

    • 'keyboard': Manual keyboard control

  • collision_mode: Defines collision detection behavior

    • 'stop': Stop simulation when collision occurs (default)

    • 'unobstructed': Ignore all collisions

    • 'unobstructed_obstacles': Ignore only obstacle collisions

  • obstacle_map: Optional. Path to an obstacle map image, or a generator spec (e.g. { name: perlin, ... }). See Configure grid map.

Performance Considerations#

  • Smaller step_time: More accurate physics but slower simulation

  • Larger sample_time: Faster simulation but less smooth visualization

  • World size: Larger worlds require more computational resources

Tip

You can use sample_time to control the rendering frequency and accelerate the simulation speed. The default value of sample_time is the same as step_time.

For more detailed parameter information, see the YAML Configuration reference.

Tip

Automatic Configuration Detection: The default YAML configuration file has the same name as your Python script. For example, if you create a script named test.py, IR-SIM automatically looks for test.yaml in the same directory.

import irsim

# Automatically uses 'test.yaml' if this file is 'test.py'
env = irsim.make()

This feature simplifies development by eliminating the need to specify configuration files explicitly.

Basic Simulation Loop#

After creating an environment, you’ll typically run a simulation loop:

import irsim

env = irsim.make('config.yaml')

# Main simulation loop
for i in range(1000):
    env.step()        # Update simulation state
    env.render(0.05)  # Render with 0.05 second interval (20Hz)
    
    if env.done():    # Check if simulation should end
        break

env.end()  # Clean up resources

Core Methods Explained#

  • env.step(): Advances the simulation by one time step

  • env.render(interval): Updates the visualization with specified time interval between frames

  • env.done(): Returns True if simulation completion conditions are met

  • env.reset(random=False): Restores objects to their initial states. With random=True, rebuilds the world from the cached YAML parse so any randomized elements (e.g. distribution: random, random shape generators) are re-sampled from the current RNG state — use together with irsim.util.random.set_seed(seed) for reproducible fresh scenes. The YAML file on disk is not re-read; to pick up on-disk edits, use env.reload() instead.

  • env.refresh(): Refreshes state-derived attributes (geometry, sensor readings, collision tree, and status) without advancing the simulation. Useful after mutating object states directly (e.g. robot.set_state(...)) when you need sensors and collisions brought up to date before the next env.step().

  • env.reload(world_name=None): Re-parses the YAML file (optionally a different one) and rebuilds world/objects.

  • env.end(): Properly closes the environment and releases resources

  • env.close(): Alias for env.end(), provided for Gym-style API compatibility

Tip

Update order

The environment advances all objects first, then updates all sensors. This two-phase update ensures sensors read the latest world state consistently. If you step objects manually, either pass sensor_step=True to ObjectBase.step(...) or call obj.sensor_step() after updating states.

Environment Control and Status#

Status Management#

import irsim

env = irsim.make('config.yaml')

# Check current status
print(f"Current status: {env.status}")
print(f"Current time: {env.time}")

# Control simulation state
env.pause()    # Pause the simulation
env.resume()   # Resume the simulation

# Simulation loop with status checking
for i in range(50):
    env.step()
    env.render(0.05)

    if i < 10:
        env.pause()
    elif i > 20 and i < 30:
        env.resume()
    
    if env.status == "Pause":
        print("Environment is paused")
    
    if env.done():
        print("Simulation completed successfully")

env.end()

Available Status Values#

  • "Running": The environment is running in auto control mode

  • "Running (keyboard)": The environment is running in keyboard control mode

  • "Pause": Simulation is paused

  • "Done": Simulation has completed

  • "Arrived": All robots have arrived at their goals

  • "Collision": A collision has occurred

  • "Pause (Debugging)": Debugging mode (when F5 key is pressed)

  • "Reset": The environment is reset

  • "Reload": The environment is reloaded

  • "Save Figure": The figure is saved

  • "Quit": The environment is quit

Configure Environment Title#

By default, the simulation time and status are shown in the environment title. You can customize this behavior by setting the show_title and customizing the title by env.set_title().

import irsim

env = irsim.make('config.yaml')

# Set custom title
env.set_title("Multi-Robot Navigation Simulation")

# Update title dynamically
for i in range(100):
    env.step()
    
    # Update title every 10 steps
    if i % 10 == 0:
        env.set_title(f"Simulation Step: {i}")
    
    env.render(0.05)

env.end()
world:
  height: 20
  width: 20
  control_mode: 'auto'
  plot:
    show_title: true    # Show title with time and status
    show_axis: true     # Optional: show axis labels

Dynamic Object Management#

In addition to defining objects in YAML configuration files, you can create and add objects programmatically at runtime. This is useful for spawning objects dynamically during simulation, such as generating random obstacles or adding robots on-the-fly.

Creating Objects Programmatically#

Use env.create_robot() and env.create_obstacle() to create objects with keyword arguments:

import irsim

env = irsim.make('empty_world.yaml')

# Create a differential-drive robot
robot = env.create_robot(
    kinematics={"name": "diff"},
    shape={"name": "circle", "radius": 0.2},
    state=[1, 1, 0],
    goal=[8, 8, 0],
    name="robot_0",
)

# Create a static circular obstacle
obstacle = env.create_obstacle(
    shape={"name": "circle", "radius": 0.5},
    state=[5, 5, 0],
    name="obs_0",
)

Common keyword arguments include:

  • kinematics (dict): Kinematics model, e.g. {"name": "diff"}, {"name": "omni"}, {"name": "acker"}. Omit or use {"name": "static"} for static objects.

  • shape (dict): Shape definition, e.g. {"name": "circle", "radius": 0.5} or {"name": "polygon", "vertices": [[0,0],[1,0],[0,1]]}.

  • state (list): Initial state [x, y, theta, ...].

  • goal (list): Goal state [x, y, theta, ...].

  • color (str): Object color (default varies by kinematics type).

  • name (str): Unique object name. Must not conflict with existing objects.

  • goal_threshold (float): Distance threshold for arrival detection (default: 0.1).

For the full list of parameters, see the ObjectBase class documentation.

Adding Objects to the Environment#

After creating objects, add them to the environment with env.add_object() or env.add_objects():

# Add a single object
env.add_object(robot)

# Add multiple objects at once
env.add_objects([obstacle])

Each object must have a unique name. Adding an object with a duplicate name raises a ValueError.

Multiple Environments#

IR-SIM supports creating and running multiple environments simultaneously. Each environment maintains its own isolated state, including world parameters, objects, and simulation time. This is useful for:

  • Parallel simulations: Running multiple scenarios simultaneously

  • Comparison studies: Comparing different algorithms or configurations

  • Training: Running multiple instances for reinforcement learning

Creating Multiple Environments#

import irsim

# Create two separate environments
env1 = irsim.make('scenario_a.yaml')
env2 = irsim.make('scenario_b.yaml')

# Each environment has its own state
print(f"Env1 robots: {env1.robot_number}")
print(f"Env2 robots: {env2.robot_number}")

Isolated Parameters#

Each environment has completely separate parameter instances:

import irsim

env1 = irsim.make('world1.yaml')
env2 = irsim.make('world2.yaml')

# World parameters are isolated
env1.world_param.control_mode = 'keyboard'
print(f"Env1 control mode: {env1.world_param.control_mode}")  # keyboard
print(f"Env2 control mode: {env2.world_param.control_mode}")  # auto (unchanged)

# Simulation time is independent
for _ in range(10):
    env1.step()

for _ in range(5):
    env2.step()

print(f"Env1 time: {env1.time}")  # 1.0 (10 steps * 0.1)
print(f"Env2 time: {env2.time}")  # 0.5 (5 steps * 0.1)

Running Multiple Environments#

import irsim

env1 = irsim.make('scenario_a.yaml', display=True)
env2 = irsim.make('scenario_b.yaml', display=True)

# Run both environments in the same loop
for i in range(500):
    # Step both environments
    env1.step()
    env2.step()

    # Render both (creates two windows)
    env1.render(0.01)
    env2.render(0.01)

    # Check completion independently
    if env1.done() and env2.done():
        break

env1.end()
env2.end()
import irsim

# Create multiple headless environments for training
num_envs = 4
envs = [
    irsim.make(f'training_world.yaml', display=False, seed=i)
    for i in range(num_envs)
]

# Run training loop
for episode in range(100):
    # Reset all environments
    for env in envs:
        env.reset()

    # Collect experiences from all environments
    for step in range(1000):
        actions = [get_action(env) for env in envs]  # Your policy

        for env, action in zip(envs, actions):
            env.step(action)

        # Check if any environment is done
        if all(env.done() for env in envs):
            break

# Clean up
for env in envs:
    env.end()

Parameter Isolation Details#

Each environment instance creates and binds its own parameter objects:

world_param - Simulation state and settings:

Attribute

Type

Default

Description

time

float

0.0

Current simulation time

control_mode

str

"auto"

Control mode ("auto" or "keyboard")

collision_mode

str

"stop"

Collision handling mode

step_time

float

0.1

Time step duration (seconds)

count

int

0

Simulation step counter

env_param - Environment objects and utilities:

Attribute

Type

Description

objects

list[ObjectBase]

List of all objects in the environment

logger

EnvLogger

Logger instance for this environment

GeometryTree

STRtree

Spatial index for collision detection

platform_name

str

Operating system name

path_param - File path management:

Attribute

Type

Description

root_path

str

Path to irsim package directory

ani_buffer_path

str

Path for animation frame buffer

ani_path

str

Path for saved animations

fig_path

str

Path for saved figures

Objects within each environment reference their own environment’s parameters:

Note

When creating multiple environments with display=True, each environment opens its own visualization window. For training or batch simulations, use display=False to disable rendering and improve performance.