Easy Absolute Orientation: PNI SpacePoint Fusion in Python

SpacePoint Fusion

My college roommate Donnie mentioned the PNI SpacePoint Fusion in comments of the HMC5843 post, and it seemed too good to be true.  A 9 DOF controller (3 axes each of magnetometer, accelerometer, and gyro) with a Kalman filter to calculate a smooth quaternion that interfaces as a USB HID device, all for under $100.  I’d be surprised if PNI is making any profit on it.  I sound more like a shill than I’m normally comfortable with, but I’m truly impressed with this gadget. I have some plans for it involving a Microvision SHOWWX that I’m quite excited about; I’ll write more on that when it’s available in a couple of months.

SpacePoint Fusion Innards

PNI provides some Windows only sample apps that show off how weirdly stable and precise the SpacePoint Fusion is.  Luckily, since it’s a normal USB HID device (redundant, I know), and PNI provides application notes, it’s easy to use on any platform.  I wrote a Python module that uses libhid via python-hid to make it easy to prototype with in Linux.  The usage is pretty simple, as shown below.  Note that when plugging the device in, you need to keep it still for a few seconds while the gyros are calibrated.  After that, the quaternion, accelerometer, and button data can be updated 62.5 times a second.

>>> import spacepoint
>>> fusion = spacepoint.SpacePoint()
>>> print repr(fusion.quat)
(0.987518310546875, -0.04425048828125, -0.04119873046875, 0.145294189453125)
>>> print repr(fusion.accel)
(-0.054016113354999999, 0.018859863306999999, -0.89648437622400001)
>>> print repr(fusion.buttons)
(0, 0)
>>> fusion.update()
>>> print repr(fusion)
accel: (-0.054016113354999999, 0.018859863306999999, -0.89648437622400001)
 quat: (0.97186279296875, -0.233428955078125, -0.030548095703125, 0.005401611328125)
 buttons: (0, 0)

Update on February 7, 2010: I emailed PNI about a bug in the firmware, and got the following response:

Thank you for submitting the SpacePoint bug regarding libusb, Python, and Linux. You’re right! There is a bug in the SpacePoint FW that prevented opening interface 1 without opening interface 0 when using libusb under Linux. While your work around was effective in allowing the device to operate normally, one should be able to open interface 1 directly without the work around. We were able to use your Python source code to quickly diagnose and repair the bug. Please see the attached for the modified Python script. Please feel free to post this paragraph, the modified code, and all bragging rights on your blog (https://eclecti.cc/).

Units being shipped now have the fix. I modified the Python module to handle units both with and without the firmware fix and bumped the version to 0.2.

SpacePoint Python Module
Standalone spacepoint.py

Setting udev rules to get the permissions right

In most cases, the module will just work properly.  However, if you get the following error, you probably don’t have the right permissions to access the usb device.

>>> import spacepoint
>>> fusion = spacepoint.SpacePoint()
hid_force_open failed with return code 12.

On most modern Linux distros, you can fix this by setting a udev rule for the device. In Ubuntu Karmic Koala, saving the following as /etc/udev/rules.d/45-spacepoint.rules , running sudo service udev restart , and then unplugging and replugging in the device should fix it:

# PNI SpacePoint Fusion
SYSFS{idVendor}=="20ff", SYSFS{idProduct}=="0100", MODE="0664", GROUP="admin"
11 Comments on Easy Absolute Orientation: PNI SpacePoint Fusion in Python

Cheap 3D in OpenGL with a ChromaDepth GLSL Shader


I have probably stated in the past that I don’t do 3d.  As of a few months ago, this is no longer accurate.  Between Deep Sheep, a computer graphics course, and a computer animation course, I have grown an additional dimension.  This dimension is now bearing dimensional fruit.

After watching Coraline in 3d over spring break, I became obsessed with the possibilities of 3d.  Of course, as a student, I can’t quite afford fancy glasses or a polarized projector.  My budget is a bit closer to the free red/blue glasses one might find in a particularly excellent box of cereal.  Searching around the internet, and eBay specifically, I came across a seemingly voodoo-like 3d technology I’d never heard of:  cardboard glasses with clear looking plastic sheet lenses that could turn hand drawn images 3d.  This technology is ChromaDepth, which makes red objects appear to float in air, while blue objects seem to recede into the background.  Essentially, it uses prisms to offset red and blue light by different amounts on each eye, giving an illusion of depth as your brain attempts to perceive it.  So, creating a ChromaDepth image is just a matter of coloring objects at different distances differently, which is something computers are great at!

Of course, I am far from the first person to apply a computer to this.  Mike Bailey developed a cool solution in OpenGL a decade ago which maps an HSV color strip texture based on the object’s depth in the image.  The downside there is that objects can no longer have actual textures.  Textures are pretty tricky with ChromaDepth, in that changing the color of an object will throw off the depth.

I wrote fragment and vertex shaders in GLSL that resolve this problem.  The hue of the resulting fragments depends only on the distance from the camera in the scene, with closer objects appearing redder continuing through the spectrum to blue objects in the distance.  The texture, diffuse lighting, specular lighting and material properties of the object set the brightness of the color, giving the illusion of shading and texture while remaining ChromaDepth safe.  My code is available below.  Sticking with the theme of picking a different license for each work, this is released under WTFPL.  I can’t release the source of the OpenGL end of it, as it is from a school project.  It should be fairly simple to drop into anything though.  You will need ChromaDepth glasses to see the effect, which you can get on eBay or elsewhere for <$3 each.

ChromaDepth GLSL Vertex Shader
ChromaDepth GLSL Fragment Shader

5 Comments on Cheap 3D in OpenGL with a ChromaDepth GLSL Shader