Skip to main content
OpenTrack has a modular plugin architecture that allows you to extend functionality by creating custom trackers, filters, and protocols. All plugins use the same base API defined in api/plugin-api.hpp.

Plugin Architecture Overview

Plugin Types

OpenTrack supports three types of plugins:

Trackers

Read input from hardware devices or algorithms to generate head pose data (XYZ position + Yaw, Pitch, Roll)

Filters

Process and smooth raw tracking data to reduce noise and improve responsiveness

Protocols

Send processed tracking data to games and simulators using various output methods

Pose Data Structure

All plugins work with a 6-DOF pose:

Setting Up Your Plugin

1

Create Plugin Directory

Create a directory for your plugin in the OpenTrack source tree:
2

Create CMakeLists.txt

Create a minimal CMakeLists.txt:
The otr_module() function automatically:
  • Finds all .cpp, .h, .hpp, .ui, and .qrc files
  • Links against Qt and OpenTrack APIs
  • Sets up installation rules
  • Configures translations
3

Create Plugin Files

Create header and implementation files:
  • myplugin.h - Class declarations
  • myplugin.cpp - Implementation
  • myplugin_dialog.cpp - UI dialog (optional)
  • myplugin.ui - Qt Designer UI file (optional)
4

Link Against OpenTrack API

Important: You must link against opentrack-api in CMakeLists.txt to avoid vtable link errors:

Developing a Tracker Plugin

Tracker Interface

Implement the ITracker interface:

Complete Tracker Example

Here’s a complete working tracker that generates sinusoidal test data:

Tracker Best Practices

The data() method is called 250 times per second. Never perform blocking operations or heavy computation in this method.

Use Separate Threads

Perform heavy computation (image processing, sensor polling) in a separate thread and cache results

Initialize in start_tracker()

Open devices, allocate resources, and start threads in start_tracker(), not in the constructor

Return Status Properly

Return status_ok() on success or error("message") with a descriptive error message

Clean Up in Destructor

Stop threads, release resources, and close devices in the destructor

Developing a Filter Plugin

Filter Interface

Filter Example

Developing a Protocol Plugin

Protocol Interface

Protocol Example

Plugin Metadata

Metadata Class

Every plugin must provide metadata:

Plugin Dialogs

Plugins can provide configuration dialogs:

Base Dialog

Dialog Example

Plugin Declaration Macros

Use these macros to export your plugin:
These macros expand to export the required functions:

Module Status Handling

Returning Status

Building and Testing

1

Build Your Plugin

2

Install Plugin

Plugins are installed to ${CMAKE_INSTALL_PREFIX}/lib/opentrack/ or similar.
3

Test in OpenTrack

Run OpenTrack and select your plugin from the appropriate dropdown (Input, Filter, or Output).

Additional Resources

Plugin API Header

Complete API reference with documentation

Test Tracker Example

Simple working example plugin

Core Hacking Guide

Guide for working with OpenTrack core code

Building from Source

Set up your build environment

Tips and Best Practices

The UI thread and tracking thread are separate. Use proper synchronization (mutexes, atomics) when sharing data between threads.
  • Avoid memory allocations in hot paths (data(), filter(), pose())
  • Use double-buffering for thread communication
  • Profile your code to find bottlenecks
  • Always return descriptive error messages
  • Use qDebug() for logging during development
  • Handle device disconnection gracefully
  • Use Qt’s signal/slot mechanism for UI updates
  • Store settings using opentrack-options API
  • Support translations with tr() strings