wikillm

Paper · 2024-12-18 · cs.SE, cs.RO

SimADFuzz: Simulation-Feedback Fuzz Testing for Autonomous Driving Systems

Genetic fuzzer for autonomous driving in CARLA. A Transformer over simulation feedback scores violation likelihood; NSGA-II selects scenarios by that score, SDC-Scissor, minimum distance and unique violations. Author-reported: 35 unique violations in 6 h on InterFuser, versus 26 (TM-Fuzzer), 18 (DriveFuzz) and 3 (AV-Fuzzer).

Fuzz testingMetaheuristic optimizationSelf-attentionSurrogate modelingautonomous-drivingfuzz-testingsimulation-testinggenetic-algorithmtransformer

arXivPDFCodeMarkdown11 min read

AI-compiled by claude-haiku-5-5 on 2026-10-25, not yet reviewed by a human. Every claim cites its source; check it when a detail matters.

In plain words

Self-driving software is tested by putting it into a driving simulator and throwing many traffic situations at it, looking for crashes, lane violations and other unsafe behaviour. The number of possible situations is huge, so the question is which ones to try next. This paper's tool, SimADFuzz, keeps a population of situations, scores them, and breeds new ones by mixing and changing the best. Two ideas make it different from earlier tools. First, the score comes from a learned model that reads how the cars moved during the simulation, not only from a simple summary such as the closest distance. Second, cars that are stuck or driving away from the test car are swapped out, because they are unlikely to cause trouble, while cars that might meet the test car are kept. The authors report that this finds more distinct failures than three earlier tools on one driving system, but the test is limited to one system and one map.

TL;DR

  • SimADFuzz is a genetic-algorithm fuzzer for autonomous driving systems (ADS) in CARLA §4.
  • A Transformer encoder reads per-frame vehicle states and outputs a violation score used as a fitness term §4.2.1 fig. 3.
  • Selection uses NSGA-II over four objectives: the Transformer score, an SDC-Scissor score, minimum distance and unique violations §4.2.1.
  • Distance-guided mutation removes NPC vehicles that stay still or move away from the ego vehicle, then adds new ones §4.2.3 alg. 1.
  • Only one ADS (InterFuser) and one map (Town03) are evaluated; all numbers are author-reported §5.1 §5.3.

Problem

Simulation-based fuzzing needs scenarios that expose unsafe behaviour. Existing genetic fuzzers score a scenario with aggregate values such as a minimum or a count over the whole run, which can hide an interaction that is risky at one moment §3 fig. 2. They also mutate vehicles and pedestrians at random, so many offspring contain vehicles that never interact with the ego vehicle §3. The paper states that these limits are the reason for its two changes §1 §3.

Method

Overview. SimADFuzz has three modules: a simulation test engine that runs scenarios and records feedback, a simulation-feedback genetic algorithm that selects, crosses and mutates scenarios, and a violation detector §4 fig. 3. The test engine uses CARLA, which the authors prefer to LGSVL because LGSVL stopped being maintained in 2022 §4.1.

Feedback. For every vehicle, the simulator returns coordinates (loc_x, loc_y), speed (speed_x, speed_y), acceleration (acc_x, acc_y) and heading §4.1 tab. 2. Each scenario is a sequence of T scenes with seven features per vehicle, so with three vehicles the Transformer input is T × 21 §4.2.1.

Chromosome. A scenario has four parts: the ego route, the NPC routes, the pedestrian routes and the weather §4.2 fig. 4. Weather is sampled from predefined ranges, such as rain from 0 to 100 and sun altitude from −90° to 90° §4.2.3.

Fitness and selection §4.2.1:

  • Violation prediction model (VPM). A Transformer encoder embeds the scene sequence; a single fully connected output gives a scalar that the paper describes as a violation probability.
  • SDC-Scissor. A classifier on static road features of the driving path gives a safe/unsafe score. The paper's Table 3 lists the features tab. 3.
  • Minimum distance between the ego vehicle and any other vehicle over the run.
  • Number of unique violations found in the run.

These four objectives are combined with NSGA-II, which keeps the Pareto-optimal set §4.2.1.

Crossover §4.2.2. Two parents exchange routes. The ego route and weather are kept unchanged. For NPCs, the trajectory of an NPC in one parent is tested against the ego trajectory of the other; if they intersect, an NPC is swapped with a randomly chosen NPC of the other parent. For pedestrians, the paper says half of them are swapped at random.

Mutation §4.2.3 alg. 1. An NPC is removed if its total path length is below a threshold w (stuck), or if its distance to the ego vehicle has not shrunk over any window of length u (leaving). The ego and remaining NPC routes are re-drawn on the same road, and removed NPCs are replaced by vehicles with random start and end points. Pedestrians are spawned near the ego vehicle, and weather is re-sampled §4.2.3. The distance matrix used by the algorithm is defined in §4.2.3 (unnumbered equation).

Pseudocode
# Distance-guided mutation  [alg. 1] [§4.2.3]
# Input:  npcs (NPC routes), ego (route), dist (T, |V|, |V|) distance matrix
#         stuck_w (path length threshold), window_u (window, in seconds)
# Output: NPC routes for the offspring

def mutate_npcs(npcs, ego, dist, stuck_w, window_u):
    # Mark NPCs whose total path length is below the threshold  [alg. 1]
    removed = set()
    for npc in npcs:
        if path_length(npc) < stuck_w:
            removed.add(npc)
            continue
        # Mark NPCs whose distance to the ego never shrinks in a window
        # [alg. 1] [§4.2.3]
        if never_closing(npc, ego, dist, window_u):
            removed.add(npc)
    # Keep the other NPCs on their road, re-route the ego  [alg. 1]
    kept = [reroute_same_road(npc) for npc in npcs if npc not in removed]
    ego = reroute_same_road(ego)
    # Replace each removed NPC with one on a random route  [alg. 1]
    new_npcs = [random_npc() for _ in removed]
    return kept + new_npcs

Feedback features into the model (code path, see Paper vs code). Positions are shifted so that the ego's first position is the origin, duplicate frames are dropped, and the sequence is passed to the model without padding [code: fuzz.py#L368-L378].

Violations §4.3. Five types are detected: collision and lane invasion (CARLA sensors), speeding (ego speed above the limit for a duration T_speeding), running a red light, and stuck (ego stationary for a duration T_stuck). Each violation is saved with its scenario and a CARLA recording so it can be replayed §4.3.

Loop. Seeds are random ego routes in Town03 §5.1.2. Offspring are created with crossover and mutation probability 0.5 each, evaluated, and merged into the population by NSGA-II §5.1.2 §4.2.1 fuzz.py. The paper does not give the loop's stopping rule beyond the time budgets in §5.2.

Training of the VPM and SDC-Scissor §5.1.2. The authors generate 1,000 short scenarios of 2 minutes each, and train the VPM with Adam, learning rate 0.001, binary cross-entropy and early stopping (patience 10 epochs). SDC-Scissor is trained with logistic regression.

Hyperparameters

NameValueWhereNotes
Population size20§5.1.2Paper value. Repo default is 10 fuzz.py
Crossover probability0.5§5.1.2Code uses the same value fuzz.py
Mutation probability0.5§5.1.2Code uses the same value fuzz.py
Simulator frame rate20 Hz§5.1.2Code: fixed step 1/20 s sim_executor.py
Maximum simulation length10 min§5.1.2Code: 60 × 10 s loop sim_executor.py
MapTown03§5.1.2Code default fuzz.py
Scenario composition1 ego, 2 NPC vehicles, 10 pedestrians§5.1.2Code fuzz.py
VPM embedding dimension128tab. 4Code: model width is 21 (3 × 7); 128 is the feed-forward width models.py models.py
VPM heads3tab. 4Code: heads = car number = 3 fuzz.py models.py
VPM encoder layers3tab. 4Code default is 2 and the fuzzer does not override it models.py models.py
VPM dropoutnot stated§5.1.2Code: 0.2 models.py
VPM optimiserAdam, lr 0.001§5.1.2Training code not in repo
VPM lossbinary cross-entropy§5.1.2Training code not in repo
VPM early stoppingpatience 10 epochs§5.1.2Training code not in repo
VPM training data1,000 scenarios, 2 min each§5.1.2Not in repo
Stuck-vehicle threshold w10 mtab. 4Code uses 5 m for NPCs fuzz.py; 10 m for ego route fuzz.py
Leaving-vehicle window u10 stab. 4Code uses 60 frames (3 s at 20 Hz) fuzz.py
Pedestrian distance bound20 mtab. 4Code spawns in a ±30 m box, minimum 10 m fuzz.py
Pedestrian speednot stated—Code: uniform 0 to 10 fuzz.py
SDC-Scissor modellogistic regression§5.1.2Code loads a joblib model with predict_proba; type not checked fuzz.py fuzz.py
Speeding grace period Tnot stated§4.3Code: 3 s sim_executor.py
Stuck duration T_stucknot stated§4.3Code: speed under 1 km/h for 60 s sim_executor.py
Unique-violation match±10 s, ±30 m§5.1.3Dedup in the fuzzer uses 20 s and 5 m fuzz.py
Run length3 h ablation, 6 h comparison§5.2.1 §5.2.2Code loop stops at 6 h fuzz.py

Results

Author-reported. Setup: InterFuser as the ADS under test, CARLA, Town03, 20 Hz, 10-minute simulations, one seed set shared by all fuzzers §5.1. The paper does not state hardware; the repository README lists an RTX 3090 GPU and CARLA 0.9.13 README.md.

SettingMetricBaselineThis paperSource
Ablation, 3 h: R+R vs VS+DUnique violations1424§5.2.1 fig. 7
6 h vs AV-FuzzerUnique violations335§5.2.2 fig. 8
6 h vs DriveFuzzUnique violations1835§5.2.2 fig. 8
6 h vs TM-FuzzerUnique violations2635§5.2.2 fig. 8
First collisionTime21 min (TM-Fuzzer)17 min§5.2.2
Composition of the 35Collisions / lane invasions / stuck—4 / 20 / 11§5.2.2
Speeding or red-light violationsCount—0 for all fuzzers§5.2.2
Ego trajectory coverage, Town03Share of waypointsAV-Fuzzer 3.04%, DriveFuzz 13.85%, TM-Fuzzer 24.88%, R+R 19.65%61.25% (VS+D)§5.2.3 fig. 13
NPCs within 50 m of ego, 3 hCountVS+R 23VS+D 35tab. 5

Margins quoted in the text: 32 over AV-Fuzzer, 27 over DriveFuzz and 9 over TM-Fuzzer §5.2.2 §7. The 6-hour counts above give 32 and 9 but 17 for DriveFuzz (see Pitfalls).

Violation types reported in tab. 6: four collisions (one with a pedestrian, three with vehicles), two lane invasions and two stuck cases. All eight reproduced §5.2.2.

Paper vs code

Official repository: yagol2020/SimADFuzz (Apache-2.0), cloned at a4930f58c28797b16aa51e77e3d93a14e093cdd1. The paper does not print the URL; the link was found through a GitHub search on the title. The owner is "Yagol" at NUAA, the university of the first two authors, and the handle matches the first author's e-mail in the paper header. This is the basis for treating the repository as the authors' own; the paper itself does not link it. The repository README gives a figshare DOI, 10.6084/m9.figshare.28769768 README.md.

  • Transformer size. Paper: embedding 128, 3 heads, 3 layers tab. 4. Code: input width 21, 3 heads, 2 layers, feed-forward width 128 models.py fuzz.py. The released checkpoint's layer count was not checked.
  • Output nonlinearity. Paper: the output node gives a probability §4.2.1. Code: a raw linear output, no sigmoid; the fitness uses this raw value models.py fuzz.py.
  • Sequence model. Paper: no positional encoding is mentioned §4.2.1. Code: none is added; the last time step of the encoder is used as the feature models.py.
  • Population size. Paper: 20 §5.1.2. Code: 10 fuzz.py and README README.md.
  • Pedestrian swap. Paper: half of the pedestrians are swapped at random §4.2.2. Code: random.choices draws indices with replacement, five draws fuzz.py; repeated indices swap twice and cancel out.
  • Weather in crossover. Paper: weather is unchanged by crossover §4.2.2. Code: each weather value is swapped with probability 0.5 fuzz.py.
  • Mutation with restart. Paper: mutation always changes the parent's NPCs and pedestrians §4.2.3. Code: with probability 0.5, or when the ego route is shorter than 10 m, the parent is discarded and a new random scenario is made fuzz.py.
  • Stuck NPC threshold. Paper: 10 m tab. 4. Code: 5 m fuzz.py.
  • Leaving window. Paper: 10 s tab. 4. Code: 60 frames, 3 s at 20 Hz fuzz.py sim_executor.py.
  • Pedestrian placement. Paper: spawned within 20 m of the ego tab. 4. Code: a ±30 m box fuzz.py; the coordinates drawn after the 10 m check are drawn again without it fuzz.py.
  • SDC-Scissor input. Paper: SDC-Scissor classifies the scenario §4.2.1. Code: a probability is computed for every vehicle, but only the ego value is used as fitness fuzz.py fuzz.py. Features come from a separate service on port 12555 models.py README.md.
  • Unique-violation rule. Paper: ±10 s and ±30 m §5.1.3. Code: two violations are the same if they are within 20 s and either axis is within 5 m fuzz.py. The evaluation script that produced the paper's counts is not in the repository.
  • Training code. Paper gives Adam, BCE, early stopping and the 1,000-scenario dataset §5.1.2. The repository has no training script; it ships only the checkpoints Transformer.ck.pth and sdc.ck.pth.

No discrepancies were found for the 20 Hz rate, the 10-minute length, the 0.5 probabilities, the 6-hour loop, the seven vehicle features or the four fitness objectives.

Pitfalls

  • Inconsistent counts. The 6-hour DriveFuzz count is 18 §5.2.2, so 35 − 18 = 17, but the text and conclusion say 27 more §5.2.2 §7. Check the source before quoting the 27.
  • Raw score. The fitness uses the VPM's unbounded linear output models.py although the paper calls it a probability. Any reimplementation must choose; matching the code means no sigmoid.
  • Variable length. Duplicate frames are removed before the model fuzz.py, so T differs per run. The model takes no padding or mask.
  • No positional encoding is used, so frame order enters only through the attention pattern and the position of the last time step.
  • Checkpoint vs paper. The architecture in code differs from tab. 4. Use the checkpoint's own shapes if you need the exact model, and check them.
  • Missing training pipeline. The dataset, labels and optimiser code are not published; the VPM cannot be retrained from the repo.
  • Hard-coded CUDA. The model is moved to the GPU at import fuzz.py fuzz.py. Without a GPU the fuzzer will not start as written.
  • Cost. Each candidate is one simulation of up to 10 minutes [code: sim_executor.py#L472], and the evaluation loop runs them one after another fuzz.py fuzz.py. The number of simulations per hour is not stated.
  • Environment. Python 3.7 for the fuzzer, Python 3.10 for SDC-Scissor, CARLA 0.9.13 in Docker, and InterFuser weights are needed; the README asks the user to set res_path to a real directory README.md.
  • Early stops. A simulation that fails returns a sentinel and is dropped fuzz.py. Scenarios that end early (collision, goal reached, stuck) are scored on a shorter run sim_executor.py.
  • Only one ADS, one map. The authors list this as a threat to external validity §5.3; InterFuser's conservative settings (5 m/s limit, traffic-light confidence 0.3) explain why no speeding or red-light violation was found §5.2.2.
  • Baselines. The three baselines are described in one paragraph each §5.1.3; the paper gives no versions or settings for them.

Lineage

  • Builds on: genetic fuzzing with scenario selection, crossover and mutation (AV-Fuzzer, DriveFuzz, Doppel) §2 tab. 1; the Transformer encoder §4.2.1; NSGA-II selection §4.2.1; SDC-Scissor for road-feature classification §4.2.1.
  • Compared against: AV-Fuzzer, DriveFuzz and TM-Fuzzer §5.1.3. Doppel is discussed as prior work §3.
  • Superseded by: not known from content already in this wiki.

Source and license

Adapted from “SimADFuzz: Simulation-Feedback Fuzz Testing for Autonomous Driving Systems” by Huiwen Yang, Yu Zhou, Taolue Chen (arXiv:2412.13802), used under CC BY 4.0. Changes: condensed and restructured for implementation, with tables, equations and algorithms taken from the paper and its code, each cited to its source. Not affiliated with or endorsed by the authors. Code citations refer to https://github.com/yagol2020/SimADFuzz at commit a4930f58c287 (Apache-2.0). Any quoted code is shown under that license.