Project Snail Trail

A first look at the new trail visualizer

Last week was productive, but short. I spent Wednesday through Friday visiting my brother’s familiy out of town, so Wednesday and Friday were spent mostly driving and Thursday I only had about four hours to work while my nieces and nephews were at school. I actually spent most of that time looking at public domain images on Clker. I was initially looking for map marker icons, but then decided to search on the term snails and see what they had. I’ve asked a friend to draw a cute snail for the projects mascot, but until he comes through I think I’ll just go with what I found on clker – after all, using a public domain image seems to fit nicely with the goal of this whole project (creating a public dataset of movement data).

The images are vector graphics so you can scale them to any size you like without losing quality. I don’t have a lot of experience with this, so Thursday morning while the kids were at school, a few hours of my time went to playing around with graphic editing and conversion tools. By the end of the day, I was clicking on a cute little snail in place of the initial android icon I had been using and looking at a trail of snails in my mapview. I also replaced the microphone icon I procured from the tab view turorial with an abstract looking snail curl. Nothing big, but it’s amazing the effect a little bit of branding has.

Yesterday I finally dug into a number of classes in the graphics and map api packages including Canvas, Paint, Projection, Overlay, and more with MapView. I had been using the ItemizedOverlay class to display tracked locations on a map, but I wasn’t so happy with that approach as it forces you to pass in a some sort of drawable icon to place on each of the location. Considering it renders a shadow behind each of the icons, it seemed a bit overengineered for my needs – it was slow and it really didn’t even accomplish what I wanted. I was looking for a visualization that showed points (ideally circles with sizes that represented the accuracy of each tracked location) connected by lines. I eventually figured out I needed to extend the com.google.android.maps.Overlay class and add in my own implementation of the draw(Canvas, MapView, boolean) method. From there I use MapView.getProjection() to get a projection object which I can use to convert GeoPoints to Points that I can then use to call Canvas.drawLine(...) or Canvas.drawPoint(...) for each of the locations and paths between the locations. While I was at it, I also added in some logic to figure out the minimum and maximum latitude and longitude for given set of points and automatically center and zoom the map to closest zoom that still displays all points for the trip.

Snail Trails TrailViewer

If you look at the map to the left (or possibly above/below depending on your screen size) you’ll see the current incarnation of the trail viewer. It no longer resides in its own tab, instead the app now has two tabs – one for configuration and one that lists trips. In the list view, you can click on any of the trips and it will pull up a full screen map of that trip. Blue dots represent locations provided by the phones gps and green dots those from the network provider. Smaller darker dots represent fixes with a higher reported accuracy while larger more transparent dots represent those with lower accuracy. If dots are larger and darker, it generally means there are lots of dimmer dots drawn on top of each other. While this is all a nice improvement over a bunch of overlapping snails, the lines connecting the dots are what really make the difference. Without those lines it would have taken longer to notice/figure out the anomaly that cached network provided locations were causing.

Looking at the image, for the most part you see a relatively sane trip from the bottom right to the top left. This was me walking to Target and the gym to watch my wife play volleyball. Currently the program just kicks in every three minutes to request a location fix, but you’ll notice a few small blue dots close together near the start of the trip – that was me repeatedly clicking a button to force a lookup. After that the dots are relatively evenly spread out until I get up to target. Once I was inside target, the gps wasn’t getting a signal anymore so I would expect the network provider to take over – however, I didn’t have my network data plan enabled, so the network provider returned cached information – apparently my last known location from half an hour earlier (but with no timestamp indication that the data was stale). This is why you see the crazy red line that jumps from target all the way back down to the start of my trip, then back up to target when I walk outside again and get a gps fix. At that point I decided to turn on the my data plan and see what location the network provider would return with it on – surprisingly I was able to get gps fixes inside of the gym and you can see the line between my actual location inside the gym and my estimated location across the street (I’m guessing that’s a cell tower).

It seems the lesson I’ve learned from all of this is that I need to ignore locations that come from the network provider if they have additional metadata labeling them as coming from a “cached” source rather than from the “server”. Additionally, I need to do a little more research and see if the circles I’m drawing really are representative of the reported accuracy – and if they are, it looks like I may need to ignore network provided location data all together…

##Next Steps

I think at this point I have a well enough working trail viewer. Now I need to get back to identifying the start and end of actual trips – at the moment I’m just arbitrarily cutting off trip files every 40 or so locations. I also need to make the program smart enough so that it polls the gps more often when the device is actually in motion, and less often between trips (when the device is relatively stationary). Those problems are more or less related since periods of rest are essentially the time to end one trip and start a new one.