@aura3d/engine 1.5.0 → 1.5.2

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.
Files changed (63) hide show
  1. package/README.md +111 -46
  2. package/dist/engine/agent-api/ApplicationKits.d.ts +307 -0
  3. package/dist/engine/agent-api/ApplicationKits.d.ts.map +1 -0
  4. package/dist/engine/agent-api/ApplicationKits.js +650 -0
  5. package/dist/engine/agent-api/ApplicationKits.js.map +1 -0
  6. package/dist/engine/agent-api/CombatFrameData.d.ts +210 -0
  7. package/dist/engine/agent-api/CombatFrameData.d.ts.map +1 -0
  8. package/dist/engine/agent-api/CombatFrameData.js +324 -0
  9. package/dist/engine/agent-api/CombatFrameData.js.map +1 -0
  10. package/dist/engine/agent-api/FocusSelection.d.ts +186 -0
  11. package/dist/engine/agent-api/FocusSelection.d.ts.map +1 -0
  12. package/dist/engine/agent-api/FocusSelection.js +436 -0
  13. package/dist/engine/agent-api/FocusSelection.js.map +1 -0
  14. package/dist/engine/agent-api/GameGenreKits.d.ts +32 -1
  15. package/dist/engine/agent-api/GameGenreKits.d.ts.map +1 -1
  16. package/dist/engine/agent-api/GameGenreKits.js +51 -7
  17. package/dist/engine/agent-api/GameGenreKits.js.map +1 -1
  18. package/dist/engine/agent-api/GameSceneGeometryBindings.d.ts +10 -0
  19. package/dist/engine/agent-api/GameSceneGeometryBindings.d.ts.map +1 -1
  20. package/dist/engine/agent-api/GameSceneGeometryBindings.js +7 -0
  21. package/dist/engine/agent-api/GameSceneGeometryBindings.js.map +1 -1
  22. package/dist/engine/agent-api/PlatformerMotion.d.ts +177 -0
  23. package/dist/engine/agent-api/PlatformerMotion.d.ts.map +1 -0
  24. package/dist/engine/agent-api/PlatformerMotion.js +207 -0
  25. package/dist/engine/agent-api/PlatformerMotion.js.map +1 -0
  26. package/dist/engine/agent-api/SceneQueries.d.ts +124 -0
  27. package/dist/engine/agent-api/SceneQueries.d.ts.map +1 -0
  28. package/dist/engine/agent-api/SceneQueries.js +221 -0
  29. package/dist/engine/agent-api/SceneQueries.js.map +1 -0
  30. package/dist/engine/agent-api/SpatialAnchoring.d.ts +279 -0
  31. package/dist/engine/agent-api/SpatialAnchoring.d.ts.map +1 -0
  32. package/dist/engine/agent-api/SpatialAnchoring.js +394 -0
  33. package/dist/engine/agent-api/SpatialAnchoring.js.map +1 -0
  34. package/dist/engine/agent-api/VehicleChassis.d.ts +192 -0
  35. package/dist/engine/agent-api/VehicleChassis.d.ts.map +1 -0
  36. package/dist/engine/agent-api/VehicleChassis.js +322 -0
  37. package/dist/engine/agent-api/VehicleChassis.js.map +1 -0
  38. package/dist/engine/agent-api/VehicleDriverAi.d.ts +123 -0
  39. package/dist/engine/agent-api/VehicleDriverAi.d.ts.map +1 -0
  40. package/dist/engine/agent-api/VehicleDriverAi.js +217 -0
  41. package/dist/engine/agent-api/VehicleDriverAi.js.map +1 -0
  42. package/dist/engine/agent-api/WorldLabelRenderer.d.ts +146 -0
  43. package/dist/engine/agent-api/WorldLabelRenderer.d.ts.map +1 -0
  44. package/dist/engine/agent-api/WorldLabelRenderer.js +331 -0
  45. package/dist/engine/agent-api/WorldLabelRenderer.js.map +1 -0
  46. package/dist/engine/agent-api/index.d.ts +64 -1
  47. package/dist/engine/agent-api/index.d.ts.map +1 -1
  48. package/dist/engine/agent-api/index.js +148 -2
  49. package/dist/engine/agent-api/index.js.map +1 -1
  50. package/dist/engine/agent-api/product-viewer-runtime.d.ts.map +1 -1
  51. package/dist/rendering/CameraFraming.d.ts +77 -0
  52. package/dist/rendering/CameraFraming.d.ts.map +1 -1
  53. package/dist/rendering/CameraFraming.js +176 -1
  54. package/dist/rendering/CameraFraming.js.map +1 -1
  55. package/dist/rendering/Renderer.d.ts +25 -2
  56. package/dist/rendering/Renderer.d.ts.map +1 -1
  57. package/dist/rendering/Renderer.js +11 -3
  58. package/dist/rendering/Renderer.js.map +1 -1
  59. package/dist/rendering/index.d.ts +3 -3
  60. package/dist/rendering/index.d.ts.map +1 -1
  61. package/dist/rendering/index.js +1 -1
  62. package/dist/rendering/index.js.map +1 -1
  63. package/package.json +120 -115
@@ -0,0 +1,322 @@
1
+ /**
2
+ * Reusable vehicle chassis: contact, suspension, attitude and wheel visuals.
3
+ *
4
+ * ## The defects this addresses
5
+ *
6
+ * Turbo Drift Circuit drove a 2D kinematic point (`game.racing`) and then pinned
7
+ * the car's rendered Y to a single literal, `TRACK_SURFACE_Y`. That has three
8
+ * visible consequences:
9
+ *
10
+ * 1. **The car sinks into the tarmac.** A model grounded on a frozen plane cannot
11
+ * respond to the surface it is actually over. There is no contact model, so
12
+ * there is nothing to hold the tyres on the road.
13
+ * 2. **No suspension.** The chassis never pitches under braking, never rolls in a
14
+ * corner, and the wheels never travel. A car that stays perfectly level at
15
+ * 111 km/h reads as a sprite sliding on a plane, which is what it is.
16
+ * 3. **Wheels do not turn or steer.** Nothing derived wheel spin from speed or
17
+ * wheel yaw from steering input.
18
+ *
19
+ * This module is the reusable answer. It takes a planar vehicle state -- position,
20
+ * heading, speed, steering, lateral slip -- plus a surface query, and produces the
21
+ * full 3D pose a renderer needs: chassis height from four independent contact
22
+ * points, pitch and roll from load transfer, per-wheel suspension travel, wheel
23
+ * spin and steer angles, and a contact report that states whether every tyre is
24
+ * on the ground.
25
+ *
26
+ * It is pure: no renderer, no DOM, no asset loading. That makes vehicle behaviour
27
+ * unit-testable, which is the only way "the car is grounded" becomes a fact rather
28
+ * than an opinion about a screenshot.
29
+ */
30
+ /** Flat surface at a fixed height, for prototypes and tests. */
31
+ export function flatVehicleSurface(height = 0, grip = 1) {
32
+ return { sample: () => ({ height, normal: [0, 1, 0], grip }) };
33
+ }
34
+ const WHEEL_LAYOUT = [
35
+ { id: "front-left", forward: 0.5, lateral: -0.5, steered: true },
36
+ { id: "front-right", forward: 0.5, lateral: 0.5, steered: true },
37
+ { id: "rear-left", forward: -0.5, lateral: -0.5, steered: false },
38
+ { id: "rear-right", forward: -0.5, lateral: 0.5, steered: false }
39
+ ];
40
+ /**
41
+ * Create a vehicle chassis.
42
+ *
43
+ * `rideHeight` and `wheelRadius` should be derived from the vehicle asset's own
44
+ * bounds. That is the difference between this and the constant it replaces: the
45
+ * caller states a proportion of a measured asset, not a number that happened to
46
+ * look right once.
47
+ */
48
+ export function createVehicleChassis(spec, surface) {
49
+ const resolved = {
50
+ wheelbase: positive(spec.wheelbase, 1),
51
+ trackWidth: positive(spec.trackWidth, 0.8),
52
+ wheelRadius: positive(spec.wheelRadius, 0.15),
53
+ rideHeight: positive(spec.rideHeight, 0.3),
54
+ suspensionTravel: positive(spec.suspensionTravel ?? spec.rideHeight * 0.35, 0.05),
55
+ springRate: positive(spec.springRate ?? 14, 1),
56
+ dampingRatio: positive(spec.dampingRatio ?? 0.72, 0.05),
57
+ maxSteerAngle: positive(spec.maxSteerAngle ?? 0.52, 0.05),
58
+ /*
59
+ * Attitude limits are capped by the suspension that has to produce them.
60
+ *
61
+ * Body pitch and roll are *consequences* of spring compression, not independent
62
+ * rotations of a rigid body. Applying an attitude larger than the springs can
63
+ * absorb rotates the chassis off its own wheels: at a 0.055 rad pitch over a
64
+ * 0.66-unit wheelbase the front corners move 0.018 units, which exceeded the whole
65
+ * 0.031-unit travel and lifted both front tyres into the air on a flat road. That
66
+ * is the sinking defect's mirror image and just as wrong.
67
+ *
68
+ * The cap is the angle at which a corner's vertical displacement equals half the
69
+ * available travel, leaving the other half for road surface.
70
+ */
71
+ maxPitch: Math.min(Math.max(0, spec.maxPitch ?? 0.055), attitudeLimitForTravel(spec.suspensionTravel ?? spec.rideHeight * 0.35, spec.wheelbase)),
72
+ maxRoll: Math.min(Math.max(0, spec.maxRoll ?? 0.085), attitudeLimitForTravel(spec.suspensionTravel ?? spec.rideHeight * 0.35, spec.trackWidth))
73
+ };
74
+ // Per-wheel suspension state: current compression and its velocity.
75
+ const compression = new Map();
76
+ for (const wheel of WHEEL_LAYOUT)
77
+ compression.set(wheel.id, { value: 0, velocity: 0 });
78
+ let spin = 0;
79
+ let pitch = 0;
80
+ let roll = 0;
81
+ let currentPose;
82
+ let telemetry = {
83
+ speed: 0, speedKph: 0, pitch: 0, roll: 0, steerAngle: 0,
84
+ wheelSpinRate: 0, groundedWheels: 4, maxContactGap: 0, averageCompression: 0, surfaceGrip: 1
85
+ };
86
+ /** Wheel contact-patch position in world space for a planar state. */
87
+ const wheelContactPoint = (state, wheel) => {
88
+ const cos = Math.cos(state.heading);
89
+ const sin = Math.sin(state.heading);
90
+ const forward = wheel.forward * resolved.wheelbase;
91
+ const lateral = wheel.lateral * resolved.trackWidth;
92
+ return {
93
+ // Heading 0 faces +X, so forward is (cos, sin) in XZ and lateral is its normal.
94
+ x: state.x + cos * forward - sin * lateral,
95
+ z: state.z + sin * forward + cos * lateral
96
+ };
97
+ };
98
+ const resolvePose = (dt, state, settleImmediately) => {
99
+ const step = Math.max(0, Math.min(0.1, dt));
100
+ const throttle = clamp01(state.throttle ?? 0);
101
+ const brake = clamp01(state.brake ?? 0);
102
+ const slip = clamp01(state.slip ?? 0);
103
+ const steerInput = clamp(state.steer ?? 0, -1, 1);
104
+ /*
105
+ * The wheels own the road; the springs own the body.
106
+ *
107
+ * Two earlier orderings were wrong in opposite directions, and both reproduce a
108
+ * version of the reported defect:
109
+ *
110
+ * 1. Place each wheel on its own surface sample and average -- the contact gap
111
+ * becomes self-referential, so a car could drive over a cliff and still report
112
+ * itself grounded.
113
+ * 2. Rotate the body to a target pitch/roll and hang wheels from it -- the rotation
114
+ * consumes more travel than exists (0.018 units of corner rise against 0.031
115
+ * units of travel), lifting the front tyres off a flat road.
116
+ *
117
+ * The physical arrangement is that a wheel rests on the surface beneath it, and the
118
+ * spring above it sets how far the body's corner floats over that wheel. Load
119
+ * transfer therefore *lowers a corner of the body* rather than raising a wheel, and
120
+ * the body's pitch and roll are read back from the four corner heights. Wheels stay
121
+ * on the ground by construction, and the attitude is always one the suspension can
122
+ * actually support.
123
+ */
124
+ const longitudinalLoad = brake - throttle;
125
+ const speedFactor = Math.min(1, Math.abs(state.speed) / 12);
126
+ const lateralLoad = clamp(steerInput * speedFactor + steerInput * slip * 0.5, -1, 1);
127
+ // Fraction of available travel that load transfer may consume, leaving headroom.
128
+ const loadTravelShare = 0.5;
129
+ const samples = WHEEL_LAYOUT.map((wheel) => {
130
+ const point = wheelContactPoint(state, wheel);
131
+ const sample = surface.sample(point.x, point.z);
132
+ return { wheel, point, sample };
133
+ });
134
+ const meanGrip = samples.reduce((sum, entry) => sum + (entry.sample.grip ?? 1), 0) / samples.length;
135
+ const cornerHeights = [];
136
+ const wheels = samples.map(({ wheel, point, sample }) => {
137
+ const spring = compression.get(wheel.id) ?? { value: 0.5, velocity: 0 };
138
+ /*
139
+ * Target compression from load transfer. A front wheel (`forward > 0`) compresses
140
+ * under braking; an outside wheel compresses in a corner. 0.5 is rest.
141
+ */
142
+ const target = clamp01(0.5 + (wheel.forward * longitudinalLoad
143
+ + wheel.lateral * lateralLoad) * loadTravelShare);
144
+ if (settleImmediately) {
145
+ spring.value = target;
146
+ spring.velocity = 0;
147
+ }
148
+ else {
149
+ // Explicit spring-damper integration so the damping behaviour is visible.
150
+ const acceleration = (target - spring.value) * resolved.springRate
151
+ - spring.velocity * 2 * resolved.dampingRatio * Math.sqrt(resolved.springRate);
152
+ spring.velocity += acceleration * step;
153
+ spring.value = clamp01(spring.value + spring.velocity * step);
154
+ }
155
+ compression.set(wheel.id, spring);
156
+ /*
157
+ * The wheel rests on its own surface. This is unconditional: a tyre cannot be
158
+ * inside the road, and on a driveable surface it should not be above it either.
159
+ */
160
+ const wheelCentreY = sample.height + resolved.wheelRadius;
161
+ // The body's corner floats above that wheel by ride height, less compression.
162
+ const cornerY = wheelCentreY - resolved.wheelRadius + resolved.rideHeight
163
+ - (spring.value - 0.5) * resolved.suspensionTravel;
164
+ cornerHeights.push(cornerY);
165
+ return {
166
+ id: wheel.id,
167
+ position: [point.x, wheelCentreY, point.z],
168
+ steerAngle: wheel.steered ? steerInput * resolved.maxSteerAngle : 0,
169
+ spin,
170
+ compression: spring.value,
171
+ // A wheel is grounded when its surface is reachable within suspension travel.
172
+ // A hole deeper than the travel leaves the wheel hanging, which is correct.
173
+ grounded: true,
174
+ contactGap: 0
175
+ };
176
+ });
177
+ /*
178
+ * A wheel over a drop deeper than the suspension can reach is not grounded.
179
+ *
180
+ * Measured against the body: if a corner would have to sit further above its wheel
181
+ * than ride height plus full travel, the wheel has run out of extension and hangs.
182
+ */
183
+ const bodyY = cornerHeights.reduce((sum, value) => sum + value, 0) / cornerHeights.length;
184
+ const maxReach = resolved.rideHeight + resolved.suspensionTravel * 0.5;
185
+ const resolvedWheels = wheels.map((wheel, index) => {
186
+ const sample = samples[index].sample;
187
+ const requiredDrop = bodyY - sample.height;
188
+ if (requiredDrop <= maxReach)
189
+ return wheel;
190
+ // Out of travel: the wheel stays at its fullest extension below the body and
191
+ // reports the gap to the surface it cannot reach.
192
+ const hangingCentreY = bodyY - maxReach + resolved.wheelRadius;
193
+ return {
194
+ ...wheel,
195
+ position: [wheel.position[0], hangingCentreY, wheel.position[2]],
196
+ compression: 0,
197
+ grounded: false,
198
+ contactGap: requiredDrop - maxReach
199
+ };
200
+ });
201
+ /*
202
+ * Read the body's attitude back from the four corner heights.
203
+ *
204
+ * Front corners lower than rear means the nose has dropped, which is pitch. Left
205
+ * lower than right is roll. Derived rather than imposed, so the attitude can only
206
+ * be one the springs produced.
207
+ */
208
+ const cornerBy = (id) => {
209
+ const index = WHEEL_LAYOUT.findIndex((wheel) => wheel.id === id);
210
+ return cornerHeights[index] ?? bodyY;
211
+ };
212
+ const frontHeight = (cornerBy("front-left") + cornerBy("front-right")) / 2;
213
+ const rearHeight = (cornerBy("rear-left") + cornerBy("rear-right")) / 2;
214
+ const leftHeight = (cornerBy("front-left") + cornerBy("rear-left")) / 2;
215
+ const rightHeight = (cornerBy("front-right") + cornerBy("rear-right")) / 2;
216
+ // A lower nose is a positive pitch, matching the convention that braking pitches
217
+ // the car nose-down with a positive angle.
218
+ pitch = clamp(Math.asin(clamp((rearHeight - frontHeight) / Math.max(1e-6, resolved.wheelbase), -1, 1)), -resolved.maxPitch, resolved.maxPitch);
219
+ // A lower left side is a negative roll, so steering right (which loads the left)
220
+ // produces a negative roll and steering left a positive one.
221
+ roll = clamp(Math.asin(clamp((leftHeight - rightHeight) / Math.max(1e-6, resolved.trackWidth), -1, 1)), -resolved.maxRoll, resolved.maxRoll);
222
+ // Rolling rotation from distance travelled. A stationary car's wheels must not
223
+ // spin, and a fast car's must, which is what makes motion legible.
224
+ const spinRate = resolved.wheelRadius > 0 ? state.speed / resolved.wheelRadius : 0;
225
+ spin = (spin + spinRate * step) % (Math.PI * 2);
226
+ const spunWheels = resolvedWheels.map((wheel) => ({ ...wheel, spin }));
227
+ const averageCompression = spunWheels.reduce((sum, wheel) => sum + wheel.compression, 0) / spunWheels.length;
228
+ const maxContactGap = Math.max(...spunWheels.map((wheel) => wheel.contactGap));
229
+ // Lowest contact patch across the four wheels: where a grounded model sits.
230
+ const contactPlaneY = Math.min(...resolvedWheels.map((wheel) => wheel.position[1] - resolved.wheelRadius));
231
+ currentPose = {
232
+ position: [state.x, bodyY, state.z],
233
+ groundedPosition: [state.x, contactPlaneY, state.z],
234
+ rotation: [pitch, state.heading, roll],
235
+ wheels: spunWheels,
236
+ contactGap: Math.min(...spunWheels.map((wheel) => wheel.contactGap)),
237
+ grounded: spunWheels.every((wheel) => wheel.grounded),
238
+ averageCompression
239
+ };
240
+ telemetry = {
241
+ speed: state.speed,
242
+ speedKph: state.speed * 3.6,
243
+ pitch,
244
+ roll,
245
+ steerAngle: steerInput * resolved.maxSteerAngle,
246
+ wheelSpinRate: spinRate,
247
+ groundedWheels: spunWheels.filter((wheel) => wheel.grounded).length,
248
+ maxContactGap,
249
+ averageCompression,
250
+ surfaceGrip: meanGrip
251
+ };
252
+ return currentPose;
253
+ };
254
+ return {
255
+ kind: "aura-vehicle-chassis",
256
+ spec: resolved,
257
+ step(dt, state) {
258
+ return resolvePose(dt, state, false);
259
+ },
260
+ pose() {
261
+ return currentPose ?? resolvePose(0, { x: 0, z: 0, heading: 0, speed: 0, steer: 0 }, true);
262
+ },
263
+ telemetry() {
264
+ return telemetry;
265
+ },
266
+ reset(state) {
267
+ for (const wheel of WHEEL_LAYOUT)
268
+ compression.set(wheel.id, { value: 0.5, velocity: 0 });
269
+ spin = 0;
270
+ pitch = 0;
271
+ roll = 0;
272
+ return resolvePose(0, state, true);
273
+ }
274
+ };
275
+ }
276
+ /**
277
+ * Derive chassis geometry from a vehicle asset's rendered bounds.
278
+ *
279
+ * This is what removes the need for a `CAR_SCENE_HEIGHT`-style constant. Given the
280
+ * size the asset actually renders at, the wheelbase, track width, wheel radius and
281
+ * ride height follow from standard automotive proportions, so a different car
282
+ * produces a different chassis instead of inheriting the old one's numbers.
283
+ */
284
+ export function vehicleChassisSpecFromBounds(size, options = {}) {
285
+ // The longest horizontal axis is the body length; the other is its width.
286
+ const length = Math.max(size[0], size[2]);
287
+ const width = Math.min(size[0], size[2]);
288
+ const height = size[1];
289
+ const wheelDiameter = height * (options.wheelDiameterFraction ?? 0.42);
290
+ const wheelRadius = wheelDiameter / 2;
291
+ return {
292
+ wheelbase: length * (options.wheelbaseFraction ?? 0.6),
293
+ trackWidth: width * (options.trackFraction ?? 0.82),
294
+ wheelRadius,
295
+ // The chassis origin sits at the body's vertical centre, which is one wheel
296
+ // radius plus half the remaining body height above the contact patch.
297
+ rideHeight: wheelRadius + (height - wheelDiameter) * 0.5,
298
+ suspensionTravel: wheelRadius * 0.42
299
+ };
300
+ }
301
+ /**
302
+ * Largest body rotation a given suspension travel can produce over a given span.
303
+ *
304
+ * A corner sits `span / 2` from the rotation axis, so rotating by `theta` moves it
305
+ * `sin(theta) * span / 2` vertically. Half the travel is reserved for the road, so
306
+ * the limit is `asin(travel / 2 / (span / 2))`.
307
+ */
308
+ function attitudeLimitForTravel(travel, span) {
309
+ const halfSpan = Math.max(1e-6, span / 2);
310
+ const budget = Math.max(0, travel) / 2;
311
+ return Math.asin(Math.min(1, budget / halfSpan));
312
+ }
313
+ function clamp(value, min, max) {
314
+ return Math.min(max, Math.max(min, Number.isFinite(value) ? value : min));
315
+ }
316
+ function clamp01(value) {
317
+ return clamp(value, 0, 1);
318
+ }
319
+ function positive(value, fallback) {
320
+ return Number.isFinite(value) && value > 0 ? value : fallback;
321
+ }
322
+ //# sourceMappingURL=VehicleChassis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VehicleChassis.js","sourceRoot":"","sources":["../../../../../packages/engine/src/agent-api/VehicleChassis.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Reusable AI driving: racing line, look-ahead steering, curvature-based speed.
3
+ *
4
+ * ## The defect this replaces
5
+ *
6
+ * Turbo's opponent was a route-local controller that steered only to null its
7
+ * lateral offset from the racing line:
8
+ *
9
+ * ```ts
10
+ * const steeringCorrection = -snapshot.signedTrackOffset * steeringGain;
11
+ * ```
12
+ *
13
+ * A pure proportional term on present error has no notion of where the track goes
14
+ * next. Approaching a corner it steers straight until it is already off the line,
15
+ * then over-corrects, which is why the opponent read as moving sideways and leaving
16
+ * the circuit. It also had no braking model tied to the corner ahead, so it entered
17
+ * every turn at cruise speed and understeered out of it. And because the kit's
18
+ * off-track handler pulls a certified car back toward the centreline, the recovery
19
+ * looked like the car being dragged rather than driving.
20
+ *
21
+ * This module drives the way a driver does: it samples the route **ahead** of the
22
+ * car, aims at a look-ahead point on the racing line, and sets a target speed from
23
+ * the curvature it is about to meet. It also detects being stuck and being off
24
+ * track, and recovers deliberately.
25
+ *
26
+ * Pure and deterministic: given the same route and the same seed it produces the
27
+ * same lap, so a race is reproducible and testable.
28
+ */
29
+ export interface DriverRoutePoint {
30
+ readonly x: number;
31
+ readonly y: number;
32
+ }
33
+ /**
34
+ * Route the driver follows.
35
+ *
36
+ * Supplied by the caller from its own track topology, so the driver has no
37
+ * knowledge of any particular circuit.
38
+ */
39
+ export interface DriverRoute {
40
+ /** Sample the racing line at a normalized progress 0..1. */
41
+ sample(progress: number): {
42
+ readonly x: number;
43
+ readonly y: number;
44
+ readonly heading: number;
45
+ };
46
+ /** Half-width of the drivable road at a progress. */
47
+ halfWidth(progress: number): number;
48
+ /** Total route length in world units, used to convert look-ahead distance to progress. */
49
+ readonly length: number;
50
+ }
51
+ export interface DriverVehicleState {
52
+ readonly progress: number;
53
+ readonly speed: number;
54
+ readonly heading: number;
55
+ /** Lateral offset from the racing line, signed positive to the left of travel. */
56
+ readonly signedTrackOffset: number;
57
+ readonly position: {
58
+ readonly x: number;
59
+ readonly y: number;
60
+ };
61
+ readonly offTrack: boolean;
62
+ }
63
+ export interface DriverInput {
64
+ readonly throttle: number;
65
+ readonly brake: number;
66
+ readonly steer: number;
67
+ readonly drift: boolean;
68
+ }
69
+ export type DriverAggression = "cautious" | "balanced" | "aggressive";
70
+ export interface DriverConfig {
71
+ readonly maxSpeed: number;
72
+ /** Fraction of `maxSpeed` targeted on a straight. */
73
+ readonly paceFraction?: number | undefined;
74
+ /**
75
+ * Look-ahead time in seconds. The driver aims where it will be this far in the
76
+ * future, which is what lets it turn *before* the corner instead of after it.
77
+ */
78
+ readonly lookAheadSeconds?: number | undefined;
79
+ /** Minimum look-ahead distance so a stationary car still has an aim point. */
80
+ readonly minLookAhead?: number | undefined;
81
+ /** Lateral correction gain. Scaled internally by route width. */
82
+ readonly lineGain?: number | undefined;
83
+ /** Heading correction gain. */
84
+ readonly headingGain?: number | undefined;
85
+ /**
86
+ * Lateral acceleration the driver is willing to carry through a corner, in world
87
+ * units per second squared. This is what sets corner entry speed.
88
+ */
89
+ readonly corneringAcceleration?: number | undefined;
90
+ readonly aggression?: DriverAggression | undefined;
91
+ /** Reaction delay in seconds. A human driver is not instantaneous. */
92
+ readonly reactionSeconds?: number | undefined;
93
+ /** Deterministic seed for line variation. */
94
+ readonly seed?: number | undefined;
95
+ }
96
+ export interface DriverTelemetry {
97
+ readonly controller: "aura-vehicle-driver-ai";
98
+ readonly aggression: DriverAggression;
99
+ readonly targetSpeed: number;
100
+ readonly lookAheadDistance: number;
101
+ readonly upcomingCurvature: number;
102
+ readonly cornerSpeedLimit: number;
103
+ readonly steerFromLine: number;
104
+ readonly steerFromHeading: number;
105
+ readonly recovering: boolean;
106
+ readonly stuckSeconds: number;
107
+ readonly decisionCount: number;
108
+ readonly input: DriverInput;
109
+ }
110
+ export interface VehicleDriverAi {
111
+ readonly kind: "aura-vehicle-driver-ai";
112
+ /** Decide inputs for the coming step. */
113
+ decide(dt: number, state: DriverVehicleState): DriverInput;
114
+ telemetry(): DriverTelemetry;
115
+ reset(): void;
116
+ }
117
+ /**
118
+ * Create a deterministic AI driver for a route.
119
+ */
120
+ export declare function createVehicleDriverAi(route: DriverRoute, config: DriverConfig): VehicleDriverAi;
121
+ /** Smallest signed angle from `b` to `a`, in -pi..pi. */
122
+ export declare function angleDelta(a: number, b: number): number;
123
+ //# sourceMappingURL=VehicleDriverAi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VehicleDriverAi.d.ts","sourceRoot":"","sources":["../../../../../packages/engine/src/agent-api/VehicleDriverAi.ts"],"names":[],"mappings":"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"}