# VR IMU Driver

This project provides access to raw IMU (Inertial Measurement Unit) data from VR headsets, even when optical tracking is lost.

## Problem

The standard OpenVR API only provides IMU data through the `TrackedDevicePose_t` structure, which becomes invalid when optical tracking is lost. This means applications cannot access raw IMU data during tracking loss.

## Solution

This project implements a multi-layered approach to access raw IMU data:

1. **Standard Pose Method**: Uses the standard OpenVR API to get IMU data from the tracked device pose when tracking is available.
2. **Direct Driver Access**: Implements direct access to the driver's IMU data, bypassing the dependency on optical tracking.
3. **Fallback Mechanism**: Returns zero values when all other methods fail, ensuring that the application always receives some data.

## Files

- `OpenVRNativePlugin.cpp`: Main implementation of the plugin that provides access to raw IMU data.
- `OpenVR_Modifications.md`: Detailed instructions for modifying the OpenVR library to implement direct IMU data access.

## Implementation Details

### Standard Pose Method

The standard pose method uses the OpenVR API's `GetDeviceToAbsoluteTrackingPose` function to get the angular velocity of the headset. This method works well when optical tracking is available but fails when tracking is lost.

```cpp
vr::TrackedDevicePose_t poses[vr::k_unMaxTrackedDeviceCount];
g_pVRSystem->GetDeviceToAbsoluteTrackingPose(
    vr::TrackingUniverseRawAndUncalibrated, 
    0, 
    poses, 
    vr::k_unMaxTrackedDeviceCount);

if (poses[vr::k_unTrackedDeviceIndex_Hmd].bDeviceIsConnected) {
    *x = poses[vr::k_unTrackedDeviceIndex_Hmd].vAngularVelocity.v[0];
    *y = poses[vr::k_unTrackedDeviceIndex_Hmd].vAngularVelocity.v[1];
    *z = poses[vr::k_unTrackedDeviceIndex_Hmd].vAngularVelocity.v[2];
    return true;
}
```

### Direct Driver Access

The direct driver access method attempts to access the raw IMU data directly from the driver. This requires modifying the OpenVR library to expose a new interface for IMU data access.

```cpp
// Define the IVRRawIMUData interface that would be in a modified OpenVR
class IVRRawIMUData
{
public:
    virtual bool GetRawGyroscopeData(float* x, float* y, float* z) = 0;
    virtual bool GetRawAccelerometerData(float* x, float* y, float* z) = 0;
    virtual bool GetIMUSampleTimestamp(double* timestamp) = 0;
};

// Using the interface
if (g_pRawIMUData) {
    return g_pRawIMUData->GetRawGyroscopeData(gyroX, gyroY, gyroZ);
}
```

### Fallback Mechanism

When all other methods fail, the fallback mechanism returns zero values to ensure that the application always receives some data.

```cpp
*x = 0.0f;
*y = 0.0f;
*z = 0.0f;
return true;
```

## Usage

### Initialization

```cpp
// Initialize the plugin
bool success = InitializePlugin();
if (!success) {
    // Handle error
}
```

### Getting Raw Gyroscope Data

```cpp
float gyroX, gyroY, gyroZ;
bool success = GetRawGyroscopeData(&gyroX, &gyroY, &gyroZ);
if (success) {
    // Use the gyroscope data
    printf("Gyro: %f, %f, %f\n", gyroX, gyroY, gyroZ);
}
```

### Getting Raw Accelerometer Data

```cpp
float accelX, accelY, accelZ;
bool success = GetRawAccelerometerData(&accelX, &accelY, &accelZ);
if (success) {
    // Use the accelerometer data
    printf("Accel: %f, %f, %f\n", accelX, accelY, accelZ);
}
```

### Shutdown

```cpp
// Shutdown the plugin when done
ShutdownPlugin();
```

## Building

This project is built using Visual Studio. Open the solution file `VRIMUDriver.sln` and build the project.

## OpenVR Library Modifications

To fully implement the direct driver access method, you need to modify the OpenVR library to expose the driver's IMU data. See `OpenVR_Modifications.md` for detailed instructions.

## License

This project is licensed under the MIT License - see the LICENSE file for details.