Validate design decisions, and test parameters of Leeds Gryphon Racing FS25/26 car
This simulator is a Quasi-static, steady-state lap time sim. Fancy words. What do they mean?
- Quasi-static: Break track into small segments, at each segment, determine what's the max speed, propagate speeds forwards, and backwards, and we get a nice speed profile!
- Steady-state: We assert all forces to be resolved at any point in time. (Especially lateral and yaw balance)
A more in-depth description of the simulator can be found on the wiki
This project is managed with uv. The easiest way to run the simulator and scripts is through uv run python <path-to-script> so everyone uses the same dependency environment.
Most day-to-day simulation changes should be made in config.json and parameters.json.
- Install Python
- Use a Python version compatible with
pyproject.toml(requires-python). - You can install Python from python.org or let
uvmanage Python versions.
- Install Git
- Download from git-scm.com.
- Install uv
- Official docs: docs.astral.sh/uv
Windows (PowerShell):
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"macOS / Linux:
curl -LsSf https://astral.sh/uv/install.sh | sh- (Recommended) VS Code + Python extension
- Visual Studio Code
- Python extension (
ms-python.python)
From your terminal:
git clone https://github.com/LGRSimulations/LGR_FullTrackQSLapTimeSim.git
cd LGR_FullTrackQSLapTimeSim
uv syncNotes:
uv synccreates/updates.venvand installs all dependencies.- You can run scripts without activating the environment by using
uv run .... - If you want to activate manually:
- Windows PowerShell:
.\.venv\Scripts\Activate.ps1 - macOS/Linux:
source .venv/bin/activate
- Windows PowerShell:
Major engineering updates are logged in:
docs/MAJOR_CHANGE_LOG.md
Use this template for every major change:
docs/CHANGE_ENTRY_TEMPLATE.md
Each entry must include:
- Problem (high-level and low-level)
- Diagnosis
- Solution and implementation
- Impact and explanation
The repository has been cleaned up so user-facing scripts live under a single tools/ directory:
tools/analysis/for analysis and validation utilitiestools/sweeps/for one-off test sweepstools/tracks/for track-generation scripts
You can run these from the repository root after uv sync:
- Simulator:
uv run python src/main.py - Parameter sweep:
uv run python src/sweep.py <param> <values> [--steps N] - A/B diagnostics:
uv run python src/ab_testing/run_ab_suite.py [flags] - Tyre verification (CSV/PNG/HTML):
uv run python tools/analysis/compare_tyre_model.py - Tyre verification with visual windows:
uv run python tools/analysis/compare_tyre_model.py --visualise - Corner archetypes analysis:
uv run python tools/analysis/corner_archetypes.py - Lift/coast sweep:
uv run python tools/sweeps/lift_coast_test.py - Straight-line traction test:
uv run python tools/sweeps/straight_line_test.py - Skidpad track generator:
uv run python tools/tracks/skidpad_creator.py - Straight track generator:
uv run python tools/tracks/straight_line_creator.py
Preferred workflow: use uv.
Run from repository root:
uv sync
# Main simulator
uv run python src/main.py
# Parameter sweep
uv run python src/sweep.py mass 250,350 --steps 5
# A/B diagnostics
uv run python src/ab_testing/run_ab_suite.py --output-dir ab_test_outputs/full_v1
# Tyre model verification
uv run python tools/analysis/compare_tyre_model.py
# Additional tools
uv run python tools/analysis/corner_archetypes.py
uv run python tools/sweeps/lift_coast_test.py
uv run python tools/sweeps/straight_line_test.py
uv run python tools/tracks/skidpad_creator.py
uv run python tools/tracks/straight_line_creator.py- Preferred:
uv run python src/main.py- Alternative after activating
.venv:
python src/main.pyThis runs the simulator and generates the plots/results for the track selected in config.json.
- Refer to
config.json, this is where we choose the datasets we want to use for the lap time sim. - Refer to
parameters.json - Datasets are found in the
datasetsfolder. Datasets include Powertrain, Tyre, FSUK track data, etc.
Run a lap time simulation while sweeping a single vehicle parameter over values.
From the project root:
uv run python src/sweep.py <param> <values> [--steps N]-
<param>Name of the vehicle parameter to sweep.- You can use either the internal attribute name (for example
aero_centre_of_pressure) or the JSON key (for exampleaero_cp).
- You can use either the internal attribute name (for example
-
<values>
Format depends on parameter type:- Numeric scalar:
min,maxfor range sweep (uses--steps) or explicit comma list. Example:250,350 - String: comma-separated explicit values.
Example:
F25_IC_Car,F26_IC_Car - List (for example
gear_ratios):- Single list: comma-separated items
Example:
2.75,2.0,1.667,1.304,1.208 - Multiple candidate lists: separate lists with
;, and wrap each list in[...]Example:[2.75,2.0,1.667,1.304,1.208];[3.2,2.3,1.9,1.5,1.35]
- Single list: comma-separated items
Example:
- Numeric scalar:
-
--steps N(optional)
Number of points in the sweep (default: 5).
Sweep from 250 to 350 with default steps (5) to artifacts/sweeps/mass_sweep.csv
uv run python src/sweep.py mass 250,350 --output artifacts/sweeps/mass_sweep.csvSweep with custom steps
uv run python src/sweep.py mass 250,350 --steps 10Sweep using JSON key alias
uv run python src/sweep.py aero_cp 0.8,1.2 --steps 5Sweep multiple gear ratio sets
uv run python src/sweep.py gear_ratios "[2.75,2.0,1.667,1.304,1.208];[3.2,2.3,1.9,1.5,1.35]"For each parameter value:
- Loads track from config.json
- Creates vehicle from config
- Runs run_lap_time_simulation
- Prints lap time results in the format:
mass = 250.00, Lap Time = 72.31 s
- If
--outputis omitted, the CSV is written toartifacts/sweeps/data.csv.
- The parameter must exist in vehicle.params
- Track path and vehicle configuration are read from config.json
Run the focused A/B diagnostic matrix to compare baseline behavior against candidate model variants (including tyre changes).
From the project root:
uv run python src/ab_testing/run_ab_suite.py --output-dir ab_test_outputs/full_v1- Tracks:
FSUK,SkidpadF26,StraightLineTrack - Variants: configurable via
--variants(default:baseline,b1,tyre_peak_load_clamp) - Parameters (focused 8):
downforce_coefficientaero_cpcog_zfront_track_widthrear_track_widthroll_stiffnessmax_roll_angle_degbase_mu
- Levels per parameter:
low,nominal,high(default ±20%)
ab_runs.csv: run-level records (status, lap time, fallback rate, fallback gate pass/fail, limiter mode breakdown)- Includes explicit rollover context columns:
rollover_modeanduse_rollover_speed_cap(alwaysrollover_on/true)
- Includes explicit rollover context columns:
ab_sensitivity.csv: per-track/variant sensitivity summary and stale flagsab_summary.md: human-readable diagnostic summary
uv run python src/ab_testing/run_ab_suite.py --tracks FSUK,SkidpadF26 --variants baseline,tyre_peak_load_clamp --fallback-threshold 0.15 --stale-threshold 0.05 --output-dir ab_test_outputs/customWhere:
--tracksselects a comma-separated subset of known tracks--variantsselects one or more model variants for quick A/B comparisons--fallback-thresholdsets pass/fail cutoff forfallback_rate--stale-thresholdsets stale sensitivity cutoff in seconds--output-dirselects artifact destination
Use this script to compare TTC tyre data against the current model and produce CSV/PNG/HTML artifacts.
Default run (recommended for CI and sharing):
uv run python tools/analysis/compare_tyre_model.pyRun with interactive visual windows:
uv run python tools/analysis/compare_tyre_model.py --visualiseRun validation gate with explicit threshold:
uv run python tools/analysis/compare_tyre_model.py --validate --rmse-threshold-pct 12
Run baseline vs tyre-clamp variant quickly with strict gates:
```bash
uv run python tools/analysis/compare_tyre_model.py --validate --model-variant baseline --rmse-threshold-pct 12 --max-high-load-growth-ratio 1.35
uv run python tools/analysis/compare_tyre_model.py --validate --model-variant tyre_peak_load_clamp --rmse-threshold-pct 12 --max-high-load-growth-ratio 1.05
Main outputs are written to:
- `artifacts/tyre_validation/tyre_model_verification.csv`
- `artifacts/tyre_validation/tyre_model_verification.html`
- `artifacts/tyre_validation/*.png`
### First-Principles Migration Plan
Use the milestone checklist for physics-first simulator hardening:
- `docs/FIRST_PRINCIPLES_MIGRATION_CHECKLIST.md`
### Milestone 1 Verification (One Command)
From the project root, run:
```bash
uv run python -m unittest tests.test_limiting_case_contracts -v
uv run python tools/analysis/m1_magic_constant_scan.py --strict
This validates:
- limiting-case solver behavior
- equation units contracts
- sign-convention symmetry
- residual telemetry presence/finite values for solved points
- strict undocumented-constant scan for core solver files
From the project root, run:
uv run python -m unittest tests.test_tyre_force_contracts tests.test_tyre_peak_load_clamp_contracts tests.test_tyre_validity_domain_contracts -v
uv run python tools/analysis/compare_tyre_model.py --validate --model-variant tyre_peak_load_clamp --rmse-threshold-pct 12 --max-high-load-growth-ratio 1.05 --max-out-of-domain-count -1
uv run python src/ab_testing/run_ab_suite.py --tracks StraightLineTrack --variants baseline --output-dir ab_test_outputs/m2_domain_smoke --fallback-threshold 0.15 --stale-threshold 0.05 --max-out-of-domain-count -1Hard gate baseline (measured):
- FSUK baseline max
tyre_out_of_domain_total=129380 - SkidpadF26 baseline max
tyre_out_of_domain_total=0 - StraightLineTrack baseline max
tyre_out_of_domain_total=0 - Recommended global threshold:
130000
Strict command (fails with non-zero exit if any run exceeds threshold):
uv run python src/ab_testing/run_ab_suite.py --tracks FSUK,SkidpadF26,StraightLineTrack --variants baseline --output-dir ab_test_outputs/m2_domain_hard_gate --fallback-threshold 0.15 --stale-threshold 0.05 --max-out-of-domain-count 130000Notes:
--max-out-of-domain-count -1keeps out-of-domain telemetry enabled in reporting mode.- Non-negative thresholds enable hard-gate behavior for CI.
From the project root:
uv sync
uv run python src/main.py
uv run python src/sweep.py mass 250,350 --steps 5
uv run python src/ab_testing/run_ab_suite.py --output-dir ab_test_outputs/full_v1
uv run python tools/analysis/compare_tyre_model.pyOpen an issue or discussion! Ping me (Branson Tay) a Teams or LinkedIn message, am happy to discuss the simulator in more detail.