Head Tracking API - RiftCat/vridge-api GitHub Wiki
- Works as REP ZMQ socket listening at port assigned by control service while VRidge is running.
- Uses protobuf-serialized messages
- If you use any of the rotational writes, VRidge will suspend using phone rotational data for few seconds (so the camera doesn't jump around between phone rotation and your rotation). If you don't send rotational data for few seconds (currently: 5), VRidge will resume using phone rotational data.
See Control channel page to find out how to connect to this endpoint.
There are multiple packet types that you can send, they can be divided into 3 main categories. See struct definition to see byte layout. All responses return ReplyCode: 0
on success. See response packets for error codes.
Send a REQ packet with TaskType = 50
.
Data[]
array is ignored. This is equivalent to using recenter hotkey.
You can notify SteamVR that HMD is outside tracking range. SteamVR currently shuts off display when HMD is outside range.
Send a REQ packet with TaskType = 254
. First byte of Data[]
array should be equal to:
// Currently tracked.
Active = 0
// Not in tracking range or tracking unavailable due to other reasons.
TempUnavailable = 1
Note: Starting with VRidge v2.3, when reprojection-enabled device (Oculus Go, Gear VR, Vive Focus, Daydream phones) is connected, only positional data is allowed to be written ("Sends position only" packet types). These devices already have high quality rotational sensors and the experience can only be worse when paired with detached external rotational tracking system. This doesn't block writing positional data and/or yaw offsets.
In source code you will also find pose matrix formats. They are still working but they are deprecated and removed from this table.
Code | Description | Data[] contents | Data format | VR rotation | VR position | Notes |
---|---|---|---|---|---|---|
3 | Sends radian rotation and position | float[6] | [pitch(+up), yaw (+to left),roll(+left), X, Y, Z] | From the array | From the array | Rotation in radians |
4 | Sends quaternion rotation and position | float[7] | [X, Y, Z, W, X, Y, Z] (quaternion, then position) | From the array | From the array | |
5 | Sends position only | float[3] | [X, Y, Z] | From the phone | From the array |
You can read current phone tracking data, compare it to your own data and set rotational offset that will be applied to each mobile frame. This offset lasts until canceled or restarted. Due to nature of rotational drift it is recommended to update the offset every now and then.
Code | Description | Data[] contents | Data format | Notes |
---|---|---|---|---|
199 | Requests current pose | null | null | Returns most recent pose used to render along with offset data |
201 | Sets an offset to be used by future phone data | float[1] | yaw | Lasts until shutdown or reset with call below |
210 | Resets async offset | null | null | Resets offset sent with 201 |
Code | Description | Response | Notes |
---|---|---|---|
2 | Sending current tracked pose | TrackedPose | In response to 199. |
TrackedPose is formatted as below:
[ProtoContract]
public class TrackedPose
{
/// <summary>
/// Current head orientation as 4 element XYZW quaternion.
/// </summary>
[ProtoMember(1)]
public float[] HeadOrientation;
/// <summary>
/// Current head position as 3 element XYZ vector.
/// </summary>
[ProtoMember(2)]
public float[] HeadPosition;
/// <summary>
/// Current offset applied to each head-related (Controller w/ HeadRelation.IsInHeadSpace or internal VRidge mobile tracking data) pose due to user recenter.
/// In 99% cases, you can forget about it.
/// </summary>
[ProtoMember(3)]
public float RecenterYawOffset;
/// <summary>
/// Current offset applied to each pose due to API SetYawOffset call.
/// </summary>
[ProtoMember(4)]
public float ApiYawOffset;
}
Important note:
Data
array is always 64 byte long. DataLength holds actual number of meaningful bytes that should be used.
[ProtoContract]
public struct HeadTrackingRequest
{
private const int CurrentVersion = 3;
/// <summary>
/// Should always be 3 for v3
/// </summary>
[ProtoMember(1)]
public int Version;
/// <summary>
/// Describes how API should handle the incoming data.
/// See Writing tracking data paragraph for task codes.
/// </summary>
[ProtoMember(2)]
public byte TaskType;
/// <summary>
/// Tracking data itself.
/// </summary>
[ProtoMember(3)]
public byte[] Data;
}
[ProtoContract]
public struct HeadTrackingResponse
{
[ProtoMember(1)]
public int Version;
[ProtoMember(2)]
public byte ReplyCode;
// Only filled in response to current pose requests
[ProtoMember(4)]
public TrackedPose TrackedPose;
}
You can find those files here.