|
|
|
|
@@ -0,0 +1,80 @@
|
|
|
|
|
# Prediction Subsystem
|
|
|
|
|
|
|
|
|
|
<!-- begin:auto-docs -->
|
|
|
|
|
_(no submodules)_
|
|
|
|
|
<!-- end:auto-docs --> - rotation-predictor — **Path:** `bitpacker-game/src/…
|
|
|
|
|
- [rotation-predictor](./rotation-predictor.md) — **Path:** `bitpacker-game/src/prediction/rotation-predictor.ts` **Export:** See source for details.
|
|
|
|
|
- rotation-predictor — **Path:** `bitpacker-game/src/…
|
|
|
|
|
|
|
|
|
|
- [rotation-predictor](./rotation-predictor.md) — **Path:** `bitpacker-game/src/prediction/rotation-predictor.ts` **Export:** See source for details.
|
|
|
|
|
|
|
|
|
|
- rotation-predictor — **Path:** `bitpacker-game/src/…
|
|
|
|
|
|
|
|
|
|
- [rotation-predictor](./rotation-predictor.md) — **Path:** `bitpacker-game/src/prediction/rotation-predictor.ts` **Export:** See source for details.
|
|
|
|
|
|
|
|
|
|
- rotation-predictor — **Path:** `bitpacker-game/src/…
|
|
|
|
|
|
|
|
|
|
- [rotation-predictor](./rotation-predictor.md) — **Path:** `bitpacker-game/src/prediction/rotation-predictor.ts` **Export:** See source for details.
|
|
|
|
|
- [rotation-predictor](./rotation-predictor.md) — **Path:** `bitpacker-game/src/prediction/rotation-predictor.ts` **Export:** See source for details.
|
|
|
|
|
|
|
|
|
|
## Purpose
|
|
|
|
|
|
|
|
|
|
Position and rotation extrapolation primitives for the `GameBitPacker`. The module is a re-export barrel that surfaces every prediction algorithm — Kalman filter, motion-math derivatives (velocity, acceleration, jerk), per-algorithm predictor classes (`PositionPredictor`, `RotationPredictor`), and the seven supported extrapolation algorithms (linear, quadratic, cubic, hermite, catmull-rom, velocity-verlet, kalman). Consumers pick an algorithm via the `PredictionAlgorithm` enum on the `predictionOptions` they pass to `GameBitPacker`.
|
|
|
|
|
|
|
|
|
|
The Kalman family is the most accurate (model-based filter that learns process and measurement noise from observed updates). The polynomial family (linear / quadratic / cubic) is cheap and good enough for slow-moving entities. Hermite and Catmull-Rom interpolation produce smooth trajectories from sparse samples and are the right pick for cinematic camera or replay playback. Velocity-Verlet is the staple for physics-driven motion where acceleration is known.
|
|
|
|
|
|
|
|
|
|
## Features
|
|
|
|
|
|
|
|
|
|
- `initKalmanState`, `kalmanPredict`, `updateKalmanFilter` — Kalman filter primitives
|
|
|
|
|
- `calculateVelocity`, `calculateAcceleration`, `calculateJerk`, `calculateVelocityAt`, `calculateAccelerationAt` — discrete-difference motion math
|
|
|
|
|
- `linearPredict`, `quadraticPredict`, `cubicPredict`, `hermitePredict`, `catmullRomPredict`, `verletPredict` — six pure extrapolation functions
|
|
|
|
|
- `PositionPredictor`, `RotationPredictor` — stateful predictors that remember a rolling history and pick the algorithm at construction
|
|
|
|
|
|
|
|
|
|
## Usage: Basic Example
|
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
import { PositionPredictor, PredictionAlgorithm } from "@suaveplan/bitpacker-game";
|
|
|
|
|
|
|
|
|
|
const predictor = new PositionPredictor({
|
|
|
|
|
algorithm: PredictionAlgorithm.LINEAR,
|
|
|
|
|
historySize: 5,
|
|
|
|
|
});
|
|
|
|
|
predictor.observe({ x: 0, y: 0, z: 0 }, 0);
|
|
|
|
|
predictor.observe({ x: 1, y: 0, z: 0 }, 16);
|
|
|
|
|
predictor.observe({ x: 2, y: 0, z: 0 }, 32);
|
|
|
|
|
const next = predictor.predict(48); // { x: 3, y: 0, z: 0 }
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Usage: Advanced Example
|
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
import {
|
|
|
|
|
initKalmanState,
|
|
|
|
|
kalmanPredict,
|
|
|
|
|
updateKalmanFilter,
|
|
|
|
|
calculateVelocity,
|
|
|
|
|
} from "@suaveplan/bitpacker-game";
|
|
|
|
|
|
|
|
|
|
let kf = initKalmanState({ x: 0, y: 0, z: 0 });
|
|
|
|
|
function frame(observation: { x: number; y: number; z: number }, dt: number) {
|
|
|
|
|
kf = updateKalmanFilter(kf, observation, dt);
|
|
|
|
|
const predicted = kalmanPredict(kf, dt);
|
|
|
|
|
const v = calculateVelocity(predicted, kf.position, dt);
|
|
|
|
|
return { predicted, velocity: v };
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## API Reference
|
|
|
|
|
|
|
|
|
|
This module is a barrel re-export; see the per-algorithm `.md` files (when they ship) for full per-function semantics. The headline exports are:
|
|
|
|
|
|
|
|
|
|
- `PositionPredictor` and `RotationPredictor` — stateful predictors with `observe(value, timestamp)` and `predict(timestamp)` methods
|
|
|
|
|
- The six pure prediction functions, each `(history: Vector3[], dt: number) => Vector3`
|
|
|
|
|
- `initKalmanState(initial)`, `updateKalmanFilter(state, obs, dt)`, `kalmanPredict(state, dt)` for direct Kalman usage
|
|
|
|
|
|
|
|
|
|
## Implementation Notes
|
|
|
|
|
|
|
|
|
|
- **Algorithm choice is a behaviour decision.** The `PredictionAlgorithm` enum is open via declaration merging, but each value implies different observation requirements: linear needs 2 samples, quadratic 3, cubic 4, Catmull-Rom 4, Hermite 2 + tangents, Verlet 2 + acceleration, Kalman a fitted state. Picking an algorithm without enough history degrades to a fallback (typically linear).
|
|
|
|
|
- **`historySize` is a soft cap, not a hard one.** The predictor stores up to `historySize` samples in a ring buffer; older samples are dropped on overflow. A larger buffer improves polynomial fit accuracy but raises latency on unstable observations.
|
|
|
|
|
- **No coordinate-system assumption.** All predictors operate on a generic `Vector3` (`{ x, y, z }`); rotations are wrapped to `[-π, π]` by `RotationPredictor` before extrapolation to avoid spurious 2π jumps on yaw wrap.
|
|
|
|
|
- **Process / measurement noise are tunable.** Kalman state exposes `processNoise` and `measurementNoise`. The defaults are tuned for 60 Hz simulation; faster sample rates need lower noise values to avoid over-smoothing.
|