> ## 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.

# Plugin API Overview

> Overview of OpenTrack's plugin system architecture and interfaces

## Introduction

OpenTrack provides a flexible plugin system that allows developers to extend functionality through three main plugin types:

* **Trackers**: Capture head pose data from hardware devices or computer vision
* **Protocols**: Output tracking data to games and applications
* **Filters**: Process and smooth raw tracking data

All plugins are dynamically loaded at runtime and communicate through standardized C++ interfaces.

## Plugin Types

### Tracker Plugins

Tracker plugins implement the `ITracker` interface to provide pose data from various sources:

* Computer vision trackers (face tracking, point tracking)
* Hardware devices (VR headsets, sensor hats, joysticks)
* Network-based trackers (UDP, proprietary protocols)

**Key responsibilities:**

* Initialize and configure tracking hardware/algorithms
* Continuously provide 6DOF pose data (X, Y, Z, Yaw, Pitch, Roll)
* Handle centering/reset operations

### Protocol Plugins

Protocol plugins implement the `IProtocol` interface to transmit tracking data to games:

* Game-specific protocols (FreeTrack, TrackIR, FlightGear)
* Generic protocols (UDP, shared memory)
* Virtual device emulation

**Key responsibilities:**

* Receive pose data at 250Hz
* Transform and transmit data to target applications
* Report connected game name

### Filter Plugins

Filter plugins implement the `IFilter` interface to process tracking data:

* Smoothing filters (EWMA, Kalman)
* Motion filters (acceleration-based)
* Custom transformation pipelines

**Key responsibilities:**

* Filter input pose data to reduce jitter
* Apply deadzone and smoothing algorithms
* Handle centering events

## Core Data Types

### Pose Representation

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

Pose data is represented as a 6-element vector with the following axis ordering:

```cpp theme={null}
enum Axis : int
{
    TX = 0,    // Translation X (left/right)
    TY = 1,    // Translation Y (up/down)
    TZ = 2,    // Translation Z (forward/back)
    Yaw = 3,   // Rotation around Y axis
    Pitch = 4, // Rotation around X axis
    Roll = 5   // Rotation around Z axis
};
```

### Module Status

```cpp theme={null}
struct module_status
{
    QString error;
    bool is_ok() const;
};
```

Used to report initialization success or failure:

```cpp theme={null}
// Success
return status_ok();

// Failure with error message
return error("Camera not found");
```

## Plugin Registration

Each plugin must implement three components:

1. **Implementation class**: Implements the interface (`ITracker`, `IProtocol`, or `IFilter`)
2. **Dialog class**: Provides UI for configuration
3. **Metadata class**: Provides name and icon

### Registration Macros

Plugins are registered using macros that export the required factory functions:

```cpp theme={null}
// Tracker registration
OPENTRACK_DECLARE_TRACKER(tracker_class, dialog_class, metadata_class)

// Protocol registration
OPENTRACK_DECLARE_PROTOCOL(protocol_class, dialog_class, metadata_class)

// Filter registration
OPENTRACK_DECLARE_FILTER(filter_class, dialog_class, metadata_class)
```

## Metadata Interface

```cpp theme={null}
class Metadata : public TR, public Metadata_
{
    Q_OBJECT
public:
    virtual QString name() = 0;  // Plugin display name
    virtual QIcon icon() = 0;    // Plugin icon (or empty)
};
```

**Example implementation:**

```cpp theme={null}
class MyTrackerMetadata : public Metadata
{
    Q_OBJECT
    QString name() override { return tr("My Tracker"); }
    QIcon icon() override { return QIcon(":/images/icon.png"); }
};
```

## Dialog Base Class

```cpp theme={null}
class BaseDialog : public QDialog
{
    Q_OBJECT
public:
    virtual bool embeddable() noexcept;        // Can embed in main UI
    virtual void set_buttons_visible(bool x);  // Show/hide OK/Cancel
    virtual void save();                       // Save settings
    virtual void reload();                     // Reload settings
signals:
    void closing();                            // Dialog closing
};
```

All dialog classes inherit from `ITrackerDialog`, `IProtocolDialog`, or `IFilterDialog`, which extend `BaseDialog`.

## Threading Model

<Warning>
  Plugin methods are called from different threads. Proper synchronization is required.
</Warning>

### Tracker Thread Safety

* `start_tracker()`: Called from UI thread
* `data()`: Called at \~250Hz from pipeline thread
* `center()`: Called from UI thread

**Use mutexes to protect shared state:**

```cpp theme={null}
void Tracker::data(double* data)
{
    QMutexLocker lock(&data_mutex);
    // Copy pose data safely
    for (int i = 0; i < 6; i++)
        data[i] = current_pose[i];
}
```

### Protocol Thread Safety

* `initialize()`: Called from UI thread
* `pose()`: Called at 250Hz from pipeline thread
* `game_name()`: Called from UI thread

### Filter Thread Safety

* `initialize()`: Called from UI thread
* `filter()`: Called at 250Hz from pipeline thread
* `center()`: Called from UI thread

## Best Practices

<AccordionGroup>
  <Accordion title="Performance Guidelines">
    * Keep `data()`, `pose()`, and `filter()` methods fast (called at 250Hz)
    * Use separate threads for expensive computations
    * Avoid blocking operations in data path
    * Pre-allocate buffers where possible
  </Accordion>

  <Accordion title="Error Handling">
    * Return descriptive error messages from `initialize()`
    * Use `module_status::error()` for initialization failures
    * Log errors using `qDebug()` for runtime issues
    * Validate all user inputs in dialog classes
  </Accordion>

  <Accordion title="Resource Management">
    * Initialize resources in `initialize()` or `start_tracker()`
    * Clean up in destructor
    * Use RAII for automatic cleanup
    * Release hardware devices properly
  </Accordion>

  <Accordion title="Settings Management">
    * Use `options::opts` base class for settings
    * Use `options::value<T>` for individual settings
    * Connect to `bundle_::saving` and `bundle_::reloading` signals
    * Apply settings atomically with mutex protection
  </Accordion>
</AccordionGroup>

## Build System Integration

Plugins are built as shared libraries and must:

1. Link against `opentrack-api` to avoid vtable errors
2. Export symbols using `OTR_PLUGIN_EXPORT`
3. Be placed in the appropriate directory at runtime

**CMakeLists.txt example:**

```cmake theme={null}
opentrack_boilerplate(
    opentrack-tracker-myplugin
    SOURCES tracker.cpp tracker.h dialog.cpp
    LINK opentrack-api opentrack-video opentrack-cv
)

target_link_libraries(opentrack-tracker-myplugin opentrack-api)
```

## Next Steps

<CardGroup cols={3}>
  <Card title="Tracker Interface" icon="video" href="/api/tracker-interface">
    Complete ITracker API reference
  </Card>

  <Card title="Protocol Interface" icon="share-nodes" href="/api/protocol-interface">
    Complete IProtocol API reference
  </Card>

  <Card title="Filter Interface" icon="filter" href="/api/filter-interface">
    Complete IFilter API reference
  </Card>
</CardGroup>
