@inventure71/paddockjs 2.0.1 → 4.0.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 +176 -1
- package/INSTALL_AND_UPDATE.md +24 -4
- package/README.md +84 -512
- package/docs/architecture.md +38 -24
- package/docs/component_inventory.md +72 -0
- package/docs/composable-layouts.md +77 -0
- package/docs/concepts.md +2 -2
- package/docs/custom_model_controller.md +6 -6
- package/docs/data-helpers.md +50 -0
- package/docs/data_contract.md +104 -27
- package/docs/getting-started.md +75 -0
- package/docs/headless-environment.md +68 -0
- package/docs/index.md +18 -4
- package/docs/learnings.md +6 -6
- package/docs/rules.md +12 -8
- package/docs/sense_contract.md +1 -1
- package/docs/system_specs.md +71 -21
- package/docs/theming.md +64 -0
- package/docs/training.md +26 -19
- package/docs/troubleshooting.md +76 -0
- package/docs/upgrading-hosts-to-3.md +42 -0
- package/examples/python/README.md +6 -0
- package/examples/python/base_policy_server.py +19 -0
- package/package.json +10 -3
- package/src/api/PaddockSimulatorController.js +150 -24
- package/src/api/runtimeTheme.js +59 -0
- package/src/app/F1SimulatorApp.js +213 -29
- package/src/app/banners/raceDataBannerController.js +71 -36
- package/src/app/banners/stewardMessageController.js +5 -4
- package/src/app/camera/cameraConstants.js +2 -0
- package/src/app/camera/cameraController.js +86 -29
- package/src/app/camera/cameraGeometry.js +12 -1
- package/src/app/domBindings.js +89 -9
- package/src/app/layoutScheduler.js +27 -0
- package/src/app/layoutSupport.js +165 -0
- package/src/app/raceOverlayClearanceSupport.js +158 -0
- package/src/app/readouts/carOverviewRenderer.js +16 -8
- package/src/app/readouts/controlStateRenderer.js +1 -1
- package/src/app/readouts/raceStatusRenderer.js +30 -21
- package/src/app/readouts/readoutFormatters.js +2 -0
- package/src/app/readouts/telemetryRenderer.js +17 -8
- package/src/app/readouts/timingTowerRenderer.js +262 -49
- package/src/app/runtime/frameLoop.js +5 -1
- package/src/app/runtime/runtimeVisibility.js +66 -5
- package/src/config/cssValues.js +16 -0
- package/src/config/defaultOptions.js +58 -38
- package/src/config/themeOptions.js +830 -0
- package/src/config/timingGapMode.js +13 -0
- package/src/config/urlOptions.js +25 -0
- package/src/data/championship.js +14 -9
- package/src/data/index.d.ts +212 -0
- package/src/data/index.js +14 -0
- package/src/environment/controllerLoop.js +17 -3
- package/src/environment/episode.js +11 -1
- package/src/environment/index.d.ts +1 -2
- package/src/environment/metrics.js +59 -16
- package/src/environment/observationVector.js +50 -33
- package/src/environment/observations.js +89 -20
- package/src/environment/options.js +1 -1
- package/src/environment/runtime.js +44 -11
- package/src/environment/scenarios.js +1 -1
- package/src/environment/sensors/carRays.js +48 -37
- package/src/environment/sensors/index.js +501 -97
- package/src/environment/sensors/indexedRayBands.js +134 -46
- package/src/environment/sensors/rayBandTrace.js +1171 -0
- package/src/environment/sensors/rayChannels.js +108 -0
- package/src/environment/sensors/rayConfig.js +71 -25
- package/src/environment/sensors/rayGeometry.js +23 -17
- package/src/environment/sensors/sensorTargets.js +67 -1
- package/src/environment/sensors/surfaceRays.js +167 -118
- package/src/environment/sensors/trackRays.js +157 -48
- package/src/index.d.ts +153 -9
- package/src/index.js +52 -3
- package/src/simulation/collisionGeometry.js +260 -96
- package/src/simulation/driver/driverController.js +1 -1
- package/src/simulation/driver/edgeRecovery.js +1 -1
- package/src/simulation/driver/racingControls.js +2 -2
- package/src/simulation/driver/rejoinControls.js +2 -2
- package/src/simulation/pit/pitFlow.js +21 -9
- package/src/simulation/pit/pitKinematics.js +2 -2
- package/src/simulation/pit/pitQueue.js +5 -3
- package/src/simulation/pit/pitRouteMovement.js +9 -4
- package/src/simulation/pit/pitRouting.js +79 -46
- package/src/simulation/pit/pitState.js +1 -0
- package/src/simulation/pit/pitTireService.js +7 -3
- package/src/simulation/race/raceFinish.js +25 -8
- package/src/simulation/race/raceOrder.js +189 -32
- package/src/simulation/race/raceProgress.js +129 -37
- package/src/simulation/race/raceSetup.js +4 -6
- package/src/simulation/race/raceStep.js +26 -14
- package/src/simulation/race/safetyCar.js +1 -1
- package/src/simulation/race/stalledDnf.js +1 -1
- package/src/simulation/raceSimulation.js +20 -17
- package/src/simulation/rules/collisionSteward.js +40 -23
- package/src/simulation/rules/rulesReview.js +77 -56
- package/src/simulation/snapshots/raceSnapshots.js +37 -0
- package/src/simulation/timing/drsTiming.js +143 -30
- package/src/simulation/timing/gapEstimation.js +25 -3
- package/src/simulation/timing/lapTelemetry.js +138 -40
- package/src/simulation/timing/raceTiming.js +5 -1
- package/src/simulation/timing/sectorPerformance.js +104 -26
- package/src/simulation/timing/timingHistory.js +229 -14
- package/src/simulation/timing/timingLines.js +65 -7
- package/src/simulation/track/pitLaneLayout.js +30 -3
- package/src/simulation/track/pitLaneState.js +218 -19
- package/src/simulation/track/spatialQueries.js +66 -33
- package/src/simulation/track/trackMath.js +91 -24
- package/src/simulation/track/trackModel.js +2 -0
- package/src/simulation/track/trackQueryIndex.js +1468 -189
- package/src/simulation/track/trackQueryPitIndex.js +138 -14
- package/src/simulation/track/trackQueryScratch.js +7 -0
- package/src/simulation/track/trackQueryStats.js +25 -0
- package/src/simulation/track/trackSnapshotJson.js +139 -0
- package/src/simulation/track/trackStatePolicy.js +249 -2
- package/src/simulation/vehicle/contactResolution.js +99 -62
- package/src/simulation/vehicle/mainTrackWheelSurface.js +73 -34
- package/src/simulation/vehicle/pitWheelSurface.js +81 -28
- package/src/simulation/vehicle/runoffResponse.js +54 -29
- package/src/simulation/vehicle/vehicleGeometry.js +245 -51
- package/src/simulation/vehicle/vehicleKinematics.js +2 -2
- package/src/simulation/vehicle/vehiclePhysics.js +45 -30
- package/src/simulation/vehicle/vehicleSnapshots.js +35 -1
- package/src/simulation/vehicle/vehicleState.js +7 -1
- package/src/simulation/vehicle/wheelSurface.js +807 -92
- package/src/simulation/warmup/runtimeWarmup.js +0 -1
- package/src/styles.css +1568 -519
- package/src/ui/bannerTemplates.js +38 -28
- package/src/ui/cameraControlsTemplate.js +16 -5
- package/src/ui/carOverviewTemplate.js +12 -5
- package/src/ui/raceCanvasTemplate.js +31 -8
- package/src/ui/raceControlsTemplate.js +27 -10
- package/src/ui/shellTemplate.js +3 -1
- package/src/ui/telemetryDrawerTemplate.js +23 -10
- package/src/ui/telemetryTemplates.js +58 -32
- package/src/ui/templateUtils.js +48 -0
- package/src/ui/timingTowerTemplate.js +29 -12
package/docs/training.md
CHANGED
|
@@ -46,6 +46,7 @@ The current expert API is a JavaScript environment contract. It supports:
|
|
|
46
46
|
- reset-only scenario placement through `scenario.preset`, `scenario.placements`, `scenario.traffic`, and episode-boundary `resetDrivers(placements)`
|
|
47
47
|
- multi-car interaction profiles through `participantInteractions`, including no-collision training cars that are hidden from other cars' ray and nearby-car sensors by default
|
|
48
48
|
- per-driver episode state and neutral step metrics for batched training loops
|
|
49
|
+
- `episode.maxSteps` as a controlled-driver episode safety horizon; the default is high for browser/expert usability, so training and evaluation loops should set an explicit smaller value
|
|
49
50
|
- neutral rollout recording through `createRolloutRecorder()`
|
|
50
51
|
- deterministic evaluation metrics through `runEnvironmentEvaluation()` and `createEvaluationTracker()`
|
|
51
52
|
- a JSON-serializable worker protocol wrapper through `createEnvironmentWorkerProtocol()`
|
|
@@ -93,7 +94,7 @@ Use a user-owned controller for browser playback and JavaScript training-style l
|
|
|
93
94
|
```js
|
|
94
95
|
import {
|
|
95
96
|
createPaddockDriverControllerLoop,
|
|
96
|
-
} from '@inventure71/paddockjs';
|
|
97
|
+
} from '@inventure71/paddockjs/environment';
|
|
97
98
|
|
|
98
99
|
const controller = {
|
|
99
100
|
async init(ctx) {
|
|
@@ -155,15 +156,15 @@ built-in driver applied. This is intended for audits or clean local imitation
|
|
|
155
156
|
datasets; it does not blend built-in AI with a model during normal controlled
|
|
156
157
|
stepping.
|
|
157
158
|
|
|
158
|
-
For model training, prefer `physicsMode: '
|
|
159
|
+
For model training, prefer `physicsMode: 'advanced'` so the policy learns against the same grip, yaw-rate, contact-patch, kerb, and runoff behavior exposed by those senses. Arcade physics can still be useful as a debugging baseline, but it should not be treated as the main training target for realistic driver policies.
|
|
159
160
|
|
|
160
|
-
Surface-aware rays are opt-in because they are more expensive than the default road-edge/car channels. The environment normalizes both the
|
|
161
|
+
Surface-aware rays are opt-in because they are more expensive than the default road-edge/car channels. The environment normalizes both the compact ray shape and the newer per-ray layout:
|
|
161
162
|
|
|
162
163
|
```js
|
|
163
164
|
const env = createPaddockEnvironment({
|
|
164
165
|
drivers,
|
|
165
166
|
controlledDrivers: ['budget'],
|
|
166
|
-
physicsMode: '
|
|
167
|
+
physicsMode: 'advanced',
|
|
167
168
|
observation: { profile: 'physical-driver' },
|
|
168
169
|
sensors: {
|
|
169
170
|
rays: {
|
|
@@ -181,13 +182,15 @@ const env = createPaddockEnvironment({
|
|
|
181
182
|
|
|
182
183
|
Only requested ray channels are computed. The default compact config still computes the existing road-edge and car readings, so existing policy vectors keep their current shape unless the profile or sensor config opts into richer fields. Barrier walls are not a ray channel; they are visible track geometry and a terminal destruction condition in both physics modes. Active ray objects, vectors, schemas, and visualizations must not expose barrier ray fields.
|
|
183
184
|
|
|
184
|
-
`precision: 'driver'` is the default and the recommended model-facing ray contract.
|
|
185
|
+
`precision: 'driver'` is the default and the recommended model-facing ray contract. Safe main-track road-edge, kerb, and illegal-surface rays use direct indexed boundary intersections against the same surface bands used by wheel surfaces and rendering. Normal driver rays validate direct candidates against driver-precision track state; the `batch-training` profile keeps the accelerated direct indexed contract for safe main-track rays. Surface-only batch-training rays also reuse same-pose `progress`/`signedOffset` origin-state synthesis plus shared surface-hit and track-band boundary scratch, so kerb/illegal-surface vector batches avoid nearest-track origin classification and per-ray hit-object replacement. Recovery rays can also use the direct path when the indexed boundary is validated against driver-precision track state, including barrier-to-runoff illegal-surface recovery and off-track road/kerb re-entry. Low-curvature recovery and validation samples may reuse the origin segment to stay off generic nearest-track classification, while curved ambiguous recovery, pit-connector, and pit-lane-origin rays stay inside the ray-band tracer and use one bounded sampled validation pass for all requested road/surface channels instead of falling back to separate legacy road and surface scans. `precision: 'debug'` uses the same tracer-owned path with additional sampled refinement for clearly labeled diagnostics; only missing-index cases use the older sampled fallback path. If the Policy Runner or expert visualization is showing model senses, it must render the active observation values exactly and must not replace them with debug-precision readings.
|
|
186
|
+
|
|
187
|
+
Scratch-backed driver ray batches keep requested-channel dispatch in reusable scalar channel flags rather than rebuilding channel `Set` containers per ray. The indexed boundary traversal also reuses one query-index sample point across ray-grid steps instead of allocating temporary points. The runtime benchmark gate enforces zero channel-set allocations, stable channel-flag containers, and sample-point reuse for the common direct ray path.
|
|
185
188
|
|
|
186
189
|
When a full observation includes both `object` and `vector`, Policy Runner model inputs that need ray geometry use the observation object's actual `angleDegrees` and `lengthMeters`. Compact vector schemas intentionally carry ray channel values, not out-of-band ray geometry, so consumers with per-driver sensor overrides must read the active object observation or the exact per-driver spec instead of reconstructing layout from a default preset.
|
|
187
190
|
|
|
188
191
|
The model-facing sense proof boundary is documented in [Model Sense Contract](sense_contract.md). The executable contract test compares object observations against independent simulator-snapshot oracles, decodes vector entries by schema name, and checks compact vector-only output against full output for the same deterministic state. New model-facing sense fields must extend that oracle instead of relying only on snapshot or shape tests.
|
|
189
192
|
|
|
190
|
-
Track-position, wheel-surface, pit-lane, and ray
|
|
193
|
+
Track-position, wheel-surface, pit-lane, and ray queries use the internal startup-built track query index. Browser/expert mounts, headless environments, direct race-simulation construction, compact vector-only training loops, and `batch-training` ray runs all use that canonical indexed path. Indexed pit-road state resolution reuses route candidate buckets, one polyline projection result, and index-owned cumulative route distance tables for entry, fast-lane, working-lane, and exit classification; connector-adjacent direct pit-entry/pit-exit shortcut checks reuse that same projection target and route metadata. Endpoint-progress shortcut checks use precomputed route endpoint segment windows, while mid-connector points use bounded indexed route candidates without becoming full pit-lane queries. The runtime track-query benchmark explicitly probes those pit-road routes and requires direct connector scratch reuse, positive endpoint-window connector projections, zero connector full-route projection scans, grid hits, scratch reuse, precomputed route distances, zero cumulative-distance rebuilds, zero road-grid misses, and zero pit fallbacks. This does not change the observation shape. Ray `precision: 'driver'` uses indexed projection plus driver-precision validation for road-edge, kerb, and illegal-surface distances, preserving zero-distance origin surface hits and avoiding debug-only refinement in policy inputs. The internal ray-band tracer reports whether a ray used the pure `direct` path or bounded `sampled` recovery so benchmarks can catch regressions without changing public ray objects or vectors. Debug precision remains available only for explicitly labeled diagnostics.
|
|
191
194
|
|
|
192
195
|
`resetDrivers()` is part of episode control, not policy action. After reset placement, the environment immediately reclassifies the selected cars against the same runoff/barrier rules used during stepping before building observations. Recovery starts inside the legal recovery band remain normal physical starts. Placements that are already inside the barrier destruction boundary return a terminal per-driver episode state and miss-valued rays, so a batch loop can assign its own negative reward and reset that driver without paying for far-out ray geometry. In multi-driver batches, top-level `done` is true once every reported controlled driver is terminal, including mixed states where one driver is terminated and another is max-step truncated; per-driver `info.drivers[driverId]` keeps the distinct reason.
|
|
193
196
|
|
|
@@ -287,6 +290,8 @@ Use that override deliberately. The default no-collision training profile is sen
|
|
|
287
290
|
|
|
288
291
|
Compact vector mode is intended for high-throughput loops. `env.getObservationSpec()` remains the canonical schema source, so external code can request `output: 'vector'` and `includeSchema: false` without serializing object observations and schema data on every step. If `sensorsByDriver` changes ray or nearby-car shape for specific drivers, read `observationSpec.perDriver[driverId].vector.schema` for that driver's exact compact schema. JavaScript training loops can also request `vectorType: 'float32'` for typed numeric buffers. Keep the default array output for JSON-only bridges unless the bridge explicitly packs typed arrays.
|
|
289
292
|
|
|
293
|
+
The HTTP Policy Runner server path uses this compact convention by default. `/policy/reset` sends `protocolVersion: 2` plus static metadata, `previousActionFields`, and `metricFields` once, and `/policy/decide-batch` sends only `driverIds` plus aligned `vectors`, `previousActions`, `metrics`, and `events` arrays. Servers should read model inputs from `body.vectors[index]` where `body.driverIds[index]` is the driver being evaluated; `previousActions[index]` is a `[steering, throttle, brake]` tuple for the same driver, and `metrics[index]` follows the reset-time `metricFields` order. Rich observation objects and schemas are no longer repeated on every decision. This is a breaking transport contract for policy-server integrations. There is no rich per-decision fallback in Policy Runner server mode; use object/full observation output only in local JavaScript, headless, debug, or explicit state/export flows.
|
|
294
|
+
|
|
290
295
|
Use `result.stateOutput` to avoid returning more state than the loop needs:
|
|
291
296
|
|
|
292
297
|
```js
|
|
@@ -304,19 +309,23 @@ const env = createPaddockEnvironment({
|
|
|
304
309
|
|
|
305
310
|
`stateOutput: 'minimal'` returns the lean public observation snapshot. `stateOutput: 'none'` returns `state: null`. The default is still `full` for existing callers. `resetDriversObservationScope: 'reset'` also scopes `info.controlledDrivers` to the drivers present in that reset result's `observation` and `metrics`; use `info.drivers` if you need all configured drivers' episode bookkeeping. When `stateOutput: 'none'`, `observation.output: 'vector'`, and `includeSchema: false`, the environment uses an internal compact training snapshot before building observations and metrics. That optimization is not exposed as policy state. Reward callbacks still receive the documented reward context on `step(actions)`, and reset/read calls remain reward-neutral.
|
|
306
311
|
|
|
307
|
-
|
|
312
|
+
Advanced-mode velocity senses are authoritative only when the simulator owns a real world velocity. Arcade snapshots intentionally expose `velocityX/Y` as `null`. When advanced-mode cars are terminal or held by race control, grid logic, or pit queue logic, the environment freezes scalar speed and `velocityX/Y` together at zero instead of carrying old motion into observations or recorded transitions.
|
|
308
313
|
|
|
309
|
-
On the local
|
|
314
|
+
On the local 3.0.0-to-4.0.0 comparison runs (`physicsMode: 'advanced'`, `physical-driver`, `driver-front-heavy` rays, procedural worst-seed checks, and vector observations), the current engine-style paths measured as a net runtime improvement in real environment stepping:
|
|
310
315
|
|
|
311
316
|
```txt
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
+
20-car race step 4.67x faster than 3.0.0
|
|
318
|
+
normal env, seed 104729 4.05x faster than 3.0.0
|
|
319
|
+
normal env, seed 4101 1.45x faster than 3.0.0
|
|
320
|
+
normal env, seed 47 5.07x faster than 3.0.0
|
|
321
|
+
batch-training env, worst seeds 1.32x-1.39x faster than 3.0.0
|
|
322
|
+
wheel surface near pit connector 89.27x faster than 3.0.0
|
|
323
|
+
snapshot JSON, 20 cars 4.21x faster than 3.0.0
|
|
317
324
|
```
|
|
318
325
|
|
|
319
|
-
|
|
326
|
+
Those numbers are hardware- and track-dependent, but the relative result is the useful guidance: compact state/observation output reduces serialization/allocation overhead, indexed track queries prevent off-track recovery rays from becoming the dominant cost center in real environment loops, and direct indexed ray-band intersections keep common driver-precision road/surface rays off the expensive sampled nearest-query path. The high-volume seed sweep covered 69 procedural seeds, 447,120 ray builds, 3,129,840 individual rays, 149,040 wheel-surface classifications, and 1,380 environment steps with zero invalid ray payloads, zero invalid environment observations, zero invalid wheel classifications, and zero nearest/pit fallbacks.
|
|
327
|
+
|
|
328
|
+
There is one deliberate microbenchmark caveat: adversarial standalone `buildRaySensors()` sweeps that force normal-profile rays from kerb, gravel, and runoff poses on complex generated tracks can be slower than 3.0.0 because the current path performs more bounded indexed exact validation to preserve driver-precision surface semantics. On the worst checked seeds, real environment stepping still measured faster than 3.0.0. Treat the standalone ray torture case as a precision/diagnostic stress test, not the expected training-loop cost.
|
|
320
329
|
|
|
321
330
|
## Scenario Reset Control
|
|
322
331
|
|
|
@@ -404,7 +413,7 @@ recorder.recordStep(result, action, next);
|
|
|
404
413
|
|
|
405
414
|
Each transition has `{ observation, action, reward, nextObservation, terminated, truncated, info }`. If the environment has no reward callback, `reward` is still `null`; the recorder does not invent one. Recorded transitions snapshot arrays, typed vectors, actions, observations, rewards, and info at record time, so later policy-loop mutations do not rewrite previous rollout rows.
|
|
406
415
|
|
|
407
|
-
Environment step results also include reward-neutral `metrics[driverId]` facts such as progress delta, legal progress delta, kerb use, illegal/off-track state, severe cuts, destruction state, under-30-kph state, spin/backwards/instability state, lap completion, lap time, and contact count. `spinOrBackwards` is true for large heading-error backwards cases and for active simulator instability labels such as `spin-risk`, `understeer`, `oversteer`, and `destroyed`. `contactCount` counts each normalized physical contact event once per involved driver even when the event carries
|
|
416
|
+
Environment step results also include reward-neutral `metrics[driverId]` facts such as progress delta, legal progress delta, kerb use, illegal/off-track state, severe cuts, destruction state, under-30-kph state, spin/backwards/instability state, lap completion, lap time, and contact count. `spinOrBackwards` is true for large heading-error backwards cases and for active simulator instability labels such as `spin-risk`, `understeer`, `oversteer`, and `destroyed`. `contactCount` counts each normalized physical contact event once per involved driver even when the event carries older `carId`/`otherCarId` fields and normalized `driverIds`. These metrics are facts for logging, evaluation, and user-defined reward functions; PaddockJS does not turn them into a built-in objective. If a car touches the rendered barrier wall's inner face in either physics mode, that driver receives `metrics[driverId].destroyed: true` and `info.drivers[driverId].endReason: 'destroyed'`; external training code should assign any super-negative crash reward itself and then call `resetDrivers()` for the next episode. If opt-in `rules.modules.stalledDnf.enabled: true` retires a controlled car for being stuck off legal surfaces, the episode terminates with `endReason: 'stalled-off-track'` while `metrics[driverId].destroyed` stays `false`.
|
|
408
417
|
|
|
409
418
|
Deterministic evaluation helpers report simulator quality metrics such as distance, off-track steps, contacts, recovery success, pass count, and first lap time when available. They use the same wheel-level legal-surface and contact-event semantics as environment metrics. `runEnvironmentEvaluation()` can accept compact base options with `result.stateOutput: 'none'`; it internally requests the minimal snapshot needed for evaluation bookkeeping. Direct `createEvaluationTracker(result)` calls require a result with `state.snapshot`, so use `stateOutput: 'minimal'` or `full` for manual tracker wiring. Evaluation helpers do not update a model or compute rewards.
|
|
410
419
|
|
|
@@ -415,10 +424,8 @@ Deterministic evaluation helpers report simulator quality metrics such as distan
|
|
|
415
424
|
## Visual Playback Loop
|
|
416
425
|
|
|
417
426
|
```js
|
|
418
|
-
import {
|
|
419
|
-
|
|
420
|
-
mountF1Simulator,
|
|
421
|
-
} from '@inventure71/paddockjs';
|
|
427
|
+
import { createPaddockDriverControllerLoop } from '@inventure71/paddockjs/environment';
|
|
428
|
+
import { mountF1Simulator } from '@inventure71/paddockjs';
|
|
422
429
|
|
|
423
430
|
const simulator = await mountF1Simulator(root, {
|
|
424
431
|
drivers,
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Troubleshooting
|
|
2
|
+
|
|
3
|
+
Use this when a host integration or package release check fails.
|
|
4
|
+
|
|
5
|
+
## Raw Node Import Fails
|
|
6
|
+
|
|
7
|
+
Do not use this as the main package check:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
node -e "import('@inventure71/paddockjs')"
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The root package is browser-oriented and imports CSS/assets. Use the browser-free subpaths in Node:
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
import { createPaddockEnvironment } from '@inventure71/paddockjs/environment';
|
|
17
|
+
import { DriverData } from '@inventure71/paddockjs/data';
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## CSS Is Missing
|
|
21
|
+
|
|
22
|
+
Import the package stylesheet from a browser entry when the host bundler does not extract it automatically:
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
import '@inventure71/paddockjs/styles.css';
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
If styles are present but the simulator is squeezed or overlapping, check the host container size before changing package internals. PaddockJS supports roots at least `320px` wide and shows an `Unsupported size` placeholder below supported bounds.
|
|
29
|
+
|
|
30
|
+
## Assets Do Not Resolve
|
|
31
|
+
|
|
32
|
+
PaddockJS owns default simulator assets. Hosts should not copy them manually. In the package repo, verify publish contents with:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm run pack:dry
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
In a host app, verify through the host's browser build rather than a raw Node import.
|
|
39
|
+
|
|
40
|
+
## Simulator Looks Frozen
|
|
41
|
+
|
|
42
|
+
Check whether browser expert mode is enabled:
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
expert: { enabled: true, controlledDrivers: ['budget'] }
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Expert mode intentionally waits for `simulator.expert.step(actions)`. Basic website mounts should omit `expert` unless they are playing back a model or debugging policy observations.
|
|
49
|
+
|
|
50
|
+
## Policy Server Receives No Observations
|
|
51
|
+
|
|
52
|
+
Policy Runner server mode uses protocol version `2`. `/policy/decide-batch`
|
|
53
|
+
receives aligned compact arrays, not rich `observations`. Static specs,
|
|
54
|
+
configuration, `previousActionFields`, and `metricFields` are sent once to
|
|
55
|
+
`/policy/reset`, so servers should cache `observationSpec` and read model
|
|
56
|
+
inputs from `body.vectors[index]` for `body.driverIds[index]` during decisions.
|
|
57
|
+
|
|
58
|
+
## Theme Toggle Resets The Race
|
|
59
|
+
|
|
60
|
+
Use runtime theme APIs instead of restarting:
|
|
61
|
+
|
|
62
|
+
```js
|
|
63
|
+
simulator.setThemeMode('dark');
|
|
64
|
+
simulator.setTheme({ tokens: { primary: '#008c55' } });
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`restart(nextOptions)` is for race/data/seed changes, not normal light/dark presentation sync.
|
|
68
|
+
|
|
69
|
+
## 3.x Upgrade Symptoms
|
|
70
|
+
|
|
71
|
+
- Remove host usage of `trackQueryIndex`; indexed track queries are package internals.
|
|
72
|
+
- Replace old strict physics usage with `physicsMode: 'advanced'`, or omit `physicsMode` for the default `arcade` mode.
|
|
73
|
+
- Use `@inventure71/paddockjs/environment` for headless simulation.
|
|
74
|
+
- Use `@inventure71/paddockjs/data` for CSS-free data/tooling imports.
|
|
75
|
+
|
|
76
|
+
See [Upgrading Hosts To PaddockJS 3.x](upgrading-hosts-to-3.md).
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Upgrading Hosts To PaddockJS 4.x
|
|
2
|
+
|
|
3
|
+
Use this checklist when moving a browser host website from 2.x-era PaddockJS usage to the 4.x package API.
|
|
4
|
+
|
|
5
|
+
1. Install the 4.x package:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @inventure71/paddockjs@4
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
2. Import package CSS intentionally anywhere browser mounts are used:
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
import '@inventure71/paddockjs/styles.css';
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The stylesheet is scoped to PaddockJS roots and uses system fonts by default. Load any branded web fonts from the host app instead of relying on package-side remote font imports.
|
|
18
|
+
|
|
19
|
+
3. Remove host usage of `trackQueryIndex`. Track query indexing is package-owned and internal in 4.x.
|
|
20
|
+
|
|
21
|
+
4. Replace `physicsMode: 'simulator'` with `physicsMode: 'advanced'`, or omit `physicsMode` to keep the default `arcade` mode.
|
|
22
|
+
|
|
23
|
+
5. Decide how the host should theme the simulator. Use mount-time `theme` for defaults, then use `simulator.setThemeMode(mode)` or `simulator.setTheme(theme)` for site light/dark toggles. Do not call `restart({ theme })` only to change presentation.
|
|
24
|
+
|
|
25
|
+
6. Reuse public theme helpers instead of copying CSS variable names:
|
|
26
|
+
|
|
27
|
+
```js
|
|
28
|
+
import {
|
|
29
|
+
PADDOCK_THEME_CSS_VARIABLES,
|
|
30
|
+
PADDOCK_THEME_TOKEN_KEYS,
|
|
31
|
+
applyPaddockTheme,
|
|
32
|
+
resolvePaddockTheme,
|
|
33
|
+
} from '@inventure71/paddockjs';
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
7. Decide whether the host should enable the driver camera with `ui.driverCamera: true` or `initialCameraMode: 'driver'`.
|
|
37
|
+
|
|
38
|
+
8. Use `@inventure71/paddockjs/environment` for browser-free simulation/training imports.
|
|
39
|
+
|
|
40
|
+
9. Use `@inventure71/paddockjs/data` for CSS-free data/helper imports such as `DriverData`, `normalizeSimulatorDrivers`, `createProceduralTrack`, and speed conversion helpers.
|
|
41
|
+
|
|
42
|
+
10. Rebuild the host bundle and browser-smoke the host page, including theme toggles, selected-driver surfaces, and any composable mount roots.
|
|
@@ -14,6 +14,8 @@ It is not a trainer and not a model/checkpoint format owner. It only shows trans
|
|
|
14
14
|
- Preview latest-frame HTTP endpoint (for polling visualizers)
|
|
15
15
|
- `http://127.0.0.1:8787/preview/frame`
|
|
16
16
|
|
|
17
|
+
Policy HTTP uses protocol version `2`. `POST /policy/reset` receives static metadata (`actionSpec`, `observationSpec`, configuration) once per session. `POST /policy/decide-batch` is compact and receives `driverIds`, `vectors`, `previousActions`, `metrics`, and `events`; it does not receive rich observation objects, schemas, snapshots, or track metadata every decision.
|
|
18
|
+
|
|
17
19
|
## Run
|
|
18
20
|
|
|
19
21
|
```bash
|
|
@@ -55,6 +57,10 @@ Subclass `BasePolicyServer` and override:
|
|
|
55
57
|
|
|
56
58
|
Use `broadcast_preview_frame(snapshot, observation, meta)` to push authoritative frames to the browser renderer.
|
|
57
59
|
|
|
60
|
+
Inside `decide_batch(ctx)`, compact per-driver fields are aligned arrays:
|
|
61
|
+
`ctx["vectors"][index]` belongs to `ctx["driverIds"][index]`. The base example's
|
|
62
|
+
`compact_values_by_driver(ctx, "vectors")` helper maps them back to driver ids.
|
|
63
|
+
|
|
58
64
|
## Important Boundary
|
|
59
65
|
|
|
60
66
|
- This server does not step the simulator by itself.
|
|
@@ -10,6 +10,9 @@ This file is intentionally minimal and transport-focused:
|
|
|
10
10
|
- /preview (broadcasts {snapshot, observation, meta})
|
|
11
11
|
|
|
12
12
|
Extend `BasePolicyServer` and override hook methods to plug your own model/runtime.
|
|
13
|
+
Policy HTTP uses protocolVersion 2. Reset receives static specs/configuration;
|
|
14
|
+
decide-batch receives compact per-driver vectors instead of rich observations.
|
|
15
|
+
Compact per-driver fields are arrays aligned with driverIds.
|
|
13
16
|
"""
|
|
14
17
|
|
|
15
18
|
from __future__ import annotations
|
|
@@ -33,6 +36,20 @@ def _zero_action() -> Dict[str, float]:
|
|
|
33
36
|
}
|
|
34
37
|
|
|
35
38
|
|
|
39
|
+
def compact_values_by_driver(context: Mapping[str, Any], field: str) -> Dict[str, Any]:
|
|
40
|
+
"""Map a compact aligned field such as vectors/metrics back to driver ids."""
|
|
41
|
+
driver_ids = list(context.get("driverIds") or [])
|
|
42
|
+
values = context.get(field) or []
|
|
43
|
+
if isinstance(values, Mapping):
|
|
44
|
+
return {driver_id: values.get(driver_id) for driver_id in driver_ids}
|
|
45
|
+
if not isinstance(values, list):
|
|
46
|
+
return {driver_id: None for driver_id in driver_ids}
|
|
47
|
+
return {
|
|
48
|
+
driver_id: values[index] if index < len(values) else None
|
|
49
|
+
for index, driver_id in enumerate(driver_ids)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
36
53
|
@dataclass
|
|
37
54
|
class ServerState:
|
|
38
55
|
session_id: int = 0
|
|
@@ -70,6 +87,8 @@ class BasePolicyServer:
|
|
|
70
87
|
async def decide_batch(self, context: Mapping[str, Any]) -> Dict[str, Dict[str, float]]:
|
|
71
88
|
"""Return per-driver controls for one batched policy step."""
|
|
72
89
|
driver_ids = list(context.get("driverIds") or [])
|
|
90
|
+
vectors_by_driver = compact_values_by_driver(context, "vectors")
|
|
91
|
+
_ = vectors_by_driver
|
|
73
92
|
return {driver_id: _zero_action() for driver_id in driver_ids}
|
|
74
93
|
|
|
75
94
|
async def publish_preview_frame(self, frame: Mapping[str, Any]) -> None:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inventure71/paddockjs",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A data-driven browser F1 simulator component for host websites.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -45,6 +45,11 @@
|
|
|
45
45
|
"import": "./src/environment/index.js",
|
|
46
46
|
"default": "./src/environment/index.js"
|
|
47
47
|
},
|
|
48
|
+
"./data": {
|
|
49
|
+
"types": "./src/data/index.d.ts",
|
|
50
|
+
"import": "./src/data/index.js",
|
|
51
|
+
"default": "./src/data/index.js"
|
|
52
|
+
},
|
|
48
53
|
"./styles.css": "./src/styles.css"
|
|
49
54
|
},
|
|
50
55
|
"files": [
|
|
@@ -75,13 +80,15 @@
|
|
|
75
80
|
"test": "node scripts/run-vitest.mjs --slow",
|
|
76
81
|
"test:fast": "node scripts/run-vitest.mjs",
|
|
77
82
|
"types:check": "tsc -p tsconfig.types.json --noEmit",
|
|
78
|
-
"check": "
|
|
79
|
-
"check
|
|
83
|
+
"docs:check": "node scripts/docs-check.mjs",
|
|
84
|
+
"check": "npm run docs:check && npm run test:fast && npm run types:check && npm run pack:dry && npm run consumer:smoke && npm run showcase:ci && npm run browser:smoke:quick -- --skip-build",
|
|
85
|
+
"check:release": "npm run docs:check && npm test && npm run types:check && npm run pack:dry && npm run consumer:smoke && npm run showcase:ci && npm run browser:smoke:full -- --skip-build",
|
|
80
86
|
"pack:dry": "npm pack --dry-run",
|
|
81
87
|
"consumer:smoke": "node scripts/consumer-package-smoke.mjs",
|
|
82
88
|
"browser:smoke": "node smoke/browser-smoke.mjs",
|
|
83
89
|
"browser:smoke:quick": "node smoke/browser-smoke.mjs --quick",
|
|
84
90
|
"browser:smoke:full": "node smoke/browser-smoke.mjs --full",
|
|
91
|
+
"benchmark:runtime": "node scripts/benchmark-runtime-efficiency.mjs",
|
|
85
92
|
"showcase:install": "npm --prefix local-preview ci",
|
|
86
93
|
"showcase:dev": "npm --prefix local-preview run dev",
|
|
87
94
|
"showcase:build": "npm --prefix local-preview run build",
|