The development of a working prototype for the game was our main goal. Thus we had to consider various technologies and evaluate them. We also had to create a framework. A framework that allows the modification and manipulation of the code that runs inside the prototype, even after the prototype was physically manufactured. In fact we even had to consider some fail-back methods in case some of the technology inside the ball fails or gets damaged. This led us to build a fairly complex (although not extremely complicated) network that had to work together seamlessly.
But before going into details of the whole code, we will explain some important parts of the system that finally creates Urban Defender.
The system consits of the following parts:
- Arduino Nano
- ZigBee Point to Point
- 12 LEDs, paired and powered by 6 PWMs
- 1 control LED
- 1 vibrator
- Beagleboard, Ångström Linux Distribution
- USB Hub
- USB GPS Device
- USB Memory Stick
- ZigBee Point to Point
- Development / build station (for development only)
- USB Hub
- USB GPS Device
- USB Memory Stick
- Arduino Nano (Test Device with Accelerometer)
Above you can see how the whole setup looked. The reason for having two arduinos was that the developers could work and test their code while the lab guys could work on the ball itself without having to wait for each other.
And here you see how this looked in real. This is the beagleboard with the USB hub and the GPS device as well as the ZigBee station.
Perhaps the most important part in the Urban Defender system is, that the ball had to communicate to the beagleboard (the main controller) without any cables attached. But not only that, we also wanted to program the built-in arduino through that wireless connection. So that once the ball is closed we could change to programm, upload a new version without opening the ball and attaching the USB cable to the Arduino Nano.
We considered various approaches like: Bluetooth, Wireless USB and other possibilities but came to the conclusion that a connection via a ZigBee connection (which is in fact nothing more than Wireless USB) provides us with a stable enough connection.
Thanks to this setup, we not only could easily programm the arduino, but we also had an convenient way of debugging and controlling all sensory in- and output.
For location-awareness we used an unnamed GPS device we recieved from school. The problem with GPS in general is, that it has to be outside (does not work in closed rooms) and is not very accurate or takes a long time until it has a vagely correct signal. And it is fairly big and only works via usb so it does not really fit into the ball. Therefore (at least for the prototoype) it had to be added seperately, attached via the beagleboard to the player. This has some disadvantages: The district in which the player is located matters and not the district in which the ball is thrown.
The balls dependance to GPS and the problems related to GPS led to some behaviour that affected the gameplay. We had, for example, to create a feedback which indicates wether the GPS/location could be detected or not (the so called “search mode”). Throwing the ball when no GPS is available, causes also a feedback, communicating to the player that the device is not ready yet.
While working on the prototype we noticed that we had to create an override for the GPS. In order to test the ball and the gameplay it was not always practical to go outside to test if everything works. So we created a graphical interface which lets us simulate all states and behaviours.
We had the choice to either control everything from python using some library, or writing code that runs on the arduino itself. At the point we made the very first prototype we did not knew how the whole system will work later - communication between arduino and beagleboard has not yet been established. So the first program that ran, which tried to find out if the ball was thrown against a wall, got written at a very early time.
This specific part is very time critical and later, when the second and third prototype came, when we could communicate between python and arduino, we chose the already working code in favour of reimplementing it. So, all code that actually read the accelerometer values and controlled the vibrator and leds was written in c++ to run on the Arduino Nano. Serial communication was used communicate between the two devices. And with the help of the Aduino Messenger class, the implementation was only a matter of some hours.
Not being dependant on a “master” that controls the Arduino completely was also a good idea because it could happen that the beagleboard went out of reach or was restarted very often. So the Arduino / the ball, could, to some level, work without being connected to the Beagleboard.
Python controlled the whole gameplay. It not only decided if a throw-action that was detected by the ball was valid, it also controls the location and tells the Arduino what state should be indicated. It was also responsible for maintaining the state of the game (the score) by using pickle, retrieving the gps location, checking if the player is within a certain district (by examining a kml), playing the correct sound and much more.
Beagleboard / Linux
Except some issues related to an íncomplete python setup, we ran in almost no problems. The USB hub required additional external power in order to work correctly but this worked right from the beginning. Only the sound was too silent to hear so we had to use some archaic tools in order to fix that:
- ./alsamixer (This, opened in zterm, reveals some highly abstract ascii art)
- ./alsactl store (to save the new level)
We had to come up with a quick way to create and manipulate districts. The final concept draft would have included a zone editor and also a web-based visualization of the ownership of these zones. For the prototype we decided not to create these elements in order to save time. In order to create these Zones in a convenient way, we used Google Earth to draw the shapes and then exported these as a KML file. The python code then read this KML file, updated the current game configuration and used the name as well as the geometry to check if a location read from the gps-device is inside a polygon. For this, the gps location information has to be converted from latitude/longitude to a cartesian coordinate system. The method to check if a coordinate is inside a polygon is derivated from here.
In order to quickly test interaction and feedback we had to come up with a way to control the ball with a very simple user interface.
This interface is written in pyhton with the help of TkInter, a python port of Tcl/Tk. Although it does not produce the nicest controls/interface ever seen, it did a great job and was fairly simple.
With the help of that interface, testing the feedback and the reaction of the player, implementing new feedback as well as documenting and demonstrating the prototype is much easier.
In order store the state of the game and to allow a multiplayer system, the data to whom a zone belongs has to be stored inside the beagleboard. In python, to store / serialize data into a file is extremely easy, by using pickle. The data for urban defender is stored in two files. One containing only geometric information, the KML File and one containing the state of the game. At startup the KML file is compared against the current game state. If there are new areas inside the KML file, they are included as neutral zones and are available in the gameplay. Also, the geometry of a zone will always be taken from the KML file. Thus, adding new zones or altering existing ones is very easy. Every time a valid smash is detected, the gamestate is stored. The file in which this state is saved is inside the user’s home folder (and not in the memory stick). Therefore the memory stick (which contains the player-id inside an config file) can be changed to switch players.