Sat 2 Sep 2006
infer latitude and longitude from cell id and the FCC database
Posted by joeldg under coding , phones , serverThe problem: Most current cell phones (except exceptionally new ones) do not come with built in GPS devices. Phones do however connect to radio towers within range, which broadcast ID’s. I am interested to determine if there is an easier way to generate lat/long location from radio towers, instead of using a bluetooth GPS device, by using inference from publically accessible data and geocoding, combined with the cell tower ID broadcast to my phone.
In many countries the latitude and longitude of cell towers is public data. In the US it is public sort of, when registering with FCC, the companies do not need to register the broadcast cell-id which is transmitted to the phones. To make matters more complex, different cell companies can broadcast different ID’s from the same towers. From this, many different projects have popped up to attempt to map cell-id to latitude and longitude. They work, I assume, to refine the results for each tower. The good news is, is that the FCC being a public entity is bound by the freedom of information act and must publish (even in a nasty form) it’s data. The FCC provides a large database of the exact location of towers, but we just don’t know what those towers are called and who uses them.
The idea here is that we can make some educated guesses in an attempt to refine the FCC data with what little information we are given by the tower itself and some simple server-side geocoding. Basically we are going hack the cell-id’s ‘into’ the FCC data, which we must assume will have missing towers and incomplete data as the requirement to register a tower only applies to certain tower types and array heights.
If you read my post about working with lat/long pairs in mysql and doing great circle searches, then you may find the following code snippets interesting as it is to work with doing computation on latitude and longitude. I worked these out by porting some and reading some math forums, they will come in handy for inferring my location in proximity of cell towers.
First we have a few support functions, converting to radians, and converting between lat/long types (Degree/minute/second format to degree’s and back):
function rad($v){
return ($v*M_PI/180);
}
/*
degree,minute,seconds to decimal degrees
note: this could also be done in a single line using ternary
*/
function dms2deg($D,$M,$S,$dir){
if(strpos(‘ WsSs’, $dir)>0){
return(-1 * ($D + ($M + $S/60)/60));
}else{
return($D + ($M + $S/60)/60);
}
}
function dms($rad) {
$d = abs($rad * 180 / M_PI);
$d += 1/7200; // add ½ second for rounding
$deg = floor($d);
$min = floor(($d-$deg)*60);
$sec = floor(($d-$deg-$min/60)*3600);
// add leading zeros if required
if ($deg< 100) $deg = ‘0′ + $deg;
if ($deg< 10) $deg = ‘0′ + $deg;
if ($min< 10) $min = ‘0′ + $min;
if ($sec< 10) $sec = ‘0′ + $sec;
return $deg + ‘\u00B0′ + $min + ‘\u2032′ + $sec + ‘\u2033′;
}
These are used in the following functions. First one thing we must have the ability to do is to determine the distance between two points on the map. We can use the following PHP function to do this:
/*
distance between two points using sherical law of cosines
cos c = cos a cos b + sin a sin b cos C
*/
function distance($lat1, $lon1, $lat2, $lon2, $units = ‘miles’){
$lat1 = rad($lat1); $lon1 = rad($lon1);
$lat2 = rad($lat2); $lon2 = rad($lon2);
switch ($units){
case “miles”: $r = 3963.1; break;;
case “nmiles”: $r = 3443.9; break;;
case “kilo”: $r = 6378; break;;
}
// this is another way to do it
#$rv = pi()/180;
#$a1 = $lat1 * $rv; $b1 = $lon1 * $rv;
#$a2 = $lat2 * $rv; $b2 = $lon2 * $rv;
#return (acos(cos($a1)*cos($b1)*cos($a2)*cos($b2) + cos($a1)*sin($b1)*cos($a2)*sin($b2) + sin($a1)*sin($a2)) * $r);
return acos(sin($lat1)*sin($lat2) + cos($lat1)*cos($lat2)*cos($lon2-$lon1)) * $r;
}
Next, it would be helpful to know the bearing from one point to another point.
/*
initial bearing from point 1 to point 2
*/
function bearing($lat1,$lon1, $lat2, $lon2) {
$y = sin($lon2-$lon1) * cos($lat2);
$x = cos($lat1)*sin($lat2) - sin($lat1)*cos($lat2)*cos($lon2-$lon1);
return atan2($y, $x);
}
We also would like to be able to find the exact midpoint between two points,
/*
find out what the midpoint between two points is
*/
function midpoint($lat1, $lon1, $lat2, $lon2) {
$lat1 = rad($lat1); $lon1 = rad($lon1);
$lat2 = rad($lat2); $lon2 = rad($lon2);
$dLon = $lon2 - $lon1;
$Bx = (cos($lat2) * cos($dLon));
$By = (cos($lat2) * sin($dLon));
$lat3 = atan2( sin($lat1) + sin($lat2), sqrt( (cos($lat1)+$Bx) * (cos($lat1)+$Bx) + ($By * $By)) );
$lon3 = $lon1 + atan2($By, cos($lat1) + $Bx);
if (!$lat3 || !$lon3) return false;
return array($lat3 * 180 / M_PI, $lon3 * 180 / M_PI);
}
Now that we can have some functions to work lat/long pairs we need to see how to put things together. I am going to use the following image to help explain some concepts first:

POINT 1, central park: We can see cell tower “a”, we geocode our location and mark down in the database that tower “a” is within range of the geocoded location we are at, all is good, and this is about as far as anyone has gotten so far. We run a great circle search from our location and mark the towers near us with the cell-id “a” and also make a note of the signal strength.
POINT 2, west side : We pick up an unknown tower “D” we mark it down along with a geocoded location, we also pick up “a” again and mark it again, along with signal strength and provide towers within our great circle the cell-id info. This helps refine ‘a’ but we assume we are further out as the signal strength is lower.
POINT 3, hells kitchen: we now pick up another tower “b” which we can mark in the database, we also pick up “a” within this, however both have low signal strength, we mark both with the cell-id’s and signal strength. And we can figure that we are about halfway between ‘a’ and ‘b’ we can also make some guesses about direction being travelled by using our current point along with current cell and more than one reading.
POINT 4, West village: Now we only have tower “b”, we mark this tower known with strength and it is known so again we are just confirming it’s presence.
POINT 5, Fulton street: again we have a known tower ‘c’, we mark it along with the signal strength, our prior mark was with tower ‘b’ we can infer by signal strength and our prior location that we should be about halfway between ‘b’ and ‘c’
A lot of this data can be refined as we go, but as you can see, with only a few real points and a few cell towers we can gather a lot of location data, also, we can keep a live map of our locations and where we have travelled. In some areas we can get location to within a reasonable degree that we could zoom a map to street level close by.
In an area such as Manhattan with the intense cell coverage, we can quickly refine our location to a reasonable area and pinpoint which row in the FCC database cooresponds to which cell-id by just walking around for a few minutes. In more rural areas this might be a slightly more interesting problem, but if you mark your headings as you travel we could even determine your location on the map by your speed and bearing.
September 3rd, 2006 at 10:31 am
[…] infer latitude and longitude from cell id and the FCC database […]
QuoteSeptember 5th, 2006 at 5:46 am
[…] [Geowanking] Some location inference. [Geowanking] Some location inference. Joel De Gan joeldg at gmail.com Mon Sep 4 17:53:25 UTC 2006 Previous message: [Geowanking] IP Address geocoding Next message: [Geowanking] Some location inference. Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] Hi all.. I am a lurker, but thought you might be interested in a post I made about using the FCC database of registered (and applied) cell towers for use in making some guesses about which tower is associated with which cell id. http://blog.peoplesdns.com/archives/34 Just some ideas and php code I am throwing around to figure out how an average cell user (sans gps) can be located. — Joel De Gan coder, linux - php, python http://blog.peoplesdns.com Previous message: [Geowanking] IP Address geocoding Next message: [Geowanking] Some location inference. Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] More information about the Geowanking mailing list […]
QuoteSeptember 7th, 2006 at 7:52 am
[…] infer […]
QuoteSeptember 8th, 2006 at 5:26 am
Unfortunately FCC database is somewhat incomplete. Read http://www.towermaps.com/fcc.htm
QuoteSeptember 17th, 2006 at 9:32 pm
[…] FCC Cell Phone Tower Locations joeldg writes "I wrote an article about utilizing the FCC database of known tower locations and how to infer the cell ID’s of those towers based on a small number of geocoded points around those towers. This is a different approach than just using fixed points within range of a tower in that we identify the exact location of the tower which is broadcasting a cellid." http://blog.peoplesdns.com/archives/34 […]
QuoteSeptember 21st, 2006 at 8:21 am
Original post: infer latitude and longitude from cell id and the FCC database by at Google Blog Search: mark down Pages: Start 1 2 3 4 5 6 7
QuoteSeptember 27th, 2006 at 4:28 pm
[…] Hi all.. I am a lurker, but thought you might be interested in a post I made about using the FCC database of registered (and applied) cell towers for use in making some guesses about which tower is associated with which cell id. http://blog.peoplesdns.com/archives/34 Just some ideas and php code I am throwing around to figure out how an average cell user (sans gps) can be located. — Joel De Gan coder, linux - php, python http://blog.peoplesdns.com _______________________________________________ Geowanking mailing list Geowanking@lists.burri.to http://lists.burri.to/mailman/listinfo/geowanking […]
QuoteJuly 11th, 2007 at 4:33 pm
I receive a great number of inquiries to my website from individuals looking to acquire cell site location data. Unfortunately, the data is available only from data integrators who have contracts with the wireless carriers. There are some interesting projects whereby people have tracked either visually or electronically the strength and location of GSM cell sites including the cell-id.
QuoteSeptember 19th, 2007 at 9:48 pm
[…] Joel De Gan wrote about matching this data up with the FCC records, but I’m not convinced that’s necessary. I think the fingerprinting approach would be better. Simply store the raw readings of cell tower ID and signal strength mapped to locations, and use a little AI to intelligently infer your unknown location from known cell IDs and signal strengths. This could take into account interference from buildings, mountains, etc, rather than try to map out every single cell tower then perform the triangulation. Actual triangulation using signal strength would assume every tower has identical antennas and transmit power, and is uniform 360 degrees around. […]
QuoteOctober 28th, 2007 at 10:08 pm
read more
QuoteJanuary 11th, 2008 at 7:01 pm
[…] But that doesn’t really help too much for writing code… I know I could figure it out, but when Joel De Gan has already figured it out and published his code, why not use that? […]
QuoteFebruary 12th, 2008 at 7:18 am
cell phone gps…
umm it really depends….
QuoteFebruary 19th, 2008 at 6:43 am
[…] […]
QuoteMay 8th, 2008 at 10:16 pm
Could they be combined? Presumably they work whether or not you’re roaming? And in the USA cell tower locations are supposed to be in the public domain, although without the IDs the operators assign this isn’t the complete solution (see theNavigating the Surface blogfor some ideas around how to fill in that last gap). Of course knowing which cell towers the phone can see can’t be done from a mobile web page (can it?), but if you’re willing to create a downloadable app then this is a solution.
Quote