> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/opentrack/opentrack/llms.txt
> Use this file to discover all available pages before exploring further.

# Tracker Setup

> Configure head tracking hardware and software trackers in OpenTrack

Trackers are input modules that provide 6DOF (degrees of freedom) head position and rotation data. OpenTrack supports a wide variety of tracking technologies.

## Tracker Module System

OpenTrack uses a plugin-based tracker system:

```cpp theme={null}
struct OTR_API_EXPORT ITracker {
    virtual module_status start_tracker(QFrame* frame) = 0;
    virtual void data(double *data) = 0;
    virtual bool center();
};
```

### Module Selection

Trackers are selected through the module settings:

```cpp theme={null}
struct module_settings {
    bundle b { make_bundle("modules") };
    value<QString> tracker_dll { b, "tracker-dll", "pt" };
};
```

## Available Trackers

OpenTrack includes support for many tracking technologies:

<Tabs>
  <Tab title="Optical">
    ### PointTracker (pt)

    Uses webcam to track LEDs or reflective markers.

    **Best for**: DIY LED tracking setups, TrackIR alternatives

    **Requirements**:

    * Webcam (higher resolution = better accuracy)
    * 3 LED or reflective points on headset
    * Good lighting conditions

    ### Aruco Markers

    Tracks printed ArUco fiducial markers.

    **Best for**: Quick testing without special hardware

    **Requirements**:

    * Webcam
    * Printed ArUco marker attached to headset

    ### Easy Tracker

    Face tracking using computer vision.

    **Best for**: No additional hardware needed
  </Tab>

  <Tab title="Inertial">
    ### FreeTrack/TrackIR

    Commercial optical tracking systems.

    ### Hatire (Arduino)

    Arduino-based IMU tracking via serial port.

    **Configuration**:

    ```cpp theme={null}
    // Serial communication at 250Hz
    // 6DOF: TX, TY, TZ, Yaw, Pitch, Roll
    ```

    ### Joystick

    Use game controller as head tracker input.
  </Tab>

  <Tab title="Network">
    ### FreePIE UDP

    Receives tracking data via UDP from FreePIE or compatible applications.

    **Port**: Configurable (default varies by tracker)

    ### UDP Generic

    Generic UDP receiver for custom tracking solutions.

    **Data format**: 6 doubles (X, Y, Z, Yaw, Pitch, Roll)
  </Tab>

  <Tab title="VR/AR">
    ### Eyeware Beam

    Head tracking using Eyeware Beam iOS app.

    ### Tobii Eye Tracker

    Integration with Tobii eye tracking hardware.

    ### Xreal One

    Support for Xreal AR glasses tracking.
  </Tab>
</Tabs>

## Tracker Initialization

When a tracker starts, it goes through this initialization sequence:

<Steps>
  <Step title="Module Loading">
    The tracker plugin is loaded from the shared library:

    ```cpp theme={null}
    std::shared_ptr<ITracker> pTracker;
    // Loaded from tracker-{name}.dll/so
    ```
  </Step>

  <Step title="Initialization">
    The tracker's start\_tracker method is called:

    ```cpp theme={null}
    module_status start_tracker(QFrame* frame) {
        // Initialize hardware/software
        // Optional: Display video feed in frame
        return status_ok(); // or error("message")
    }
    ```
  </Step>

  <Step title="Data Streaming">
    The data() method is called at \~250Hz:

    ```cpp theme={null}
    void data(double *data) {
        // data[0-2]: TX, TY, TZ (cm)
        // data[3-5]: Yaw, Pitch, Roll (degrees)
    }
    ```
  </Step>
</Steps>

## Data Format

All trackers must provide data in OpenTrack's standard format:

```cpp theme={null}
using Pose = Mat<double, 6, 1>;

enum Axis : int {
    TX = 0, TY = 1, TZ = 2,      // Translation (cm)
    Yaw = 3, Pitch = 4, Roll = 5  // Rotation (degrees)
};
```

<Note>
  **Translation units**: Centimeters
  **Rotation units**: Degrees
  **Coordinate system**: Right-handed
</Note>

### Axis Definitions

* **TX**: Left (-) / Right (+)
* **TY**: Down (-) / Up (+)
* **TZ**: Forward (-) / Backward (+)
* **Yaw**: Left (-) / Right (+)
* **Pitch**: Down (-) / Up (+)
* **Roll**: Left (-) / Right (+)

## Centering Support

Trackers can optionally handle centering internally:

```cpp theme={null}
virtual bool center() {
    // Return true if tracker handles centering internally
    // Return false to use OpenTrack's centering
    return false;
}
```

### Centering Flow

```cpp theme={null}
const bool own_center_logic = center_ordered && libs.pTracker->center();

if (own_center_logic) {
    // Tracker resets itself
    center.P  = {};
    center.QC = {};
    center.QR = {};
} else {
    // OpenTrack handles centering
    center.P  = value;
    center.QC = dquat::from_euler(...).conjugated();
    center.QR = dquat::from_euler(...).conjugated();
}
```

## Tracker Dialog

Each tracker can provide a configuration dialog:

```cpp theme={null}
struct OTR_API_EXPORT ITrackerDialog : public BaseDialog {
    virtual void register_tracker(ITracker *tracker);
    virtual void unregister_tracker();
};
```

The dialog receives a pointer to the active tracker instance for live configuration updates.

## Common Tracker Settings

### Video Feed Display

Optical trackers can display camera feed:

```cpp theme={null}
module_status start_tracker(QFrame* frame) {
    if (frame) {
        // Set up video widget in frame
        video_widget = new VideoWidget(frame);
    }
    return status_ok();
}
```

### Exposure and Gain

For optical trackers, proper camera settings are critical:

<Warning>
  **Low exposure** (1-5ms) and **high gain** provide best results for LED tracking.
  Automatic exposure often causes tracking issues.
</Warning>

### Point Extraction

Optical trackers typically use threshold-based point extraction:

1. Apply brightness threshold
2. Find connected components (blobs)
3. Calculate blob centroids
4. Match points to 3D model

## Tracker Performance

The pipeline runs at \~250Hz (4ms interval):

```cpp theme={null}
void pipeline::run() {
    while (!isInterruptionRequested()) {
        logic();
        
        constexpr ms interval{4};
        backlog_time += ms{t.elapsed_ms()} - interval;
        
        const int sleep_ms = (int)std::clamp(
            interval - backlog_time, ms{0}, ms{10}
        ).count();
        
        portable::sleep(sleep_ms);
    }
}
```

<Note>
  Trackers should not block in the data() method. Use a separate thread for computation and return the latest data.
</Note>

## Error Handling

Trackers can report errors during initialization:

```cpp theme={null}
module_status initialize() override {
    if (!hardware_found()) {
        return error(tr("Hardware not found"));
    }
    
    if (!calibration_valid()) {
        return error(tr("Calibration required"));
    }
    
    return status_ok();
}
```

## Creating Custom Trackers

To implement a custom tracker:

<Steps>
  <Step title="Implement ITracker interface">
    ```cpp theme={null}
    class MyTracker : public ITracker {
        module_status start_tracker(QFrame* frame) override;
        void data(double *data) override;
    };
    ```
  </Step>

  <Step title="Implement dialog (optional)">
    ```cpp theme={null}
    class MyTrackerDialog : public ITrackerDialog {
        void register_tracker(ITracker* t) override;
        void unregister_tracker() override;
    };
    ```
  </Step>

  <Step title="Implement metadata">
    ```cpp theme={null}
    class MyTrackerMetadata : public Metadata {
        QString name() override { return tr("My Tracker"); }
        QIcon icon() override { return QIcon(":/icon.png"); }
    };
    ```
  </Step>

  <Step title="Register plugin">
    ```cpp theme={null}
    OPENTRACK_DECLARE_TRACKER(
        MyTracker,
        MyTrackerDialog,
        MyTrackerMetadata
    )
    ```
  </Step>
</Steps>

## Troubleshooting

<Accordion title="Tracking is jittery">
  1. Check tracker update rate (should be stable)
  2. Verify lighting conditions (for optical trackers)
  3. Enable filtering (see [Filters guide](/guides/filters))
  4. Check for USB bandwidth issues
</Accordion>

<Accordion title="Tracking drifts over time">
  1. Inertial drift is normal for IMU trackers
  2. Enable fusion with optical tracking if possible
  3. Periodically recenter
  4. Check for magnetic interference (IMU trackers)
</Accordion>

<Accordion title="Tracker not detected">
  1. Verify hardware is connected
  2. Check device drivers are installed
  3. Try different USB ports
  4. Check OpenTrack logs for error messages
</Accordion>

<Accordion title="Data is inverted or swapped">
  Use axis mapping and inversion in [Configuration](/guides/configuration):

  ```cpp theme={null}
  axis_opts::src = desired_axis;    // Map input axis
  axis_opts::invert_pre = true;     // Invert if needed
  ```
</Accordion>

## Next Steps

<CardGroup cols={2}>
  <Card title="Output Setup" icon="gamepad" href="/guides/output-setup">
    Configure game/simulator output protocols
  </Card>

  <Card title="Filters" icon="sliders" href="/guides/filters">
    Add smoothing and noise reduction
  </Card>

  <Card title="Mapping Curves" icon="chart-line" href="/guides/mapping-curves">
    Fine-tune tracking response
  </Card>
</CardGroup>
