Skip to content

Configuration Reference

PGTG is configured through the PGTGEnv constructor. A few options are plain scalars; the more expressive ones are grouped into configuration contexts that can be passed as an instance, a dict, or (for some) a file path.

from pgtg import PGTGEnv
from pgtg.contexts import ObservationContext

env = PGTGEnv(
    traffic_density=0.05,
    observation_context=ObservationContext(sliding=True, window_size=(9, 9)),
    reward_context={"crash_penalty": 5.0, "separate_reward_cost": True},
    random_map_context={"width": 6, "height": 6, "obstacle_probability": 0.2},
)

When creating the environment through Gymnasium, pass the same keyword arguments to gym.make("pgtg-v5", ...).

Constructor arguments

Argument Type Default Description
map_path str | None None Load a fixed map. Accepts a benchmark name ("benchmark_2x2""benchmark_5x5") or a path to a JSON map file. None generates a random map each episode.
render_mode "human" | "rgb_array" | "pil_image" | None None See render modes.
only_render_obs bool False Render the agent's observation instead of the entire map: cropped to the observation window and limited to the features in obs_features.
traffic_density float 0.0 Fraction of eligible lane cells occupied by traffic.
traffic_light_phases_duration tuple[int, int, int] (10, 3, 10) Green/yellow/red durations in steps. Setting the middle value to 0 disables yellow.
ignore_traffic_collisions bool False If True, collisions with traffic are ignored.
car_spawn_exclusion_radius int 1 Cars never spawn within this Chebyshev distance of the agent. 1 clears the agent's cell and its 8 neighbours; 0 reserves only the agent's own cell; < 0 disables the exclusion.
observation_context ObservationContext | dict | list[str] | None None What the agent observes. See below.
reward_context RewardContext | dict | None None Reward and penalty structure. See below.
random_map_context RandomMapContext | dict | None None Procedural-generation parameters. See below.
obstacles list[Obstacle] | None None Custom obstacle handlers. See Custom Obstacles.
driver_profile_config DriverProfileConfig | dict | str | None None Driver-profile behaviors and weights. See Driver Profiles.
driver_profile_weights dict[DriverProfile | str, float] | None None Shortcut to reweight the profiles without changing their behavior.
traffic_rules_config TrafficRulesConfig | dict | str | None None Custom traffic rules. See Custom Traffic Rules.
rules_active list[str] | None None Which of the loaded traffic rules (defaults + any from traffic_rules_config) are active, by name. None = all loaded rules; a list = only those named ([] = none).
tiles str | None None Path to a custom tiles file; tile size is inferred from it. See Custom Tiles & Maps.
obstacle_masks str | None None Path to a custom obstacle-masks file.
traffic_lanes str | None None Path to a custom traffic-lanes file.
seed int | None None Master seed. See reproducibility.
log_level int | None None Level of the process-wide "pgtg" logger; None leaves it unchanged (logging.WARNING initially). PGTG attaches no handler of its own — see logging.

ObservationContext

Controls what the agent observes and how large the observed window is. Pass it as an instance, a dict, or a plain list of feature names (interpreted as obs_features).

Field Type Default Description
obs_features set[MapFeature] {WALL, GOAL, TRAFFIC, TRAFFIC_LIGHT} (+ obstacles that can appear, see note) Which map features become observation planes. Pass string names (e.g. "ice") as a list and they are converted to the enum; or pass MapFeature members directly. TRAFFIC_LIGHT expands to three color planes.
window_size tuple[int, int] | int None → one tile (9×9 with the default tile set) Size of the observed window. A single int is treated as a square.
sliding bool False If True, the window is centered on the agent; otherwise the current tile is observed. Automatically set to True when window_size is given.
subgoal_direction bool False Add a Discrete(9) compass pointing to the next subgoal.
global_pos bool False Add the agent's absolute (x, y) position to the observation.
local_pos bool True Include the agent's position within the occupied tile.
velocity bool True Include the agent's velocity.

Obstacles are added automatically

obs_features only needs the structural features above. Obstacle planes (ice/sand/broken_road and any custom obstacle) are added per environment based on whether the obstacle can actually appear (see Observation follows generation). You may still list an obstacle explicitly (by name or MapFeature) to force its channel on even when it is never generated here.

Valid feature names: "wall", "goal" (= final goal or subgoal), "final_goal", "subgoal", "ice", "broken_road", "sand", "traffic", "traffic_light".

# Observe only walls, ice, and traffic, through a 5×5 sliding window.
ObservationContext(obs_features=["wall", "ice", "traffic"], window_size=5)

RewardContext

Controls the reward and penalty structure. See Reward for the semantics.

Field Type Default Description
subgoal_reward float 1 Reward for reaching a subgoal (or the final goal).
final_goal_bonus float 0 Extra reward added when the final goal is reached.
crash_penalty float 1.0 Subtracted for hitting a wall or traffic. Ends the episode.
traffic_light_penalty float 0.5 Subtracted for running a red light. Does not end the episode.
standing_still_penalty float 0 Subtracted each step the agent does not move.
already_visited_penalty float 0 Subtracted for entering a cell already visited this episode.
split_subgoal_reward bool False Divide subgoal_reward by the number of subgoals, keeping the per-track total constant.
separate_reward_cost bool False Report penalties only as info["cost"] without subtracting them from the reward. (for safe RL).

RandomMapContext

Controls procedural map generation (used only when map_path is None). See Maps & Procedural Generation.

Field Type Default Description
width int 4 Map width in tiles.
height int 4 Map height in tiles.
connections_percentage float in [0, 1] 0.5 Fraction of possible tile connections. 0.0 → minimal start→goal path; 1.0 → fully connected.
start_position tuple[int, int] | tuple[int, int, str] | "random" (0, -1, "west") Start tile (and optional entry direction) on a border.
goal_position tuple[int, int] | tuple[int, int, str] | "random" (-1, 0, "east") Goal tile (and optional direction) on a border.
min_dist_start_goal int | None None Minimum path length between start and goal. Requires both positions to be "random".
obstacle_probability float in [0, 1] 0.0 Per-tile probability of receiving an obstacle.
obs_feature_weights dict[MapFeature | int, float] each obstacle's registered obstacle_weight (built-ins default to 1) Relative weights for which obstacle type is placed. Normalized internally; string keys accepted. A weight of 0 excludes that obstacle from generation (and, via observe=auto, from the observation).

Set weights globally with set_obstacle_weight

obs_feature_weights is per-environment. To change an obstacle's default weight for every environment built afterwards, call pgtg.set_obstacle_weight({"ice": 0.2, "broken road": 0.0}). See Retuning weights globally.

Coordinates can be negative

In start_position/goal_position, a coordinate of -1 counts from the far edge, so (-1, 0, "east") means "top-right tile, exit east".

RandomMapContext(
    width=8,
    height=8,
    connections_percentage=0.4,  # sparser
    obstacle_probability=0.25,
    obs_feature_weights={"ice": 3.0, "sand": 1.0},
)

Passing configuration as dicts or paths

Every context accepts a dict, which is convenient with gym.make or when writing a config file:

import gymnasium as gym

env = gym.make(
    "pgtg-v5",
    reward_context={"subgoal_reward": 10, "split_subgoal_reward": True},
    observation_context={"sliding": True, "window_size": 7},
)

driver_profile_config and traffic_rules_config additionally accept a path to a JSON/YAML file. See Driver Profiles and Custom Traffic Rules.


Logging

PGTG logs to the standard-library logger named "pgtg". Records propagate, so your application decides where they go:

import logging

logging.basicConfig(level=logging.INFO)  # your app's configuration wins
logging.getLogger("pgtg").setLevel(logging.DEBUG)  # PGTG specifically

Without any logging configuration, warnings and errors still reach stderr through Python's standard handler.

For PGTG's own colorized output in a script or notebook, opt in explicitly:

from pgtg.core.logger import PGTGLogger

PGTGLogger.enable_console_handler(level=logging.DEBUG)

ANSI colors are enabled only when stderr is a TTY. Pass colorize=True/False to override the detection.

The logger is process-wide

PGTGEnv(log_level=...) sets the level of the shared "pgtg" logger, so it affects every PGTG environment in the process, not just that instance. The default None leaves the level untouched.