Open-source project
LucasAlegre/sumo-rl avatar
LucasAlegre/sumo-rl

SUMO-RL: Gymnasium and PettingZoo traffic signal control environments

Reinforcement Learning environments for Traffic Signal Control with SUMO. Compatible with Gymnasium, PettingZoo, and popular RL libraries.

1,078 stars266 forksPythonMIT

At a glance

What is it?
SUMO-RL wraps the SUMO traffic simulator in Gymnasium and PettingZoo APIs so you can train single-agent or multi-agent signal controllers. The wrapper is thin, the reward and observation functions are replaceable, and the real cost is SUMO itself.
Who is it for?
Adopt SUMO-RL if you already have a SUMO network and want a Gymnasium or PettingZoo loop around it, or if you are studying multi-agent signal control and need a replaceable reward function. Do not adopt it if you have no .net.xml and .rou.xml files, or if you need a simulator you can install without touching SUMO_HOME.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Activity is slowing. The repository last received commits 6 months ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 18, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What SUMO-RL adds on top of the SUMO simulator

SUMO is a microscopic traffic simulator. It loads a road network and a route file, moves individual vehicles along lanes, and exposes the running simulation through TraCI, a socket API that lets an external program read lane state and change traffic light phases. That is enough to build a controller, but not enough to build a learning loop. SUMO-RL supplies the loop.

The repository's stated goals are to provide a simple interface for reinforcement learning with SUMO, support multiagent RL, stay compatible with gymnasium.Env and libraries such as stable-baselines3 and RLlib, and keep state and reward definitions easy to modify. The audience is therefore narrow and specific: researchers and engineers who already have a SUMO scenario and want to treat each traffic light as an agent that picks the next green phase. If you do not have a network file, this library gives you nothing to run.

The design keeps the wrapper thin. SumoEnvironment is the main class. TrafficSignal retrieves information and actuates on traffic lights through TraCI. There is no scheduler, no replay buffer and no training algorithm in the core package. You bring the RL library.

How the environment maps traffic lights to observations, actions and rewards

Each traffic signal agent sees a vector built from three parts. The first is a one-hot encoding of the current active green phase. The second is a binary flag for whether min_green seconds have passed in that phase. The remaining entries are per-lane: the density of incoming lane i (vehicles divided by lane capacity) and its queue length (vehicles below 0.1 m/s, again divided by capacity).

The action space is discrete. Every delta_time seconds an agent chooses the next green phase configuration. In the 2-way single intersection example the README cites, there are four discrete actions. A phase change is not instantaneous: the next phase is preceded by a yellow phase lasting yellow_time seconds, which the agent does not choose and cannot skip. That delay is part of the environment dynamics, and it is the reason naive phase-switching policies waste time in yellow.

The default reward is the change in cumulative vehicle delay, meaning how much the summed waiting time of approaching vehicles moved relative to the previous step. The README notes that other reward functions ship inside TrafficSignal and can be selected with the reward_fn parameter. You can also pass your own callable, which receives the traffic signal object. The example in the README returns traffic_signal.get_average_speed().

Because observation and reward are both injectable, the library is really a scaffold: the interfaces are the product, and the defaults are a starting point you are expected to replace.

Installing SUMO-RL and running a first single-agent loop

SUMO is a separate system dependency and must be installed first. On Ubuntu the README uses the SUMO stable PPA, installing sumo, sumo-tools and sumo-doc. After that, SUMO_HOME must point at the installation, /usr/share/sumo by default.

bash
sudo add-apt-repository ppa:sumo/stable
sudo apt-get update
sudo apt-get install sumo sumo-tools sumo-doc
echo 'export SUMO_HOME="/usr/share/sumo"' >> ~/.bashrc
source ~/.bashrc

The README also documents an optional variable for Libsumo, which it says gives roughly an 8x performance boost. The trade-off is explicit: with this active you cannot run sumo-gui or multiple simulations in parallel.

bash
export LIBSUMO_AS_TRACI=1

With SUMO in place, the Python package installs from PyPI. The README also gives an editable install from the repository for the unreleased version. Note that the pyproject.toml pins sumolib and traci at 1.14.0 or newer, so an older SUMO installation will not satisfy the dependency.

bash
pip install sumo-rl

A first run needs your own .net.xml and .rou.xml files. The README's Gymnasium example registers the environment as 'sumo-rl-v0' and passes the two file paths, an output CSV name, use_gui, and num_seconds. The loop below follows that example: reset, then step with random actions until the episode terminates or truncates. You should see SUMO open if use_gui is true, and a CSV written to the path you gave.

python
import gymnasium as gym
import sumo_rl
env = gym.make('sumo-rl-v0',
               net_file='path_to_your_network.net.xml',
               route_file='path_to_your_routefile.rou.xml',
               out_csv_name='path_to_output.csv',
               use_gui=True,
               num_seconds=100000)
obs, info = env.reset()
done = False
while not done:
    next_obs, reward, terminated, truncated, info = env.step(env.action_space.sample())
    done = terminated or truncated

For a network with more than one traffic light, the README directs you to sumo_rl.parallel_env with the PettingZoo parallel API, or to env for the AEC API. The constructor arguments are the same file paths. The README's multi-agent snippet uses the bundled RESCO grid4x4 network under nets/RESCO/grid4x4/, which is useful because it means you can run a multi-agent example without authoring a network first.

Where the wrapper gets in your way

The dependency on SUMO_HOME is the first real constraint. SUMO-RL does not bundle a simulator, does not download one, and does not check that the variable is set before failing. If your deployment environment cannot install system packages from a PPA, the library is not usable there without building SUMO yourself.

The Libsumo switch is a genuine trade-off rather than a free speedup. Enabling LIBSUMO_AS_TRACI removes the ability to run sumo-gui and removes parallel simulations. For multi-agent experiments where you want several scenarios running at once, that is disqualifying, and the README says so directly rather than hiding it.

The observation space is also opinionated in a way that matters for generalization. Density and queue length are normalized by lane capacity, and the phase is one-hot encoded. That is fine for a fixed network. It does not obviously transfer across networks with different lane counts or different numbers of phases, and the README does not describe any transfer mechanism. If your research question is about generalization across intersections, you will be replacing the observation function, not using the default.

Finally, the repository's own test workflow runs on Linux. The install instructions are Ubuntu-specific (add-apt-repository, apt-get). Nothing in the README describes a macOS or Windows path, so plan on WSL, a container, or building SUMO from source.

SUMO-RL versus writing TraCI code yourself

The direct alternative is not another RL library. It is writing your own TraCI loop. TraCI already gives you lane queries and phase control, and the README links to the SUMO TraCI documentation. A hand-written loop means you define the observation vector, the action mapping, the yellow-phase handling and the episode boundary yourself.

That is more work, and the work is exactly what SUMO-RL has already done. The yellow-phase insertion, the min_green bookkeeping, the per-lane normalization and the Gymnasium and PettingZoo conformance are the parts people get wrong or skip. If you need a nonstandard action space, for instance choosing phase durations rather than phases, SUMO-RL's discrete action space will not fit and a custom loop will be faster than fighting the abstraction.

A second comparison worth making is between the single-agent and multi-agent paths inside the library itself. Using single-agent=True turns SumoEnvironment into a regular Gymnasium environment, which is the right choice when your network has one traffic light. The multi-agent path through parallel_env or env is the right choice when it has several. Choosing the single-agent path on a multi-intersection network means you are ignoring the other signals' state, and the library will not stop you.

Licence, maintenance and upgrade cost

SUMO-RL is MIT licensed, as stated in the README badge and in the pyproject.toml license field. MIT is permissive: you can use, modify and redistribute it, including in closed products, provided the copyright notice and permission notice are retained. That is a summary of the licence text, not legal advice, and the LICENSE file at the repository root is the authoritative document. Your own obligations depend on the scenario files you load, which come from your own sources or from the bundled networks, not from the library's licence.

The last push to the default branch was on 2026-03-08. The most recent tagged release is v1.4.5 from 2024-05-07, with v1.4.4 and v1.4.3 before it. The gap between the last release and the last push means the main branch and the PyPI package are not the same thing, which is why the README offers the editable install for the unreleased version. If you install from PyPI you are on v1.4.5 unless a newer tag exists.

Upgrade cost is dominated by two moving parts. The Python dependency floor is sumolib and traci at 1.14.0 or newer, so upgrading SUMO can break the environment if the TraCI surface changes. The Gymnasium floor is 0.28 and PettingZoo is 1.24.3, and Gymnasium's reset and step signatures (obs, info and the five-tuple) are already reflected in the README examples. Both are pre-1.0 or near-1.0 ecosystems where API churn is normal, so pinning versions in your own project is the practical move.

Editorial conclusion

Adopt SUMO-RL if you already have a SUMO network and want a Gymnasium or PettingZoo loop around it, or if you are studying multi-agent signal control and need a replaceable reward function. Do not adopt it if you have no .net.xml and .rou.xml files, or if you need a simulator you can install without touching SUMO_HOME. Before committing, verify that your SUMO version is at least 1.14.0 and that your network file loads in sumo-gui, because SUMO-RL will not tell you why a malformed network fails.

Frequently asked questions

How do I install SUMO-RL and SUMO?

Install SUMO first, then the Python package. The README uses the SUMO stable PPA on Ubuntu to install sumo, sumo-tools and sumo-doc, sets SUMO_HOME to /usr/share/sumo, and then installs the wrapper with pip install sumo-rl.

Is the SUMO traffic simulator free?

SUMO itself is a separate project and the README does not discuss its licence or pricing. What the README does state is that SUMO-RL is MIT licensed, so the wrapper around the simulator is permissively licensed.

What is SUMO-RL?

SUMO-RL provides a simple interface to instantiate reinforcement learning environments with SUMO for traffic signal control. It supports single-agent Gymnasium environments and multi-agent PettingZoo environments, and its stated goals include compatibility with stable-baselines3 and RLlib.

What do I need before I can run a SUMO-RL environment?

You need a SUMO installation with SUMO_HOME set, plus your own network file and route file. The README's Gymnasium example passes net_file, route_file, out_csv_name, use_gui and num_seconds to gym.make('sumo-rl-v0').

What is the default reward in SUMO-RL?

The default reward function is the change in cumulative vehicle delay, meaning how much the total waiting time of approaching vehicles changed relative to the previous time step. The README notes that other reward functions ship in TrafficSignal and can be selected with the reward_fn parameter.

Official sources

  1. License: MIT
  2. LucasAlegre/sumo-rl on GitHub
  3. Project website
  4. README
  5. Releases
Community notes

Community notes