Open-source project
ZhengYinan-AIR/Diffusion-Planner avatar
ZhengYinan-AIR/Diffusion-Planner

Diffusion Planner on nuPlan: one denoising pass, and a license file that disagrees with itself

[ICLR 2025 Oral] The official implementation of "Diffusion-Based Planning for Autonomous Driving with Flexible Guidance"

1,076 stars180 forksPythonLicense varies

At a glance

What is it?
Diffusion Planner is the official ICLR 2025 implementation of diffusion-based driving planning for autonomous driving, predicting neighbours and planning the ego vehicle in one pass on nuPlan. Its tables are careful, its install path is pinned to a simulator, and its own setup.py states two incompatible licensing terms.
Who is it for?
This is a nuPlan research artifact, not a vehicle stack. Adopt it when your work sits in closed-loop simulation and you want a diffusion planner with a published checkpoint and an environment you can audit.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Activity is slowing. The repository last received commits 8 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 November 7, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One denoising pass plans the ego and predicts its neighbors

Diffusion Planner is the code behind a diffusion model that plans driving trajectories, and its architecture list fits in three bullets. The backbone is DiT-based, built around fusing noised future ego trajectories with conditional scene information.

The second bullet carries more weight than the first. Key participants are modeled jointly with the ego future, so one network both predicts what nearby vehicles will do and decides the ego response, which removes the usual seam between a prediction head and a planning head. Sampling is the other decision. The README puts diffusion sampling at around 20Hz and treats inference speed, rather than a long chain of refinements, as the reason the model fits inside a driving loop.

Refinement still exists in the project, as a separate variant row and a separate runner script, and that is exactly where the two benchmark tables stop agreeing. Look at the column labels before the numbers. (NR) and (R) show up in both tables, and neither abbreviation is explained anywhere in the visible README text. The same expert row reads 93.53 in one family and 80.32 in the other, so whichever split that is, it moves scores by more than ten points.

The conda path runs through nuplan-devkit, not from a wheel

The only install path the project prints runs through nuplan-devkit, and the order is not negotiable in practice. A conda environment on python=3.9 comes first, then the simulator, then the planner. Two requirement files do different jobs here. `requirements.txt` belongs to nuplan-devkit and pins the simulator stack, while `requirements_torch.txt` carries the torch build for the planner itself.

bash
conda create -n diffusion_planner python=3.9
conda activate diffusion_planner

# install nuplan-devkit
git clone https://github.com/motional/nuplan-devkit.git && cd nuplan-devkit
pip install -e .
pip install -r requirements.txt

# setup diffusion_planner
cd ..
git clone https://github.com/ZhengYinan-AIR/Diffusion-Planner.git && cd Diffusion-Planner
pip install -e .
pip install -r requirements_torch.txt

After that block a reader should have an importable package named diffusion_planner, installed in editable mode from setup.py, sitting inside an environment where the nuPlan simulator already imports. The dataset has to be ready before any of it means anything, and the README points at the nuplan-devkit dataset_setup guide for that job. The top-level file list holds no downloader, so fetching and preparing nuPlan is yours to do first.

Because the devkit goes in editable too, anyone already keeping nuplan somewhere else ends up maintaining a second environment rather than risking the simulator's dependency pins.

Two lines apart in setup.py, two opposite permission terms

The only licensing statement anywhere in the codebase contradicts itself, and setup.py holds both halves. The metadata field reads `license="MIT"` while the classifier list carries `"License :: Free for non-commercial use"`, a packaging tag that forbids commercial reuse even though MIT grants none, and the repository's own license field stays unresolved, so the authors have to say which line governs.

python
name="diffusion_planner",
version="1.0.0",
"License :: Free for non-commercial use",
license="MIT",

The same block is where version tracking stops working. setup.py pins `version="1.0.0"`, the project publishes no GitHub releases, and the last push was on 2026-03-10, so there is nothing between those facts to cross-check a checkout against. Anyone upgrading this code therefore upgrades to whatever the branch currently holds, and the frozen version string will never move to warn them. The author field names the first three contributors listed on the paper, which is a packaging habit rather than a credit decision, and the only interpreter classifier is Python 3.9.

Learning-based columns put the unrefined model on top

In the learning-based table, Diffusion Planner without refinement posts 89.87, 82.80, 75.99, 69.22, 89.19 and 82.93 across the six columns, and every one of those is the highest figure in its column. PLUTO w/o refine. is the nearest learning-based rival at 88.89, 78.11, 70.03, 59.74, 89.90 and 78.62, with PlanTF underneath both.

Two details make that sweep less tidy than it looks. First, the asterisk footnote says that pre-searched reference lines or additional proposals count as model inputs, and the asterisked rows are PDM-Open, PLUTO w/o refine. and STR2-CPKS-800M w/o refine., so at least one direct competitor is being handed help the planner does not get. Second, the Diffusion-es w/o LLM row collapses to 50.00 on the first column and leaves the other five blank, which puts most of the distance between 50.00 and 89.87 on the language model component rather than the diffusion head, with nothing in the table to separate them further.

GameFormer shows the same dependence from the other side: 13.32 and 8.69 without refinement against 79.94 and 79.78 for the refined entry in the other table. A no-refinement story is conditional on that language model component being present.

Two hundredths decide the top mark on Test14-hard R

The rule-based and hybrid table is where the refined variant appears, even though a learned model sits inside a table of rule-based and hybrid baselines. Diffusion Planner w/ refine posts 94.26, 92.90, 78.87, 82.00, 94.80 and 91.75.

On Test14-hard R the two marked scores are 82.02 for STR2-CPKS-800M and 82.00 for the planner, two hundredths apart, while PLUTO's 80.08 sits more than two full points below both. A column decided by two hundredths settles nothing, and STR2-CPKS-800M also leaves both Test14 columns blank, so its 82.02 has no cross-check against it.

The expert row is the sharper case. Log-replay scores 93.53 and 94.03 on the NR columns where the refined planner claims 94.26 and 94.80, yet on Test14-hard NR the same expert holds 85.96 against the planner's 78.87. A learned planner can pass a logged human on two splits and lose to it on the hard one, and neither table breaks the splits down to explain why.

Four shell scripts stand in for the missing commands

The repository top level carries four shell scripts and one notebook, and their names carry more information than the README does. `torch_run.sh` is the launch surface, `data_process.sh` and `data_process.py` are the preprocessing pair, `sim_diffusion_planner_runner.sh` runs the planner in simulation, and `run_nuboard.ipynb` is the only notebook in the list.

`sim_guidance_demo.sh` is the one worth reading first. The paper title promises guidance that can be shaped at inference time, and the README names three architecture bullets without ever defining what the guidance term is, so that demo script is the only artefact pointing at it. Nothing in the visible text says what you can change, whether it is a language model, a cost function or a switch, and no arguments are given for any of the scripts.

For someone planning a training run, that gap is the cost to price in. The commands live in the shell files, while the documentation stops at the install snippet and a checkpoint download line pointing at Hugging Face. Checked in beside them, `normalization.json` and `nuplan_train.json` are the two config files a run would hinge on, and neither one is explained.

nuPlan preparation dominates the setup bill

Before any model runs, the nuPlan dataset has to be prepared, and the reference for that job is the nuplan-devkit dataset_setup documentation rather than anything in this repository. Scope follows from the file list: no downloader, no container recipe, no ROS manifest. Interpreter support is narrow too, with python=3.9 in the install command and a single interpreter classifier in setup.py.

The real-time claim stays inside the simulator. Around 20Hz refers to sampling in the loop the README describes, with no hardware, batch size or GPU count named anywhere, so it cannot be transferred to your own machine from the repository alone. This is the wrong tool for an onboard planner, and also the wrong tool if you want the table without the devkit's simulator stack.

For closed-loop research reproduction it is unusually complete, because the checkpoint is hosted on Hugging Face rather than left behind a training run. Just keep the boundary in view: simulation research, one dataset family, one planner.

Flow Planner and Hyper Diffusion Planner change the design

The same group has already moved twice, and both successors are linked from the project description with different goals. Flow Planner (NeurIPS 2025) lives under a different organization, DiffusionAD, and is described as a learning-based framework with advanced interactive behavior modeling. Hyper Diffusion Planner sits under ZhengYinan-AIR instead and is aimed at real vehicle deployment.

The difference in approach sits in what each project names as its target. Flow Planner puts interactive behavior modeling at the center, while Hyper Diffusion Planner takes real vehicle deployment as the goal, which the current repository does not attempt. Neither is a drop-in swap for this code. Its value is narrower: it is the nuPlan closed-loop reference for diffusion planning, with joint prediction and planning and a checkpoint you can download. Read both successors before taking a dependency on this one.

Editorial conclusion

This is a nuPlan research artifact, not a vehicle stack. Adopt it when your work sits in closed-loop simulation and you want a diffusion planner with a published checkpoint and an environment you can audit. Leave it alone for on-vehicle use: the repository has no container recipe, no ROS package and no hardware timing beyond the sampling figure. Before you depend on it, settle three things. Which line of setup.py governs use, what the guidance term in the paper title actually refers to, and how the hard-split column was scored when two baselines sit two hundredths apart.

Frequently asked questions

What does Diffusion Planner need before it can run on nuPlan?

A conda environment on python=3.9, an editable install of nuplan-devkit with its requirements.txt, an editable install of Diffusion-Planner with requirements_torch.txt, and the nuPlan dataset prepared following the nuplan-devkit dataset_setup guide. The install snippet in the repository is the only documented path to a working environment.

Is Diffusion Planner free for commercial use?

The repository license field is unresolved and setup.py carries two conflicting statements, `license="MIT"` and the classifier "License :: Free for non-commercial use". Ask the authors which one applies before shipping this code in a product.

How does Diffusion Planner compare with PLUTO and PDM-Closed on nuPlan?

On Val14 (NR) the unrefined planner posts 89.87 against 88.89 for PLUTO w/o refine., and on Val14 (R) it posts 82.80 against 78.11. The refined variant reaches 94.26 and 92.90 on those two columns, where PDM-Closed records 92.84 and 92.12.

How fast is Diffusion Planner at inference time?

The README puts diffusion sampling at around 20Hz and frames that speed as the reason the model fits a real-time loop. No hardware, batch size or measurement setup is named, so the figure cannot be carried over to another machine from the repository alone.

Should I use Diffusion Planner or Flow Planner?

Flow Planner (NeurIPS 2025) is described as a learning-based framework with advanced interactive behavior modeling, while Hyper Diffusion Planner targets real vehicle deployment. Diffusion-Planner stays the nuPlan closed-loop reference for the diffusion planning approach, with joint prediction and planning and a published checkpoint.

How do I evaluate the Diffusion Planner checkpoint in nuBoard?

The checkpoint is hosted on Hugging Face, and `run_nuboard.ipynb` is the only notebook at the repository top level. The closed-loop evaluation section of the README stops at the download step and gives no arguments for the notebook or the simulation runner.

Official sources

  1. Issues
  2. Project website
  3. README
  4. ZhengYinan-AIR/Diffusion-Planner on GitHub
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/zhengyinan-air-diffusion-planner.svg)](https://hysenlabs.com/projects/zhengyinan-air-diffusion-planner)

Was this useful?