# 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 the driver's IMU data.

```cpp
// This would require a modified OpenVR that exposes this function
vr::IVRDriverContext* pDriverContext = nullptr;
vr::EVRInitError error = vr::VRInitError_None;
pDriverContext = (vr::IVRDriverContext*)vr::VR_GetGenericInterface("IVRDriverContext", &error);

if (pDriverContext) {
    vr::IVRServerDriverHost* pDriverHost = pDriverContext->GetDriverHost();
    if (pDriverHost) {
        vr::IVRDevice* pDevice = pDriverHost->GetDevice(vr::k_unTrackedDeviceIndex_Hmd);
        if (pDevice) {
            vr::IVRIMUDevice* pIMUDevice = pDevice->GetIMUInterface();
            if (pIMUDevice) {
                return pIMUDevice->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.