Tracking events
After connecting, your app subscribes to one stream of events from the hub. Each event says which device it is about and what happened.
Tracking event
Section titled “Tracking event”Sent continuously, many times a second, for each device that can see a calibrated screen.
| Field | Type | Meaning |
|---|---|---|
aimpoint |
2D vector | Where the device is aimed, as a fraction of the screen: (0, 0) is the top-left corner, (1, 1) the bottom-right. See the aimpoint. |
distance |
meters | How far the device is from the screen, along its line of sight. |
pose |
3×3 rotation, 3D translation | Where the device is in front of the screen and which way it points. See the 3D frame. |
screen_id |
integer, 0 to 5 | Which calibrated screen aimpoint and pose refer to. |
timestamp |
microseconds | The device’s clock for this update. See Timestamps. |
A few more details:
aimpoint(0, 0)withdistance0 means the device was tracked but no aim could be worked out for that update. Treat it as “no aim”.- Zeroing moves the aimpoint, not the pose. A device’s
zero changes
aimpointanddistance;posealways describes the device itself. - With more than one screen, aiming well past the left or right edge of the
current screen makes the hub look for the device on the other screens.
Tracking events pause briefly and
screen_idmay change.
Impact event
Section titled “Impact event”Sent when a device detects a shot by its recoil, or when an accessory such as a Bluetooth magazine reports one.
| Field | Type | Meaning |
|---|---|---|
timestamp |
microseconds | The device’s clock when the shot was detected. 0xFFFFFFFF means the shot came from an accessory, which has no device clock. |
The impact arrives a moment after the trigger breaks, and the device may have moved since. Scoring shots shows how to find where it was aimed.
Other events
Section titled “Other events”| Event | Meaning |
|---|---|
ZeroResult(bool) |
Answer to a zero or reset-zero request: whether it worked. |
SaveZeroResult(bool) |
Answer to saving or clearing a zero. |
AccelerometerEvent |
Raw motion: accel in m/s² and gyro, in the device’s sensor axes, and the device timestamp. euler_angles is not filled in. |
BatteryEvent |
percent charged, and whether it is charging. |
CapabilitiesChanged |
The device’s connection changed, for example it lost or regained its tracking channel. Re-read anything you cached about it. |
Timestamps
Section titled “Timestamps”Device timestamps are microseconds on the device’s own clock: not wall-clock time, and not comparable between devices. They are 32-bit, so they wrap around to 0 about every 71 minutes; compare them modulo 2³².
Screens
Section titled “Screens”get_screen_info_by_id(id) returns the four corners of a calibrated screen in
meters: tl, tr, bl, and br (in C, bounds[0] to bounds[3] in that
order). They come from the screen calibration, whose y axis points down;
see Screen corners before using them
with a pose.

