Skip to main content
Up and Coming
April 25, 2013

Basic Linux Rift library with OpenGL in C

Ok, don't get too excited. This is a very simple C port of the SDK 1.5 library. I did this mostly to satisfy my own curiosity, but if there is enough interest, I'm willing to make it a more complete project.

Right now all it will do is connect to the Rift, open up a GL window, and move an arrow around to follow the HMD tracker. Now that the new SDK is out, there are GL shaders which I'll work into the simple demo scene for the next pass.

I'm still playing around with this, but tf there is interest, I can put the code up in a private git repo so others can contribute.

Enjoy

-nsb

    73 replies

    Up and Coming
    May 13, 2013
    "JWB" wrote:

    Sweet, thanks for that. Be aware that there's an out of bounds error in the sendSensorScaleRange function within OVR_HID.c, for which I've attached a patch. Interested parties should inspect the patch, as I didn't perform a detailed analysis: merely eliminating the out of bounds assignment. I would have posted it sooner, but I've been busy playing with my Raspberry Pi.


    That is an excellent excuse for not posting sooner. :) Good catch! The correct solution would be to increase the buffer size, as that is supposed to be an 8-byte packet. I'm guessing nsb missed a copy+paste change there. Two lines should be changed (three, including the comment)...


    diff --git a/lib/OVR_HID.c b/lib/OVR_HID.c
    index 85eb202..beb428d 100644
    --- a/lib/OVR_HID.c
    +++ b/lib/OVR_HID.c
    @@ -170,11 +170,11 @@ BOOLEAN getDeviceInfo( Device *dev )
    /////////////////////////////////////////////////////////////////////////////////////////////
    // Sensor Scale Range
    // HID Type: Set Feature
    -// HID Packet Length: 7
    +// HID Packet Length: 8
    /////////////////////////////////////////////////////////////////////////////////////////////
    BOOLEAN sendSensorScaleRange( Device *dev, const struct SensorScaleRange *r)
    {
    - UInt8 Buffer[7];
    + UInt8 Buffer[8];
    int res;
    UInt16 CommandId = 0;

    @@ -187,7 +187,7 @@ BOOLEAN sendSensorScaleRange( Device *dev, const struct SensorScaleRange *r)
    Buffer[6] = r->MagScale & 0xFF;
    Buffer[7] = r->MagScale >> 8;

    - res = ioctl(dev->fd, HIDIOCSFEATURE(7), Buffer);
    + res = ioctl(dev->fd, HIDIOCSFEATURE(8), Buffer);
    if (res < 0)
    {
    perror("sendSensorScaleRange");


    I haven't used the feature yet -- I haven't really played with raw sensors or alternate sensor-fusion!

    Pending request for more time in the day... DENIED. Aww shucks... gotta keep trying. :)
    Participant
    May 13, 2013
    "atavener" wrote:
    The correct solution would be to increase the buffer size, as that is supposed to be an 8-byte packet.

    Thanks for the correction, and commit "atavener's proper oob correction." At first I increased the Buffer array size to 8, but since I'm still not familiar with the inner workings (it seems my in-hand Pi is proving a greater distraction than the documentation for a device I don't yet have) I wasn't sure if it was safe to adjust the ioctl as well — and now I know.
    Participant
    May 13, 2013
    Looks great! Unfortunately I don't have a Rift to work with yet, but I'm curious to see any results with the RPi - I'd wonder whether it'd be feasible to use a uDoo or even a beefier OMAP 5 SoC with an Arduino to provide basic IR/radio positional tracking alongside some rendering capability. I'm expecting that most Linux devs releasing on other platforms will stick with the official SDK - that said, can't wait to see some homebrew Linux projects using this!
    Up and Coming
    May 13, 2013
    "Vaerraent" wrote:
    I'm expecting that most Linux devs releasing on other platforms will stick with the official SDK - that said, can't wait to see some homebrew Linux projects using this!


    It would be nice if the official SDK was this one (the future, matured version of this one at least). C, hardware abstraction, cross-platform, pthreads-optional. The existing SDK is designed with a lot of assumptions -- basically, making a Win32 game in C++. Not console-friendly, mobile friendly, or resource friendly. And the pImpls at this point really are blemishes rather than the right "system abstraction", in my opinion. So even after official Linux support, I'll be sticking with this. We'll see if the official SDK transforms over time. Maybe if it gives birth to a base library (don't even need matrix/vector/quat and sensor-fusion at the lowest level of "system compatibility")...
    Participant
    May 13, 2013
    I have to agree that it's best to interface with hardware in C and that cross-platform support is important, but I think there's room for both - I don't see Unity or Torque3D adopting this, for example, they'll want something that's as homogeneous as possible across all platforms for ease of updating, debugging etc. But it's true, more options are always better! That way, everybody will have a choice of which particular implementation, license or feature set will support their goals best.
    Participant
    May 15, 2013
    The gldemo together with atavener's libnsb_ovr works pretty well (some sensor jitter), and I'm relieved I'm not the only one thinking we need a simpler cross-platform library like this. Was great to be able to try the rift for the first time on linux.

    I am however pretty worried about the licensing issues around this considering the restrictive nature of the SDK's license. The usb protocol can be reverse engineered, but at what about the lens/projection specific parts? If we can't legally derive them from the oculus sdk one would have to basically reinvent them from measuring the lenses, correct? And if the result is too close to what the oculus sdk has, who would have the burden of proof for whether it's a derivative work or not? At what point are the crucial parts just math/characteristics?

    Other people being worried by this / putting effort into putting together solutions:
    viewtopic.php?f=26&t=855
    http://robmyers.org/2013/04/26/oculus-rift-free-software-projects/
    Up and Coming
    May 15, 2013
    "Fawz" wrote:
    The gldemo together with atavener's libnsb_ovr works pretty well (some sensor jitter)


    It's nsb's libnsb_ovr, just to clarify. ;)

    "Fawz" wrote:
    I am however pretty worried about the licensing issues around this considering the restrictive nature of the SDK's license. The usb protocol can be reverse engineered, but at what about the lens/projection specific parts? If we can't legally derive them from the oculus sdk one would have to basically reinvent them from measuring the lenses, correct? And if the result is too close to what the oculus sdk has, who would have the burden of proof for whether it's a derivative work or not? At what point are the crucial parts just math/characteristics?

    Other people being worried by this / putting effort into putting together solutions:
    viewtopic.php?f=26&t=855
    http://robmyers.org/2013/04/26/oculus-rift-free-software-projects/


    Well, the distortion is pretty standard, and the measurements are reported by the device in a way that future devices can be supported. The real Oculus software-property is their particular sensor-fusion. The way to make a "free" library would be to leave out all higher-level sensor interpretation -- leaving just another HIDevice interface. You could then work from freely available sensor-fusion projects (eg. PSMoveAPI) or roll-you-own if you're into the stuff.

    This demo isn't using prediction, which is probably the reason for the extra jitter you're noticing.

    My implementation (in OCaml, before I had the Rift) of the stereo+warp is fairly different from the Oculus version, but for this demo I wanted to parallel theirs for compatibility/understanding. I suppose this part might seem like some special magic, but it's really a limited case of a more general "camera model", such as you might find more commonly in non-realtime renderers.

    Your concerns are well founded though. This library as-is is a derivative work. For my own uses it's suitable as I'm not going to make a competing product (rather, a supporting product!), and their SDK is not usable for me. Perhaps Oculus will decide at some future point to be like Apple and say "no you can't use that library for products because it's not canon", at which time I know I could put aside their sensor fusion and have fun with alternatives which might not show off the Rift as well. Less satisfactory, but it works for me -- when I backed the Kickstarter I wasn't expecting anything but hardware protocol!

    I understand their concerns for someone leveraging their work to make a competing product without investing the same effort. Hopefully that's the only intent they use their licensing restriction for. I'm okay with that -- if you're making an HMD, there's plenty of other sensor-fusion work and papers to draw inspiration from.
    Inspiring
    May 15, 2013
    You can see my post here about licensing derivative works. It might apply here:
    viewtopic.php?f=26&t=855&p=11353#p11353
    AMD Ryzen 7 1800X | MSI X370 Titanium | G.Skill 16GB DDR4 3200 | EVGA SuperNOVA 1000 | Corsair Hydro H110i Gigabyte RX Vega 64 x2 | Samsung 960 Evo M.2 500GB | Seagate FireCuda SSHD 2TB | Phanteks ENTHOO EVOLV
    Up and Coming
    May 15, 2013
    I am using raw Tracker DK data that I extracted from HID packets using the signal11 library. I extracted the data without any masking and without using the (public comain) "bit hack". What I have so far works great on my Raspberry Pi and in x86 linux. I plan to release that under an MIT license (eventually).

    I stopped using the libnsb_ovr C+linux partial SDK port, because it used HIDAPI, which did not work on my Linux Mint (but did work on Kali Linux). The HIDAPI stuff does work on my RasPi though, but I want my stuff more portable (not HIDAPI dependent).

    I am exploring sensor fusion algorithms, and leaning heavily toward RLS (Recursive Least Squares), which has been tested and proven superior to Kalman filter fusion (faster and more accurate, but harder to wrap my brain around).

    I also found a simpler "approximate" conversion between Euler and quaternion that I plan to use.

    But yes, if you directly port the Oculus-derived sensor fusion code, then you need to keep their license intact in your new code.

    I also plan to try doing the sensor fusion in a GLSL shader, so the shaders can do the "PTZ Tweening" stuff directly from an oversized framebuffer, just because it seems like an interesting project.
    :D
    This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
    New Participant
    May 16, 2013
    nsb and atavener, great job with the library and gldemo!

    atavener, I couldn't get your gldemo working on my ubuntu laptop - it has an nvidia video card that supports only OpenGL version 3.3.0, so I got some BadAlloc errors. After changing glutInitContextVersion from 4,2 to 3,3 I can run the application but it crashes shortly, after displaying the following

    tesselate: verts = 3, tris = 1
    output: verts = 6, tris = 4
    tesselate: verts = 6, tris = 4
    output: verts = 15, tris = 16
    Segmentation fault (core dumped)

    Any idea if I could change something to avoid this..? I'm not really familiar with opengl so I don't know how I should debug this.