@inventure71/paddockjs 4.1.0 → 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +76 -0
- package/INSTALL_AND_UPDATE.md +31 -5
- package/README.md +34 -3
- package/docs/advanced_ai_pace.md +131 -0
- package/docs/advanced_physics_rebuild.md +166 -0
- package/docs/architecture.md +111 -30
- package/docs/cleanup_coverage.md +284 -0
- package/docs/component_inventory.md +32 -16
- package/docs/composable-layouts.md +2 -0
- package/docs/concepts.md +12 -1
- package/docs/custom_model_controller.md +1 -1
- package/docs/data_contract.md +33 -10
- package/docs/data_model.md +4 -2
- package/docs/efficiency_cleanup_2026-10-13.md +80 -0
- package/docs/getting-started.md +3 -0
- package/docs/grid_walk.md +80 -0
- package/docs/index.md +5 -2
- package/docs/keyboard_driving_fix.md +118 -0
- package/docs/limit_driving_2026-10-14.md +88 -0
- package/docs/loading.md +141 -0
- package/docs/maintainability_audit_2026-09-08.md +146 -0
- package/docs/racing_ai_improvements.md +145 -0
- package/docs/rules.md +43 -13
- package/docs/sense_contract.md +4 -1
- package/docs/system_specs.md +40 -12
- package/docs/testing-reliability-guide.md +67 -0
- package/docs/v11_improvements.md +108 -0
- package/package.json +23 -15
- package/src/api/MountedSimulatorComponents.js +101 -0
- package/src/api/PaddockSimulatorController.js +56 -81
- package/src/app/BrowserExpertAdapter.js +0 -6
- package/src/app/BrowserExpertExternalRenderer.js +72 -50
- package/src/app/ExternalTrackSnapshot.js +50 -0
- package/src/app/F1SimulatorApp.js +242 -297
- package/src/app/HostLifecycleEmitter.js +93 -0
- package/src/app/banners/raceDataBannerController.js +9 -4
- package/src/app/camera/cameraConstants.js +1 -1
- package/src/app/camera/cameraController.js +10 -13
- package/src/app/camera/cameraGeometry.js +1 -1
- package/src/app/controls/SimulatorViewControls.js +45 -0
- package/src/app/controls/workbenchBindings.js +64 -0
- package/src/app/controls/workbenchDisclosure.js +41 -0
- package/src/app/domBindings.js +21 -13
- package/src/app/gridWalk/GridWalkController.js +180 -0
- package/src/app/gridWalk/gridWalkCamera.js +88 -0
- package/src/app/gridWalk/gridWalkControls.js +24 -0
- package/src/app/gridWalk/gridWalkCrew.js +246 -0
- package/src/app/gridWalk/gridWalkLabels.js +104 -0
- package/src/app/gridWalk/gridWalkLayout.js +46 -0
- package/src/app/gridWalk/gridWalkNavigation.js +99 -0
- package/src/app/gridWalk/gridWalkProjectBanner.js +43 -0
- package/src/app/gridWalk/gridWalkSession.js +50 -0
- package/src/app/layoutSupport.js +2 -0
- package/src/app/raceOverlayClearanceSupport.js +21 -7
- package/src/app/readouts/carOverviewRenderer.js +9 -4
- package/src/app/readouts/readoutFormatters.js +1 -8
- package/src/app/readouts/telemetryRenderer.js +1 -3
- package/src/app/readouts/timingTowerRenderer.js +48 -50
- package/src/app/rendering/appAssets.js +8 -10
- package/src/app/rendering/carRenderer.js +27 -79
- package/src/app/rendering/displayUtils.js +0 -6
- package/src/app/rendering/expertSensorRenderer.js +1 -1
- package/src/app/rendering/replayGhostRenderer.js +4 -1
- package/src/app/rendering/trackRenderer.js +2 -2
- package/src/app/runtime/frameLoop.js +18 -17
- package/src/app/runtime/pixiStartupLifecycle.js +94 -0
- package/src/app/runtime/runtimeTiming.js +4 -1
- package/src/app/runtime/runtimeVisibility.js +7 -2
- package/src/config/cssValues.js +1 -1
- package/src/config/defaultOptions.js +12 -173
- package/src/config/restartOptions.js +1 -0
- package/src/config/runtimeSeed.js +10 -0
- package/src/config/simulatorDefaults.js +106 -0
- package/src/config/telemetryModules.js +20 -0
- package/src/config/theme/cssTokens.js +85 -0
- package/src/config/theme/themeCss.js +72 -0
- package/src/config/theme/themeInputs.js +155 -0
- package/src/config/theme/themeResolver.js +172 -0
- package/src/config/theme/themeSelectors.js +69 -0
- package/src/config/theme/themeTokens.js +257 -0
- package/src/config/theme/themeUtils.js +15 -0
- package/src/config/themeOptions.js +14 -830
- package/src/config/timingGapMode.js +0 -2
- package/src/config/uiOptions.js +53 -0
- package/src/data/championship.js +16 -158
- package/src/data/championshipDefaults.js +87 -0
- package/src/data/driverData.js +10 -20
- package/src/data/entryIdentity.js +67 -0
- package/src/data/entryPresentation.js +23 -0
- package/src/data/entryTypes.d.ts +160 -0
- package/src/data/index.d.ts +12 -195
- package/src/data/ratingScale.js +14 -0
- package/src/data/teamTypes.d.ts +23 -0
- package/src/data/trackTypes.d.ts +101 -0
- package/src/data/vehicleData.js +12 -23
- package/src/environment/actions.js +3 -2
- package/src/environment/controllerLoop.js +57 -44
- package/src/environment/controllerScheduler.js +30 -0
- package/src/environment/driverObservations.js +260 -0
- package/src/environment/driverReset.js +51 -0
- package/src/environment/episode.js +0 -1
- package/src/environment/evaluation.js +6 -90
- package/src/environment/evaluationTracker.js +100 -0
- package/src/environment/events.js +23 -0
- package/src/environment/index.d.ts +35 -91
- package/src/environment/metrics.js +3 -17
- package/src/environment/observationSchema.js +104 -0
- package/src/environment/observationVector.js +16 -115
- package/src/environment/observations.js +16 -316
- package/src/environment/options.js +5 -24
- package/src/environment/renderFrames.js +21 -0
- package/src/environment/resetOptions.js +41 -0
- package/src/environment/results.js +125 -0
- package/src/environment/rewards.js +10 -16
- package/src/environment/runtime.js +17 -300
- package/src/environment/scenarioOptions.js +90 -0
- package/src/environment/scenarioPlacements.js +70 -0
- package/src/environment/scenarioPresets.js +78 -0
- package/src/environment/scenarios.js +5 -236
- package/src/environment/scratch.js +18 -0
- package/src/environment/sensorOptions.js +20 -0
- package/src/environment/sensors/index.js +2 -556
- package/src/environment/sensors/indexedRayBands.js +0 -18
- package/src/environment/sensors/nearbyCars.js +18 -15
- package/src/environment/sensors/opponentRadar.js +3 -2
- package/src/environment/sensors/pitConnectorProximity.js +20 -0
- package/src/environment/sensors/rayBandTrace.js +1 -37
- package/src/environment/sensors/rayBatch.js +81 -0
- package/src/environment/sensors/rayConfig.js +26 -0
- package/src/environment/sensors/rayGeometry.js +0 -8
- package/src/environment/sensors/rayGuards.js +0 -6
- package/src/environment/sensors/rayOutputs.js +75 -0
- package/src/environment/sensors/rayQuery.js +110 -0
- package/src/environment/sensors/rayScratch.js +146 -0
- package/src/environment/sensors/sensorTargets.js +12 -4
- package/src/environment/sensors/surfaceRays.js +6 -61
- package/src/environment/sensors/trackRays.js +7 -80
- package/src/environment/simulationSetup.js +30 -0
- package/src/environment/specs.js +15 -109
- package/src/index.d.ts +43 -202
- package/src/index.js +28 -6
- package/src/placeholder/index.js +1 -8
- package/src/rendering/displayLifecycle.js +6 -0
- package/src/rendering/proceduralTrackAsset.js +1 -1
- package/src/rendering/renderSnapshot.js +3 -0
- package/src/rendering/track/finishLineRenderer.js +1 -1
- package/src/rendering/track/gridRenderer.js +1 -1
- package/src/rendering/track/offsetStrokeSafety.js +2 -2
- package/src/rendering/track/pitLaneRenderer.js +1 -1
- package/src/rendering/track/trackMaterialRenderer.js +4 -4
- package/src/rendering/track/trackRenderConstants.js +0 -1
- package/src/rendering/track/trackRenderGeometry.js +1 -7
- package/src/simulation/collisionGeometry.js +12 -20
- package/src/simulation/driver/advancedPathControls.js +53 -0
- package/src/simulation/driver/advancedRacePace.js +112 -0
- package/src/simulation/driver/advancedRacingControls.js +61 -0
- package/src/simulation/driver/advancedRacingEnvelope.js +255 -0
- package/src/simulation/driver/advancedRacingSteering.js +76 -0
- package/src/simulation/driver/advancedRacingTiming.js +16 -0
- package/src/simulation/driver/arcadeRacePace.js +83 -0
- package/src/simulation/driver/arcadeRacingControls.js +111 -0
- package/src/simulation/driver/arcadeRacingEnvelope.js +63 -0
- package/src/simulation/driver/driverControlConstants.js +0 -2
- package/src/simulation/driver/driverController.js +16 -5
- package/src/simulation/driver/edgeRecovery.js +2 -3
- package/src/simulation/driver/racingControls.js +10 -396
- package/src/simulation/driver/racingDriverProfile.js +48 -0
- package/src/simulation/driver/racingLinePlan.js +54 -20
- package/src/simulation/driver/rejoinControls.js +59 -112
- package/src/simulation/driver/safetyCarControls.js +12 -0
- package/src/simulation/driver/trafficScan.js +136 -27
- package/src/simulation/participants/participantInteractions.js +24 -15
- package/src/simulation/pit/pitCarPlacement.js +29 -0
- package/src/simulation/pit/pitFlow.js +8 -30
- package/src/simulation/pit/pitIntent.js +4 -3
- package/src/simulation/pit/pitOccupancy.js +2 -2
- package/src/simulation/pit/pitQueue.js +2 -18
- package/src/simulation/pit/pitRouteMovement.js +1 -36
- package/src/simulation/pit/pitRouting.js +5 -81
- package/src/simulation/pit/pitService.js +3 -32
- package/src/simulation/pit/pitServiceConstants.js +1 -0
- package/src/simulation/pit/pitServiceProgress.js +34 -0
- package/src/simulation/pit/pitSnapshots.js +8 -4
- package/src/simulation/pit/pitState.js +1 -5
- package/src/simulation/race/classification.js +1 -8
- package/src/simulation/race/raceFinish.js +3 -8
- package/src/simulation/race/raceOrder.js +2 -13
- package/src/simulation/race/raceProgress.js +6 -20
- package/src/simulation/race/raceSetup.js +1 -1
- package/src/simulation/race/raceStep.js +20 -11
- package/src/simulation/race/redFlag.js +2 -4
- package/src/simulation/race/safetyCar.js +5 -9
- package/src/simulation/race/stalledDnf.js +2 -4
- package/src/simulation/raceSimulation.js +6 -38
- package/src/simulation/replay/replayGhosts.js +44 -32
- package/src/simulation/rules/collisionSteward.js +0 -14
- package/src/simulation/rules/penaltyActions.js +37 -0
- package/src/simulation/rules/penaltyLedger.js +8 -1
- package/src/simulation/rules/pitLaneSpeedingSteward.js +1 -1
- package/src/simulation/rules/rulesReview.js +20 -16
- package/src/simulation/rules/trackLimitsSteward.js +2 -2
- package/src/simulation/simMath.js +4 -0
- package/src/simulation/snapshots/raceSnapshots.js +30 -11
- package/src/simulation/timing/drsState.js +8 -0
- package/src/simulation/timing/drsTiming.js +2 -4
- package/src/simulation/timing/lapTelemetry.js +7 -4
- package/src/simulation/timing/sectorPerformance.js +14 -6
- package/src/simulation/timing/timingLines.js +12 -6
- package/src/simulation/track/pitLaneAccess.js +2 -2
- package/src/simulation/track/pitLaneLayout.js +4 -135
- package/src/simulation/track/pitLaneModel.js +70 -0
- package/src/simulation/track/pitLaneState.js +0 -1
- package/src/simulation/track/pitServiceLayout.js +121 -0
- package/src/simulation/track/proceduralTrack.js +77 -0
- package/src/simulation/track/spatialQueries.js +76 -31
- package/src/simulation/track/trackBuilder.js +54 -0
- package/src/simulation/track/trackConstants.js +0 -22
- package/src/simulation/track/trackMath.js +4 -29
- package/src/simulation/track/trackModel.js +12 -240
- package/src/simulation/track/trackModelCache.js +105 -0
- package/src/simulation/track/trackNearestQueries.js +1218 -0
- package/src/simulation/track/trackQueryConstants.js +3 -0
- package/src/simulation/track/trackQueryConstruction.js +368 -0
- package/src/simulation/track/trackQueryIndex.js +12 -1933
- package/src/simulation/track/trackQuerySegments.js +174 -0
- package/src/simulation/track/trackQueryStats.js +12 -0
- package/src/simulation/track/trackRayQueries.js +165 -0
- package/src/simulation/vehicle/advancedContactResponse.js +89 -0
- package/src/simulation/vehicle/advancedTireForces.js +92 -0
- package/src/simulation/vehicle/advancedVehicleModel.js +65 -0
- package/src/simulation/vehicle/advancedVehiclePhysics.js +127 -0
- package/src/simulation/vehicle/contactResolution.js +23 -9
- package/src/simulation/vehicle/mainTrackWheelSurface.js +2 -13
- package/src/simulation/vehicle/pitWheelSurface.js +0 -12
- package/src/simulation/vehicle/runoffResponse.js +2 -4
- package/src/simulation/vehicle/sampledWheelSurface.js +266 -0
- package/src/simulation/vehicle/vehicleGeometry.js +85 -103
- package/src/simulation/vehicle/vehicleKinematics.js +10 -0
- package/src/simulation/vehicle/vehiclePhysics.js +42 -196
- package/src/simulation/vehicle/vehicleSnapshots.js +18 -6
- package/src/simulation/vehicle/vehicleState.js +5 -3
- package/src/simulation/vehicle/wheelSurface.js +13 -432
- package/src/simulation/vehicle/wheelSurfaceCache.js +55 -0
- package/src/simulation/vehicle/wheelSurfaceSummary.js +101 -0
- package/src/styles.css +173 -19
- package/src/ui/bannerTemplates.js +4 -2
- package/src/ui/cameraControlsTemplate.js +4 -2
- package/src/ui/gridWalkTemplate.js +29 -0
- package/src/ui/htmlEscaping.js +8 -0
- package/src/ui/raceCanvasTemplate.js +3 -2
- package/src/ui/shellTemplate.js +3 -0
- package/src/ui/telemetryDrawerTemplate.js +4 -2
- package/src/ui/telemetryTemplates.js +3 -22
- package/src/ui/templateUtils.js +2 -8
- package/src/ui/viewControlsTemplate.js +21 -0
- package/examples/train-basic-policy.mjs +0 -276
- package/examples/trainingData.mjs +0 -133
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Racing-driver AI improvements: arcade and advanced
|
|
2
|
+
|
|
3
|
+
## Goal and acceptance
|
|
4
|
+
|
|
5
|
+
Improve both built-in drivers relative to the September 9 advanced-AI closeout. Measure braking, corner exit and traffic decisions under unchanged physics. Preserve arcade defaults, public actions/observations, deterministic stepping, recovery, pits and package layout. Faster solo driving is insufficient if representative full fields become substantially less reliable. No claim of globally optimal driving.
|
|
6
|
+
|
|
7
|
+
## Checkable plan
|
|
8
|
+
|
|
9
|
+
- [x] Preserve a source snapshot and inspect current dirty Git state and driver ownership.
|
|
10
|
+
- [x] Complete baseline package gate and matched solo/full-field measurements for both modes.
|
|
11
|
+
- [x] Diagnose concrete pace losses; compare bounded independent candidates in isolated source copies.
|
|
12
|
+
- [x] Select changes on lap times, contacts, off-road time and finish rate; reject fragile gains.
|
|
13
|
+
- [x] Integrate feature-owned controls, meaningful production regressions and authoritative docs.
|
|
14
|
+
- [x] Repeat accepted races, compare unchanged raw physics, measure CPU cost with paired existing benchmarks.
|
|
15
|
+
- [x] Pass package/release/browser/packed-consumer gates; update Linear and report read-only Git status.
|
|
16
|
+
|
|
17
|
+
## Ownership and design gate
|
|
18
|
+
|
|
19
|
+
`driver/racingControls.js` dispatches modes and preserves its existing internal exports. Arcade `arcadeRacingControls.js` owns target-line composition, geometric steering, edge guarding and pedals; `arcadeRacePace.js` owns preview and corner-line planning. `driverController.js` owns the backward-facing recovery transition. Advanced `advancedRacingControls.js` composes geometric steering, existing traffic planning and `advancedRacePace.js` speed envelopes; `advancedPathControls.js` also serves recovery/safety driving, which must remain stable. `racingLinePlan.js` owns shared overtaking intentions. Vehicle modules exclusively own physical forces/integration and the analytic arcade tarmac corner-capacity estimate; physical laws and constants are not tuning targets.
|
|
20
|
+
|
|
21
|
+
Inputs are track geometry, vehicle capability/state, existing traffic and racing intentions. Outputs remain bounded steering/throttle/brake. Candidate logic must have a narrow feature owner, no whole-app helper or hidden persistent state. The racing-driver hypotheses are braking too early or too late, unnecessary coasting, failing to unwind steering on exit, and confusing overtaking intention with available space. Each must be supported by simulation traces before adoption.
|
|
22
|
+
|
|
23
|
+
Risks: corner-entry understeer, exit oversteer, oscillatory controls, unsafe passing, tire wear, pit-coordinate mismatches and procedural-track overfitting. Evaluate development and held-out tracks, complete ten-car races with wear/pits, recovery regressions and deterministic repeats. Any structural or behavior change requires evidence and matching documentation.
|
|
24
|
+
|
|
25
|
+
## Baseline and artifacts
|
|
26
|
+
|
|
27
|
+
Baseline source: `/tmp/paddockjs-racing-ai-20260909/baseline`. Earlier ongoing work, including the first advanced AI improvement, is preserved. No Git/GitHub mutations are authorized or performed.
|
|
28
|
+
|
|
29
|
+
## Verified findings and candidate decisions
|
|
30
|
+
|
|
31
|
+
- Arcade speed preview (`driver/racingControls.js`): the sharpest future curvature became the current corner target, ignoring braking distance. In track 20260427, the car slowed from 283 km/h at 239 m to 151 km/h at 432 m while the road was still straight; the first bend began around 540 m. A distance-aware envelope avoids unnecessary early braking while retaining conservative reaction distance.
|
|
32
|
+
- Arcade steering combined target-point angle, future-heading feedforward and lateral correction. On track 7110 at 1319 m, the target required negative steering, but the combined controller commanded positive steering before any tire saturation. Pure pursuit inverted through arcade's own bicycle yaw relation points toward the intended path and compensates tire condition, avoiding contradictory corrections.
|
|
33
|
+
- Arcade corner targets barely responded to tire wear. Its physical lateral capacity scales static grip with tire factor squared and downforce with tire factor. Worn tires therefore require much lower corner speeds than the old 96 km/h corner floor. The driver must respect a physical ceiling after intentional pace floors and DRS bonuses.
|
|
34
|
+
- Baseline arcade full fields finished 44/60: all 16 retirements were stalled off track. Worn-tire gravel drive capacity can be lower than rolling resistance even at maximum drive, so simply raising recovery throttle cannot fix these departures. The accepted direction prevents avoidable departures instead of altering physics.
|
|
35
|
+
- Advanced: tighter/longer geometric pursuit and a corner-profile offset did not give useful repeatable gains. Aggressively later braking was faster alone but slower and less clean in traffic. These variants are rejected. The accepted advanced change restrains lateral lane movement under corner load, releasing it on exit. Combined with a modest braking-preview reserve change from 50% to 55%, it improves solo pace and field reliability; the 60% corner reserve, steering model and recovery controls remain unchanged.
|
|
36
|
+
|
|
37
|
+
Baseline `npm run check` passed with 1043 fast tests and 88 slow skips, plus types, packing, consumer/build and browser gates. There were no pre-existing gate failures. Both modes completed all 16 wear-disabled solo stints. Arcade accumulated 273.733 seconds off road; advanced had zero. Advanced baseline full fields finished 60/60.
|
|
38
|
+
|
|
39
|
+
## Accepted implementation and limits
|
|
40
|
+
|
|
41
|
+
Arcade uses inverse bicycle-model pursuit with tire-condition compensation, a 12 m sampled speed preview and conservative braking/reaction distance. Existing rating, aggression, DRS, edge and traffic inputs remain, but they cannot exceed the worn-tire corner ceiling. The old generic control profile and discarded additive steering calculations were removed. Recovery handles backward-facing placements; it does not alter the physical ability to escape a surface.
|
|
42
|
+
|
|
43
|
+
Advanced keeps the existing pursuit model and following-distance safety. Its selected lane target interpolates from the actual chassis center toward the planned lane according to unused cornering budget, preventing abrupt lateral moves while heavily loaded. The braking preview uses 55% of estimated available capacity after lateral demand, still below the longitudinal control limit. The shared 60% racing corner reserve remains unchanged. There are no persistent new state owners, caches, added grip, position corrections or public API changes.
|
|
44
|
+
|
|
45
|
+
Both controllers remain deterministic heuristic drivers. Results do not establish global optimality or guarantee clean racing on every procedural track, setup or user placement. Nonzero contacts and brief field excursions remain. Arcade's physical worn-tire gravel stall limitation is unchanged.
|
|
46
|
+
|
|
47
|
+
## Driving measurements
|
|
48
|
+
|
|
49
|
+
Same Node v24.13.0, Darwin arm64, fixed 1/60 s step, seeds, tracks, drivers, entries and rules before/after. Solo tests use race seed 100, one bundled driver, three laps, no standing-start sequence and tire wear disabled. Flying time is the mean of laps two and three. The first eight tracks are development cases; the remaining eight are held-out cases. All 32 final solo runs finish without off-road time or DNFs.
|
|
50
|
+
|
|
51
|
+
| Track seed | Arcade before (s) | Arcade after (s) | Quicker | Advanced before (s) | Advanced after (s) | Quicker |
|
|
52
|
+
| --- | ---: | ---: | ---: | ---: | ---: | ---: |
|
|
53
|
+
| 7109 | 137.150 | 123.317 | 10.09% | 144.167 | 143.550 | 0.43% |
|
|
54
|
+
| 7110 | 173.533 | 138.183 | 20.37% | 168.150 | 167.050 | 0.65% |
|
|
55
|
+
| 7200 | 149.911 | 129.508 | 13.61% | 150.284 | 149.227 | 0.70% |
|
|
56
|
+
| 7201 | 161.142 | 136.633 | 15.21% | 169.517 | 168.683 | 0.49% |
|
|
57
|
+
| 12 | 138.833 | 122.031 | 12.10% | 139.349 | 138.300 | 0.75% |
|
|
58
|
+
| 26 | 131.171 | 107.467 | 18.07% | 123.000 | 122.083 | 0.75% |
|
|
59
|
+
| 61 | 178.065 | 148.900 | 16.38% | 179.783 | 178.733 | 0.58% |
|
|
60
|
+
| 20260427 | 151.693 | 132.901 | 12.39% | 155.567 | 154.983 | 0.37% |
|
|
61
|
+
| 28 | 167.533 | 140.450 | 16.17% | 176.150 | 174.817 | 0.76% |
|
|
62
|
+
| 62 | 161.783 | 136.908 | 15.38% | 161.267 | 160.250 | 0.63% |
|
|
63
|
+
| 69 | 147.695 | 131.817 | 10.75% | 158.598 | 157.742 | 0.54% |
|
|
64
|
+
| 7202 | 141.001 | 117.417 | 16.73% | 138.433 | 137.667 | 0.55% |
|
|
65
|
+
| 7203 | 104.985 | 96.867 | 7.73% | 104.033 | 102.988 | 1.00% |
|
|
66
|
+
| 101 | 134.817 | 118.967 | 11.76% | 136.767 | 136.267 | 0.37% |
|
|
67
|
+
| 9099 | 182.923 | 156.383 | 14.51% | 199.017 | 198.400 | 0.31% |
|
|
68
|
+
| 12345 | 153.847 | 127.745 | 16.97% | 149.667 | 148.783 | 0.59% |
|
|
69
|
+
|
|
70
|
+
Full fields use the six actual demo configurations with ten driver/entry pairs, normal tire wear, pits and interactions. Hero runs five laps; others run three. **Arcade baseline retires 16 cars, so its field-duration differences are not equal-completion race comparisons.** Finish counts, incidents and clean solo pace must be considered together.
|
|
71
|
+
|
|
72
|
+
### Arcade full fields
|
|
73
|
+
|
|
74
|
+
| Field | Finishers before → after | Last finish before → after (s) | Mean finish before → after (s) | Contacts | Off-road (car-seconds) |
|
|
75
|
+
| --- | ---: | ---: | ---: | ---: | ---: |
|
|
76
|
+
| hero | 8 → 10 | 796.733 → 724.667 | 776.554 → 701.100 | 82 → 50 | 279.933 → 0.000 |
|
|
77
|
+
| components | 7 → 10 | 627.967 → 501.733 | 584.274 → 482.592 | 73 → 65 | 542.517 → 2.467 |
|
|
78
|
+
| dashboard | 5 → 10 | 530.417 → 445.800 | 503.560 → 433.562 | 70 → 43 | 371.350 → 0.000 |
|
|
79
|
+
| timing-overlay | 6 → 10 | 618.467 → 497.467 | 568.528 → 479.483 | 82 → 52 | 381.100 → 0.000 |
|
|
80
|
+
| compact-race | 8 → 10 | 509.283 → 407.633 | 478.856 → 393.245 | 75 → 57 | 228.617 → 0.167 |
|
|
81
|
+
| full-dashboard | 10 → 10 | 350.583 → 329.283 | 336.478 → 311.360 | 57 → 38 | 79.733 → 1.067 |
|
|
82
|
+
|
|
83
|
+
Total finishers: 44/60 → 60/60. Contacts: 439 → 305. Aggregate off-road time: 1883.250 → 3.700 car-seconds.
|
|
84
|
+
|
|
85
|
+
### Advanced full fields
|
|
86
|
+
|
|
87
|
+
| Field | Finishers before → after | Last finish before → after (s) | Mean finish before → after (s) | Contacts | Off-road (car-seconds) |
|
|
88
|
+
| --- | ---: | ---: | ---: | ---: | ---: |
|
|
89
|
+
| hero | 10 → 10 | 864.083 → 887.817 | 846.897 → 839.533 | 10 → 12 | 5.650 → 0.000 |
|
|
90
|
+
| components | 10 → 10 | 601.567 → 597.350 | 590.820 → 586.737 | 7 → 3 | 0.100 → 0.300 |
|
|
91
|
+
| dashboard | 10 → 10 | 532.883 → 528.933 | 520.068 → 516.378 | 5 → 1 | 0.000 → 0.467 |
|
|
92
|
+
| timing-overlay | 10 → 10 | 609.700 → 604.583 | 595.245 → 591.433 | 6 → 3 | 0.100 → 0.767 |
|
|
93
|
+
| compact-race | 10 → 10 | 491.167 → 486.567 | 478.878 → 475.007 | 7 → 3 | 0.000 → 0.433 |
|
|
94
|
+
| full-dashboard | 10 → 10 | 370.817 → 356.183 | 353.282 → 345.350 | 9 → 6 | 3.917 → 0.000 |
|
|
95
|
+
|
|
96
|
+
Total finishers: 60/60 → 60/60. Contacts: 44 → 28. Aggregate off-road time: 9.767 → 1.967 car-seconds.
|
|
97
|
+
|
|
98
|
+
Advanced mean finishing times improve in every field, but hero's last-car completion is 2.75% slower (864.083 → 887.817 s). This is an explicit tradeoff, not a universal race-duration improvement. Five other fields finish sooner. The tight full-dashboard field improves from 370.817 to 356.183 s. Arcade's baseline means include only its surviving finishers; they are shown for context rather than treated as a matched population speed claim.
|
|
99
|
+
|
|
100
|
+
## Measurement integrity
|
|
101
|
+
|
|
102
|
+
The two existing AI harnesses now accept validated `--physics-mode arcade|advanced`; advanced remains the default for existing invocations. Solo records include source fingerprints. Field benchmark v2 derives lap intervals from canonical timing-line crossings, because pit movement can advance completed-lap counters before `lastLapTime` updates. Each finished car's lap intervals reconcile with its finish time within one fixed step. Completed pit exits are read from `pitStop.stopsCompleted` and checked against pit-exit events; pit service completion is a separate event. This corrects reporting only and leaves trajectory/event hashes unchanged.
|
|
103
|
+
|
|
104
|
+
All final solo trajectories match the accepted isolated candidates exactly. Both modes' six full fields are repeated twice with exact deterministic result hashes. Source fingerprint for the final simulation/data tree: `29c71119c480dfca686dc479545ad4b7e4098af9738c63e85100067ba83a6998`.
|
|
105
|
+
|
|
106
|
+
## Verification and runtime cost
|
|
107
|
+
|
|
108
|
+
- Baseline package gate passed without pre-existing failures.
|
|
109
|
+
- Focused AI suite: 44 passed, including worn-tire/DRS/braking/steering/wrong-way cases, loaded-corner lane restraint, clean stints and complete fields. Existing advanced full-field assertions were strengthened.
|
|
110
|
+
- An initial release run failed the old assertion that a particular 30-second approach must reach over 7 m lateral offset. The new faster line reaches 6.181 m there, but reaches 8.085 m on the tight demo circuit with legal kerb use. The original pace fixture and all its speed/off-road thresholds remain; the unchanged 7 m threshold now has a dedicated 90-second tight-circuit test, additionally requiring actual kerb contact, legal surfaces and average speed above 180 km/h. All 10 driver-controller tests passed after this coverage separation; no runtime change or relaxed numeric threshold was used to pass it.
|
|
111
|
+
- Raw physics: 216 combinations across both modes, three surfaces, three tire states, three speeds and four control patterns, each integrated for 120 steps. Complete vehicle states match baseline exactly.
|
|
112
|
+
- Package `npm run check` passed on the final runtime source: 1051 fast tests, 92 slow skips, docs, public types, dry pack, packed-consumer install/build and bundle checks, showcase/demo builds, quick Chromium and demo smoke. Final `npm run check:release` passed with all 1144 tests across 62 files, public types, pack/consumer/build checks, the full Chromium matrix and demo smoke (desktop runtime, public surfaces, presets, expert, headless, search and mobile layout).
|
|
113
|
+
- Twelve paired runs (two batches of six, alternating before/after order) of all 23 standard runtime workloads passed `--verify`. Same Apple M4 Pro host, Node v24.13.0 and settings; our test/benchmark processes were otherwise stopped. The unchanged local-preview source dependency was copied into the frozen baseline to run the common harness. The measured field workloads include setup, instrumentation and 180 steps for 16 cars; these are not browser frame timings.
|
|
114
|
+
|
|
115
|
+
| CPU workload | Before median (ms) | After median (ms) | Before range (ms) | After range (ms) |
|
|
116
|
+
| --- | ---: | ---: | ---: | ---: |
|
|
117
|
+
| Arcade field | 46.916 | 52.846 | 45.239–69.124 | 50.845–154.979 |
|
|
118
|
+
| Advanced field | 174.944 | 163.604 | 167.632–250.340 | 159.241–400.565 |
|
|
119
|
+
| Headless vector | 140.565 | 134.068 | 132.149–163.235 | 127.945–275.706 |
|
|
120
|
+
|
|
121
|
+
Arcade has a consistent planning cost: the two batch median comparisons are +13.26% and +13.11%; the pooled comparison is +12.64% (about 5.93 ms per whole field workload). Advanced's batch signs disagree (+17.38% versus −7.17%), with overlapping ranges/outliers; the pooled −6.48% median is **not a reliable throughput improvement claim**. The headless-vector batches likewise disagree. No CPU speedup is claimed or speculative cache introduced. All raw runs and per-workload comparisons remain in the task artifacts.
|
|
122
|
+
|
|
123
|
+
## Changed files and closeout
|
|
124
|
+
|
|
125
|
+
Runtime: `src/simulation/driver/racingControls.js`, new `arcadeRacingControls.js` and `arcadeRacePace.js`, `driverController.js`, `advancedRacingControls.js`, `advancedRacePace.js`, and `src/simulation/vehicle/vehiclePhysics.js` (analytic planning helper only). Tests: new `src/__tests__/arcadeAIRacing.test.js`, updated `advancedAIRacing.test.js`, and a separated kerb-use characterization in `driverController.test.js`. Measurement: `scripts/benchmark-advanced-ai.mjs`, `benchmark-advanced-ai-fields.mjs`, `runtimeEfficiencyBenchmarks.mjs`. Documentation: `docs/rules.md`, `architecture.md`, a historical follow-up link in `advanced_ai_pace.md`, and this report.
|
|
126
|
+
|
|
127
|
+
Artifacts: `/tmp/paddockjs-racing-ai-20260909/`, including frozen baseline, accepted/rejected source copies, JSONL measurements, physics comparison and gate logs. Reproduce:
|
|
128
|
+
|
|
129
|
+
```sh
|
|
130
|
+
node scripts/benchmark-advanced-ai.mjs . 7109,7110,7200,7201,12,26,61,20260427,28,62,69,7202,7203,101,9099,12345 --physics-mode arcade
|
|
131
|
+
node scripts/benchmark-advanced-ai.mjs . 7109,7110,7200,7201,12,26,61,20260427,28,62,69,7202,7203,101,9099,12345 --physics-mode advanced
|
|
132
|
+
node scripts/benchmark-advanced-ai-fields.mjs . --physics-mode arcade --repeats 2
|
|
133
|
+
node scripts/benchmark-advanced-ai-fields.mjs . --physics-mode advanced --repeats 2
|
|
134
|
+
node scripts/benchmark-runtime-efficiency.mjs --profile=standard --json --verify
|
|
135
|
+
npm run check
|
|
136
|
+
npm run check:release
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Git remains approval-gated. Existing dirty work is preserved; this task does not establish repository-wide cleanliness. Review the bounded changes against the task snapshot and the combined working diff before proposing exact staging/commit actions. No Git/GitHub mutation is authorized or performed.
|
|
140
|
+
|
|
141
|
+
Work log: [Racing-driver AI improvements: arcade and advanced](https://linear.app/mgiorgetti/document/racing-driver-ai-improvements-arcade-and-advanced-9dac1149e8ab).
|
|
142
|
+
|
|
143
|
+
Current read-only Git inspection: branch `v11`, HEAD `fedff4e`, recorded `origin/v11` at 0 ahead/0 behind without fetching; index empty, 123 modified tracked paths and 50 untracked entries. Earlier work is preserved.
|
|
144
|
+
|
|
145
|
+
Subsequent skill-dependent physical-envelope tuning, timing-line boundary repair and measured limitations are documented in [limit driving, 2026-10-14](limit_driving_2026-10-14.md). Earlier results above describe their recorded candidate.
|
package/docs/rules.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Race Rules
|
|
2
2
|
|
|
3
|
+
## Optional Grid Walk presentation
|
|
4
|
+
|
|
5
|
+
[Grid Walk](grid_walk.md) holds normal browser playback before the existing start sequence. The first Race transition clears the crew before simulation time advances; reduced/paused motion clears immediately. Returning later pauses the race and renders original starting poses without writing them into physics. Resuming preserves time, laps, RNG, cars, tires, pits and order. Rolling starts remain rolling starts. Only explicit restart creates a fresh race.
|
|
6
|
+
|
|
3
7
|
This file documents the rules currently implemented by the simulator. If the race engine changes, update this file with the behavior change.
|
|
4
8
|
|
|
5
9
|
## Default Race Rules
|
|
@@ -190,6 +194,8 @@ The simulation builds hidden timing lines around every track at an F1-style mini
|
|
|
190
194
|
|
|
191
195
|
Seconds gaps are the difference between when two cars crossed the same timing line. The race engine falls back to timing-history interpolation only before the cars have a shared timing-line sample. The timing tower can switch at runtime between `Int` mode, which displays interval to the car ahead, and `Gap` mode, which displays direct gap to the leader. When the relevant gap is one or more whole laps, the tower shows `+1`, `+2`, and so on instead of a misleading seconds estimate. Timing continues to be calculated during pre-start, safety-car, and post-finish states even when the UI shows state labels such as `Grid`, `SC`, or `FIN`.
|
|
192
196
|
|
|
197
|
+
Lap telemetry clamps `completedLaps` to the configured `totalLaps`, including overshoot in large or accelerated fixed steps, so post-finish snapshots cannot report more completed laps than the race distance contract allows.
|
|
198
|
+
|
|
193
199
|
## Units
|
|
194
200
|
|
|
195
201
|
The race engine uses simulator units internally. `src/simulation/units.js` converts simulator distance and speed to public meter and km/h values. Public timer, lap-time, sector-time, gap-time, penalty-time, and service-countdown values are seconds. Public distance values with a `Meters` suffix are meters. The current speed calibration maps the simulation maximum speed to an F1-like `330 km/h`; rendered car sprite dimensions are a visual scale and are not used as the physical distance scale.
|
|
@@ -198,7 +204,23 @@ The race engine uses simulator units internally. `src/simulation/units.js` conve
|
|
|
198
204
|
|
|
199
205
|
The default `physicsMode` is `'arcade'`, which preserves the existing forgiving vehicle behavior for current browser hosts and demos.
|
|
200
206
|
|
|
201
|
-
`physicsMode: 'advanced'` is opt-in
|
|
207
|
+
`physicsMode: 'advanced'` is an opt-in planar Formula-style handling model. Four contact patches produce longitudinal/lateral forces from local wheel velocity, surface grip and load. A nonlinear lateral brush curve shares each tire's friction circle with rear-wheel drive or braking. Centered 50/50 static mass, longitudinal and lateral load transfer, tire load sensitivity, front brake bias, aerodynamic downforce and drag affect the available forces. Force and moment sums integrate world velocity and yaw inertia at internal steps no larger than 1/240 s. Steering commands set a rate-limited physical wheel angle; speed-dependent keyboard conditioning belongs to the human input layer, not vehicle physics or policy actions. Tire forces create steering resistance through their directions; the old synthetic steering-scrub and target-yaw formulas are removed.
|
|
208
|
+
|
|
209
|
+
The demo advanced lab applies human-only keyboard assistance: key travel ramps before speed-dependent steering lock, and observed tire overload reduces the digital accelerator demand to reserve turning grip. It does not steer toward the track or change the physical forces. Its host scheduler caps stepping at 60 Hz independently of display refresh and discards catch-up debt after a stall. External policy action scaling and the general controller-loop scheduler contract are unchanged.
|
|
210
|
+
|
|
211
|
+
The existing setup ratings remain intact. For the baseline car, `powerNewtons` times 0.5 sets peak rear drive force, transitioning at 28 m/s to constant power (602 kW for the default 43000 N rating). `brakeNewtons` is apportioned 57% front / 43% rear before tire adhesion; full default braking can hold the car against full throttle. Braking and rolling resistance share a contact stopping-impulse budget so they cannot create reverse motion or energy at rest. DRS reduces aerodynamic drag and downforce. The existing 330 km/h integration envelope is retained. These are explicit simulation calibrations, not proprietary F1 data.
|
|
212
|
+
|
|
213
|
+
Body slip is actual velocity direction minus body heading. Kerbs are legal but reduce available grip; a slipping car can lose steering authority rather than always losing more scalar speed. Gravel and grass affect each contact patch separately, including asymmetric resistance and yaw moments. Wheel load transfer is quasi-static: no suspension travel, vertical motion, tire carcass/temperature model or individual wheel rotational state is simulated. Brake demand beyond adhesion is approximated as a contact sliding against its actual velocity; gear shifts, wheel-spin dynamics and a full collision manifold are outside this model.
|
|
214
|
+
|
|
215
|
+
Advanced car contacts use mass/inertia-dependent normal impulses with a contact point approximated from opposing oriented body support features. They do not directly rotate the heading. Arcade contact response is unchanged. Existing fixed pit-car ownership, contact event deduplication and stewarding remain authoritative. Rendered barriers still destroy cars at the same footprint boundary; advanced physics does not soften that race rule.
|
|
216
|
+
|
|
217
|
+
External state placement rejects non-finite values and resynchronizes world velocity when speed/heading changes without an explicit velocity vector. Grid/red-flag/queue/terminal holds freeze velocity, yaw and acceleration together. Pit routing remains the existing bounded route movement and service model. Advanced racing AI follows the velocity direction and adds the front tire slip needed to produce its requested turning force. Its race-specific speed planner uses dynamically transferred contact loads and the weaker yaw-balanced axle rather than a fixed share of static total grip. It solves upcoming corner limits using downforce at the candidate corner speed, then works backward through a sampled braking envelope that reserves lateral grip. The actual overtaking/correction path can impose a tighter limit than the centerline. A bounded force controller compensates drag and rolling resistance and responds quickly enough to follow that braking envelope. The 330 km/h package envelope is a ceiling, not a guaranteed speed: engine force, drag, tires, traffic and track geometry determine the achieved pace.
|
|
218
|
+
|
|
219
|
+
The advanced racing controller matches a slower car's speed and physical following gap until there is actual lateral clearance, even when a pass is planned. It retains the existing lane selection, traffic penalties and recovery/safety-car controllers. All changes produce ordinary steering/throttle/brake commands; there are no pose writes or extra grip. Pace and racecraft determine control ability; consistency determines bounded continuous line and speed-judgement variation. Risk tolerance and aggression independently reduce the chosen margins. Skill does not add physical grip or power, and mistakes are not scheduled accidents. Advanced corner force budgets range from 74% to 96% of the predicted dynamically loaded balanced-axle bound; longitudinal budgets range from 86% to 98%. These policy budgets are not measured utilization of every tire. The current vehicle, tires, surfaces, DRS and traffic remain limiting.
|
|
220
|
+
|
|
221
|
+
Advanced braking preview inspects contiguous geometry from the current position. It reserves the steering pursuit distance, the controller yaw-response and driver anticipation distances, and one sampling interval before counting available braking distance. It must not shift its sampling origin past nearby bends. Pedals reserve lateral adhesion and account for rear-drive allocation, brake bias, load transfer and resistance. The bounded brake solver handles a feasible nonzero braking window even when zero braking overloads the front axle. Arcade racing uses its own actual yaw and longitudinal limits, with a shorter smooth pursuit horizon in tight geometry; it does not introduce an advanced friction circle. Recovery, safety-car and automatic pit controllers retain their separate ownership.
|
|
222
|
+
|
|
223
|
+
Measured pace, incidents, rejected alternatives and limitations are recorded in [the first advanced AI pace report](advanced_ai_pace.md), [the both-mode racing AI report](racing_ai_improvements.md), and [the skill-dependent limit-driving report](limit_driving_2026-10-14.md).
|
|
202
224
|
|
|
203
225
|
Simulator snapshots and environment observations expose additional vehicle telemetry: `lateralG`, `longitudinalG`, `gripUsage`, `slipAngleRadians`, `tractionLimited`, and `stabilityState`. These fields are optional public telemetry; existing `speedKph`, wheel-surface, steering, throttle, and brake fields remain unchanged.
|
|
204
226
|
|
|
@@ -206,11 +228,13 @@ Simulator snapshots and environment observations expose additional vehicle telem
|
|
|
206
228
|
|
|
207
229
|
Lap is computed from each car's cumulative race distance over the track length. Total laps are provided by mount options and default to `10`.
|
|
208
230
|
|
|
231
|
+
Hidden timing-line crossings use exact forward `(previousDistance, currentDistance]` boundaries and the same representable line distance for indexing and recording. A car infinitesimally before a line must still record that crossing; no tolerance band may silently drop a lap timestamp.
|
|
232
|
+
|
|
209
233
|
Each track is automatically divided into three equal sectors. Sector and lap telemetry is recorded when a car's cumulative race distance crosses a sector boundary or start/finish boundary. Completed current-lap sector split times before the active sector are exposed as `currentSectors`, while `liveSectors` keeps only the active sector's elapsed time updated before the boundary is crossed and clears any future-sector values. `sectorProgress` is recomputed every snapshot as the live S1/S2/S3 fill state for the current lap, so sector-map UI does not derive progress from completed split state or keep stale future sectors lit. Timing values are stored in seconds and exposed on each car snapshot as `lapTelemetry`.
|
|
210
234
|
|
|
211
235
|
Each car is marked `finished` when it reaches `track.length * totalLaps`. It receives a frozen provisional `finishRank`, exposes `raceStatus: 'waved-flag'` / `wavedFlag: true`, and emits a `car-finish` event. The first finisher becomes provisional `winner`, but the race keeps running until every race participant has either crossed the finish distance or is currently DNF. While the field is still finishing, timing order keeps already-finished cars in provisional finish order ahead of cars still running, and DNF cars sit below active cars in the order they retired. A car that has already crossed the finish line keeps that result even if it later touches the barrier or satisfies stalled-off-track detection while the rest of the field is still finishing; post-finish retirement checks do not turn it into DNF. A DNF car restored before final classification re-enters the live order and must finish before the race can complete; restoring it after final classification does not reopen the race.
|
|
212
236
|
|
|
213
|
-
When all cars have finished or reached DNF, the simulator records `finishedAt` and final `classification`, emits a `race-finish` event, freezes order to the classified result after outstanding penalties and classification consequences, deploys the safety car, and switches race mode to `safety-car`. DNF classification entries appear after finishers with `finished: false`, no finish time, and DNF reason/time/order metadata. Finished cars keep circulating under safety-car behavior instead of hard-stopping. The current implementation does not yet implement championship scoring.
|
|
237
|
+
When all cars have finished or reached DNF, the simulator records `finishedAt` and final `classification`, emits a `race-finish` event, freezes order to the classified result after outstanding penalties and classification consequences, deploys the safety car, and switches race mode to `safety-car`. DNF classification entries appear after finishers with `finished: false`, no finish time, and DNF reason/time/order metadata. Finished cars keep circulating under safety-car behavior instead of hard-stopping. Timing presentation derives its final state from `raceControl.finished`, so winner and `FIN` labels remain final even though circulation mode is now `safety-car`. The current implementation does not yet implement championship scoring.
|
|
214
238
|
|
|
215
239
|
## DRS
|
|
216
240
|
|
|
@@ -263,7 +287,7 @@ The AI has separate behavior for:
|
|
|
263
287
|
- Off-track rejoin.
|
|
264
288
|
- Safety-car queueing.
|
|
265
289
|
|
|
266
|
-
|
|
290
|
+
Arcade green-flag behavior uses:
|
|
267
291
|
|
|
268
292
|
- Driver aggression.
|
|
269
293
|
- Racecraft.
|
|
@@ -271,22 +295,22 @@ Green-flag behavior uses:
|
|
|
271
295
|
- Patience.
|
|
272
296
|
- Current tire energy.
|
|
273
297
|
- Track curvature.
|
|
274
|
-
-
|
|
275
|
-
-
|
|
298
|
+
- Distance to upcoming bends and available braking distance.
|
|
299
|
+
- Geometric pursuit of a forward lane target, adjusted for tire response.
|
|
276
300
|
- Nearby traffic.
|
|
277
301
|
- Preferred and available lane offsets.
|
|
278
302
|
|
|
279
|
-
The
|
|
303
|
+
The arcade racing controller drives through normal vehicle inputs only. It chooses a forward racing target using lane intentions, corner offsets and edge pressure, then inverts the arcade bicycle yaw response to steer toward that target. This avoids contradictory target-angle and future-heading steering commands. The driver samples upcoming corners and retains speed until braking distance requires a slowdown, reserving reaction distance and conservative deceleration. Driver ratings and DRS influence desired pace, but a tire-condition-aware yaw-capacity ceiling takes precedence over corner and maneuvering speed floors. Heading/edge/steering-load penalties and bounded pedal controls remain active. A backward-facing car enters the existing recovery controller before forward racing pursuit resumes. No position, heading, force or steering-rate limit is overridden.
|
|
280
304
|
|
|
281
|
-
|
|
305
|
+
Advanced green-flag driving uses velocity-oriented pursuit with inverse tire-slip steering, a candidate-speed corner/braking envelope and bounded force control described under [Physics Modes](#physics-modes). The additional following limit uses actual chassis-center spacing and the speed of a physically blocking car; lane selection alone is not evidence that a pass has cleared it. While cornering consumes the racing grip budget, the driver reduces lateral movement toward the planned lane and holds a consistent line. It progressively releases the lane change as corner load falls on exit. Driver ability and risk determine the chosen lateral and longitudinal margins within the four-contact physical envelope; braking reserves lateral demand and the pursuit/response/anticipation distance. The former fixed 60% corner and 55% braking shares are superseded by this policy. The built-in driver is a deterministic heuristic policy, not a trained model or a globally optimal racing-line solver.
|
|
282
306
|
|
|
283
|
-
Traffic decisions use
|
|
307
|
+
Traffic decisions use wrapped physical track gaps and chassis-center lateral spacing in the retained main-track frame. A lapped car or a car across the start line can be the nearest physical passing/following target regardless of classification rank. Retired, destroyed and collision-disabled participants do not create blocking or defensive pressure; separate pit-lane traffic is excluded from tactical lane targets while overlapping pit-entry traffic still counts. Race classification and timing gaps keep their existing cumulative-distance meaning. Current measured comparisons and limitations are recorded in [the v11 improvement evidence](v11_improvements.md).
|
|
284
308
|
|
|
285
|
-
|
|
309
|
+
Both modes match a physically blocking car's speed and following gap until lateral clearance exists. This limit takes precedence over arcade maneuvering speed floors, so stopped traffic can require stopping. A committed pass suppresses conflicting rear-defense movement, and a driver does not defend against a physically rearward car that is lapping it. Arcade drivers hold their current chassis line during loaded turns with nearby traffic and release that hold on exit; inward edge recovery takes priority. Advanced drivers constrain their final target to the lateral corridor available beside overlapping cars, rather than checking only an intermediate lane intention. Their corner line hold also permits inward correction near the road edge. These choices remain ordinary steering/brake/throttle inputs with no physics overrides.
|
|
286
310
|
|
|
287
|
-
|
|
311
|
+
Rejoin behavior remains physics-driven. A recovery hold prevents a car from immediately returning to racing pace while heading or edge margin is unstable. Arcade recovery uses inward-biased targets and outward-edge-motion checks. Advanced recovery follows a centerline target ahead at reduced surface-dependent speed, budgets lateral tire capacity and arrests a large sideways/backward slide before accelerating toward the track. At crawling speed, worn-tire runoff recovery includes rolling resistance within the rear tires' available adhesion so the car is not held below the force needed to move. Barrier contact still destroys the car; recovery does not soften that rule.
|
|
288
312
|
|
|
289
|
-
Tire energy can degrade to 1%. The vehicle physics layer converts tire energy into a nonlinear grip factor, so degradation has a visible performance cost across the full 100% to 1% range
|
|
313
|
+
Tire energy can degrade to 1%. The vehicle physics layer converts tire energy into a nonlinear grip factor, so degradation has a visible performance cost across the full 100% to 1% range. Recovery is not guaranteed on every surface: in arcade mode, sufficiently worn tires at rest in gravel can have less available drive acceleration than rolling resistance. The racing AI accounts for remaining corner capacity to avoid unnecessary departures; it does not add recovery force.
|
|
290
314
|
|
|
291
315
|
## Vehicle Physics
|
|
292
316
|
|
|
@@ -323,11 +347,13 @@ Track state can classify a car as on:
|
|
|
323
347
|
|
|
324
348
|
Surface affects grip, drag, and rolling resistance.
|
|
325
349
|
|
|
326
|
-
|
|
350
|
+
`src/simulation/vehicle/wheelSurface.js` classifies each wheel contact patch against the shared track model. Its worst-surface classification (`barrier > gravel > grass > kerb > pit-box > pit-lane > pit-entry/pit-exit > track`) remains the car's reported surface and arcade grip/drag input. Arcade also retains its capped asymmetric wheel-resistance yaw bias. Advanced physics instead uses each wheel's own surface and normal load to calculate forces; one wheel on gravel is not equivalent to four wheels on gravel.
|
|
351
|
+
|
|
352
|
+
Normal main-track wheel queries use the existing analytic signed-offset path; pit connectors resolve wheel centers locally and use full patch sampling for ambiguous overlap. One wheel on a kerb does not itself violate track limits. Reaching the rendered barrier wall's inner face destroys the car in either mode. Pit entry, lane, exit and box remain legal surfaces and do not count toward stalled off-track DNF timing.
|
|
327
353
|
|
|
328
354
|
Rendered material bands use those same thresholds. The visible gravel band starts at the outer kerb edge and ends at the simulated gravel edge; the visible runoff band starts at the gravel edge and ends at the barrier centerline; the barrier wall is drawn from the same `track.barrierWidth` used by destruction. Rendering, ray surface hits, wheel-surface classification, and barrier destruction must stay on this shared geometry contract.
|
|
329
355
|
|
|
330
|
-
When pit stops are enabled, each team is assigned one shared service area in the working lane plus two garage boxes. Driver pairs share the service area, and the service area, queue slot, and garage boxes inherit the team color from `driver.team.color` when present, otherwise the lead driver's color. The current automatic stop plan distributes pit calls across available race laps as bounded pit trains, then lets opportunistic cars join the entry only when fewer than `pitStops.maxConcurrentPitLaneCars` are active and the nearest active pit-lane car is at least `pitStops.minimumPitLaneGapMeters` ahead; committed cars enter at the next pit-entry window and can queue in the working lane if their team service area is busy. Built-in AI cars also request stops from tire condition: below `pitStops.tirePitRequestThresholdPercent` they request `pitIntent: 1`, and below `pitStops.tirePitCommitThresholdPercent` they request `pitIntent: 2`. Expert-controlled cars do not receive those tire-threshold automatic calls; their model or host must request the stop with `pitIntent`. Hosts and expert actions can change a pending stop with `pitIntent`: `0` clears the pending call, `1` stays active until a free-enough pit-entry window appears, and `2` commits to entering at the next pit-entry window even if capacity or gap checks would block mode `1`. The same request may include a target compound, either through `setPitIntent(driverId, intent, targetCompound)` or expert action `pitCompound`; invalid compounds are rejected. Pit intent and target compound are locked while the car is entering, queued, servicing, or exiting, and intent resets to `0` after pit exit. Completed stops can be re-armed by later tire condition or host intent, so pit stops are not one-use per race. Safety-car mode does not block pit intent. Closed pit-lane race-control state keeps pending calls on track until `setPitLaneOpen(true)`, while red-flag state freezes cars and closes the effective pit lane until cleared. If the gap is too small for mode `1`, the following car stays on the main track and retries later rather than being forced to stop in the lane. Allowed cars steer through a forward main-track approach into the pit-entry road, slow to the configured limiter speed before the main pit-lane start, follow the main fast lane, pass through the team-colored queue point, hold for any pit-served penalties, hold for the resolved tire-service time, change to the requested compound or default alternate compound, add that compound to `usedTireCompounds`, then steer back to the racing surface through `pit-exit`. While a car is stationary in service, the browser renderer shows a small countdown above it: red `+Ns` for pit-served penalty hold time and yellow `Ns` for normal pit-service time. The queue point is a rolling gate when the active service area is free, so the car continues into service without a full stop. If a team-mate is already servicing or still exiting from the active service area, the arriving car targets the queue point behind that service area, holds a bounded approach speed until the final capture distance, waits without obstructing the main fast lane, then follows a short queue-release route only after the active service area is physically clear; this keeps both the queue stop and the move into service continuous instead of snapping the car between slots or crawling through the last several meters. Cars whose position is controlled by pit entry, queue, service, or exit logic are not laterally displaced by generic collision correction; if another car overlaps one, the movable car is corrected away while the pit-controlled car stays on its authored route or stop point. `pitStops.variability.enabled` optionally adjusts service time from `team.pitCrew.speed`, `team.pitCrew.consistency`, and `team.pitCrew.reliability`; `pitStops.variability.perfect: true` forces `pitStops.defaultStopSeconds` for training. The pit limiter applies only on the straight main pit lane and working lane between the lane start and lane end; the pit-entry connector road and pit-exit connector road are legal pit-lane surfaces but are not speed-limited by `pitStops.pitLaneSpeedLimitKph`, although automatic entry routing caps connector overspeed so worn-tire cars can still reach the limiter and assigned service area.
|
|
356
|
+
When pit stops are enabled, each team is assigned one shared service area in the working lane plus two garage boxes. Driver pairs share the service area, and the service area, queue slot, and garage boxes inherit the team color from `driver.team.color` when present, otherwise the lead driver's color. The current automatic stop plan distributes pit calls across available race laps as bounded pit trains, then lets opportunistic cars join the entry only when fewer than `pitStops.maxConcurrentPitLaneCars` are active and the nearest active pit-lane car is at least `pitStops.minimumPitLaneGapMeters` ahead; committed cars enter at the next pit-entry window and can queue in the working lane if their team service area is busy. Built-in AI cars also request stops from tire condition: below `pitStops.tirePitRequestThresholdPercent` they request `pitIntent: 1`, and below `pitStops.tirePitCommitThresholdPercent` they request `pitIntent: 2`. Expert-controlled cars do not receive those tire-threshold automatic calls; their model or host must request the stop with `pitIntent`. Hosts and expert actions can change a pending stop with `pitIntent`: `0` clears the pending call, `1` stays active until a free-enough pit-entry window appears, and `2` commits to entering at the next pit-entry window even if capacity or gap checks would block mode `1`. The same request may include a target compound, either through `setPitIntent(driverId, intent, targetCompound)` or expert action `pitCompound`; invalid compounds are rejected. Pit intent and target compound are locked while the car is entering, queued, servicing, or exiting, and intent resets to `0` after pit exit. Completed stops can be re-armed by later tire condition or host intent, so pit stops are not one-use per race. When tire condition automatically re-arms a completed stop, it chooses a different available compound instead of silently reusing the current tire; an explicit host/model target compound is preserved. Safety-car mode does not block pit intent. Closed pit-lane race-control state keeps pending calls on track until `setPitLaneOpen(true)`, while red-flag state freezes cars and closes the effective pit lane until cleared. If the gap is too small for mode `1`, the following car stays on the main track and retries later rather than being forced to stop in the lane. Allowed cars steer through a forward main-track approach into the pit-entry road, slow to the configured limiter speed before the main pit-lane start, follow the main fast lane, pass through the team-colored queue point, hold for any pit-served penalties, hold for the resolved tire-service time, change to the requested compound or default alternate compound, add that compound to `usedTireCompounds`, then steer back to the racing surface through `pit-exit`. While a car is stationary in service, the browser renderer shows a small countdown above it: red `+Ns` for pit-served penalty hold time and yellow `Ns` for normal pit-service time. The queue point is a rolling gate when the active service area is free, so the car continues into service without a full stop. If a team-mate is already servicing or still exiting from the active service area, the arriving car targets the queue point behind that service area, holds a bounded approach speed until the final capture distance, waits without obstructing the main fast lane, then follows a short queue-release route only after the active service area is physically clear; this keeps both the queue stop and the move into service continuous instead of snapping the car between slots or crawling through the last several meters. Cars whose position is controlled by pit entry, queue, service, or exit logic are not laterally displaced by generic collision correction; if another car overlaps one, the movable car is corrected away while the pit-controlled car stays on its authored route or stop point. `pitStops.variability.enabled` optionally adjusts service time from `team.pitCrew.speed`, `team.pitCrew.consistency`, and `team.pitCrew.reliability`; `pitStops.variability.perfect: true` forces `pitStops.defaultStopSeconds` for training. The pit limiter applies only on the straight main pit lane and working lane between the lane start and lane end; the pit-entry connector road and pit-exit connector road are legal pit-lane surfaces but are not speed-limited by `pitStops.pitLaneSpeedLimitKph`, although automatic entry routing caps connector overspeed so worn-tire cars can still reach the limiter and assigned service area.
|
|
331
357
|
|
|
332
358
|
## Contact And Collision Handling
|
|
333
359
|
|
|
@@ -363,3 +389,7 @@ These are not currently implemented:
|
|
|
363
389
|
- Race finish ceremony.
|
|
364
390
|
- Multiplayer controls.
|
|
365
391
|
- Official timing rules, licensing, or real-world team identities.
|
|
392
|
+
|
|
393
|
+
## Penalty Snapshot Ownership
|
|
394
|
+
|
|
395
|
+
Public penalty snapshots copy supported consequence and diagnostic arrays. Changing a returned consequence cannot change live pit-service seconds or enforcement; future ledger updates likewise do not mutate earlier snapshots. This ownership rule does not alter penalty calculation or service sequencing.
|
package/docs/sense_contract.md
CHANGED
|
@@ -43,7 +43,10 @@ while the vector oracle uses schema names and object fields rather than calling
|
|
|
43
43
|
the same active observation values. Debug-only precision may exist only when
|
|
44
44
|
clearly labeled and must not be presented as model input.
|
|
45
45
|
- `getObservationSpec()` is the canonical schema for compact loops, including
|
|
46
|
-
per-driver sensor overrides.
|
|
46
|
+
per-driver sensor overrides. Surface fields use canonical `kerb`, then
|
|
47
|
+
`illegalSurface` order when enabled, regardless of configuration order.
|
|
48
|
+
`environmentObservationSchema.test.js` covers this across full/compact,
|
|
49
|
+
schema-free, array/Float32, and per-driver override paths.
|
|
47
50
|
|
|
48
51
|
## Remaining Formal Limits
|
|
49
52
|
|