CyBARguide is a project developed and written by Sue Long and Mike Pinkerton under the guidance of Dr. Gregory Abowd at the Georgia Institute of Technology. It provides a solution for locating and navigating to locations for after-hour refreshment and entertainment using a Global Positioning System (GPS) and an Apple Newton MessagePad 120. In addition to finding where an establishment is located, the user also has access to a fully customizable database of information about each establishment.
We designed CyBARguide to be as generic and customizable as possible. Each subsystem within CyBARguide is designed to be replaced by a different implementation should the need arise. For example, to shift from a GPS based coordinate system to an indoor, index based coordinate system only requires rewriting the Positioning Subsystem and providing a new map implementation. The information and display systems remain untouched.
As alluded to above, CyBARguide is divided up into several subsystems, each of which will be described in full detail in the following sections:
The Display Subsystem is responsible for displaying the best map that can display both the user's current location and their chosen destination. It contains a list of all the maps available to the system and selects the one with the highest level of detail at each notification that the user has moved. In addition, the display system handles the user interaction for scrolling and zooming maps (both automatically and via direct manipulation).
What makes this system so flexible is that it relies on the maps to determine if objects should be displayed or not. Each Map object has methods to determine if a given location is within the region defined by that map and also to translate from global coordinates to (x,y) coordinates on the screen. This frees the display system from having to know anything about the current positioning system or even how locations are stored.
When the user moves, the Positioning Subsystem calls the UpdatePosition() method on the display system. This scans through the list of maps, asking each in turn if it can display both the current position and the current destination (picked by the user). Out of the maps that can display both, the display system then picks the one with the most detail (highest zoomLevel field) and displays that map.
The user can also zoom in and out from the currently displayed map. Each Map object stores what map contains it at a higher level and what maps it itself contains. When the user chooses to zoom in/out, the display system queries the current Map object for what the appropriate map to zoom to is and then switches maps to display the new one. Again, the display system does not explicitly know the map hierarchy.
Even though the display system as a whole is responsible for displaying local establishments of refreshment on the screen, it again hands this task over to the Map objects that have been written to the specific positioning system. On startup, each map requests the list of all bars in the information system and then filters out the ones that it cannot display and caches the ones that it can. When the display system switches to a new map, it only needs to walk down this filtered list and add them to the current view. Again, the Map object does all the work.
In summary, the display system handles, in a very generic way, displaying and switching maps. When the positioning system changes (from GPS to something else), the only part that needs to be rewritten for the new position system is the Map object.
The Positioning Subsystem is responsible for obtaining the user's position (by some means) and then telling the Display Subsystem to move to this new location. The current implementation of the positioning system is written to read and parse GPS coordinates from an external GPS unit connected to the serial port. Switching to a different method of determining the user's position (for example, an index-based system like in the current Cyberguide) requires rewriting this subsystem.
This implementation uses the OS 2.0 endpoints wrapped in a user proto so it can be easily replaced. The position system was developed separately from the display system, but because it is a user proto, integrating it into the existing application took less than 10 minutes.
The positioning system consists of two user defined proto called PositionSytemProto and protoDisconnectSlip and some constants defined in ProjectData. The main parts of the positioning system are contained in the PositionSystemProto. The protoDisconnectSlip is just a floatNGo proto that pops up when disconnecting the system. The PositionSystemProto contains a proto endpoint, which is the primary communication mechanism on the Newton. The endpoint is configured for a read only serial connection. The communication is only one-way, from the GPS unit to the Newton. There are several ways to specify input to the Newton. This endpoint is configured to read in an exact byte count (here 300 bytes) and parse the data stream looking for a specific GPS encoding as specified by one of the NMEA standards. The current latitude and longitude are then parsed out of the string by a method called getLatLong.
Before handing the new position off to the display system, the position subsystem asks the global system for the current state of the positioning system (on/off). If it is off (which happens when the user manually scrolls or zooms the map), the update method in the display system is not called. If it is on, the position system informs the display system by calling its UpdatePosition() method.
To modify the positioning system to work with other GPS systems or other positioning devices you will need to know a few more details. First, the current endpoint is set for serial communiction at a baud rate of 4800. To use another GPS unit be sure to change the baud rate accordingly. Also, we are using a rather common NMEA format, but if an alternative format was used the input byte count may need to be modified and the parsing routing would must surely need to be modified. To use a PCMCIA GPS unit, you will have to get the appropriate driver from the manufacturer. This would most likely be in the form of either a ROM patch or a software user proto you would work from. Modification to our positioning system to allow it to work with the discrete remote control system in the GVU Lab would require only that you modify the inputspec to read in a smaller number of bytes and that you modify the parsing script to parse the correct expected input.
Unfortunately, the information system is the least implemented system of all. Currently, it reads objects out of a static array and does not even fill in the information panels with the appropriate information (though they are all complete). At the moment, it really is true that all roads lead to the Highlander. =)
All of the above subsystems are tied together by the Global Subsystem, which all the systems have access to via parent inheritance. All other subsystems are user protos which reside in the top level of a clView. Thus, they all have access to any functions or globals stored in the top level view's frame.
To minimize the reliance on exact names within the individual subsystems, systems use a function defined in this top level to access a pointer to the another subsystem. This way, the actual name of the user proto is known only at the very top level and implementations of each system only require knowledge of the inherited global function, not the exact name. An example of one of these functions is the GetDisplaySystem() function which returns a pointer to the current implementation of the Display Subsystem.
Our implementation of CyBARguide is a well designed starting point for many improvements and addititions to the project. Here is a non-exhaustive list of possible future work on CyBARguide.
Currently, to view information about a specific bar you must move to its location on the map and click on it to bring up the information browser. We would like to implement a complex querying system that would let you query on all attributes of a bar, anything from "all bars that have Guiness on tap" to "all bars that have air hockey machines and play bluegrass music". This would involve implementing a querying engine built around soup indices.
Our positioning system gives you fairly accurate readings, but you are still off by a block or so from your actual position. We have a few suggestions as to how to correct this delta. First, you could try to allow the user to modify or correct your current position, adding a delta factor to the latitude and longitude read in from the GPS unit. In addition you could try getting futher latitude and longitude from other NMEA formats. We are using the most frequently occuring encoding, there are however several other formats we are recieving from the GPS unit, but ignoring. There may be additional information in these other formats that may more accurately report our current position.
We would like to make the information browser completely user modifiable, so it could double as a data entry application. We would also like to store all the information in soups instead of hardcoding it in the application. Soups give you the ability to modify information without recompiling the application. They also allow you indexing capabilities for quick lookup.
We would like to make several modifications to the display system. First, if possible, we would like to generate new bitmap images of maps at runtime, instead of having specific bitmaps hardcoded at compile time. Building bitmaps at run time will allow the user to see maps centered around the current position.
Finally, we would like to add path generation to CyBARguide. The idea behind path generation is that the user would ask how to get from one location to another and CyBARguide would provide directions in both words and actual markups on the map. Providing directions would require a large database of all major intersections and the implementation of some sort of shortest path algorithm. To add markups to bitmaps would require both a mechanism for pasting two bitmaps together and generating a third as well as a method for deciding where on the original map the markups should go.
Migrating the maps to soup entries might make this easier.
Hopefully, we can get someone to combine all of these into one connector sometime next quarter.
In addition to beeps, the GPS unit flashes its current status using a sequence of dots (short flashes) and dashes (long flashes). The most common that you will see are:
Save a copy of this as a PICT resource (make sure you don't save over your color map, else you'll have to scan it again if you don't like your results) and give it an appropriate name. The name you give the resource is the name that you will use when loading this map in NTK.
Once the package is intalled on the Newton, the only other step is to plug the GPS unit into the serial port of the Newton.