Skip to main content
Mantis data collection needs a pose source: the tracking system that reports where each rig is. (Mantis teleop never tracks; it drives the grippers straight from the rig triggers.) Mantis supports three sources, selected under Mantis settings → Tracking in the control panel (default: Lighthouse). Pick one per installation: the choice, its setup state, and its device bindings are all stored on the host, so every collection run uses the same source without per-run flags.
Keep the product names distinct: VIVE Tracker 3.0 is the Lighthouse device (there is no “Quest 3.0” tracker), Meta Quest is the WebXR source, and VIVE Ultimate Tracker is the inside-out source.
Before starting, finish the Mantis hardware setup: the hub connected, Mantis selected on its tile, the CAN side mapping confirmed, and the grippers-only teleop check passed. Then open Mantis settings → Tracking and choose the source; the selection saves to the host immediately, so runs and the setup actions below always use it.

Set up the source

The Tracking tab walks each source through a step-by-step flow. Each step resolves from what the host actually reports (not from ticking a box), Continue unlocks once it is resolved, a step that regresses later pulls the flow back to it, and the flow stays on a step while its action is running. The device setup flow ends once the sides are identified (or, for Quest, once the headset’s calibration key is saved). Lighthouse collection also requires a current pass from the always-visible Lighthouse tracking quality card. The equivalent CLI commands are listed alongside; see the tracker CLI reference for their flags.
Quest uses the headset’s own controller tracking through WebXR, so there is no runtime to install and no tracker to bind; WebXR handedness assigns left and right. The only stored state is the calibration key that identifies the controller generation and pose datum.
1

Source

Choose Quest (the selection saves immediately). The Quest headset and the host must be on the same LAN (or use the wired Quest-over-USB link, managed under General settings → Quest).
2

Headset

Start a Quest bring-up collection run: axol collect-data --mantis true --mantis_allow_uncalibrated true (or Start Collect data with mantis_allow_uncalibrated set under Advanced); teleop never starts the VR server. Then in the Quest browser open axol.almond.bot, enter the host, connect, accept the host’s certificate the first time, and choose Enter VR. Hold both Touch controllers.The step shows each controller’s reported WebXR profile and pose space and, when both match, a copyable common calibration key (for example quest:oculus-touch-v3:grip). Press Use this key, then Save settings. The step resolves once the saved key is a grip-space datum matching the live controllers; a stale report, a target-ray fallback, or two controllers reporting different keys is held rather than accepted.
The client sends gripSpace poses (with targetRaySpace only as an older-runtime fallback), works without body/elbow tracking, and preserves lost optical tracking per side so the server can hold safely. Quest 3 Touch Plus controllers in the standard cradle use a built-in factory tracker→gripper transform; other controllers need a bench-measured transform for both sides under the exact saved key. See Transforms.
The readiness the flow shows is also enforced by the operation backend: a direct CLI or REST start cannot bypass the runtime, permission, dongle/AP, binding, live-input, or production-transform gates.

Start gesture and recovery

Hold both rigs at the agreed start pose, release both controller grips, then press both grips together to align and engage. The controller triggers operate the grippers. In data collection, A starts and confirms a take, exactly as on Axol.If tracking is lost on either side, both sides freeze. Restore both, then release and press both grips again; recovery never resumes motion on its own. Reset returns to rest and needs the same fresh gesture.

Transforms

Absolute (Mantis) IK solves the world yaw and translation at engage time, but it does not discover where the gripper TCP sits relative to the tracker. That rigid tracker → TCP transform must come from somewhere:
Mantis datasets recorded with axol ≤ 0.2.4 used an Rx(+90°) Vive rotation that pitched every recorded gripper ~90° away from the operator’s hold; Axol could not replay them. Repair them with axol migrate-dataset --mantis-tcp-rotation before replay or training.axol 0.2.5–0.2.16 shipped a Vive translation ([0, 0.0355, -0.092] / [0, 0.0465, -0.092]) that put the tracker 92 mm in front of the gripper instead of 47 mm behind it. collect-data refuses to append to a dataset recorded with it; record to a new repo_id.
Overrides and Quest measurements live in ~/.almond/mantis/tcp_transform.json, keyed per side by the identified device (survive:<tracker serial>, ultimate:<mac>, or quest:<profile>:grip). pos is the gripper TCP origin in the tracker’s local frame in metres; quat is the TCP orientation in that frame as [qx, qy, qz, qw]. The file is edited directly (or via PUT /api/tracker/calibration/<source>); the panel does not edit transforms. The full schema, the Ultimate convention rules, and the bring-up route for a missing constant (--mantis_allow_uncalibrated true for a calibration-only capture) are in the tracker CLI reference. Production collect-data refuses to start with a missing, stale, or unapproved transform on either side.

Acceptance

For Lighthouse, pass Validate tracking with the guided hold–sweep–hold procedure. Under the strict policy this is required before the first session each day; a report expires after 12 hours and is invalidated by changes to the tracked setup. A current pass is a preflight check; under the strict policy live tracking remains monitored throughout collection. Before recording training data, run a short bring-up collection run (axol collect-data --mantis true --mantis_allow_uncalibrated true, discarding every take) with the workspace clear and check, with the selected live source:
  1. Physical left/right, scale, every translation axis, wrist rotation, and tracker→TCP alignment. With Quest, the headset’s live URDF overlay shows the virtual arms; with Lighthouse/Ultimate, use the control panel’s mirrored view.
  2. Recovery: deliberately occlude or de-localize one side and confirm both freeze; restore tracking and confirm nothing moves until the start gesture is repeated.
tracker.identify binds a tracker to a side by which one you move, not by which rig it is mounted on. If the tracker bound as left sits on the rig held in the right hand, the engage fit faces the robot base backwards and every recorded pose is yawed 180° with the columns swapped. With both sides calibrated, the engage refuses this: the log reports Teleop engage rejected: both grippers face away from the robot's rest heading, the session disengages, and nothing is recorded until both grips are released and squeezed again with the rigs in the correct hands (or re-identified). Hold each rig like the robot holds its rest gripper — fingers down, tracker face up, handle towards you — when engaging; a rig pointed straight up or down is not checked. Recording also counts frames where a hand travelled beyond Axol’s reach (out_of_reach in the episode QA line, plus a warning): the rig has no arm to stop you, but Axol cannot follow those poses on replay. Under the strict policy, the episode controls show Checking, Live tracking checks passed, a warning, or a tracking fault. Recording waits for live tracking readiness. A reduced-redundancy warning may still permit recording; review its reason and restore coverage. A serious pose fault latches Retake required, disables Save, and remains attached to that take even if tracking subsequently recovers. Discard and retake stays available. The final save check also checks recorded pose freshness and camera capture. A rejected take shows a separate red alert with the rejection reason. This stays visible when live tracking returns to green and the next take is ready; it clears when a new recording actually starts or an episode saves successfully. The saved counter advances only after a successful save. An intentional discard does not show a save error. Mantis collection maps each incoming tracker pose directly through its mount calibration and the current engage transform, preserving the pose’s capture timestamp. Recording does not wait for virtual-arm IK or use its causal pose filter. The virtual robot still runs IK, and the existing save-time zero-phase smoothing remains available. This avoids introducing virtual-arm processing delay into camera/pose alignment; stale or invalid tracker samples still fail the quality checks. Under the standard policy there are no live tracking checks: libsurvive’s poses stream as reported, and the episode QA gate judges each take on pose freshness, untracked frames and re-engagement (see --qa_gate). Recovery depends on the failure. For temporary visibility loss, restore coverage and wait for live checks to pass before starting a new take. For a persistent calibration fault, stop collection and run Recalibrate Lighthouse, which includes the required tracking validation; standalone validation is blocked until recalibration succeeds. For a stopped native tracking process, stop the session and investigate its process error; repeated recalibration does not repair a crashing runtime. Repair Lighthouse support if the runtime is outdated or damaged, retaining the session log if crashes recur. Smooth or fresh poses alone are not proof of spatial accuracy. A source that jumps, drifts, swaps sides, or cannot recover cleanly is not ready for collection. Mantis teleop never tracks, and axol teleop --sim --teleop.absolute_mode true is only a generic mapping demo; physical acceptance must use the real source, Mantis selected, in a collection run.

Automatic Lighthouse fault captures

Under the strict policy, managed Lighthouse collection automatically arms a diagnostic recorder when live tracking first becomes ready. The episode panel shows Automatic fault capture is ready. Use the normal web UI and wireless trackers; no extra recording command is needed. After a pose jump, stale pose stream, or left/right timing fault, the recorder saves up to 10 seconds before and 3 seconds after the first fault. Keep the collection session open until the panel says Tracking diagnostics saved, then stop the session and retain the displayed directory. Captures are stored under ~/.almond/tracker/diagnostics/fault-*/, containing summary.json and events.jsonl.gz. They remain available even when the faulty episode is discarded. The trace includes native USB/HID callback times, IMU samples and device timecodes, solver suppression reasons, native poses with their original timecodes, optical observations, Python receipt times, and bridge timing/control state. Device clocks remain per-device; the summary distinguishes native monotonic time, estimated clock mapping, and Python receipt time. An input gap alone cannot distinguish wireless loss from a stalled native USB event loop. Diagnostic writes use a separate nonblocking native pipe and background collector/writer threads. Each buffer is limited to 160,000 events and 64 MiB of encoded events; a session accepts at most three captures, separated by at least 30 seconds. Loss counters and truncated windows are explicit in the summary. These bounds can shorten the requested window under unusually high traffic. Diagnostic errors appear separately and do not change tracking acceptance or gripper control. The current native build is libusb-v4-tracking-quality. It retains the Watchman timestamp-rollover fix and diagnostics, gives each tracker an independent CRC-checked base-station identity decoder, and, under the strict policy, enables per-measurement optical outlier rejection after tracking is established. Initial acquisition and calibration keep the filter disabled. These changes address software failure modes; they do not certify accuracy or eliminate physical occlusion and reflections. After updating Axol, stop collection, run axol tracker.install, and restart the service (sudo systemctl restart axol). Earlier native builds are rebuilt automatically. On a strict-policy host upgrading from an earlier release, complete Recalibrate Lighthouse as described above. If the setup already uses fixed geometry, run Validate tracking to cover the updated solver; recalibrate when the setup has changed or the check requires it.

Next steps

Teleoperation

Check the grippers from the rig triggers (no tracking).

Data Collection

Record Mantis episodes to a LeRobot dataset.