@aura3d/physics 1.5.1 → 2.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.
Files changed (81) hide show
  1. package/dist/ArcadeCharacterController.d.ts +53 -0
  2. package/dist/ArcadeCharacterController.d.ts.map +1 -0
  3. package/dist/ArcadeCharacterController.js +98 -0
  4. package/dist/ArcadeCharacterController.js.map +1 -0
  5. package/dist/ArcadeVehicleTelemetry.d.ts +162 -0
  6. package/dist/ArcadeVehicleTelemetry.d.ts.map +1 -0
  7. package/dist/ArcadeVehicleTelemetry.js +363 -0
  8. package/dist/ArcadeVehicleTelemetry.js.map +1 -0
  9. package/dist/CharacterController.d.ts +52 -0
  10. package/dist/CharacterController.d.ts.map +1 -1
  11. package/dist/CharacterController.js +380 -7
  12. package/dist/CharacterController.js.map +1 -1
  13. package/dist/Constraint.d.ts +20 -4
  14. package/dist/Constraint.d.ts.map +1 -1
  15. package/dist/Constraint.js +34 -60
  16. package/dist/Constraint.js.map +1 -1
  17. package/dist/FightingCharacterController.d.ts +32 -0
  18. package/dist/FightingCharacterController.d.ts.map +1 -0
  19. package/dist/FightingCharacterController.js +76 -0
  20. package/dist/FightingCharacterController.js.map +1 -0
  21. package/dist/MeshBVH.d.ts +72 -0
  22. package/dist/MeshBVH.d.ts.map +1 -0
  23. package/dist/MeshBVH.js +244 -0
  24. package/dist/MeshBVH.js.map +1 -0
  25. package/dist/PathFollowDriver.d.ts +162 -0
  26. package/dist/PathFollowDriver.d.ts.map +1 -0
  27. package/dist/PathFollowDriver.js +163 -0
  28. package/dist/PathFollowDriver.js.map +1 -0
  29. package/dist/PhysicsDebugDraw.d.ts +40 -1
  30. package/dist/PhysicsDebugDraw.d.ts.map +1 -1
  31. package/dist/PhysicsDebugDraw.js +87 -17
  32. package/dist/PhysicsDebugDraw.js.map +1 -1
  33. package/dist/PhysicsWorld.d.ts +37 -18
  34. package/dist/PhysicsWorld.d.ts.map +1 -1
  35. package/dist/PhysicsWorld.js +231 -630
  36. package/dist/PhysicsWorld.js.map +1 -1
  37. package/dist/RacingLineProfile.d.ts +116 -0
  38. package/dist/RacingLineProfile.d.ts.map +1 -0
  39. package/dist/RacingLineProfile.js +181 -0
  40. package/dist/RacingLineProfile.js.map +1 -0
  41. package/dist/Raycast.d.ts +11 -0
  42. package/dist/Raycast.d.ts.map +1 -1
  43. package/dist/Raycast.js +62 -8
  44. package/dist/Raycast.js.map +1 -1
  45. package/dist/RigidBody.d.ts +16 -9
  46. package/dist/RigidBody.d.ts.map +1 -1
  47. package/dist/RigidBody.js +23 -75
  48. package/dist/RigidBody.js.map +1 -1
  49. package/dist/SurfaceQuery.d.ts +72 -0
  50. package/dist/SurfaceQuery.d.ts.map +1 -0
  51. package/dist/SurfaceQuery.js +89 -0
  52. package/dist/SurfaceQuery.js.map +1 -0
  53. package/dist/VehicleDynamics.d.ts +10 -0
  54. package/dist/VehicleDynamics.d.ts.map +1 -1
  55. package/dist/VehicleDynamics.js +31 -3
  56. package/dist/VehicleDynamics.js.map +1 -1
  57. package/dist/VehicleMotion.d.ts +125 -0
  58. package/dist/VehicleMotion.d.ts.map +1 -0
  59. package/dist/VehicleMotion.js +373 -0
  60. package/dist/VehicleMotion.js.map +1 -0
  61. package/dist/index.d.ts +62 -17
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +70 -17
  64. package/dist/index.js.map +1 -1
  65. package/dist/solverless-entry.d.ts +41 -0
  66. package/dist/solverless-entry.d.ts.map +1 -0
  67. package/dist/solverless-entry.js +40 -0
  68. package/dist/solverless-entry.js.map +1 -0
  69. package/dist/solverless.d.ts +37 -0
  70. package/dist/solverless.d.ts.map +1 -0
  71. package/dist/solverless.js +36 -0
  72. package/dist/solverless.js.map +1 -0
  73. package/dist/world-entry.d.ts +31 -0
  74. package/dist/world-entry.d.ts.map +1 -0
  75. package/dist/world-entry.js +30 -0
  76. package/dist/world-entry.js.map +1 -0
  77. package/dist/world.d.ts +18 -0
  78. package/dist/world.d.ts.map +1 -0
  79. package/dist/world.js +17 -0
  80. package/dist/world.js.map +1 -0
  81. package/package.json +10 -2
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Turns a path plus a speed target into steering, throttle and brake for `createVehicleMotion`.
3
+ *
4
+ * ## Why this exists
5
+ *
6
+ * The library shipped the two hard halves of AI driving — `createVehicleMotion` for the tyre and
7
+ * yaw dynamics, `createRacingLineProfile` for the speed a corner can be taken at — and nothing to
8
+ * join them. Every racing route therefore hand-rolled its own driver, and hand-rolled drivers all
9
+ * fail the same way. The obvious formulation, a Stanley controller that steers on
10
+ * `headingError + atan2(crossTrack, speed)`, is stable on gentle curves and diverges on a hairpin:
11
+ *
12
+ * 1. Heading error grows faster than the car can rotate, so the steering command saturates.
13
+ * 2. Saturated at full lock, the controller has no authority left and the car runs wide.
14
+ * 3. Once outside the road the nearest point on the path stops advancing, so `progress` latches.
15
+ * A latched progress freezes the speed target and the curvature feedforward.
16
+ * 4. The now-constant cross-track term flips sign every frame as the car crosses the path
17
+ * centreline, and the car saws away from the track at full lock — measured on the certified
18
+ * circuit as progress stuck at 0.2789 for 8,700 consecutive frames while lateral offset grew to
19
+ * 43 units, i.e. 98 road widths from a 0.439-wide road.
20
+ *
21
+ * The failure is not the vehicle's. Held at a fixed speed, the same car corners at radius
22
+ * 0.32-0.55 against a hairpin that demands 0.80, so it has ~40% radius margin. It was the
23
+ * controller throwing that margin away.
24
+ *
25
+ * ## What this does instead
26
+ *
27
+ * Pure pursuit: aim at a point a lookahead distance *along the path* and solve the arc that reaches
28
+ * it. This is bounded by construction — the arc to a point at a known distance has a known
29
+ * curvature, so the command cannot run away the way an unbounded error term can. Three properties
30
+ * matter for the hairpin case:
31
+ *
32
+ * - **Lookahead scales with speed** (`lookaheadTime * speed`, clamped to `[minLookahead,
33
+ * maxLookahead]`). Time-based lookahead means the car looks a fixed duration ahead rather than a
34
+ * fixed distance, which is what makes one gain work at both 2 and 12 units/second.
35
+ * - **The target is measured along arc length, not straight-line distance.** On a hairpin the point
36
+ * 0.8 units ahead along the road is nearly behind the car in a straight line; chord-based
37
+ * lookahead skips the corner entirely and cuts to the exit.
38
+ * - **Progress advances monotonically** from the driver's own integrated distance, so being off the
39
+ * road cannot latch it. This is the direct fix for failure 3 above: the driver keeps a running
40
+ * distance and only accepts a measured progress that is ahead of it, within a rejoin window.
41
+ *
42
+ * Speed control is a PI-free proportional law with an explicit brake/throttle split, because a
43
+ * single signed axis fed to a vehicle that has separate `driveForce` and `brakeForce` produces
44
+ * asymmetric response that reads as the car refusing to slow for corners.
45
+ *
46
+ * The driver is pure and allocation-free per step: no `three`, no renderer, no route names, no
47
+ * game-specific branch. Any path that can answer "where am I along you" and "what is your point at
48
+ * distance d" can be driven, which is why the input is two callbacks rather than a route type.
49
+ */
50
+ export interface PathFollowSample {
51
+ /** Path point at the requested distance. */
52
+ readonly x: number;
53
+ readonly y: number;
54
+ /** Tangent heading at that point, radians, atan2(dy, dx) convention. */
55
+ readonly heading: number;
56
+ /** Signed curvature at that point, 1/radius. Positive turns left. */
57
+ readonly curvature: number;
58
+ }
59
+ export interface PathFollowContact {
60
+ /** Distance along the path of the closest point to the car. */
61
+ readonly distance: number;
62
+ /** Signed lateral offset of the car from the path, positive to the left of travel. */
63
+ readonly signedOffset: number;
64
+ }
65
+ export interface PathFollowDriverOptions {
66
+ /** Total path length in world units. */
67
+ readonly length: number;
68
+ /** True when the path loops. Defaults to true. */
69
+ readonly closed?: boolean | undefined;
70
+ /** Path point at an absolute distance along the path. Must handle wrap on a closed path. */
71
+ sampleAt(distance: number): PathFollowSample;
72
+ /** Closest point on the path to a world position. */
73
+ contactAt(x: number, y: number): PathFollowContact;
74
+ /** Target speed at a distance along the path, world units per second. */
75
+ speedAt(distance: number): number;
76
+ /** Vehicle wheelbase, world units. Sets how much steer angle a given arc needs. */
77
+ readonly wheelbase: number;
78
+ /** Vehicle maximum steer angle, radians, matching `createVehicleMotion`. */
79
+ readonly maxSteerAngle: number;
80
+ /**
81
+ * Seconds of travel to look ahead. Larger is smoother and cuts corners more; smaller tracks the
82
+ * line tighter and saturates sooner.
83
+ *
84
+ * The default is measured, not guessed. Swept over the certified circuit at 5,400 frames per
85
+ * cell, off-track time is dominated by this parameter and barely moves with grip margin, which is
86
+ * what identifies the original failure as tracking geometry rather than tyre grip:
87
+ *
88
+ * ```text
89
+ * lookaheadTime 0.12 0.18 0.25 0.30 0.35 0.45 0.55 0.70 0.90
90
+ * off-track % 5.4 4.3 3.3 3.5 5.4 12.8 20.3 33.6 44.0
91
+ * saturated % 8.5 5.0 3.2 1.4 0.7 1.7 4.6 5.4 4.7
92
+ * ```
93
+ *
94
+ * 0.25 is the minimum. Below it the car tracks so tightly that it saturates on corner entry
95
+ * (8.5% of frames at full lock); above it the aim point cuts inside the apex and the car runs
96
+ * wide. Full sweep in `tests/unit/physics/racing-line-profile.test.ts`.
97
+ */
98
+ readonly lookaheadTime?: number | undefined;
99
+ /** Lookahead floor, world units, so a stopped car still has a target. */
100
+ readonly minLookahead?: number | undefined;
101
+ /** Lookahead ceiling, world units, so a fast straight does not aim past the next corner. */
102
+ readonly maxLookahead?: number | undefined;
103
+ /**
104
+ * Extra steer per unit of lateral offset, used only to close a standing offset that pure pursuit
105
+ * alone converges on slowly. Applied through `atan2` against speed so it fades as speed rises.
106
+ *
107
+ * 2.5 measured best on the certified circuit (3.3% off-track versus 4.2% at 0.6), and unlike a
108
+ * Stanley cross-track gain it cannot destabilise the loop on its own because the `atan2` bounds
109
+ * its contribution to under a quarter turn regardless of how large the offset grows.
110
+ */
111
+ readonly crossTrackGain?: number | undefined;
112
+ /** Throttle/brake proportional gain on speed error, per world unit per second. */
113
+ readonly speedGain?: number | undefined;
114
+ /**
115
+ * How far ahead of the car the speed target is read, in seconds of travel. Braking has to start
116
+ * before the corner, so a driver that reads the target at its own position always enters too
117
+ * fast. Defaults to 0.35.
118
+ */
119
+ readonly speedPreviewTime?: number | undefined;
120
+ /**
121
+ * How far the measured progress may sit behind the driver's integrated distance before the driver
122
+ * accepts it as a genuine rejoin rather than a stale nearest-point match. World units.
123
+ * Defaults to 8% of `length`.
124
+ */
125
+ readonly rejoinWindow?: number | undefined;
126
+ }
127
+ export interface PathFollowCommand {
128
+ /** 0..1, feed straight to `VehicleMotion.step`. */
129
+ readonly throttle: number;
130
+ /** 0..1. */
131
+ readonly brake: number;
132
+ /** -1..1. */
133
+ readonly steer: number;
134
+ /** Distance along the path the driver believes it is at. Monotonic on a closed path. */
135
+ readonly distance: number;
136
+ /** Progress 0..1 derived from `distance`. */
137
+ readonly progress: number;
138
+ /** Signed lateral offset used for this command. */
139
+ readonly signedOffset: number;
140
+ /** Speed the driver is currently asking for. */
141
+ readonly targetSpeed: number;
142
+ /** Lookahead distance used, world units. Exposed for tuning and for tests. */
143
+ readonly lookahead: number;
144
+ /** True while the steering command is at full lock, which means the driver is out of authority. */
145
+ readonly saturated: boolean;
146
+ }
147
+ export interface PathFollowDriver {
148
+ readonly kind: "aura-path-follow-driver";
149
+ /** Compute the command for the current vehicle state. Does not mutate the vehicle. */
150
+ step(state: {
151
+ readonly x: number;
152
+ readonly z: number;
153
+ readonly heading: number;
154
+ readonly speed: number;
155
+ }): PathFollowCommand;
156
+ /** Reset the integrated distance, e.g. after placing the car on the grid. */
157
+ reset(distance?: number): void;
158
+ /** Laps completed since reset, counted from monotonic distance rather than progress wrap. */
159
+ readonly lapsCompleted: number;
160
+ }
161
+ export declare function createPathFollowDriver(options: PathFollowDriverOptions): PathFollowDriver;
162
+ //# sourceMappingURL=PathFollowDriver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PathFollowDriver.d.ts","sourceRoot":"","sources":["../../../../packages/physics/src/PathFollowDriver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,4CAA4C;IAC5C,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,qEAAqE;IACrE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,+DAA+D;IAC/D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,sFAAsF;IACtF,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,uBAAuB;IACtC,wCAAwC;IACxC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,kDAAkD;IAClD,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACtC,4FAA4F;IAC5F,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAAC;IAC7C,qDAAqD;IACrD,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAAC;IACnD,yEAAyE;IACzE,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAClC,mFAAmF;IACnF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,4EAA4E;IAC5E,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B;;;;;;;;;;;;;;;;;OAiBG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,yEAAyE;IACzE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,4FAA4F;IAC5F,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C;;;;;;;OAOG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7C,kFAAkF;IAClF,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC;;;;OAIG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/C;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5C;AAED,MAAM,WAAW,iBAAiB;IAChC,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,YAAY;IACZ,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,aAAa;IACb,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,wFAAwF;IACxF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,6CAA6C;IAC7C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,mDAAmD;IACnD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,gDAAgD;IAChD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,8EAA8E;IAC9E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,mGAAmG;IACnG,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,yBAAyB,CAAC;IACzC,sFAAsF;IACtF,IAAI,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,iBAAiB,CAAC;IAC7H,6EAA6E;IAC7E,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,6FAA6F;IAC7F,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAaD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,uBAAuB,GAAG,gBAAgB,CA0GzF"}
@@ -0,0 +1,163 @@
1
+ /**
2
+ * Turns a path plus a speed target into steering, throttle and brake for `createVehicleMotion`.
3
+ *
4
+ * ## Why this exists
5
+ *
6
+ * The library shipped the two hard halves of AI driving — `createVehicleMotion` for the tyre and
7
+ * yaw dynamics, `createRacingLineProfile` for the speed a corner can be taken at — and nothing to
8
+ * join them. Every racing route therefore hand-rolled its own driver, and hand-rolled drivers all
9
+ * fail the same way. The obvious formulation, a Stanley controller that steers on
10
+ * `headingError + atan2(crossTrack, speed)`, is stable on gentle curves and diverges on a hairpin:
11
+ *
12
+ * 1. Heading error grows faster than the car can rotate, so the steering command saturates.
13
+ * 2. Saturated at full lock, the controller has no authority left and the car runs wide.
14
+ * 3. Once outside the road the nearest point on the path stops advancing, so `progress` latches.
15
+ * A latched progress freezes the speed target and the curvature feedforward.
16
+ * 4. The now-constant cross-track term flips sign every frame as the car crosses the path
17
+ * centreline, and the car saws away from the track at full lock — measured on the certified
18
+ * circuit as progress stuck at 0.2789 for 8,700 consecutive frames while lateral offset grew to
19
+ * 43 units, i.e. 98 road widths from a 0.439-wide road.
20
+ *
21
+ * The failure is not the vehicle's. Held at a fixed speed, the same car corners at radius
22
+ * 0.32-0.55 against a hairpin that demands 0.80, so it has ~40% radius margin. It was the
23
+ * controller throwing that margin away.
24
+ *
25
+ * ## What this does instead
26
+ *
27
+ * Pure pursuit: aim at a point a lookahead distance *along the path* and solve the arc that reaches
28
+ * it. This is bounded by construction — the arc to a point at a known distance has a known
29
+ * curvature, so the command cannot run away the way an unbounded error term can. Three properties
30
+ * matter for the hairpin case:
31
+ *
32
+ * - **Lookahead scales with speed** (`lookaheadTime * speed`, clamped to `[minLookahead,
33
+ * maxLookahead]`). Time-based lookahead means the car looks a fixed duration ahead rather than a
34
+ * fixed distance, which is what makes one gain work at both 2 and 12 units/second.
35
+ * - **The target is measured along arc length, not straight-line distance.** On a hairpin the point
36
+ * 0.8 units ahead along the road is nearly behind the car in a straight line; chord-based
37
+ * lookahead skips the corner entirely and cuts to the exit.
38
+ * - **Progress advances monotonically** from the driver's own integrated distance, so being off the
39
+ * road cannot latch it. This is the direct fix for failure 3 above: the driver keeps a running
40
+ * distance and only accepts a measured progress that is ahead of it, within a rejoin window.
41
+ *
42
+ * Speed control is a PI-free proportional law with an explicit brake/throttle split, because a
43
+ * single signed axis fed to a vehicle that has separate `driveForce` and `brakeForce` produces
44
+ * asymmetric response that reads as the car refusing to slow for corners.
45
+ *
46
+ * The driver is pure and allocation-free per step: no `three`, no renderer, no route names, no
47
+ * game-specific branch. Any path that can answer "where am I along you" and "what is your point at
48
+ * distance d" can be driven, which is why the input is two callbacks rather than a route type.
49
+ */
50
+ function clamp(value, min, max) {
51
+ return value < min ? min : value > max ? max : value;
52
+ }
53
+ function wrapAngle(value) {
54
+ let angle = value;
55
+ while (angle > Math.PI)
56
+ angle -= 2 * Math.PI;
57
+ while (angle < -Math.PI)
58
+ angle += 2 * Math.PI;
59
+ return angle;
60
+ }
61
+ export function createPathFollowDriver(options) {
62
+ const length = options.length;
63
+ if (!Number.isFinite(length) || length <= 0) {
64
+ throw new Error(`createPathFollowDriver requires a positive length, received ${String(options.length)}`);
65
+ }
66
+ const closed = options.closed !== false;
67
+ const wheelbase = Math.max(1e-4, options.wheelbase);
68
+ const maxSteerAngle = Math.max(1e-4, options.maxSteerAngle);
69
+ const lookaheadTime = options.lookaheadTime ?? 0.25;
70
+ const minLookahead = options.minLookahead ?? Math.max(wheelbase * 0.7, length / 160);
71
+ const maxLookahead = Math.max(minLookahead, options.maxLookahead ?? length / 8);
72
+ const crossTrackGain = options.crossTrackGain ?? 2.5;
73
+ const speedGain = options.speedGain ?? 2;
74
+ const speedPreviewTime = options.speedPreviewTime ?? 0.35;
75
+ const rejoinWindow = options.rejoinWindow ?? length * 0.08;
76
+ let travelled = 0;
77
+ let laps = 0;
78
+ function advance(measured) {
79
+ if (!closed) {
80
+ travelled = Math.max(travelled, measured);
81
+ return travelled;
82
+ }
83
+ /*
84
+ * `measured` is a nearest-point match on a wrapped path, so it can legitimately jump backwards
85
+ * across the start line. Compare in the wrapped frame and only accept forward motion, or a
86
+ * backward step small enough to be a genuine correction rather than a stale match from the far
87
+ * side of the circuit.
88
+ */
89
+ const currentWrapped = ((travelled % length) + length) % length;
90
+ let delta = measured - currentWrapped;
91
+ if (delta > length / 2)
92
+ delta -= length;
93
+ if (delta < -length / 2)
94
+ delta += length;
95
+ if (delta > 0 || delta > -rejoinWindow) {
96
+ travelled += delta;
97
+ const nextLaps = Math.floor(travelled / length);
98
+ if (nextLaps > laps)
99
+ laps = nextLaps;
100
+ }
101
+ return travelled;
102
+ }
103
+ return {
104
+ kind: "aura-path-follow-driver",
105
+ get lapsCompleted() {
106
+ return laps;
107
+ },
108
+ reset(distance = 0) {
109
+ travelled = distance;
110
+ laps = 0;
111
+ },
112
+ step(state) {
113
+ const contact = options.contactAt(state.x, state.z);
114
+ const distance = advance(contact.distance);
115
+ const speed = Math.max(0, state.speed);
116
+ const lookahead = clamp(lookaheadTime * speed, minLookahead, maxLookahead);
117
+ const aim = options.sampleAt(distance + lookahead);
118
+ /*
119
+ * Pure pursuit: with the aim point expressed in the car's frame, the arc through it has
120
+ * curvature `2 * lateralOffset / chord^2`. Deriving curvature from the geometry rather than
121
+ * from a heading-error gain is what bounds the command: a reachable point yields a reachable
122
+ * arc.
123
+ */
124
+ const dx = aim.x - state.x;
125
+ const dy = aim.y - state.z;
126
+ const cosH = Math.cos(state.heading);
127
+ const sinH = Math.sin(state.heading);
128
+ const forward = dx * cosH + dy * sinH;
129
+ const lateralToAim = -dx * sinH + dy * cosH;
130
+ const chordSquared = dx * dx + dy * dy;
131
+ let curvature = chordSquared > 1e-9 ? (2 * lateralToAim) / chordSquared : 0;
132
+ /*
133
+ * If the aim point is behind the car the arc solution degenerates — it points the car at a
134
+ * target it has already passed and can produce a near-zero command exactly when the car most
135
+ * needs to turn. Fall back to closing the heading error to the path tangent, which always has
136
+ * the right sign.
137
+ */
138
+ if (forward <= 0) {
139
+ curvature = Math.sign(wrapAngle(aim.heading - state.heading) || 1) * (1 / Math.max(1e-4, wheelbase));
140
+ }
141
+ const steerFromArc = Math.atan(wheelbase * curvature);
142
+ const crossTerm = Math.atan2(crossTrackGain * -contact.signedOffset, Math.max(0.5, speed));
143
+ const steer = clamp((steerFromArc + crossTerm) / maxSteerAngle, -1, 1);
144
+ const previewDistance = distance + Math.max(lookahead, speedPreviewTime * speed);
145
+ const targetSpeed = options.speedAt(previewDistance);
146
+ const speedError = targetSpeed - speed;
147
+ const throttle = speedError > 0 ? Math.min(1, speedError * speedGain) : 0;
148
+ const brake = speedError < 0 ? Math.min(1, -speedError * speedGain) : 0;
149
+ return {
150
+ throttle,
151
+ brake,
152
+ steer,
153
+ distance,
154
+ progress: closed ? (((distance / length) % 1) + 1) % 1 : clamp(distance / length, 0, 1),
155
+ signedOffset: contact.signedOffset,
156
+ targetSpeed,
157
+ lookahead,
158
+ saturated: Math.abs(steer) >= 0.999
159
+ };
160
+ }
161
+ };
162
+ }
163
+ //# sourceMappingURL=PathFollowDriver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PathFollowDriver.js","sourceRoot":"","sources":["../../../../packages/physics/src/PathFollowDriver.ts"],"names":[],"mappings":"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"}
@@ -4,8 +4,47 @@ export type DebugLine = {
4
4
  readonly from: Vec3;
5
5
  readonly to: Vec3;
6
6
  readonly color: Vec3;
7
+ /**
8
+ * What this line represents, so a consumer can filter or legend it.
9
+ *
10
+ * Without a category every line is an anonymous coloured segment, and a debug overlay that
11
+ * cannot say "these are contacts and those are joints" is decoration rather than a tool.
12
+ */
13
+ readonly category?: DebugLineCategory;
7
14
  };
15
+ export type DebugLineCategory = "collider" | "sensor" | "contact" | "normal" | "joint" | "sleeping" | "raycast";
16
+ /** A raycast to draw, so a developer can see the query they cannot otherwise observe. */
17
+ export type DebugRaycast = {
18
+ readonly origin: Vec3;
19
+ readonly direction: Vec3;
20
+ readonly distance: number;
21
+ /** True when the ray hit something; drawn in a different colour. */
22
+ readonly hit?: boolean;
23
+ };
24
+ export type PhysicsDebugDrawOptions = {
25
+ /** Draw contact points and their normals. */
26
+ readonly contacts?: boolean;
27
+ /** Draw joint anchors and the segment between them. */
28
+ readonly joints?: boolean;
29
+ /** Tint sleeping bodies differently from awake ones. */
30
+ readonly sleeping?: boolean;
31
+ /** Extra rays to visualise, which the world cannot know about. */
32
+ readonly raycasts?: readonly DebugRaycast[];
33
+ /** Length of a drawn contact normal, in world units. */
34
+ readonly normalLength?: number;
35
+ };
36
+ type DebugWorld = Pick<PhysicsWorld, "colliders" | "getBody"> & Partial<Pick<PhysicsWorld, "snapshot" | "constraints">>;
8
37
  export declare class PhysicsDebugDraw {
9
- buildLines(world: Pick<PhysicsWorld, "colliders" | "getBody">): readonly DebugLine[];
38
+ /**
39
+ * Build debug geometry for a world.
40
+ *
41
+ * WS-1.7 asks for colliders, contacts, normals, joints, sleeping state and raycasts. Only
42
+ * colliders existed, which is why the capability sat at "unproven with 0 consumers" — there was
43
+ * not enough here for a route to consume.
44
+ *
45
+ * Options default to off so the existing single-argument call keeps its previous output exactly.
46
+ */
47
+ buildLines(world: DebugWorld, options?: PhysicsDebugDrawOptions): readonly DebugLine[];
10
48
  }
49
+ export {};
11
50
  //# sourceMappingURL=PhysicsDebugDraw.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PhysicsDebugDraw.d.ts","sourceRoot":"","sources":["../../../../packages/physics/src/PhysicsDebugDraw.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;CACtB,CAAC;AAEF,qBAAa,gBAAgB;IAC3B,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,WAAW,GAAG,SAAS,CAAC,GAAG,SAAS,SAAS,EAAE;CAWrF"}
1
+ {"version":3,"file":"PhysicsDebugDraw.d.ts","sourceRoot":"","sources":["../../../../packages/physics/src/PhysicsDebugDraw.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IACrB;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GACzB,UAAU,GACV,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,OAAO,GACP,UAAU,GACV,SAAS,CAAC;AAEd,yFAAyF;AACzF,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oEAAoE;IACpE,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,6CAA6C;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,uDAAuD;IACvD,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,wDAAwD;IACxD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,kEAAkE;IAClE,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IAC5C,wDAAwD;IACxD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC;AAEF,KAAK,UAAU,GAAG,IAAI,CAAC,YAAY,EAAE,WAAW,GAAG,SAAS,CAAC,GAC3D,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,UAAU,GAAG,aAAa,CAAC,CAAC,CAAC;AAE1D,qBAAa,gBAAgB;IAC3B;;;;;;;;OAQG;IACH,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,GAAE,uBAA4B,GAAG,SAAS,SAAS,EAAE;CAuE3F"}
@@ -1,18 +1,88 @@
1
1
  export class PhysicsDebugDraw {
2
- buildLines(world) {
2
+ /**
3
+ * Build debug geometry for a world.
4
+ *
5
+ * WS-1.7 asks for colliders, contacts, normals, joints, sleeping state and raycasts. Only
6
+ * colliders existed, which is why the capability sat at "unproven with 0 consumers" — there was
7
+ * not enough here for a route to consume.
8
+ *
9
+ * Options default to off so the existing single-argument call keeps its previous output exactly.
10
+ */
11
+ buildLines(world, options = {}) {
3
12
  const lines = [];
13
+ const snapshot = options.contacts || options.sleeping ? world.snapshot?.() : undefined;
14
+ const sleepingIds = new Set();
15
+ if (options.sleeping && snapshot) {
16
+ for (const body of snapshot.bodies) {
17
+ if (body.sleeping)
18
+ sleepingIds.add(body.id);
19
+ }
20
+ }
4
21
  for (const collider of world.colliders()) {
5
22
  const body = world.getBody(collider.bodyId);
6
23
  if (!body) {
7
24
  continue;
8
25
  }
9
- appendColliderLines(lines, collider, body.position);
26
+ appendColliderLines(lines, collider, body.position, sleepingIds.has(body.id));
27
+ }
28
+ if (options.contacts && snapshot) {
29
+ const normalLength = options.normalLength ?? 0.25;
30
+ for (const contact of snapshot.contacts) {
31
+ const point = contact.point;
32
+ if (!point)
33
+ continue;
34
+ // A short cross at the contact point, then the normal as a ray out of it. Penetration is
35
+ // the number that matters for "is this body inside that one", so it tints the cross.
36
+ const penetrating = contact.penetration > 1e-4;
37
+ const crossColor = penetrating ? [1, 0.2, 0.2] : [0.2, 1, 0.4];
38
+ const size = normalLength * 0.25;
39
+ lines.push({ from: [point[0] - size, point[1], point[2]], to: [point[0] + size, point[1], point[2]], color: crossColor, category: "contact" });
40
+ lines.push({ from: [point[0], point[1] - size, point[2]], to: [point[0], point[1] + size, point[2]], color: crossColor, category: "contact" });
41
+ lines.push({
42
+ from: point,
43
+ to: [
44
+ point[0] + contact.normal[0] * normalLength,
45
+ point[1] + contact.normal[1] * normalLength,
46
+ point[2] + contact.normal[2] * normalLength
47
+ ],
48
+ color: [1, 1, 0.3],
49
+ category: "normal"
50
+ });
51
+ }
52
+ }
53
+ if (options.joints && world.constraints) {
54
+ for (const constraint of world.constraints()) {
55
+ const a = world.getBody(constraint.bodyA.id);
56
+ const b = world.getBody(constraint.bodyB.id);
57
+ if (!a || !b)
58
+ continue;
59
+ // The segment between the two bodies a joint connects. A joint that has come apart is
60
+ // visible as a segment that keeps growing, which is exactly the failure mode that made
61
+ // the former silent backend divergence so hard to spot.
62
+ lines.push({ from: a.position, to: b.position, color: [0.9, 0.4, 1], category: "joint" });
63
+ }
64
+ }
65
+ for (const ray of options.raycasts ?? []) {
66
+ const length = Number.isFinite(ray.distance) ? ray.distance : 1;
67
+ lines.push({
68
+ from: ray.origin,
69
+ to: [
70
+ ray.origin[0] + ray.direction[0] * length,
71
+ ray.origin[1] + ray.direction[1] * length,
72
+ ray.origin[2] + ray.direction[2] * length
73
+ ],
74
+ color: ray.hit ? [1, 0.35, 0.35] : [0.5, 0.5, 0.55],
75
+ category: "raycast"
76
+ });
10
77
  }
11
78
  return lines;
12
79
  }
13
80
  }
14
- function appendColliderLines(lines, collider, position) {
15
- const color = collider.sensor ? [1, 0.75, 0] : [0.1, 0.8, 1];
81
+ function appendColliderLines(lines, collider, position, sleeping = false) {
82
+ // Sleeping bodies are drawn dim: a body that has gone to sleep and should not have is otherwise
83
+ // indistinguishable from one that is simply not moving.
84
+ const color = sleeping ? [0.4, 0.42, 0.5] : collider.sensor ? [1, 0.75, 0] : [0.1, 0.8, 1];
85
+ const category = sleeping ? "sleeping" : collider.sensor ? "sensor" : "collider";
16
86
  if (collider.shape.kind === "box") {
17
87
  const h = collider.shape.halfExtents;
18
88
  const corners = [
@@ -27,24 +97,24 @@ function appendColliderLines(lines, collider, position) {
27
97
  ];
28
98
  const pairs = [[0, 1], [1, 2], [2, 3], [3, 0], [4, 5], [5, 6], [6, 7], [7, 4], [0, 4], [1, 5], [2, 6], [3, 7]];
29
99
  for (const [a, b] of pairs) {
30
- lines.push({ from: corners[a], to: corners[b], color });
100
+ lines.push({ from: corners[a], to: corners[b], color, category });
31
101
  }
32
102
  }
33
103
  else if (collider.shape.kind === "sphere") {
34
104
  const r = collider.shape.radius;
35
- lines.push({ from: [position[0] - r, position[1], position[2]], to: [position[0] + r, position[1], position[2]], color });
36
- lines.push({ from: [position[0], position[1] - r, position[2]], to: [position[0], position[1] + r, position[2]], color });
37
- lines.push({ from: [position[0], position[1], position[2] - r], to: [position[0], position[1], position[2] + r], color });
105
+ lines.push({ from: [position[0] - r, position[1], position[2]], to: [position[0] + r, position[1], position[2]], color, category });
106
+ lines.push({ from: [position[0], position[1] - r, position[2]], to: [position[0], position[1] + r, position[2]], color, category });
107
+ lines.push({ from: [position[0], position[1], position[2] - r], to: [position[0], position[1], position[2] + r], color, category });
38
108
  }
39
109
  else if (collider.shape.kind === "plane") {
40
- lines.push({ from: [-10, position[1], 0], to: [10, position[1], 0], color });
41
- lines.push({ from: [0, position[1], -10], to: [0, position[1], 10], color });
110
+ lines.push({ from: [-10, position[1], 0], to: [10, position[1], 0], color, category });
111
+ lines.push({ from: [0, position[1], -10], to: [0, position[1], 10], color, category });
42
112
  }
43
113
  else if (collider.shape.kind === "capsule") {
44
114
  const r = collider.shape.radius;
45
115
  const h = collider.shape.halfHeight;
46
- lines.push({ from: [position[0], position[1] - h - r, position[2]], to: [position[0], position[1] + h + r, position[2]], color });
47
- lines.push({ from: [position[0] - r, position[1], position[2]], to: [position[0] + r, position[1], position[2]], color });
116
+ lines.push({ from: [position[0], position[1] - h - r, position[2]], to: [position[0], position[1] + h + r, position[2]], color, category });
117
+ lines.push({ from: [position[0] - r, position[1], position[2]], to: [position[0] + r, position[1], position[2]], color, category });
48
118
  }
49
119
  else if (collider.shape.kind === "mesh" || collider.shape.kind === "convex-hull") {
50
120
  const { vertices, indices } = collider.shape;
@@ -52,9 +122,9 @@ function appendColliderLines(lines, collider, position) {
52
122
  const a = translate(vertices[indices[index]], position);
53
123
  const b = translate(vertices[indices[index + 1]], position);
54
124
  const c = translate(vertices[indices[index + 2]], position);
55
- lines.push({ from: a, to: b, color });
56
- lines.push({ from: b, to: c, color });
57
- lines.push({ from: c, to: a, color });
125
+ lines.push({ from: a, to: b, color, category });
126
+ lines.push({ from: b, to: c, color, category });
127
+ lines.push({ from: c, to: a, color, category });
58
128
  }
59
129
  }
60
130
  else {
@@ -69,9 +139,9 @@ function appendColliderLines(lines, collider, position) {
69
139
  for (let row = 0; row < shape.rows; row += 1) {
70
140
  for (let column = 0; column < shape.columns; column += 1) {
71
141
  if (column + 1 < shape.columns)
72
- lines.push({ from: sample(row, column), to: sample(row, column + 1), color });
142
+ lines.push({ from: sample(row, column), to: sample(row, column + 1), color, category });
73
143
  if (row + 1 < shape.rows)
74
- lines.push({ from: sample(row, column), to: sample(row + 1, column), color });
144
+ lines.push({ from: sample(row, column), to: sample(row + 1, column), color, category });
75
145
  }
76
146
  }
77
147
  }
@@ -1 +1 @@
1
- {"version":3,"file":"PhysicsDebugDraw.js","sourceRoot":"","sources":["../../../../packages/physics/src/PhysicsDebugDraw.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PhysicsDebugDraw.js","sourceRoot":"","sources":["../../../../packages/physics/src/PhysicsDebugDraw.ts"],"names":[],"mappings":"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"}