Skip to content

Repository files navigation

FS_MinLapTime

A lap time simulator written in MATLAB. Give it a circuit and a car, and it searches for the racing line and the speed profile that minimise the lap time — then renders the result at 1:1 scale.

Personal project, built from scratch. Still in development — I know there is more to add, and what comes next is written down rather than left vague.

A lap of Silverstone

F1 2026 preset at Silverstone — 88.3 s, 6.1 g peak. The car is 1.90 m wide on an 11-to-18 m ribbon, and it is never scaled up to read better on screen.


What it does

Racing line Minimum-curvature QP, constrained by the track width
Speed Forward-Backward integration over a speed-dependent acceleration envelope
Vehicle Point mass, or a four-wheel model (loads, μ(T, Fz), transfer, brake balance)
Circuits A generated Formula Student autocross; Monza and Silverstone from the TUM database
Output Lap time, analysis figures, and a 1:1 scale 3D render

The physics simulator is the only judge. Every candidate — including the ones proposed by a learned model — is scored by the same Forward-Backward pass. Nothing in this project grades its own output.


Results

The racing line, for a given car

Skidpad Autocross Monza Silverstone
Length 57.3 m 234.0 m 5 790.5 m 5 887.2 m
Centreline (naive) 4.825 s 15.905 s 143.576 s —
Optimised line 4.539 s 13.475 s 133.795 s —
Gain −5.9 % −15.3 % −6.8 % —
Solve time 1.2 s 0.9 s 6.4 s —

Monza measures 5 790.5 m against 5 793 m official — 0.04 % error on the TUM geometry. The gain is smaller there than on the autocross, which is exactly right: on a straight there is no line to optimise.

The car, once the setup is searched

Autocross Monza
Baseline setup 13.455 s 123.229 s
Optimised setup 12.135 s 116.407 s
Gain −1.320 s −6.822 s
Cl found −2.38 (at the bound) −0.84 (interior optimum)

The downforce/drag trade reverses between circuits. On Monza it is interior: even on the fastest track of the set, the car wants some downforce for the chicanes — but only just.

Two vehicle models, same track

Point mass Four wheels
Autocross, FS car 13.475 s 13.709 s (+0.234)
Monza, F1 2026 preset — 81.038 s · 326 km/h
Silverstone, F1 2026 preset — 88.341 s · 324 km/h · 6.08 g

The four-wheel model is slower, and that is the expected result: load sensitivity makes weight transfer a net loss, the tyres are not at their optimum temperature, and traction is limited by the rear axle alone. The point mass replaced all three with a single coefficient.


In pictures

Elimination race Autocross
Elimination race — 30 lines start, 2 finish. This is the judge behind the whole project. FS autocross — 234 m, a 3.5 m ribbon, a 1.20 m car.
Monza Engineering HUD
Monza — 5 791 m played in 13.6 s (×6). The model, made visible — downforce in multiples of weight, drag in kN, both accelerations in g.
F1 2026 preset Formula Student car
F1 2026 preset — 5.50 × 1.90 m, bodywork built from lofted superelliptic cross-sections. Formula Student car — 2.80 × 1.20 m, roll hoops, high rear wing on visible struts.
Silverstone Acceleration envelope
Silverstone, whole — 5 887 m. At the start line the car is 0.05 % of the lap. That is correct, and it does not get enlarged. The four-wheel envelope — what Forward-Backward actually reads: lateral ceiling, rear-axle-limited traction, braking capped by the hardware.

Tyre temperatures

The four tyre temperatures around a lap of Silverstone. The rear left runs hottest — it is the outside wheel through the fast right-handers that dominate this circuit.

Full videos (13 clips, 2560 × 1440): see the Releases tab. The repository keeps only GIFs so it stays quick to clone.


How it works

circuit + car
      │
      ├─ Method A ────── minimum-curvature QP, blend-weight sweep
      │                  every candidate scored by a real Forward-Backward lap
      │
      ├─ vehicle model
      │     ├─ point mass  → friction ellipse, single μ
      │     └─ four wheels → 4 vertical loads, μ(T, Fz), weight transfer,
      │                      brake balance, driven rear axle
      │                      └─ envelope_to_gg → 3 curves
      │
      └─ Forward-Backward ── speed profile, THE SAME in both cases

Three decisions that shape everything else

The judge never changes. Method A does not return an "optimal" line in the QP sense. It produces a family of candidates and makes them all drive, then keeps the fastest. The criterion is lap time, not integrated curvature.

The four-wheel model does not touch the solver. It resolves the four contact patches off-line and hands over three curves — ay_max(v), traction, braking — in the shape gg_diagram already consumed. A vehicle without that field takes the old path instruction for instruction, which is what keeps every earlier lap record bit-exact.

Temperature closes a loop from the outside. Grip depends on tyre temperature, tyre temperature depends on how hard the lap is driven, and Forward-Backward has no state to hold a temperature in. So: envelope → lap → temperatures along that lap → envelope again. Damped by half, without which it cycles instead of settling.


What I learned by getting it wrong

These four cost real time, and each one forced a change deeper than a patch.

A comparison that rewarded the wrong winner. In the elimination race, each line was compared against the others on its own arc length. A longer trajectory therefore looked like it was ahead. Fixed by projecting everyone onto the circuit's arc length (PaceReference = "track"), and the ranking inverted.

A numerical guard mistaken for physics. v_max = 45 m/s was a solver guard rail, not a property of the car. On Monza it clipped the lap, and 12.2 of the seconds credited to an aerodynamic gain were nothing but that clip. It is now lifted per run, never globally.

A penalty measured on the wrong quantity. Off-track distance was computed on the clipped line rather than the one actually simulated. The surrogate model was therefore learning noise: 0.2 s validation error against a 3 s expected gain.

A slip curve inconsistent with its own definition. The supplied formula returned 0.30 at the operating slip of a tyre whose peak is documented as 1. Applied as written it made the F1 car slower than the Formula Student one. I normalised it and wrote down why, instead of copying it and shipping a wrong number.


What it does not do

Stated here rather than discovered by a careful reader.

  • No DRS. The JSON fields exist; nothing reads them.
  • No suspension. Only the hook is written; vertical loads stay quasi-static.
  • Aerodynamics are four numbers (Cl, Cd, S, balance). No map, no ride height, no dirty air, no wing flex.
  • Tyres are three effects, not a Pacejka fit — nobody publishes the coefficients of a current racing tyre.
  • The F1 lap times are orders of magnitude, not predictions. TUM centreline, one aero package for every circuit. The OpenF1 cross-check gives +23 km/h at Monza and +7 at Silverstone: reported, not corrected — recalibrating on one circuit would falsify the other.
  • The learning loop does not beat Method A. Gains are hundredths of a second. That is in the report rather than hidden.
  • The renderer is MATLAB graphics, not a game engine.

Getting started

cd FS_MinLapTime
addpath scripts
setup_project          % paths, vehicle parameters, project status
run_optimization       % optimise, plot, save the record

A few useful entry points:

run_full_pipeline("monza")                         % line, energy, figures, animation
run_swarm_visualization("autocross", N = 30)       % the elimination race
run_v5_setup_opt("monza")                          % search Cl, Cd, mu
run_v10_lap("silverstone", "f1_2026")              % a lap with the four-wheel model
run_v11_cinematic("monza", "f1_2026")              % the render
build_linkedin_pack                                % the videos and their captions

The car is a JSON file you load, paint and edit:

car = load_car("f1_2026");
car.aero.Cl = -2.60;
save_car(car, "cars/monza_pack.json");
run_v10_lap("monza", "cars/monza_pack.json");

Required: MATLAB R2026a and the Optimization Toolbox. Everything else is optional — the project detects what is installed and falls back to an in-repo implementation otherwise.

How it is actually developed

From a Linux shell driving a MATLAB session on Windows, both working on one tree with no copying: the repository lives in WSL 2, MATLAB opens it over \\wsl.localhost\, and git, gh and ffmpeg stay native on the Linux side.

   Ubuntu 24.04 (WSL 2)                     Windows 11
   /root/FS_MinLapTime                      MATLAB R2026a
   git · gh · ffmpeg · bash                 cd \\wsl.localhost\Ubuntu\...
              └──────── the same files ────────┘

It costs a handful of specific gotchas — save -v7.3 fails over the SMB layer, MATLAB cannot receive change notifications so rehash path is mandatory after creating a file, and a long-lived session hides a broken one until you start cold. All of them are written down, with what they cost, in docs/workflow.md.


Repository layout

Folder
optim/ Method A, Method B, Forward-Backward
vehicle/, data/ vehicle and tyre models, acceleration envelope
cars/ JSON cars, loader, editor, OpenF1 cross-check
tracks/ track generation and TUM import
swarm/ the elimination race
setup_opt/, ml/, ml_driver/ setup search, learning loops
unreal/ track render and cinematic render
scripts/ the entry points
docs/ detailed documentation

Source code, function headers and comments are in English throughout, as are the ten documents linked below. Eight further notes in docs/ — the version-by-version development log and the per-module write-ups nothing here links to — are still in French, and say so at the top. Ask and I will translate any of them.


Documentation

docs/architecture.md data flow, what each file is for
docs/optimization_method.md Methods A, B, B_smooth
docs/vehicle_model.md point mass and the g-g diagram
docs/vehicle_v10.md JSON cars, four-wheel tyres, editor
docs/track_format.md track format and TUM import
docs/swarm_visualization.md the elimination race
docs/setup_optimization.md setup search, drag polar
docs/ml_training.md learning loop, line encoding
docs/cinematic_render.md the renderer, lofts, camera
docs/how_to_run.md step-by-step tutorial
docs/workflow.md the development setup: a Linux shell driving MATLAB
docs/development_log.md the full log, V1 → V12

Current status

This model is still under development, and I am well aware there is more to add. What runs today is listed above. What I have already identified, and have not written yet:

  • Suspension. vehicle/suspension_none.m already fixes the signature a real model must respect. What it will change is the split of lateral load transfer between the axles — which is what roll stiffness distribution actually controls, and the single biggest simplification left in the vehicle model.
  • Per-corner tyre temperature instead of a lap average. The per-point trace is real; the feedback onto grip is currently averaged over the lap.
  • Coupled ax/ay solved across the four contact patches, rather than the friction ellipse used today.
  • Wear and compounds — this simulates one lap, not a stint.
  • Validation against real track data, which is the one thing that would turn orders of magnitude into predictions.

Each version so far started from a written specification and ended with a report that says what did not work as well as what did — the full history is in docs/development_log.md. I would rather show a model whose limits I can name than one that looks finished.


Licence and data

Code under the MIT licence — see LICENSE.

The Monza and Silverstone geometries come from TUMFTM/racetrack-database (LGPL v3) and are not redistributed here; download_tum_tracks(["Monza", "Silverstone"], Import = true) fetches them. Cross-check speeds come from OpenF1, read-only.

The f1_2026 preset is calibrated on the public FIA 2026 regulations and published orders of magnitude. It uses no team data and no licensed tyre model, and its source field states which of its numbers are regulatory and which are estimates.

About

Lap time simulator in MATLAB: minimum-curvature racing line, Forward-Backward speed profile, four-wheel tyre model, 1:1 scale render

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages