Google Earth with a PS3 controller

Google Earth is a lot of fun with a 3D input device. But not everyone can justify shelling out a hundred bucks or so on a SpaceNavigator just to play with Google Earth. I've explored other possibilities, but the best alternative I've come up with is the PS3 controller. It has more than enough joysticks and buttons for five degrees of freedom. Have a look:

The PS3 controller is pretty well supported under Linux (at least if you connect it with a USB cable, it's more complicated if you want to use Bluetooth). The only problem really is mapping its various buttons and joysticks to proper functions in Google Earth. Fortunately, there is a piece of software called pystromo that can freely remap input events, thus allowing us to turn a PS3 controller into a SpaceNavigator-lookalike.

Here's what you need to do.

  • Download and unpack pystromo.
  • Open the lib/constants.py file in the pystromo directory with a text editor. Find the line containing "ABS_MISC" and add the following two lines after that (before the curly brace):
    48: "ABS_L2",
    49: "ABS_R2",
    (We have to do this, because pystromo doesn't have constants for the PS3 controller's L2 and R2 buttons.)
  • Create a new file in the pystromo directory and call it, say, config/ps3-ge.map. Put the following in it:
  • Connect your PS3 controller using a USB cable and press the PS button.
  • As root, run the following command: ./pystromo-remap.py -R -v -m config/ps3-ge.map
  • This will create a new input device, called eventN in /dev/input/. The one you're looking for is the one with the highest number. As root, run this to give your regular user access to the device: chmod 666 /dev/input/eventN
  • Open /opt/google/earth/free/drivers.ini with a text editor and put the following after the "SETTINGS" line (after the curly brace), remembering to replace eventN with the proper device number:
    SpaceNavigator/sensitivityX = 0.4
    SpaceNavigator/sensitivityY = 0.4
    SpaceNavigator/sensitivityZ = 0.1
    SpaceNavigator/sensitivityPitch = 0.05
    SpaceNavigator/sensitivityYaw = 0.05
    SpaceNavigator/sensitivityRoll = 100
    SpaceNavigator/device = /dev/input/eventN
    SpaceNavigator/zeroX = 127
    SpaceNavigator/zeroY = 127
    SpaceNavigator/zeroZ = 127
    SpaceNavigator/zeroPitch = 127
    SpaceNavigator/zeroYaw = 127
    SpaceNavigator/zeroRoll = 127
  • Run Google Earth.

You should now be able to navigate using the left and right sticks and L2/R2 buttons.


Control Google Earth with an Android tablet

I have previously described how to turn an Android device into a mouse under Linux, using the uinput module. There's no reason we should limit ourselves to a simple mouse. Some applications benefit from a multi-axis controller, which we can simulate in a similar way. One such application is Google Earth. Here's a demonstration video:

And here's how it's done. Just as before, there's an application running on the tablet that listens for touch events and broadcasts them on the network and a Python script running on the computer that listens for those events and translates them to simulated controller events that Google Earth understands. Here's the tablet application's source code and here's just the APK if you don't want to compile it yourself. The Python script that's running on the computer is here.

There are some additional hoops you have to jump through to get it running.

  • The Python part requires python-uinput, which in turn requires libsuinput.
  • Remember to unblock UDP port 20125 on your computer's firewall, as that's the port that the tablet application uses to broadcast touchscreen events (the tablet and the computer obviously have to be on the same network).
  • Run android3dmouse.py as root.
  • Run the TouchscreenBroadcaster3D application on your Android device and touch the screen (the simulated mouse device only appears on the computer after the first events are emitted).
  • Look in /dev/input/ and figure out what the newly created device is called (it's going to be the eventN file with the highest number).
  • As root, execute the following command to let Google Earth running as a regular user access the device: chmod 666 /dev/input/eventN
  • Open /opt/google/earth/free/drivers.ini with a text editor and paste in the following after the "SETTINGS" line (after the curly brace), remembering to replace eventN with the proper device name:
    SpaceNavigator/sensitivityX = 80
    SpaceNavigator/sensitivityY = 80
    SpaceNavigator/sensitivityZ = 30
    SpaceNavigator/sensitivityPitch = 0.5
    SpaceNavigator/sensitivityYaw = 0.5
    SpaceNavigator/sensitivityRoll = 0.5
    SpaceNavigator/device = /dev/input/eventN
    SpaceNavigator/zeroX = 0.0
    SpaceNavigator/zeroY = 0.0
    SpaceNavigator/zeroZ = 0.0
    SpaceNavigator/zeroPitch = 0.0
    SpaceNavigator/zeroYaw = 0.0
    SpaceNavigator/zeroRoll = 0.0
    SpaceNavigator/gutterValue = 0
  • Since X happily grabbed the new device and it now moves the mouse cursor, execute the following command to make X let it go: xinput set-int-prop "python-uinput-mouse" "Device Enabled" 8 0
  • Finally, run Google Earth.

You should now be able to pan, zoom and rotate via multi-touch gestures on your tablet's (or phone's) screen. (Yes, one more degree of freedom would be nice, but I haven't figured out a good way to do it yet.)

If you can't get this mess to work, I'm not the first one to do something like this, there's a Google Summer of Code project done by Reese Butler that works in a similar manner, but uses a slightly different control scheme. The Android part is on the Market and the computer part can be found here. Maybe you'll have more luck with that one.