Taking Control of Mathematica
August 2, 2007 — Lou D'Andria, User Interface Group
Who would think you could get so much work done just by twiddling your thumbs?
Mathematica 6 brings with it a host of new ways to interact with your output. Want to set up an arbitrary number of parameters and explore their multi-dimensional space? That’s trivial to do with the Manipulate function. However, once you start exploring this space, you immediately realize that your exploration is restricted by the mouse pointer. There’s only one pointer on the screen. It can only interact with one control (slider, checkbox, or whatever) at a time.
Fortunately, hardware developers realized long ago–long before multi-touch interfaces like Apple’s iPhone, which are in vogue at the moment–that most people have 10 fingers and so in theory can access many more degrees of freedom than the two degrees provided by a typical mouse.
Enter the gamepad.
By including native support for controllers, gamepads, joysticks, and other human interface device (HID) systems, Mathematica lets you make more efficient use of your hands, instead of limiting you to current pointer technologies.
We have tweaked mappings for a dozen or so different brands, to make sure that the joystick values have the proper orientation. It seems each hardware company takes a slightly different approach to assigning values and directions, and so normalizing across brands was an important part of providing unified access to these devices in Mathematica.
Of special note is the Logitech Dual Action USB gamepad, which had the highest signal-to-noise ratio in our tests. Notice in the picture above (it’s the dark blue controller at the very bottom) that it has two analog joysticks and more than enough buttons to keep most of your fingers occupied. The 3Dconnexion products such as SpaceNavigator (bottom center), and the SensAble PHANTOM line (top right), also have custom support, as do the sudden-motion sensors and tablet digitizers found in some laptops.
Mathematica natively supports all these devices. In fact, that native support extends to every Manipulate output. Any Manipulate you create, or any of the Demonstrations available through The Wolfram Demonstrations Project, will immediately respond to a gamepad if you happen to have one plugged in.
By default, Manipulate attaches sliders and 2D sliders to joysticks, and checkboxes to buttons. If there are more sliders than joysticks, buttons on the controller device are paired off to form a pseudo joystick, with each pair of buttons moving a value back and forth along its domain.
So in the following output, based on an example from the Manipulate tutorial, the first two variables are controlled by the left joystick, the next two by the right joystick, and the fifth variable by the horizontal axis on the hat switch control. You just plug it in and it works.
Mathematica‘s native support for controller devices also extends to 3D graphics. In that case, the natural action is to change the orientation of the 3D image on screen. Even though you can do this same thing with the mouse, using a controller turns out to be incredibly useful in practice and, like the support in Manipulate, has the benefit that you don’t need to read documentation or change your input to use the controller.
Because these automatic behaviors are so useful in practice, controllers have become almost as ubiquitous as mice around here. If there’s not one hooked up to your computer, there’s probably one very nearby. Even the young children of some employees have found themselves enthusiastically exploring the parameter space of some Demonstration or other with a gamepad. Do they understand all aspects of the object they’re investigating? Of course not. But that hands-on experience could easily become the intuitive basis for future, more rigorous investigations.
It’s worth pointing out that controller support is not limited to Graphics3D and Manipulate. In fact, most of the support in these functions is built from the ControllerState function, which gives immediate, low-level access to the instantaneous state of all attached controller devices. Using that function, along with other interface primitives like Dynamic, it’s easy to build interactive, controller-centric features in Mathematica with just a few lines of code.
There were other interesting design issues involved in supporting controller devices. For instance, how should scoping work? If there are lots of Manipulate functions or 3D graphics on the screen, which ones should respond when you wiggle a joystick?
And how do you sometimes ignore controllers like the sudden-motion sensor included in all new Apple laptops, so that 3D graphics don’t move every time you move your laptop (which, if it’s on your lap, will happen constantly)?
Well, the scoping of controller state is implemented by selection. By default, if there is an output within the current selection, then controllers will have an affect on that output, and not otherwise. Of course, if you want your output to always listen for a controller no matter what the selection is, there’s an option to do that. There’s also an option to change the relative priority of controllers when there are several present.
Between the low-level ControllerState and the automatic support in functions like Manipulate and Graphics3D, Mathematica 6 provides simple and powerful interfaces for you to access data with any controller device.
So start twiddling your thumbs, and get back to work!