Interpolation modes
Five built-in curves plus an adaptive meta-mode that reads each vehicle's feed period and chooses at runtime. You can also drop in a custom interpolator for road-snapping or prediction.
How interpolation works
On every frame, the engine asks a simple question: where should this vehicle be right now? It computes a render time slightly behind the wall clock, finds the ratio between the two latest points, and interpolates.
The render-lag buffer (renderLagMs, default 1000) is what keeps motion continuous: it guarantees there is always a next point to move toward. With renderLagMs: 0, the marker simply snaps on every ingest.
The modes
| Mode | Behavior | Best for |
|---|---|---|
linear | Straight-line lerp between two points. | Most feeds — the default. |
cubic | Smoothstep easing (ease-in-out). | Softer sub-segment motion. |
geodesic | Great-circle arc. | Ships, aircraft, long distances. |
smooth | 3-point centripetal Catmull-Rom; falls back to linear until the third ping. | Turn-heavy routes. |
none | No interpolation — render snaps to latest. | Sub-second feeds, debugging. |
adaptive | Period-aware switcher (see below). | Mixed-period feeds. |
Adaptive zones
Pass interpolation: 'adaptive' and the engine classifies each vehicle's feed period into a zone, every tick. Thresholds are configurable via the adaptive option.
| Period | Zone | Behavior |
|---|---|---|
< 500ms | none | Snap — too fast to benefit from interpolation. |
500ms – 8s | linear | Standard linear lerp. |
8s – 15s | fade | Fade out, snap, fade back in. |
> 15s | snap | Direct jump — gap too large to fake motion. |
The lower boundary minPeriodMs defaults to 500 so steady 1 Hz feeds don't sit exactly on the zone edge.
Real-time feeds & render lag
The single most important setting is renderLagMs, and the rule is short: set it to roughly your feed period. A 5-second polling feed wants renderLagMs: 5000.
For jittery feeds — where the gap between updates wobbles — enable a playout buffer. It absorbs the jitter at the cost of a little extra latency, paying out segments at a steady pace.
const tracker = new Tracker({
adapter,
interpolation: 'smooth',
playout: 'auto', // measures ~10 recent periods and equalizes the render pace
});
// or tune it manually:
const manual = new Tracker({
adapter,
interpolation: 'smooth',
playout: { pace: 5000, bufferMs: 12000, maxQueue: 20 },
});Custom interpolators
Anywhere a mode string is accepted you may pass an object implementing CustomInterpolator. The required method is compute(); prepare() (async prefetch) and dispose() are optional.
The @kinesisjs/route-aware package is a ready-made custom interpolator: it queries OSRM, snaps positions to the road graph, caches polylines in an LRU, and falls back to linear — all synchronously, never blocking the tick loop.
Where linear stops working
Honest boundaries. Plain linear interpolation is great on highways and short periods; it struggles with urban routes, traffic stops, sharp turns and GPS noise. Adaptive mode covers the period-related cases. The rest are addressed by future packages.
| Problem | Solution | Version |
|---|---|---|
| Jump between updates | Linear / smooth interpolation | v0.1 |
| Period too short / too long | Adaptive mode | v0.1 |
| Anomalous GPS jump | Built-in sanity check + fade | v0.1 |
| Routes cut through buildings | Route-aware (OSRM map-matching) | v0.1 · route-aware |
| Traffic stops, GPS noise | Predict / Kalman filtering | v0.4+ |