geographic computation in perl
TRANSCRIPT
Geographic Computation in Perl
Presented by Ian KluftSilicon Valley PerlMarch 26, 2015
Santa Clara, California
Safety warningSafety warning
If you think the world is flat,this presentation will make your head explode.
We use geographic info all the time
● Maps on desktop/mobile● Car navigation● Traffic maps● Find local services
– Restaurants
– Shopping
– Auto shop
● Nearby social peeps● Find my car● Speedometer● Run/bike/walk map● Astronomy● Other web/mobile apps
Maps go way back
● Paper maps go back to ancient times● Electronic age: GPS makes mapping more accessible● Now every smartphone has a GPS receiver● There's more to GPS & maps than most people realize● Simplified public views try to hide the technical stuff● We're going to look at some of those details...
Coordinate systemLatitude and longitude
● Any position on Earth has a coordinate● 3-dimensional positioning uses 3 numbers
– Latitude (north/south)
– Longitude (east/west)
– Altitude (relative to mean sea level/MSL)
● Latitude & longitude are specified in degrees● Altitude is specified in distance
Latitude and longitudeWhat kind of degrees?
● Not from a university● Not related to temperature● They are angles!● More precisely, angles from
the center of the Earth● Latitude = 0-90° up or down● Longitude = 0-180° either
way around
Earth is not a perfect sphere
● Earth is an ellipsoid: bulges out at equator– Centrifugal force from rotation causes this
● Geoid: mathematical models for Earth ellipsoid– Good models come from satellite measurement
● Coordinates must use the same geographic reference system– Otherwise comparing apples and oranges
– WGS84 most widely used coordinate system today
● Sea level and altitude are relative to this model
Lots of angles in Geospatial Data
● Many computations involve angles– Latitude and longitude are angles
● Manipulations use trigonometric functions● Trig functions use radians
– So numbers in degrees must be converted to and from radians
– One circle = 360 degrees = 2 * pi radians
– Radians derive 2 * pi from distance around circle relative to radius
Great Circle Routes
● Great Circle: direct route over Earth's surface– Along a line that would go
around the sphere
– i.e. from San Jose to London crosses Greenland
– Flat-projection maps distort great circle routes to look like curves
Map generated by the Great Circle Mapper copyright © Karl L. Swartz. http://www.gcmap.com/
Great Circle Formulas
● See “Aviation Formulary” sitehttp://williams.best.vwh.net/avform.htm
● Distance between points● Course between points● Latitude of point on GC● Lat/lon given radial & dist● Intersection of 2 radials
● Max latitude of a GC● GC crossing a parallel● Intermediate points on a GC● Cross track error● Along track distance● Point known offset from GC
Great Circle Formula ExampleDistance between points
● From scratch:
d=acos(sin(lat1)*sin(lat2)+cos(lat1)*cos(lat2)*cos(lon1-lon2))
● In Perl:
use Math::Trig 'great_circle_distance';
$distance = great_circle_distance($theta0, $phi0, $theta1, $phi1, [, $rho]);
● Convert angles to radians, theta = longitude, phi = latitude● Rho is the radius of the Earth – use 6366.71 km
– Don't forget to convert result from km to miles if needed
Perl Modules
● Math::Trig – trigonometry and great circle functions● GPS::Babel – convert between GPS file formats● Geo::Formatter - encode & decode lat/lon strings● Geo::GNIS - parse USGS Geographic Names data● Geo::GPX - read & write GPX open GPS data files● Geo::Horizon - distance to visual horizon● Geo::IP - estimate lat/lon coordinates for IP address
Perl Modules (continued)
● Geo::Mercator - convert coordinates to flat-projection map● Geo::Weather - retrieve weather from Weather Channel● Ham::Locator – convert between lat/lon & maidenhead coords● Net::GPSD3 - interface to GPSD server on your laptop● Geo::Google::StaticMaps – Google Maps API wrapper● Geo::OSM::Tiles - OpenStreetMap tiles● And many, many more – go search CPAN!
Example 1CanSat Search at Black Rock Desert
Location: Black Rock Desert, Nevada
Problem: Rocket launched, payload missing● Soka University (Japan) students needed data● AeroPac club knew rocket landing coordinates● Turned to Stratofox Aerospace Tracking Team● Transmitter batteries died before their contact● I wrote a Perl script to generate a grid search
Perl Script to Plot Search Grid
● Search area was 3x3 mile parallelogram● Each side divided into 10 sections, 1584' long● 10x10 loop projects each computed waypoint● Command-line controls output to text or GPX● “gpsbabel” turns GPX into many formats
– Raw Garmin waypoint data for upload to GPS
– KML for display on Google Earth
Projecting Search Grid Waypoints
● Nested loop: i = 0-10 over, j = 0-10 up● Over = 270° heading, up = 330° heading● Convert lat/lon from degrees to radians● Use Great Circle projection formula
– Compute intermediate point from i “over”
– Compute final point from j “up”
● Convert new lat/lon from radians to degrees● Code available at svperl.org with slides
Sample codeconvert feet to radians
● Convert distance in feet to radians over Earth's surface# conversion: distance in feet to radians
sub dist_ft2rad
{
my $ft = shift;
my $km = $ft / 3280.8399; # ft/km
return $km/6371.0; # divide by FAI standard Earth radius in km
}
Sample codecompute waypoint from course & distance
sub gc_waypoint
{
my $lat1 = shift; # latitude (radians)
my $lon1 = shift; # longitude (radians)
my $tc = shift; # true course (radians)
my $d = shift; # distance (radians)
my $lat = asin(sin($lat1)*cos($d)+cos($lat1)*sin($d)*cos($tc));
my $dlon = atan2(sin($tc)*sin($d)*cos($lat1),cos($d)-sin($lat1)*sin($lat));
my $lon=fmod($lon1-$dlon+pi,2*pi) - pi;
return ( $lat, $lon ); # lat/lon in radians
}
Example codecompute coordinates of search grid point
# project a waypoint in the search area
# shape of a parallelogram with sides at headings 030 (NNE) and 090 (east)
# sides are on heading 1 (030 degrees) and heading 2 (090 degrees)
# increments are 0-10
# each increment is 1584 ft so that 10 of them is 3 miles
sub project_waypoint
{
my $h1_inc = shift;
my $h2_inc = shift;
# compute intermediate point on the first side of parallelogram
my ( $lat_r1, $lon_r1 ) = gc_waypoint (
deg2rad( $point_start[0]), deg2rad( $point_start[1]),
$h1_heading, $rad_per_increment * $h1_inc );
Example code (continued)compute coordinates of search grid point
# compute final projected waypoint in search area
my ( $lat_r2, $lon_r2 ) = gc_waypoint (
$lat_r1, $lon_r1,
$h2_heading, $rad_per_increment * $h2_inc );
# convert radians to degrees
my $lat = rad2deg( $lat_r2 );
my $lon = rad2deg( $lon_r2 );
return ( $lat, $lon );
}
Result: Success!!!
Expected to be worse than needle in a haystack
Payload found 2500' west of rocket landing site
Example 2Live APRS Balloon Tracking Map
Problem: Display APRS tracking data for a balloon and our team who are tracking it
● APRS = Automatic Packet Reporting System, Ham Radio data protocol for transmitting your position
● The balloon and the tracking team all transmit their positions via APRS every minute or so
● Sites to display APRS data on a map don't do what we want
APRS.FI posted their Perl code
● Popular APRS mapping site APRS.FI uses Perl● They posted Ham::APRS::FAP (“fabulous APRS parser”) on
CPAN for all Perl developers● You need Ham Radio license to transmit APRS● You do not need Ham Radio license to receive APRS data● Many volunteers forward APRS packets to APRS-IS servers on
the Internet● Everyone can subscribe to data streams there
Custom APRS Mapping Script
● Command-line parameter sets callsigns to log● Subscribe to APRS-IS via Ham::APRS::FAP● For each incoming line:
– Parse line w/ Ham::APRS::FAP
– Save data in a per-callsign list
– Update output file in GeoRSS format
● Output file URL can be used in near real-time as an input to Google Maps
● Unfortunately, Google Maps dropped GeoRSS in 2014 update
Balloon Chase on Google Maps
● A balloon on Feb 5, 2011 was lost in the ocean● Teams chased it until Carmel – others watched