I looked into a few different devices. If you want to skip the rest of this article and just start researching potential solutions here's some of the options I considered:
- Keypad Gaming Mice (Razer Naga and Logitech G600)
- Modified Controllers
- Motion Capture Controllers
- Leap Motion
- IR camera + pupil tracking
I haven't tried out a Leap Motion yet, I think they have the potential to be great for those with limited motor control. I may apply for a development kit if they're still available.
I eventually decided that a Keypad Mouse like the Razer Naga or Logitech G600 would work best. Sadly neither company has a left handed version yet (Razer announced they would make a left handed version in March 2013). Instead I picked up a Logitech G13 gamepad. I went with Logitech over the Belkin and Razer options because it is the only gamepad I found with a true analog thumbstick. The other gamepads have a Directional-Pad (either 8 way or 4 way). The analog stick seemed to be the better option for replacing mouse control.
I recorded a few of the setups I tried out. They can be seen in the video below.
I started playing with Lua scripting to create more complex behavior than can be achieved with the standard Logitech macro editor. The only experience I'd had with Lua was some game add-on debugging a few years ago, so it was a bit of a slow start. One of my first tasks was to emulate a mouse wheel using the two keys near the thumbstick. My first attempt resulted in the code below which uses Logitech's built in event handler.
This code uses setting of MKeyState to repeatedly fire events while the key is held down. It works, but it runs into event pileup problems with sleep delays larger than a few milliseconds. Trying to mouse wheel up and down in quick succession will result in a queue of events and a laggy user experience. Some helpful people in the Logitech support forums pointed me towards llProject, a Logitech device polling library which solves a lot of common problems and allows for some pretty complex macros.
The llProject library was very well documented and easy to figure out. I was able to create an emulated mouse wheel with a very nice feel. I set it up to do an immediate tick of the wheel, followed by a large intitial delay before going into a steady repeat as long as the key is pressed. Instead of sleeping for a delay, preventing all queued tasks from executing, llProject routines yield activity and the routine manager continually checks to see if the necessary delay has passed before continuing the yielding process. This allows some routines to continue while delaying others. Here's the code I ended up with:
Feeling the mouse emulation and key layout were as good as I was going to get them, I moved towards physically modifying the G13 for easier use. I found the original G13 thumbstick to be uncomfortable and difficult to use. It is narrow enough that your thumb can very easily slide off if it isn't perfectly centered. Like many others, I decided to replace it with the thumbstick from a game controller. Xbox 360 thumbsticks are nearly a perfect fit. The only modifications necessary are widening the G13 case's thumbstick pass-through, and narrowing the 360 thumbstick's mounting hole.
I didn't have any epoxy to fill the mounting hole, so instead I drilled it out wider and glued in a section of 3/8th inch dowel. I then drilled out and lengthened a new mounting hole with a 1/64th inch drill bit.
The thumb portion and the support peg of the 360 thumbstick are much wider than the original. In order to achieve the same range of motion (and get the peg through the top of the case) you have to widen the case's thumbstick pass-through hole. I started out trying to do this with a dremel, but found it cut too unevenly and was much too aggressive. I gave up on the dremel and instead drilled the hole out to 3/4 inch with a Forstner bit. After cleaning up the cut with some 200 and 400 grit sand paper I ended up with a nice clean edge as seen in the images below.