MetaDrive: a driving simulator you can script in a Gymnasium loop
MetaDrive: Lightweight driving simulator for everyone
At a glance
- What is it?
- MetaDrive synthesises infinite driving scenes, replays real logs from nuScenes and Waymo, and exposes the whole thing as a Farama Gymnasium environment, so a reinforcement learning agent can be trained against procedurally generated traffic without a car or a rendering farm.
- Who is it for?
- MetaDrive fits a reinforcement learning researcher who needs a closed-loop driving environment with procedural variety, sensor data and a standard API, and who wants to run thousands of episodes on a single machine rather than on a fleet.
- Can I use it commercially?
- Yes. Apache-2.0 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?
- Yes. The repository last received commits 8 days 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 October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Compositional, lightweight, realistic
MetaDrive is an open-source driving simulator for AI and autonomy research, and it presents itself through three claims that are worth taking one at a time.
Compositional is the first. It supports synthesising infinite scenes with various road maps and traffic settings, or loading real-world driving logs for the research of generalizable reinforcement learning. Infinite is the important word, because the scene generator is procedural and the scenes never repeat, which is what makes it possible to train an agent that is not overfitted to one particular intersection.
Lightweight is the second, and it is the claim with a number attached. The README says it is easy to install and run on Linux, Windows and macOS with sensor simulation support, and that it can run up to plus 1000 frames per second on a standard PC. A thousand frames per second is the number that matters for reinforcement learning, where the bottleneck is usually the environment and not the policy.
Realistic is the third, and it is qualified. The README says accurate physics simulation and multiple sensory input, including point cloud, RGB, depth and semantic images, a top-down semantic map and first-person view images. The qualifier is that the inputs are there and the physics is the physics of the simulator, which is a statement about the simulator rather than about a vehicle.
The project is Apache-2.0 licensed with the text in `LICENSE.txt`, the primary language is Python, the default branch is `main`, the homepage is `metadriverse.github.io/metadrive/`, and the documentation is on Read the Docs. The last push was on 2026-10-16, and the recent releases are MetaDrive-0.4.3 from 2024-12-06, MetaDrive-0.4.2.3 from 2024-01-26 and MetaDrive-0.4.2.2 from 2024-01-22, so the published versions lag the branch by a long way.
The paper is the one to cite for academic work, by Quanyi Li, Zhenghao Peng, Lan Feng, Qihang Zhang, Zhenghai Xue and Bolei Zhou, published in IEEE Transactions on Pattern Analysis and Machine Intelligence in 2022, with the title describing the project as composing diverse driving scenarios for generalizable reinforcement learning.
A clone, an editable install and a profiling script
The quick start is three commands, and the verification step has a caveat that has caught people out.
git clone https://github.com/metadriverse/metadrive.git
cd metadrive
pip install -e .The editable install is the right choice here, because the examples and the configuration files are read from the source tree, and the README's examples live in the `metadrive/examples` directory inside the repository.
Verification is done with a profiling script:
python -m metadrive.examples.profile_metadriveThe note attached to it matters: do not run that command in a folder that has a sub-folder called `./metadrive`. The reason is visible in the command itself, since the module is resolved by name, and a directory with the same name in the working directory shadows the installed package. It is a small thing, and it is the kind of small thing that costs an afternoon when the symptom is an import error that says nothing useful.
The repository layout supports the same reading. The `metadrive/` directory is the package, `documentation/` holds the source of the documentation site, `bridges/` holds the integrations with other frameworks, `format.sh` and `.style.yapf` are the code formatting setup, `MANIFEST.in` controls what goes into the distribution, and `.readthedocs.yaml` configures the documentation build.
The environment is a Gymnasium gym, and the loop is five lines
The API is the standard one, and the README says it plainly: to build the RL environment in a Python script, you can code in the Farama Gymnasium format.
from metadrive.envs.metadrive_env import MetaDriveEnv
env = MetaDriveEnv(config={"use_render": True})
obs, info = env.reset()
for i in range(1000):
obs, reward, terminated, truncated, info = env.step(env.action_space.sample())
if terminated or truncated:
env.reset()
env.close()Four details in that snippet carry the design. The configuration is a plain dictionary passed to the constructor, and `use_render` decides whether the scene is drawn, so the same environment class serves a training run with no rendering and a demonstration run with it. `reset()` returns the observation and an info dictionary. `step()` returns the five values of the Gymnasium API, observation, reward, terminated, truncated and info, which is what makes the environment usable with any modern reinforcement learning library rather than only with the one it was written for. And `env.action_space.sample()` appears in the loop, which is the quick way to confirm that the installation works, since a random policy still produces a valid trajectory.
The `terminated` and `truncated` distinction is the one that catches people, and it is handled correctly here, since the environment returns both and the loop resets on either. A driving episode ends for two different reasons, the agent failed or the time limit was reached, and a learning algorithm that treats the second as a failure learns the wrong thing.
Three example scenarios and the flags that change them
The examples in the `metadrive/examples` directory are the fastest way to see what the simulator does, and each is a module you run.
The single agent scenario launches a simple driving scenario with auto-drive mode on, and the vehicle can be driven manually with the W, A, S and D keys:
python -m metadrive.examples.drive_in_single_agent_envThe safe scenario includes more complex obstacles and a cost to be yielded, which is the closest thing in the repository to a driving test:
python -m metadrive.examples.drive_in_safe_metadrive_envThe multi-agent scenario is launched with an environment argument:
python -m metadrive.examples.drive_in_multi_agent_env --env roundaboutThe `--env` flag accepts `roundabout`, which is the default, `intersection`, `tollgate`, `bottleneck`, `parkinglot` and `pgmap`. Those names are the interesting part, because they are a list of the situations a driving policy is expected to handle, from a junction negotiation to a toll gate to a parking lot, and they are procedural rather than recorded. Adding `--top_down` launches the top-down pygame renderer, which is the view used in the papers and the one that makes a policy's behaviour legible.
One example is an `.ipynb` notebook that can be opened directly in Colab, and the README notes that the documentation is built with `.ipynb` files so that every example in the documentation can be run locally or in Colab, with instructions for opening a GitHub repository from the Colab interface.
Real logs: nuScenes by default, Waymo on request
The synthetic scenes are for training, and the real logs are for testing whether what was learned transfers, which is the generalizable reinforcement learning problem the project is aimed at.
python -m metadrive.examples.drive_in_real_envThe default real-world dataset is nuScenes, and `--waymo` visualises Waymo scenarios instead. There is a limitation in how the replayed traffic behaves, and the README states it plainly: traffic vehicles cannot respond to surrounding vehicles if they are directly replayed. The workaround is to add the `--reactive_traffic` argument, which uses an IDM policy to control them and make them reactive. So the replay is faithful in geometry and unfaithful in behaviour until you ask for behaviour, which is a reasonable design and an important one to know about when reading the results of an experiment.
The keys are also documented. Press `r` to load a new scenario, and `b` or `q` to switch perspective, which is how a user moves between the first-person camera and the other views of the same scenario.
The datasets themselves are not bundled. The simulation code is open and the example commands are in the repository, but a user of the real environment has to have the nuScenes or Waymo data locally and to point the simulator at it, which is a large download and a licensing conversation of its own for the datasets that are not freely redistributable.
The dependency list shows what the renderer is
The `setup.py` is where the engineering of the project is visible, and two things in it are worth reading closely.
The first is the assertion at the top of the file, that the Python version is 3 and the minor version is at least 6, with the message that python version >= 3.6 is required. A simulator that a research group installs on a machine they have had for a while will meet an old Python, and the assertion is a friendly way of failing rather than a cryptic one.
The second is the set of extras, which describe the optional worlds the simulator can be dropped into:
cuda_requirement = [
"cuda-python==12.1.0",
"PyOpenGL==3.1.6",
"PyOpenGL-accelerate==3.1.6",
"pyrr==0.10.3",
"glfw",
]
gym_requirement = [
"gym>=0.19.0, <=0.26.0"
]The CUDA extra pins the CUDA Python bindings, PyOpenGL with its accelerate variant, pyrr and glfw, which is the hardware rendering path. The `gym` extra pins the OpenAI Gym package to a range, and the `ros` extra pulls in `zmq` for the ROS bridge, which is what the `bridges/` directory is for. The base install is a long list of ordinary things: requests, matplotlib, pygame, yapf, tqdm, progressbar, pillow, lxml, psutil, shapely, filelock, Pygments and mediapy. The test extra adds pandas, pytest and scipy.
The rendering stack itself is not in the requirements at all, because it is inherited. The acknowledgements state that the simulator cannot be built without the help of the Panda3D community and list the projects it leans on, including the simple physically based rendering and glTF support for Panda3D, the RenderPipeline and its water effect, the procedural model primitives, the DiamondSquare terrain generation and the asset tools. So the visual quality of the simulator is largely the work of others, and the acknowledgement is the honest description of that.
The `setup.py` also uses namespace packages and reads the version from `metadrive/version.py`, so the version in the package metadata comes from the source tree rather than from a number written in the packaging file.
Where MetaDrive is the wrong tool
The limits are the ones that come with a research simulator, and they are worth knowing before a project depends on it.
The first is the gap between a scene generator and a vehicle model. MetaDrive composes scenes, it does not reproduce a particular car, a particular tyre model or a particular test track, and the accuracy claim in the README is about the physics of the simulator. For a research question about generalizable behaviour across procedurally generated scenes, that is exactly what you want. For a question about how a specific vehicle behaves on a specific road, it is the wrong tool, and the honest alternative is a simulator whose vehicle models are validated against real measurements, which is a different product with a different price.
The second is the version gap. The published releases stop at 0.4.3 from December 2024, while the repository has been moving since, so a project that wants the code in the repository has to install from a branch, and a project that wants a release has to take a version that is well behind the tip. Neither is unusual for a research project, and both are decisions that have to be made explicitly rather than inherited.
The third is the dependency surface, and it is a large one. The CUDA extra pins specific versions of PyOpenGL and the CUDA bindings, the Gym extra pins a range, and the base install brings in a dozen packages. A training run that works on the machine it was developed on may not work on a machine with a different driver, and a simulation stack of this size is where that kind of environment mismatch shows up first, as a rendering artefact rather than as an error.
The fourth is the evaluation question, and it is the one that separates simulators from datasets. A closed-loop simulator lets an agent face consequences of its own actions, which is what a synthetic environment buys and what a dataset of recorded logs cannot give, since the logs only contain the states that were actually driven. The alternative approach for a team that does not need a closed loop is to train on the logs directly, which is cheaper and gives a model that is more faithful to real driving, and the choice between the two is a question of whether the closed loop is the point of the experiment.
Editorial conclusion
MetaDrive fits a reinforcement learning researcher who needs a closed-loop driving environment with procedural variety, sensor data and a standard API, and who wants to run thousands of episodes on a single machine rather than on a fleet. It is the wrong tool for a company that needs validated vehicle dynamics or a photorealistic reconstruction of a specific road, because it is a research simulator with an open-ended scene generator rather than a reproduction of a particular vehicle. Before adopting it, pin the version you want, since the last published release is MetaDrive-0.4.3 from 2024-12-06 while the repository has moved on, and read the dependency extras in `setup.py`, because the base install, the CUDA extra and the Gym extra are not the same environment and a training run that works on one machine may not work on another.
Frequently asked questions
How do I install MetaDrive?
Clone the repository with `git clone https://github.com/metadriverse/metadrive.git`, change into the metadrive directory and run `pip install -e .`. Verify it with `python -m metadrive.examples.profile_metadrive`, and note the README warning not to run that from a folder containing a sub-folder called metadrive.
How do I use MetaDrive as a reinforcement learning environment?
It follows the Farama Gymnasium format. Construct MetaDriveEnv with a config dictionary such as MetaDriveEnv(config={"use_render": True}), call env.reset() for the observation and info, and env.step() returns observation, reward, terminated, truncated and info.
Which scenarios can MetaDrive run?
The multi-agent example accepts --env roundabout, which is the default, intersection, tollgate, bottleneck, parkinglot and pgmap, and --top_down launches the top-down pygame renderer. The real environment replays scenarios from the nuScenes dataset by default and from Waymo with --waymo, with --reactive_traffic making the replayed traffic respond.
Does MetaDrive support GPU rendering?
There is a CUDA extra in setup.py with cuda-python 12.1.0, PyOpenGL 3.1.6 and its accelerate variant, pyrr and glfw, while the base install uses pygame, matplotlib, pillow and mediapy. There is also a gym extra pinning gym to a range and a ros extra pulling in zmq for the ROS bridge.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/metadriverse-metadrive)Was this useful?