First posted 2018-09-29
Recently I built an augmented table tennis game which required detection of each bounce of the ball on the table. The simplest idea I could think of was to use a scanning laser rangefinder (AKA LiDAR) scanning a 2D plane just above the surface of the table. I knew there were already several software products to interpret the data from these devices and convert it into TUIO. TUIO is built over OSC, which is a layer over UDP. The normal use case is to simulate a touch screen. Ideal for turning a giant LED screen into an interactive display. TUIO is supported by Ventuz, my graphics renderer of choice, which might have saved me a lot of code!
Bad news: software for touchscreens isn’t really designed for touches which are less than 3ms long. It may even filter them out deliberately as noise. That route let me to debugging third party code but was ultimately fruitless.
Good news: decoding the data coming directly from the rangefinder was not as complicated as it sounded at first. After some byte juggling, it’s just a list of distances for every scan. From that, a bit of High School trigonometry gets us to some useful coordinates. There were some problems to solve, like working out which of many hits on an object to consider as “the one”, and how to detect which objects are new and which have just moved since the last frame. I soon realized that the constrained use-case of balls on a table was quite different to simulating a touchscreen for fingers and hands, so it wasn’t really surprising that the results were faster and much more reliable.
Building my own code also allowed me to put it in a library and keep in in-process with Ventuz, the graphics renderer. That means, single click startup, no IPC and no waiting for the next graphics frame to be rendered before I can start responding to a bounce. It also allowed me to add a simple lineup mode directly to the render rather than having to switch applications all the time. It’s satisfying to see the dots “stick” to the balls as the graphics are projected onto the table.
Hopefully somebody else could use some graphics with a custom LiDAR implementation some day!