Wiki

Technical reference for system integrators and engineers.

UWB TDoA

Time-difference-of-arrival positions a tag from a single transmitted blink, heard by several time-synchronised anchors.

Where TWR spends a multi-frame exchange and two fixed turnarounds per position, TDoA spends one frame total — the tag transmits and says nothing else. That difference is what lets a site track many tags at a high update rate.

How a position is formed

One blink, three anchors, three arrival times Anchor A Anchor C Anchor B TAG t_A t_C t_B three anchors give two independent differences (t_A − t_B, t_A − t_C) — two hyperbolas, and the tag is where they cross
The tag never learns its own position and never transmits twice. All computation happens on the infrastructure side.

What it requires

TDoA moves the burden from airtime to infrastructure time synchronisation.

  • Anchors must share a common timebase. A difference in arrival times is only meaningful if the anchors agree on what time it is — at UWB precision, one nanosecond of clock error is about 30 cm of position error.
  • At least three anchors must hear each blink. Coverage overlap therefore matters more than in TWR, where a single anchor already yields a usable range.
  • The tag is transmit-only, so it never knows its own position — the position exists only in the backend.

The Leantegra implementation

The implementation is purpose-built rather than a generic TDoA stack. Four properties define it.

Master and slave anchors — wireless synchronisation

Anchors take one of two TDoA roles, configured per unit:

RoleFunction
Master anchorTransmits the reference frames that synchronise nearby anchors, and acts as the coordinate origin for the installation.
Slave anchorTimestamps both the master's reference frames and the tag blink, and reports all three timestamps.

The role is a stored parameter, so the same firmware image and the same hardware serve both positions — a unit is promoted or demoted by configuration, not by reflashing.

Synchronisation is wireless. No cabling or external clock distribution is installed between anchors: the master's own transmissions carry the timebase over the air. Each anchor therefore reports three timestamps per tag blink, all taken on its own free-running counter:

TimestampMeaning
timestamp_ref_1arrival of the master's first reference frame
timestamp_ref_2arrival of the master's second reference frame
timestampTDoAarrival of the tag blink

Because all three are measured on the same local counter, the pair of reference arrivals gives that anchor a known interval to measure the blink against — which is what removes the need for the anchors' clocks to agree in absolute terms.

The blink frame is reused, not replaced

A TDoA transmission is the same blink frame the device line already uses for discovery — the tag transmits and no reply is sent. Nothing new is added to the air interface for TDoA, and a tag needs no TDoA-specific frame type.

Each anchor that hears the blink records the tag address, the arrival timestamp and the frame's encoding header. Anything that is not a blink is discarded on this path.

A dedicated receive path

Selecting TDoA switches the radio callbacks to a TDoA-specific transmit-done and receive-OK pair, rather than running TDoA logic inside the TWR state machine. The two methods therefore do not share a code path at runtime — a TWR exchange and a TDoA capture cannot interfere with each other.

Timestamps come from the UWB counter

Arrival times are taken from the UWB timestamp counter — 40 bits at 63.8976 GHz, about 15.65 ps per tick — not from an MCU clock. This is the same counter the ranging engine uses, and its resolution is what makes a difference of arrival times meaningful at these distances.

Server-side processing

Anchors do not compute position. Each reports its timestamps for a blink, the server groups the reports belonging to the same blink — matched on tag identity and the blink's counter value — and solves for the position once enough anchors have reported.

anchor reports 3 timestamps each group by blink tag + counter normalise clocks against reference interval anchor pairs ΔD per pair solve L-M Kalman filter per tag, time-aware lat / lon + floor resolveMethod: multilateration Per anchor pair tdoa = t2 − t1 × ratio ΔD = tdoa × k + (dist₂ − dist₁)
The master anchor is assigned the coordinate origin; every other anchor's position is resolved relative to it before the solve.

Clock normalisation

Each anchor's timestamps are converted into a ratio rather than used as absolute times:

reference_interval = timestamp_ref_2 − timestamp_ref_1
tag_offset         = timestampTDoA  − timestamp_ref_1
ratio              = tag_offset / reference_interval

All subtraction is modulo the 40-bit counter width, so a counter wrap between the reference frames and the blink is handled without special-casing. Expressing the blink arrival as a fraction of the master's reference interval is what makes reports from anchors with independent, drifting clocks directly comparable.

Pairwise difference

For every unique pair of reporting anchors, the differences of the reference intervals and of the tag offsets are combined, corrected by the mean of the two anchors' ratios, and converted from counter ticks to distance:

tdoa = Δtag_offset − Δreference_interval × mean_ratio
ΔD   = tdoa × k + (dist₂ − dist₁)

where k converts counter ticks to centimetres and dist is each anchor's distance from the reference anchor. The mean-ratio term is the clock-drift correction: without it, a pair of anchors whose oscillators run at slightly different rates produces a bias that grows with the reference interval.

Solving and filtering

  • Coordinates. The reference anchor is placed at the origin. Other anchors are converted from geographic position to local X/Y by bearing and distance, so the solver works in metres.
  • Multilateration. The set of pairwise ΔD values, with the anchor coordinates and a deployment height, is solved by Levenberg–Marquardt least squares. The result is converted back to latitude and longitude relative to the reference anchor.
  • Smoothing. A per-tag Kalman filter is updated with the elapsed time since that tag's previous position, so irregular update intervals are handled correctly. The filtered output is what is published.
  • Rejection. A solve that does not converge to a numeric result is discarded rather than published.

Published positions carry resolveMethod: "multilateration" along with latitude, longitude and floor.

Selecting the method

TWR and TDoA are selected by the UWB RTLS method parameter (0x5106): 1 = TWR, 2 = TDoA. Both run inside the same Unified TDMA schedule and share the same fleet UWB PHY, so switching method does not change the schedule or the radio configuration.

Capacity planning

TDoA capacity is bounded by transmissions, not conversations. A tag sends one blink and every anchor in earshot hears it, so a measurement costs a single frame regardless of how many anchors participate:

tags per second  =  1000 ms  ÷  slot duration

concurrent tags  =  tags per second  ÷  update rate
Adding anchors costs no airtime. In TWR each additional anchor still owes a response window inside the exchange; in TDoA the same blink already reaches all of them and nothing is sent back. Extra anchors buy coverage and geometry — and therefore accuracy — rather than consuming capacity. This is the structural reason TDoA scales where TWR does not.

PHY profiles

The same four working points as TWR, but a slot holds one blink rather than a full exchange, and carries none of the fixed 2600 µs turnaround. Slot is blink plus a 10% guard, with a 0.5 ms floor:

ProfileData ratePreambleBlinkTags per second
(per anchor)
Locations per second
(3 anchors)
Maximum range110 kbps2048≈ 3.74 ms≈ 194≈ 194
Long range — default PHY850 kbps2048≈ 2.26 ms≈ 326≈ 326
Balanced850 kbps512≈ 0.73 ms≈ 994≈ 994
High capacity6.8 Mbps256≈ 0.31 ms≈ 994≈ 994
The two columns are identical, and that is the whole point. A blink is heard by every anchor in range simultaneously, so one transmission already produces a position — there is no three-times cost for turning distances into coordinates. In TWR the same two columns differ by 3×.

Set against TWR at the same radio settings — 34, 52, 118 and 160 locations per second — TDoA delivers five to eight times the positioning throughput. None of that comes from a faster radio; it comes from not repeating the conversation per anchor.

Default PHYLocations/s
TWR — poll, three responses, final≈ 52
TDoA — one blink per position≈ 326

Capacity against range

Range figures are indicative, for clear line of sight, and should be confirmed by survey. TDoA needs three anchors to hear every blink, so the relevant question is not coverage but overlap — and shortening the frame shrinks the overlap much faster than it shrinks the coverage.

Fieldbus Anchor — no front-end amplification, uplink through a WiFi module:

ProfileLocations/sRange per anchorLimited by
Maximum range≈ 194≈ 85–140 mairtime
Long range — default≈ 256≈ 60–100 mUART uplink — 256 reports/s
Balanced≈ 256≈ 30–50 mUART uplink — 256 reports/s
High capacity≈ 256≈ 15–25 mUART uplink — 256 reports/s

Locator Pro — PA / LNA on UWB and BLE, Ethernet uplink:

ProfileLocations/sRange per anchorLimited by
Maximum range≈ 194≈ 420–700 mairtime
Long range — default≈ 326≈ 300–500 mairtime
Balanced≈ 994≈ 150–250 mairtime
High capacity≈ 994≈ 75–125 mairtime
On a Fieldbus Anchor, a faster PHY buys almost no TDoA capacity. The UART to the WiFi module carries 256 observations per second, so moving off the default trades range away for a ceiling the uplink will not deliver. TDoA at high tag counts is a Locator Pro deployment.

The difference is structural rather than incremental: Locator Pro holds roughly 5× the range at every profile and has no UART stage, so it is the only device in the line where the high-capacity profile actually yields high capacity.

Antenna delay is calibrated per product for the channel in use. Changing the PHY means recalibrating — an uncalibrated change shows up as a constant distance offset, which in TDoA becomes a constant position offset rather than an obvious error.

Backhaul multiplies with anchor count

Airtime is only the first constraint. Every anchor that hears a blink produces its own report, so the traffic leaving the infrastructure is not the measurement rate — it is the measurement rate times the number of anchors in earshot:

reports/s  =  measurements/s  ×  anchors hearing each blink

At the default profile with four anchors covering each point, 326 tags per second becomes 1300 reports per second reaching the server. The property that makes TDoA cheap on air makes it expensive on the backhaul, and the two scale in opposite directions as anchors are added.

Locator Pro as the anchor

Locator Pro suits TDoA on both counts.

Range. Its PA / LNA front ends amplify both UWB and BLE. TDoA needs at least three anchors to hear every blink, so coverage overlap — not merely coverage — is the requirement, and it is a far more demanding one over a large site. Longer reach per anchor is what makes triple overlap affordable across a yard, pit or port rather than only in a dense indoor grid.

Backhaul. Locator Pro uplinks directly over Ethernet LAN:

BackhaulAt 1300 reports/s
CAN-FD chainfar beyond a shared 125 kbit/s bus, whose bit rate is itself capped by chain length
WiFishared medium and variable latency, competing with other site traffic
Ethernet LANnot a practical limit
TDoA at high tag counts is the case where backhaul choice stops being an implementation detail. A configuration that fits comfortably in the UWB schedule can still be undeliverable over a chained transport — and the symptom is lost reports, which look like poor coverage rather than a saturated bus.

On anchors whose uplink runs through a separate WiFi module, the limit arrives earlier still. A TDoA observation costs 45 bytes on the internal UART against 24 for a ranging result, and that link saturates before either the bus or the network does, at 256 observations per second. See Fieldbus Anchor for the arithmetic. Locator Pro has no such stage: the radio and the Ethernet interface share one processor.

TDoA compared with TWR

TWRTDoA
Frames per measurementthree, per anchorone, total
Anchors neededonethree
Anchor clock syncnot requiredrequired
Tag power per positionhigherlower
Scales with tag countairtime grows per tagairtime stays small
Tag transmitspoll and finalblink only, no reply
Outputdistanceposition

Reports reach the backend over MQTT on the /RTLS topic with DeviceType: "uwb2", carrying arrival timestamps for server-side multilateration rather than a single distance.