CyBARguide Project Notes

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.

Contents

Design Overview

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

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

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.

The Infomation Subsystem

The main purpose of the Information Browser is to present information about each bar to the user in an organized manner. Whenever possible we made the information browser modifiable, so users can update the information base as they use CyBARguide. Currently, the information browser reads in information that is hard coded into our application. The information browser consists of five separate templates. The main template (mainBrowser.t) comes up when a specific location is clicked on. This main template contains generic information and has links to each of the other temsplates including the ambiance template (ambiance.t), the food and drink template (food.t) the recreation template (recreation.t) specialities template (special) and the user comments template (comments.t). Further improvements to the information browser would include storing the information in soups instead of hardcoding the information into the application.

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. =)

The Global Subsystem

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.

Future Work

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.

Procedural Information

Installing new maps

The process of intstalling new maps is cumbersome at this stage and requires updating more parts of the system than it should.
  1. Make sure the map is perfectly to scale. Any abnormalities will cause the display system to incorrectly report the location of objects on the map.
  2. Convert the scanned map to a PICT resource. This is best accomplished in Photoshop.
  3. Open the "Map2Rsrc" file in ResEdit as well as the saved PICT resource file. Copy the PICT resource into the Map2Rsrc file.
  4. Give the map a name. This is how you will refer to it in NTK. The resource ID does not matter.
  5. In the Project Data file, add the map and its GPS coordinates along with its zoom level (higher means more detail) and the names of maps that you can zoom into and the map name that you zoom out to.
  6. Define a constant in Project Data that reads in the picture as a bitmap (use GetPictAsBits()).
  7. In the Maps.ns file, edit the LoadBitmap() method of the Map class to accept the new map's name and to return the constant you just defined.

Migrating the maps to soup entries might make this easier.

Pieces of GPS connector

The connector for the GPS requires some explaining:
  1. The GPS unit is configured to only send data after it gets a response from the machine it is connected to. This is done by having the host machine assert pin 5 on the serial port when it is ready to receive. Unfortunately, we cannot assert individual pins on the Newton's serial port. Therefore, the GPS company made a special connector for us that asserts pin 5 when you flip the switch to "on"
  2. A gender switcher
  3. A null modem cable
  4. A db-25 (female) to din-8 (male) that goes to the Newton

Hopefully, we can get someone to combine all of these into one connector sometime next quarter.

Beeps and Flashes From the GPS Unit

When running CyBARguide on a Newton connected to a GPS unit, you will hear two kinds of beeps that indicuate the status of the data being received from the GPS unit.

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:

Procedure for scanning maps

There is a trick to getting the maps scanned in so that they will look good and it involves a good amount of Photoshop trickery. We are eternally grateful to Sunil Mishra for helping us figure this stuff out!
  1. There are two kinds of maps: full color (from the road atlas) and blue/gray (from City Hall). Scan in the blue/gray maps using "Sharp B&W Photo" and the color maps as "full color photo." This gives it 150 dpi.
  2. If it is a color map, drop it down to grayscale.
  3. Use a Gaussian Blur with a radius of 0.7 to thicken up some of the lines so that they won't get lost in the conversion to black and white.
  4. Use an Unsharp Mask with amount = 201%, radius = 2.0 and threshold 0. This sharpens up the lines.
  5. Use Adjust Levels to tell Photoshop which colors we want to be represented as white and which we want to be black. Using the White Point dropper, click in the areas that should be considered white. Use the Black Point dropper to do the same for areas that should be black. Keep doing this until it looks pretty good. It doesn't have to be perfect.
  6. Drop the image to 72 dpi. When you're doing this, you can scale it larger or smaller, but make sure that it remains proportional!
  7. Unsharp Mask again
  8. Adjust Levels again
  9. Drop to black and white with a 50% threshold

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.

Location on hard drive

On the disk on the Mac named Santana in the OSL, there is a folder at the root level directory called "Cyberguide." Inside this folder there is a folder called "Spr-96 CyBARguide." Double-click on the app called "CyBARguide.pkg" which will open the Newton Package Installer to download the package. If the ".pkg" file isn't there, you can open the "CyBARguide" NTK project and build/download it from inside 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.

Contact Information

Mike Pinkerton
mpinkert@cc.gatech.edu

Sue Long
suelong@cc.gatech.edu

Dr. Gregory Abowd
abowd@cc.gatech.edu

College of Computing
Georgia Institute of Technology
Atlanta, GA XXXXX
http://www.cc.gatech.edu