Rusty's Blog

Thoughts and musings of someone who's not sure what 'normal' is…

Monday, August 24, 2009

DroidTrack – A tracks collector for Android phones.

Ok, first of all DroidTrack probably won’t be the final name for this collection of scripts. It would not surprise mi if someone els already had the name. That’s OK, we’ll work around that as the issue crops up.

This article will discuss a couple of methods for capturing location information and making it available.

If you went through college before Java became the popular Comp Sci language for writing programs in, you probably encountered Modula-II or earlier Pascal. Both are highly structured languages used to help teach structured programming. Lau has some similarities with Pascal. There are some good references out there, some of which have worked for me in the past.

I tend to write more in Python these days, and what I will present in a bit is more along those lines, but to show that most of this can be done in either Python or Lau, lets start with a sample of Lau.

require “android”
android.startLocating(“course”) –Obtain location from network.

android.sleep(5)  –Give the location sensor a moment to come online.

while true do
l = android.readLocation()
android.makeToast(“lat ” .. l.result.latitude .. “\nlon ” ..
l.result.longitude .. “\nalt ”  .. l.result.altitude)
android.sleep(5)
end

OK, starting with the first line. This is needed on every application that is going to interface with the Android phone.

The second line starts the locating intent. In othe words it tells the Android phone to start asking the network or the GPS receiver where the phone is and be ready to report it.

It takes a little bit of time for the service to kick in. For ‘network’ location that is because we are asking the cell phone towers to approximate where we are, and they simply take some time to get back to us. For the GPS receiver it is a bit more complicated. First the GPS receiver needs to determine what time it is. Oh, not in minutes and seconds, but at a much finer resolution. So it listens for GPS satelites and based on the time stamps that they are providing, determines approximately where all of them are relative to where the receiver is. That initial estimate gets the phone to within a certain distance of itself. Let’s estimate that to be the better part of a mile. Not really much help when trying to put us on a map, but it’s a start. Now that we have that estimate, the system improves the accuracy of the clock and gets a much tighter resolution of where it is on the globe (or above or below it.) This goes back and forth a few times. Ultimately using just this technique the GPS can estimate where it is to within about 80 feet. Well, that could put me on either side of this freeway. A major reason for this level of inaccuracy is that satelites do not have perfectly maintained orbits. So while we know that a sat is in orbit, it has a limited amount of accuracy involved as well. It may be hundreds of feet away from it’s predicted location.

Since we do like a little bit better resolution than that, they had to come up with a better way of getting an idea of where the satelites were so that we can get a better idea of where we are. The standard method of doing this is to use two GPS receivers, one at a fixed known location, that tells the mobile receiver what the inaccuracies are that the satellites are giving us. The problem is that this requires either a lot of extra hardware to get the two GPS receivers to talk to each other, it also requires that both GPS receivers work their location information out from the same satelites. That is not a given. Likewise this really only works when both receivers are seeing roughly the same sky. If you are over the horizon or around the world, you will probably see something different, in addition to having a bit of difficulty getting the current variation information.

The next best thing is to use a variation of this built into the GPS system. There are several satelites in orbit that provide ‘enhanced’ information to receivers that are designed to receive them. The enhanced information is part of a feature called WAAS – Wide Area Augmentation System. There are a collection of GPS receivers located on known locations that collect drift calculations for the satelites they ‘see’. This includes clock drift, and the like. That information is collected and sent to stations on both east and west coasts of the US, where the information is crunched and new calculations are made regarding where each satelite is in it’s orbit, as well as how far off from the standard time each clock actually is. A package of that information is sent to the enhanced capability satelites that then include it in their data stream. A WAAS enabled GPS receiver then uses that information to make improved calculations regarding it’s location. At best this gives a GPS receiver the ability to get their location to within a 2 foot circle, though on average 16 feet seems to be more common. (I’m at 45 degrees north, My experience is that the further south I get the better the accuracy is, and may get down to 5 feet or so near the equator, at which point I would suspect the resolution gets worse again.)

The big problem with GPS is that it requires a reasonably clear view of the sky. If you are in a building or in a metro area with lots of tall buildings. (Hey being in a canyon has an effect as well.) you can expect that GPS will not get you a usable location. As a result the Android phone, and most other 2nd generation and beyond phones also collect location information based on cell towers. Here the situation is a little bit different. Since the cell towers are not in orbit, and the phone is in contact with at least one, it can get an estimate of where it is by knowing what tower it is talking to, and the tower telling everyone where it is located. With 3G phones the phones are talking to multiple cell phone towers and can get an improved estimate of where it is by recognizin gthat it is probably somewhere between the cell phone towers that it can talk with. Also the phone can get some information based on how fast it gets a response from a tower. That said the accuracy is significantly lower than you see with good visibility of GPS satelites. However if I can figure out what block you are on, or what building you may be in, it makes getting emergency services to you that much easier.

So we’ve told the phone to start gathering location information, and we’ve put the application to sleep for 5 seconds for the phone to work out where it is. Let’s start a loop of what we want to do. That begins with ‘While True Do” and ends with”‘End”. (Purists will say that’s not like Pascal, where’s the ‘Begin’? I didn’t say it was pascal, just similar.)

Within the loop we need to do four things. Get the current location information, format what we want to present to user, present it, and go to sleep for some period of time. “l = android.readLocation()” does the first thing, putting it into a variable ‘l’. ‘l’ is a data structure with several blocks of information. We’re primarily interested in our longitude and latitude, which places us on the globe. In some cases we may be interested in our Altitude as well. So we’re going to construct a string: {lat ” .. l.result.latitude .. “\nlon ” .. l.result.longitude .. “\nalt ”  .. l.result.altitude} and wrap that up with a command to present it to the user, android.makeToast(). Finally we are going to let the script sleep again for 5 seconds.

Thank you to Shanjaq for the Lau script above. Lau also will alow you to ‘print’ the output. So if you want the output within the shell window, rather than as a pop-up that may obstruct whatever else you may be doing, you could replace ‘android.makeToast()” with “print()”.

As I say, I don’t know all that much Lau, and while it very likely is simple to edit and append files, I hadn’t originally started down that line. I tend to work in Pascal. ASE also support Ruby and BeanShell (not to be confused with BournShell or BournAgainShell) and both may also have similar capabilities.

So my script looks a bit different:

import android, string, time
droid = android.Android()
droid.startLocating()
time.sleep(10)
while 1:
  l = droid.readLocation()
  outstr = str(l['result']['longitude']) + ',' + strl['result']['latitude'])  + ',' + str(l['result']['altitude'])
  if l['result']['provider'] == 'network':
    droidfile = '/sdcard/droidtrack.cell'
  else:
    droidfile = '/sdcard/droidtrack.gps'
  fh = open(droidfile,'a')
  res= fh.write(outstr +'\n' )
  res = fh.close()
  time.sleep(10)

Note that you can see what the labels of each component of the data structure that droid.readLocation() provides by simply printing the result. so if ‘l = droid.readLocation()’ then you will get all the labels by doing ‘print l’ You may wish to modify the output based on what is in each portion. So for example I decided that it was important to distinguish between gps provided output and cell phone tower results. Cell phone provided results are taged with provider having a value of ‘network’. Since there are really only two ways that location information will be provided, that means that the alternative is ‘gps’.

Ok, there is also the possibility that all location information will be ‘wrong’ or ‘missing’. For the purposes of this script I’m not going to worry about those possibilities.

What I am looking for however is output in a csv format. Thats because I will be wrapping it up in a KML wrapper.

If you have been reading my earlier blogs, you might notice that you can also use resources on the internet to track this information. I can very likely make this script significantly more complex if I want to use those resources. As an example I can use xmpp to report my position to a jabber server where the information can update a “I’m located ‘here’” page if I wanted to do that. I could update the information with whether I was walking, riding the motorcycle, bicycle, do I have a radio with me, etc based on other parameters.

In APRS which is Amature Radio Positionin Reporting System, there is also a ‘smart beacon’ mode available. Currently this script tracks my position every 10 seconds, whether I’m traveling or not. That’s not quite enough data for OpenMap, but probably far more information than I need for APRS. One of the things to remember with APRS is that it is shared radio spectrum. Try not to monopolize it. Since there is more information I can work with here we can use some of the same rules that APRS uses. If I am stationary or moving at less than 5 miles per hour, a beaon every 30 minutes is probably sufficient. If I am moving from 5 miles per hour to 40 miles per hour, let’s give a position report every 10 min. Over 40 miles per hour once every 2 minutes. Since we also can see when those rates change, let’s grab a report any time we come to a full stop. Finally we probably want to know when our course changes. So if we see our bearing change by more than 15 degrees since the last time we had a bearing, we will send a report as well. If we want to be pedantic, we can also supress new bearing updates until we see a change in bearin gof less than 14 degres. That way we won’t send a report every second while we are navigating three right turns on the cloverleaf because we missed the right turn we needed to take earlier. It’s a feature we can add later.

So we start with the ‘speed’ option. This will give us a frequency of data collection of 30 min, 10 min or 2 min. :

getRate(speed):

if speed < 5:

rate=1800

else:

if speed < 40:

rate = 600

else:
rate = 120

return rate

Now we need a couple of functions to deal with major changes in speed, direction, etc. Conditions where we want to report new position information If speed crosses one of the thresholds for changing reporting, changes by more than 20 mph since the last report, or we come to a complete stop.

change_in_speed(old, new):

beacon = false

if (old = 0 and new <> 0) or (new = 0 and old <> 0) or (abs(old – new) > 20) or (old < 5 < new) or (old < 40 < new) or (new < 5 < old) or (new < 40 < old):

beacon = true

return beacon

How about a function to deal with change in bearing. This is a bit more interesting. First of all bearing is a number from 0 to 359. To do this we will set a ‘greater’ and a ‘lesser’ to compare. We then subtract the lesser from the greater. If the result is greater than 15, or less than 345 it’s time to beacon.

change_in_bearing(old,new)

if old < new:

lesser = old

greater = new

else:

lesser = new

greater = old

difference = greater – lesser

beacon = false

if (15 < difference < 345):

beacon = true

return beacon

Ok, as part of the loop we will set a counter, such that every second it is decremented by 1, we’ll start with 0 and any time we have a value of 0 we will send a beacon. So let’s use the ‘beacon_now’ variable to store this value in.

beacon_now = 0

while true:

l = droid.readLocation()

if beacon_now == 0:

Send_position_report(l['result']['longitude'], l['result']['latitude'] , l['result']['altitude'], l['result']['speed'], l['result']['bearing'])

beacon_now = getRate(l['result']['speed'])

oldPosition = l;  # Note that we only set this if we have had to beacon.

if change_in_speed(oldPosition['result']['speed'], l['result']['speed']):

beacon_now = 1

if change_in_bearing(oldPosition['result']['bearing'], l['result']['bearing']):

beacon_now = 1

beacon_now -= 1

time.sleep(1)

Now all we have to do is write the ‘Send_Position_Report()’ function. For that we can simply format a string and dump it to a text file. send an xmpp message to a tracking account, or update a twitter page.

I have taken a few liberties with the syntax for test in the change_in_speed() function. I will post an updated script as a comment. One thing I haven’t checked is how long it will take to run through the functions or comparisons. I suspect that if ASE converts this to bytecode that the response time should not be bad. Additionally I would suspect that some people will be looking for different threshods and rates. If you are a runner, you probably would not be all that pleased to get your rate of speed and location every 10 minutes. So perhaps you would rather set the rate to 120 for any speed over 5 mph. If you are a pilot, perhaps you want to set a threshold of 30 mph for ground speed, 200 for takeoff/landings and above that for cruising, with changes in speed of 50 mph to trigger track collection. You also may not be interested in getting samples as often at cruising speed as during takeoff and landings.

Ok, I’ve gone a bit affield of just a simple demonstration of how to get your location information to display on your phone. You may be looking to take this in an entirely different direction. If so, have a good time.

posted by Rusty at 11:04 pm  

Sunday, May 31, 2009

Radio Daze..

And I’ve determined at least part of what’s wrong with my APRS stuff in my car.

No, I won’t go into what APRS is, beyond saying it’s part of the amateur radio hobby. If you have found my blog, and you have questions, there are loads of resources that will tell you more than I am about to say. So go search and find. As some might say, the truth is out there.

In my car there’s a link from under my dash, to the trunk that provides a power conduit for my APRS tracker, gps and radio. A couple of months ago, the fuse blew. I replaced it, and it blew again. That can only mean a couple of things, neither of them really good.. Either something in my dash was blowing the fuse, or something in the  trunk, or on the way to the trunk. Sinc that was easier to ‘fix’, by clipping the lead to the trunk, I did that, replaced the fuse again, and happy dash. So something on the way to, or in the trunk is being a problem.

On rading how to get my position to show up for SkyWarn this week, and noticing the interest in possible watcher’s for this evening, I decided that today was the day to find and fix whatever is wrong with the APRS stuff in my trunk. And I may yet get something ‘working,’ though at the apparent expense of a radio that I wasn’t planning on replacing. Well, that’s why you make plans, so that life can alter them. Right?

Troubleshooting. Check the wire to the trunk. Not shorted between the leads. good conductivity end to end. Check.

APRS tracker? Check that’s working.

Spare battery from the trunk to power up the radio?  Well, not the best, but we’ve got something to work with. Check.

Plug the battery into the distribution system, Dead battery. Hmm. Ok, only thing I haven’t checked here separately was the radio. Pop the power cable for that off the distribution block. check draw across the leads, Short. Ok, that looks like where my problem is. What am I going to have to do to solve? Well, quick solution would be to hang the connector off a different radio, except that the connection for the APRS tracker to the radio was a custom job. I’ll just have to creat another custom I guess. So what radio? Well, the Quick and dirty solution is to use another radio already mounted in the trunk. It has the advantage of being right there. The disadvantage is that the wiring for the mike is diferent. And from a quick look at the drawings of the two connectors, while I could probably cobble together a quick sollution, that’s not the ‘right’ thing to do.

Why not? Well, that radio is in the trunk for a specific reason. That reason has nothingto do with APRS, and I don’t want to break things that way. So, using that radio is ‘out.’ Even if it is possible.

Long term I want a different radio in there any way, and now is the time to build that up. Of course now I have to dig up the specs for setting that radio up for APRS. That’s not particularly difficult, as I have already done some stuff like that, it’s just going to take a bit of soldering, and waiting until I have a connector of the appropriate type for that radio. There is one already here some place, and I’ll spend a bit of time looking yet tonight, but I suspect that I will have to wait till I can gt to the hardware store tomorrow for the final solution. We’ll see.

More to follow.

posted by Rusty at 9:43 pm  

Monday, April 27, 2009

Iron Man Bike Ride, 2009

This past Sunday I helped with the operations of the Iron Man Bike Ride in Lakevill, MN. Things didn’t go quite as planned. It wasn’t a complete failure byb any means, but it was obvious from early in the day that the weather could have been a lot more cooperative And then some.

As for myself, I knew I wouldn’t be in quite as early as I would like to have been. My work schedule is such that Saturday night I got to work at 7:00 PM to work through till 7:00 am Sunday morning. If this were any other company, I would have asked for and gotten a vacation day, but someone decided that my employer should run the department I’m a part of at the bare minimum, and if someone want’s a weekend off they can just trade with someone else for it. Well, considering what I do at the moment, that would be a bit rough, as the people I might trade withare not as ready or interested in trading as we would like. So it didn’t happen. I hear some good things are in the works related to that for the future, but I’ll wait and see on those changes.

In any case, as I was walking from my car to work Saturday night I rememberd that I had not put my HT on the charger before I left for work. While the battery was not dead by any means, it was far from being as fully charged as I would have liked. Where I was going Sunday is notorious for having bad radio coverage. They added a new repeater this year, which provided somewhat better coverage, but it ws still far from perfect.

In fact I ended up setting up a radio in my car as a cross-band repeater. I need to add a small box to my trunk now to add in an ider for when I do that. As it was, I picked the same repeater, and a non-local repeater pair on a different band, and set the radio in the car on the second band to reverse the rx/tx pair on that band so that I didn’t need to do anything ‘strange’ on my HT. With the exception of when another radio was in the area using the same repeaer, I pretty much had no problems at all on the net. I’ve heard a few people crossbanding, and all you end up with is the low frequencies, or something like that. In my case I was very happy with the results, and heard no complaints on my transmitions.

One of the things that we do at the rest stop is take down the rider numbers for any rider who drops out of the event. While there are riders who treat the event as a race, you’ll not that this is not a triathalon, and ‘race’ is not in the name of the event. The vast majority of the riders are in it simply to demonstrate to themselves that they can. And when it comes down to it, a surprising number of riders can ride 100 miles. (162 km for the rest of the world.)

The stop I was supporting is at the 70 mile mark for the 100 mile route. as a quick estimate, I would say that between 200 and 300 riders passed through the station and about 40 riders dropped out there. The number of people who dropped out is easier to estimate, simply because we had to report the rider number for each rider who dropped out. That number goes back to our network control operator, who passes the number on to the ride officials who can use that number to let friends and family members of the rider know where the rider is if they drop out. This also helps to prevent any uniquely identifiable information about the rider becoming known by people not involved in the ride. This is done for most races and events where Amature Radio operators are involved.

One problem that occasionally comes up is where one person reports a number, and the next person in the chain notes that that number isn’t in their list of numbers to report. So one or the other person has invalid information. I’m not really sure what can be done about that, but one of the things that I would like to see is an improvement in the reporting process. Riders should be able to present their rider number in a way that is pretty much self confirming. We’re getting close. Bar codes migh do it, or some form of RFID as runners use in marathons. However even those present problems with disapearing and the like. So we do the best that we can.

And we are looking at making improvements. A few years back APRS got to a point where it is inexpensive enough that almost any ham (amateur operator) can add the equipment to their car that allows them to show exactly where they are. Likewise the hardware is portable enough that you can set up a vehicle temporarily so that it can be tracked at any time.

So for events like the Iron Man Bike ride, it makes sense to add a tracker to support vehicles.

One of the things that can be done with the same service however is to be able to send other messages. Location information is simply numbers. Usually it is the latitude and longitude with an accuracy down to about 20 feet. There is no reaso to restrict the content of a transmission to location information though, another option would be to send the rider numbers via APRS.

One of the reasons that we were so busy with reporting rider numbers this year was the weather. At least one rider declared that he could handle the cold, and he could handle the rain, but the combination was just too much. We badly needed the rain, and I agree that if the temperature had been similar to that of the previous week, it would have been a very different situation.

For some 4 hours (and then a bit) I helped provide information to riders and get help for riders as well. I finally was able to get to sleep last night a bit after 9 pm. All in all, I think it was a good day.

posted by Rusty at 10:53 pm  

Powered by WordPress