Configuration

Click and Open In Colab

A MetaDrive instance accepts a dict as the environmental config. For example, you can build a MetaDrive instance with 200 generated maps via

from metadrive import MetaDriveEnv
config = dict(num_scenarios=200, start_seed=0)
env = MetaDriveEnv(config)

In this page, we describe the details of the config system and configurable options for all environments.

Config system

This section discusses how to configure the an environment in MetaDrive and some features of the config system.

Overwriting

Every environment has a default config, which records the parameters required to launch the environment. It is content is actually a nested dictionary whose keys and values represent the parameter names and corresponding values. This default config dict can be accessed via the class method:

default_config = MetaDriveEnv.default_config()

When creating environments, the external config config will overwritten default values of certain fields in the default_config. The following code exemplifies this.

from metadrive import MetaDriveEnv
default_config = MetaDriveEnv.default_config()
env = MetaDriveEnv(dict(num_scenarios=100, log_level=50))
env_config = env.config
print("default_config['num_scenarios']:", default_config["num_scenarios"])
print("env_config['num_scenarios']:", env_config["num_scenarios"])
default_config['num_scenarios']: 1
env_config['num_scenarios']: 100

Sanity Check

There is a check mechanism which prohibit users to set the value for a key that doesn’t exist in the default_config. This is helpful to make sure that users type the correct parameter name and successfully config the target parameter.

try:
    env = MetaDriveEnv(dict(non_exist_key=False))
except KeyError as error:
    print(str(error)[:62] + " ...")
"'{'non_exist_key'}' does not exist in existing config. Please ...

The check mechanism will further ensure if the type of the parameter is correct. For example, the num_scenarios should be an int type, and thus a list type parameter will raise an error.

try:
    env = MetaDriveEnv(dict(num_scenarios=[0, 1]))
except AssertionError as error:
    print(str(error)[:62] + " ...")
TypeError: num_scenarios:[0, 1] ...

Basic Config Sharing

The default configs are different across all environments, but may share some identical fields. Take the MetaDriveEnv and ScenarioEnv as example.

from metadrive.envs import MetaDriveEnv, ScenarioEnv
metadrive_config = set(MetaDriveEnv.default_config().keys())
scenario_config = set(ScenarioEnv.default_config().keys())
print("Number of parameters of MetaDriveEnv: {}".format(len(metadrive_config)))
print("Number of parameters of ScenarioEnv: {}\n".format(len(scenario_config)))

try:
    assert metadrive_config == scenario_config
except AssertionError as error:
    print("The config between MetaDriveEnv and ScenarioEnv is different.\n")
    
identical_parameters = scenario_config.intersection(metadrive_config)
print("Number of identical parameters: \
      {}".format(len(identical_parameters)))
print("Number of unique parameters in MetaDriveEnv: \
      {}".format(len(metadrive_config-identical_parameters)))
print("Number of unique parameters in ScenarioEnv: \
      {}".format(len(scenario_config-identical_parameters)))
Number of parameters of MetaDriveEnv: 114
Number of parameters of ScenarioEnv: 125

The config between MetaDriveEnv and ScenarioEnv is different.

Number of identical parameters:       93
Number of unique parameters in MetaDriveEnv:       21
Number of unique parameters in ScenarioEnv:       32

It is worth mentioning the parameter sharing mechanism, which is helpful when we create a new environment, so we don’t need to copy some common configs to the default_config to the new environments again and again. Let’s first check out how the default_config() function is implemented.

from metadrive.utils import print_source
print_source(ScenarioEnv.default_config)
@classmethod
def default_config(cls):
    config = super(ScenarioEnv, cls).default_config()
    config.update(SCENARIO_ENV_CONFIG)
    return config

It is quite simple and is implemented by overwriting the super(ScenarioEnv, cls).default_config() with Scenario_ENV_CONFIG. If we check the contents of the two config dict, we will find that the BaseEnv.default_config() = super(ScenarioEnv, cls).default_config() is the subset of ScenarioEnv.default_config() and provides the ScenarioEnv with the basic configs.

from metadrive.envs.base_env import BaseEnv
set(BaseEnv.default_config()).issubset(set(ScenarioEnv.default_config()))
True

It is the same for the MetaDriveEnv as well, whose default config is:

print_source(MetaDriveEnv.default_config)
@classmethod
def default_config(cls) -> Config:
    config = super(MetaDriveEnv, cls).default_config()
    config.update(METADRIVE_DEFAULT_CONFIG)
    config.register_type("map", str, int)
    config["map_config"].register_type("config", None)
    return config

As there is an overwriting function is called, it is ok to overwrite the values of parameters in BaseEnv.default_config() when making the default_config for a inherited environment. The following code shows that the config show_sidewalk is True in BaseEnv but is overwritten to False in ScenarioEnv because of the SCENARIO_ENV_CONFIG.

from metadrive.envs.scenario_env import SCENARIO_ENV_CONFIG

assert BaseEnv.default_config()["show_sidewalk"]
assert not ScenarioEnv.default_config()["show_sidewalk"]
assert not SCENARIO_ENV_CONFIG["show_sidewalk"]

Programming with Configs

The configs can be accessed everywhere in the program just like the simulation engine instance, so we can use these parameters to adjust the behavior of the simulation. A tutorial of accessing configs when programming new environments is available at config.

Basic Configs

As all environments are subclass of BaseEnv and share the parameters of BaseEnv, we first discuss the parameters in BaseEnv.default_config(). The available items with annotations are listed as follows. You can check this in the source code as well.

import metadrive.envs.base_env as base_env
from metadrive.utils import print_source, CONFIG
module_source = print_source(base_env, ["BASE_DEFAULT_CONFIG", ")\n\n"], colorscheme=CONFIG)
BASE_DEFAULT_CONFIG = dict(

    # ===== agent =====
    # Whether randomize the car model for the agent, randomly choosing from 4 types of cars
    random_agent_model=False,
    # The ego config is: env_config["vehicle_config"].update(env_config"[agent_configs"]["default_agent"])
    agent_configs={DEFAULT_AGENT: dict(use_special_color=True, spawn_lane_index=None)},

    # ===== multi-agent =====
    # This should be >1 in MARL envs, or set to -1 for spawning as many vehicles as possible.
    num_agents=1,
    # Turn on this to notify the simulator that it is MARL env
    is_multi_agent=False,
    # The number of agent will be fixed adn determined at the start of the episode, if set to False
    allow_respawn=False,
    # How many substeps for the agent to stay static at the death place after done. (Default for MARL: 25)
    delay_done=0,

    # ===== Action/Control =====
    # Please see Documentation: Action and Policy for more details
    # What policy to use for controlling agents
    agent_policy=EnvInputPolicy,
    # If set to True, agent_policy will be overriden and change to ManualControlPolicy
    manual_control=False,
    # What interfaces to use for manual control, options: "steering_wheel" or "keyboard" or "xbos"
    controller="keyboard",
    # Used with EnvInputPolicy. If set to True, the env.action_space will be discrete
    discrete_action=False,
    # If True, use MultiDiscrete action space. Otherwise, use Discrete.
    use_multi_discrete=False,
    # How many discrete actions are used for steering dim
    discrete_steering_dim=5,
    # How many discrete actions are used for throttle/brake dim
    discrete_throttle_dim=5,
    # Check if the action is contained in gym.space. Usually turned off to speed up simulation
    action_check=False,

    # ===== Observation =====
    # Please see Documentation: Observation for more details
    # Whether to normalize the pixel value from 0-255 to 0-1
    norm_pixel=True,
    # The number of timesteps for stacking image observation
    stack_size=3,
    # Whether to use image observation or lidar. It takes effect in get_single_observation
    image_observation=False,
    # Like agent_policy, users can use customized observation class through this field
    agent_observation=None,

    # ===== Termination =====
    # The maximum length of each agent episode. Set to None to remove this constraint
    horizon=None,
    # If set to True, the terminated will be True as well when the length of agent episode exceeds horizon
    truncate_as_terminate=False,

    # ===== Main Camera =====
    # A True value makes the camera follow the reference line instead of the vehicle, making its movement smooth
    use_chase_camera_follow_lane=False,
    # Height of the main camera
    camera_height=2.2,
    # Distance between the camera and the vehicle. It is the distance projecting to the x-y plane.
    camera_dist=7.5,
    # Pitch of main camera. If None, this will be automatically calculated
    camera_pitch=None,  # degree
    # Smooth the camera movement
    camera_smooth=True,
    # How many frames used to smooth the camera
    camera_smooth_buffer_size=20,
    # FOV of main camera
    camera_fov=65,
    # Only available in MARL setting, choosing which agent to track. Values should be "agent0", "agent1" or so on
    prefer_track_agent=None,
    # Setting the camera position for the Top-down Camera for 3D viewer (pressing key "B" to activate it)
    top_down_camera_initial_x=0,
    top_down_camera_initial_y=0,
    top_down_camera_initial_z=200,

    # ===== Vehicle =====
    vehicle_config=dict(
        # Vehicle model. Candidates: "s", "m", "l", "xl", "default". random_agent_model makes this config invalid
        vehicle_model="default",
        # If set to True, the vehicle can go backwards with throttle/brake < -1
        enable_reverse=False,
        # Whether to show the box as navigation points
        show_navi_mark=True,
        # Whether to show a box mark at the destination
        show_dest_mark=False,
        # Whether to draw a line from current vehicle position to the designation point
        show_line_to_dest=False,
        # Whether to draw a line from current vehicle position to the next navigation point
        show_line_to_navi_mark=False,
        # Whether to draw left / right arrow in the interface to denote the navigation direction
        show_navigation_arrow=True,
        # If set to True, the vehicle will be in color green in top-down renderer or MARL setting
        use_special_color=False,
        # Clear wheel friction, so it can not move by setting steering and throttle/brake. Used for ReplayPolicy
        no_wheel_friction=False,

        # ===== image capturing =====
        # Which camera to use for image observation. It should be a sensor registered in sensor config.
        image_source="rgb_camera",

        # ===== vehicle spawn and navigation =====
        # A BaseNavigation instance. It should match the road network type.
        navigation_module=None,
        # A lane id specifies which lane to spawn this vehicle
        spawn_lane_index=None,
        # destination lane id. Required only when navigation module is not None.
        destination=None,
        # the longitudinal and lateral position on the spawn lane
        spawn_longitude=5.0,
        spawn_lateral=0.0,

        # If the following items is assigned, the vehicle will be spawn at the specified position with certain speed
        spawn_position_heading=None,
        spawn_velocity=None,  # m/s
        spawn_velocity_car_frame=False,

        # ==== others ====
        # How many cars the vehicle has overtaken. It is deprecated due to bug.
        overtake_stat=False,
        # If set to True, the default texture for the vehicle will be replaced with a pure color one.
        random_color=False,
        # The shape of vehicle are predefined by its class. But in special scenario (WaymoVehicle) we might want to
        # set to arbitrary shape.
        width=None,
        length=None,
        height=None,
        mass=None,
        scale=None,  # triplet (x, y, z)

Environment Configs

Please see Environments for unique configs for each environment or check the source code of each environment.