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".
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:
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.