TRACE · v0.2

Most trackers stop at “where”. This one keeps going.

Tracking in the real world is never continuous. A vehicle goes behind a building, a person walks out of camera range. Most systems treat that as the end of the track. TRACE does not: it holds a track as a probability that something is still there rather than a yes or no, so the track fades through the gap instead of ending at it, and can be picked up again on the other side.

Nothing in the core knows what it is tracking. Cameras, ships, pallets, animals and players are the same problem with a different profile. The MOT17 and MOT20 figures below are Multiple Object Tracking Accuracy (MOTA), the single number the field uses for how well a tracker did.

LanguageC++23
MOT17 MOTA53.0%
MOT20 MOTA62.5%
Boxes scored1.47M
Last pushrecently
What the name is
TTracking — where each thing is, and how sure we are
RRe-identification — the same thing, after it was lost
AAssociation — which sighting belongs to which track
CConvergence — who is about to meet whom
EEvents — behaviour worth someone’s attention
In plain English

What this is, in one minute

The problem

Sensors miss things. A camera does not catch everyone who walks past it, a ship can switch off its transponder, a corridor may have no camera at all. Most trackers read “not seen” as “not there”, so when the thing reappears it is logged as something new. Where has it been, who has it met, is this normal for it — none of those can be answered any more.

The solution

TRACE keeps a number against each track for how likely it is that the thing is still there. A missed sighting lowers that number and widens the area it could be in; it deletes nothing. The track coasts on prediction, its uncertainty growing honestly, and when something turns up again the engine decides whether it is the same one. Both demonstrations here let you push that until it gets the decision wrong.

Who it is for

Anyone following things across more than one sensor, with gaps between them: a site whose cameras do not cover every corridor, or maritime monitoring where a vessel can switch off its transponder mid-voyage. The core does not know what it is tracking — cameras, ships, pallets, animals and players are the same problem with a different profile. It takes detections in; producing them is someone else’s job.

A gap in the coverage is not the same as an absence. The rest of this page is the engineering: the engine itself running in your browser on two scenarios, the benchmark numbers, what it costs per track, and a plain list of what it does not do.
The problem

A track that is deleted on the first missed frame was never a track

Sensors miss things. A camera has a detection probability, not a guarantee; a ship can switch off its transponder; a corridor can have no camera at all. The moment coverage drops, a tracker that equates “not seen” with “not there” loses the identity, and when the entity reappears it gets a new one. Every downstream question — where has this been, who has it met, is this normal for it — is now unanswerable.

TRACE separates two things most trackers conflate. Every track carries r, the probability that it exists at all, held apart from where it is. A missed scan lowers r and widens the position estimate; it does not delete anything. The track coasts, and its uncertainty grows honestly while it does.

That is what both demonstrations below are showing you. The dashed circle is the engine saying it is somewhere in here and I am less sure by the second — which is a useful thing to be told, and the thing a deleted track cannot tell you.

Existence

Bernoulli, not boolean

A Poisson Multi-Bernoulli Mixture (PMBM) tracker over a 320-particle filter. Existence is a probability that decays through misses and recovers on evidence, so an occlusion costs confidence rather than identity.

Possibility

A second opinion on the evidence

Alongside the probability runs a possibilistic existence that tracks the quality of evidence rather than its quantity. When the two diverge, many weak detections have been laundered into false certainty.

The engine itself

A camera estate, with corridors nobody is watching

A maze is a cheap stand-in for a real camera estate, and it gives you every property that makes multi-camera tracking hard: walls force non-linear routes, each coloured panel is one camera so crossing a boundary is a real handoff, and the hatched panels are switched off — blind corridors where the engine has to hold identity on nothing at all and pick it up again on the far side.

trace::Engine — WebAssembly

loading…
Truth — subject Truth — others Track, being seen Track, coasting blind Camera switched off

Scored against truth

Detection
—
Of what cameras gave
—
Mean error
—
Identity switches
—
Ghost tracks
—
Median scan
—

This scan

Detection so far
—
Error so far
—

Events raised —

Next predicted meeting —

Of what cameras gave is the honest denominator: no tracker can report an entity that no sensor detected, so a raw detection rate mixes the tracker’s failures with the estate’s. Above 100% means the engine held entities through scans where nothing saw them. Turn the cameras off and watch it climb.

trace::Engine out of libtrace_core.a, the same library the native tools link — —. The whole run is computed at once and played back, so the animation is not the engine’s speed; the median scan time beside it is.
How it works

Five stages, and one report

T · A

Tracking and association

A PMBM tracker with Bernoulli existence over a 320-particle mixed Ornstein–Uhlenbeck filter — velocity follows an OU process whose regime (on foot, in a vehicle, stationary) is itself a Markov chain, which is the “mixed” part. Gibbs sampling for one-to-one assignment across 14 sweeps, then a duplicate merge. Association runs per sensor, because exclusivity is a fact about a sensor and not about the world — two overlapping cameras both reporting one person is corroboration, not two people. Enforcing it globally cost 2.08 ghost tracks per scan; per sensor it is 0.08.

R

Re-identification by routine

A dormant track is reacquired through its pattern of life — a per-entity Gaussian mixture over hour, x and y. Appearance descriptors are supported and deliberately off on the public benchmarks, because a perfect oracle descriptor there moves the score not at all: 88% of the penalty is missed detections, which appearance cannot touch.

C

Three convergence predictors, stacked

Geometric intercept is exact for two entities walking towards each other and useless if either manoeuvres. Closure-rate extrapolation handles a curving route. Pattern-of-life cross-prediction is the only one that can fire while both parties are still stationary. They fail in different circumstances, so all three run and the most confident wins.

E

Eight behaviours, hot-swappable

BRUSH_PASS, SDR_PATTERN, DEAD_DROP, PARALLEL_ROUTE, MODE_TRANSITION, LOITER, COVER_STOP, CHOKEPOINT. Threat scoring fuses eight evidence dimensions through a Beta–Monte-Carlo, and the report carries the breakdown rather than the one number.

The engine itself

A ship switches off its transponder

Satellite Automatic Identification System (AIS) coverage over an ocean basin. Five vessels are in transit; one of them switches off its transponder mid-voyage and comes back up later. Nothing reports it in between — no sensor, no detection, no evidence of any kind.

Watch what the engine does with that. On the first missed scan the position estimate jumps from a few hundred metres to about twelve kilometres and the track coasts on prediction alone. A few scans later it is retired to a dormant pool rather than deleted, and when the vessel resurfaces the engine has to decide whether this is something new or something it already knows.

Drag the blackout longer and it gets that decision wrong. Five scans of silence and the identity survives; past about ten it does not, and the vessel comes back as a new track. That is the honest result and it is worth more than a demo tuned to always win — the reason is below the controls.

dark-vessel — WebAssembly

loading…
Suspect, reporting Suspect, gone dark Other traffic The suspect’s own track Other tracks

The suspect, right now

Engine’s state for it
—

Over the whole voyage

After resurfacing
—
Widest it coasted
—
Gap before it was back
—
Detection so far
—

Why it breaks. Re-identification here works by pattern of life — a per-entity mixture over hour and position, asking whether this new sighting fits something the engine already knows the routine of. A vessel on a single straight transit has no routine. It has been seen going one way, once. So past a few scans the only thing left is the motion prediction, and at twelve knots with hourly scans that uncertainty outgrows anything useful within a day.

The same mechanism is decisive where there is a routine to learn, which is what the maze above is showing. A limitation with a stated cause is worth more than a capability with none, and this one is in the repository’s own list.

The same dark-vessel scenario trace_sim runs natively, with the same profile, sensor and basin.
Evidence

Replayed against real detections, not only its own simulator

MOTChallenge sequences — real detections from real detectors on real video — are the only numbers here that TRACE’s own simulator did not produce.

BenchmarkBoxesMOTARecovery of detector ceiling
MOT17 train, 21 sequences336,89153.0%108.2%
MOT20 train, 4 sequences, 62–226 people/frame1,134,61462.5%114.7%
Train-split numbers only. These are replayed and scored locally. Nothing has been submitted to the MOTChallenge evaluation server, which is what a figure comparable to the public leaderboard would require. The ceiling is what a perfect tracker would score by echoing every detection it was handed; beating it is the entire job, and it is done by coasting through frames the detector missed.
Cost

Effectively linear in crowd size

TracksMedian ms/scanµs per track
101.7135
12026.6152
27072.1159
400127.5159

One processor core, Release build, Advanced Vector Extensions (AVX-512). Cost grows as about n1.17 and tracking alone is flat at 135–159 µs per track from ten tracks to four hundred — read it as “the constant matters and the exponent does not”.

It was n1.82 until the convergence detector stopped rebuilding each track’s pattern-of-life forecast once per pair. That bought a factor of twenty in the constant and not a better exponent — the spatial-index gate added with it had a radius wider than the scene, so it returned every pair and did nothing. Bounding each pair by its own two speeds took that detector from 56% of the engine to 44% and the exponent to near linear.

At 400 simultaneous tracks that is about 8 scans per second on one processor core: fine for a 1 Hz camera estate, not for 25 fps without partitioning across workers. The page says so because the benchmark says so.

Honest limitations

What it does not do

No detector, and no re-ID model

TRACE consumes detections. Producing them is someone else’s job.

A velocity estimate has a floor

It needs speed × heading-hold well above position noise. Below a ratio of about 5 it is not an estimate, and coasting is only as good as it is. A genuinely twisty target seen by a coarse sensor has no measurable velocity — a modelling constraint rather than a defect, but one to check a profile against before claiming anything about coasting.

Sensor availability is inferred, not known

A coverage gap is guessed at from whether anything reported at all. A real deployment knows which cameras are down and currently has no way to say so.

No audit logging, access control or retention policy

Several of the things this can be pointed at are mass-surveillance capabilities. Anyone deploying it against people needs that scaffolding built around it, and it is deliberately not provided as a default.

The CUDA path is scaffolding

src/cuda/kernels.cu exists and nothing in the engine calls it. The kernels have never run. Treat it as an unfinished branch rather than a backend — the repository says the same.

Source-available

The GNU Affero General Public License, with a commercial licence beside it

AGPL-3.0+, and the same terms as everything else here: read it, run it, check it. If the AGPL does not suit what you want to build, there is a tiered commercial licence.