summaryrefslogtreecommitdiff
path: root/scripts/osm/perl_lib/Geo/Tracks
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/osm/perl_lib/Geo/Tracks')
-rw-r--r--scripts/osm/perl_lib/Geo/Tracks/GpsBabel.pm82
-rw-r--r--scripts/osm/perl_lib/Geo/Tracks/Kismet.pm125
-rw-r--r--scripts/osm/perl_lib/Geo/Tracks/NMEA.pm373
-rw-r--r--scripts/osm/perl_lib/Geo/Tracks/TRK.pm143
-rw-r--r--scripts/osm/perl_lib/Geo/Tracks/Tools.pm395
5 files changed, 1118 insertions, 0 deletions
diff --git a/scripts/osm/perl_lib/Geo/Tracks/GpsBabel.pm b/scripts/osm/perl_lib/Geo/Tracks/GpsBabel.pm
new file mode 100644
index 0000000..a531694
--- /dev/null
+++ b/scripts/osm/perl_lib/Geo/Tracks/GpsBabel.pm
@@ -0,0 +1,82 @@
+##################################################################
+package Geo::Tracks::GpsBabel;
+##################################################################
+
+use Exporter;
+@ISA = qw( Exporter );
+use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION);
+@EXPORT = qw( read_track_GpsBabel );
+
+use strict;
+use warnings;
+use IO::File;
+
+use Geo::Geometry;
+use Utils::File;
+use Utils::Math;
+use Utils::Debug;
+use Geo::GPX::File;
+
+
+# -----------------------------------------------------------------------------
+# Read GPS Data with the help of gpsbabel converting a file to a GPX-File
+sub read_track_GpsBabel($$) {
+ my $filename = shift;
+ my $gpsbabel_type = shift;
+
+ my $data = {
+ filename => $filename,
+ tracks => [],
+ wpt => [],
+ };
+
+ printf STDERR ("Reading $filename\n") if $VERBOSE>1 || $DEBUG;
+ printf STDERR "$filename: ".(-s $filename)." Bytes\n" if $DEBUG;
+
+ my $gpsbabel_call="gpsbabel -i $gpsbabel_type -f '$filename' -o gpx -F - ";
+ printf STDERR "calling gpsbabel:\n$gpsbabel_call\n " if $DEBUG>3;
+ my $fh = IO::File->new("$gpsbabel_call |");
+ if ( !$fh ) {
+ warn "Cannot Convert $filename as Type $gpsbabel_type\n";
+ return $data;
+ }
+ $data = read_gpx_file($fh);
+ $data->{filename} = $filename;
+ return $data;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+GpsBabel.pm
+
+=head1 COPYRIGHT
+
+Copyright 2006, Jörg Ostertag
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+=head1 AUTHOR
+
+Jörg Ostertag (planet-count-for-openstreetmap@ostertag.name)
+
+=head1 SEE ALSO
+
+http://www.openstreetmap.org/
+
+=cut
diff --git a/scripts/osm/perl_lib/Geo/Tracks/Kismet.pm b/scripts/osm/perl_lib/Geo/Tracks/Kismet.pm
new file mode 100644
index 0000000..e62fc2e
--- /dev/null
+++ b/scripts/osm/perl_lib/Geo/Tracks/Kismet.pm
@@ -0,0 +1,125 @@
+##################################################################
+package Geo::Tracks::Kismet;
+##################################################################
+
+use Exporter;
+@ISA = qw( Exporter );
+use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION);
+@EXPORT = qw( read_kismet_file );
+
+use strict;
+use warnings;
+
+use Math::Trig;
+use Date::Parse;
+use Data::Dumper;
+
+use Data::Dumper;
+use Geo::Geometry;
+use Utils::Debug;
+use Utils::File;
+use Utils::Math;
+
+# -----------------------------------------------------------------------------
+# Read GPS Data from Kismet File
+sub read_kismet_file($) {
+ my $filename = shift;
+
+ my $start_time=time();
+
+ my $data = {
+ filename => $filename,
+ tracks => [],
+ wpt => [],
+ };
+
+ printf STDERR ("Reading $filename\n") if $VERBOSE>1 || $DEBUG;
+ printf STDERR "$filename: ".(-s $filename)." Bytes\n" if $DEBUG;
+
+ print STDERR "Parsing file: $filename\n" if $DEBUG;
+ my $p = XML::Parser->new( Style => 'Objects' ,
+ );
+
+ my $fh = data_open($filename);
+ return $data unless $fh;
+ my $content = [{Kids => []}];
+ eval {
+ $content = $p->parse($fh);
+ };
+ if ( $@ ) {
+ warn "$@Error while parsing\n $filename\n";
+ printf STDERR Dumper(\$content);
+ #return $content->[0]->{Kids};
+ }
+ if (not $p) {
+ print STDERR "WARNING: Could not parse osm data\n";
+ return $data;
+ }
+ if ( $DEBUG ) {
+ printf STDERR "Read and parsed $filename";
+ print_time($start_time);
+ }
+ my $track=[];
+ for my $elem ( @{$content->[0]->{Kids}} ) {
+ next unless ref($elem) eq "Geo::Tracks::Kismet::gps-point";
+ next unless $elem->{'bssid'} eq 'GP:SD:TR:AC:KL:OG';
+ delete $elem->{Kids};
+ if ( defined($elem->{"time-sec"}) && defined($elem->{"time-usec"}) ) {
+ $elem->{time} = $elem->{"time-sec"}+($elem->{"time-usec"}/1000000);
+ #printf STDERR "$elem->{time} = $elem->{'time-sec'} $elem->{'time-usec'}\n";
+ }
+ delete $elem->{'time-sec'};
+ delete $elem->{'time-usec'};
+ delete $elem->{'bssid'};
+ delete $elem->{'signal'};
+ delete $elem->{'quality'};
+ delete $elem->{'noise'};
+ $elem->{'speed'} = delete($elem->{'spd'}) * 1;
+ if ( $DEBUG > 10 ) {
+ printf STDERR "read element: ".Dumper(\$elem);
+ }
+ push(@{$track},$elem);
+ };
+
+# printf STDERR Dumper(\$track);
+
+ $data->{tracks}=[$track];
+ return $data;
+}
+
+1;
+
+
+__END__
+
+=head1 NAME
+
+Kismet.pm
+
+=head1 COPYRIGHT
+
+Copyright 2006, Jörg Ostertag
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+=head1 AUTHOR
+
+Jörg Ostertag (planet-count-for-openstreetmap@ostertag.name)
+
+=head1 SEE ALSO
+
+http://www.openstreetmap.org/
+
+=cut
diff --git a/scripts/osm/perl_lib/Geo/Tracks/NMEA.pm b/scripts/osm/perl_lib/Geo/Tracks/NMEA.pm
new file mode 100644
index 0000000..7cbb665
--- /dev/null
+++ b/scripts/osm/perl_lib/Geo/Tracks/NMEA.pm
@@ -0,0 +1,373 @@
+##################################################################
+package Geo::Tracks::NMEA;
+##################################################################
+
+use Exporter;
+@ISA = qw( Exporter );
+use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION);
+@EXPORT = qw( read_track_NMEA );
+
+use strict;
+use warnings;
+
+use Data::Dumper;
+use Date::Manip;
+use Date::Parse;
+use IO::File;
+use Math::Trig;
+
+use Geo::Geometry;
+use Utils::Debug;
+use Utils::File;
+use Utils::Math;
+
+# -----------------------------------------------------------------------------
+# Read GPS Data from NMEA - File
+sub read_track_NMEA($) {
+ my $filename = shift;
+
+ my $start_time=time();
+
+ my $new_tracks={
+ filename => $filename,
+ tracks => [],
+ wpt => []
+ };
+ printf STDERR ("Reading $filename\n") if $VERBOSE || $DEBUG;
+ printf STDERR "$filename: ".(-s $filename)." Bytes\n" if $DEBUG;
+
+ my $fh = data_open($filename);
+ return $new_tracks unless $fh;
+ my $elem ={};
+ my $last_date='';
+ my $last_time=0;
+ my $new_track=[];
+ my ($sat,$pdop,$hdop,$vdop,$sat_count);
+ my $sat_time = 0;
+ my $dop_time = 0;
+ my $IS_grosser_reiseplaner=0;
+ while ( my $line = $fh->getline() ) {
+ my ($dummy,$type,$time,$status,$lat,$lat_v,$lon,$lon_v,$speed,$alt);
+ my ($date,$mag_variation,$checksumm,$quality,$alt_unit);
+ $alt=0;
+ chomp $line;
+
+ my $full_line = $line;
+
+ $IS_grosser_reiseplaner++ if $line =~ m/Logfile for travel center/;
+
+ # Grosser Reisseplaner Line:
+ # 16.08.06 15:47:23 GPGGA,134851.835,4807.8129,N,01136.6276,E,1,04,12.8,815.8,M,47.5,M,0.0,0000*42
+ if ($IS_grosser_reiseplaner){
+ if ( $line !~ s/^\d\d\.\d\d.\d\d \d\d:\d\d:\d\d GP/\$GP/ ) {
+ printf STDERR "ERROR in Grosser Reiseplaner: $full_line\n"
+ if $DEBUG>1;
+ next;
+ };
+ }
+
+
+ # Checksumm is at line-end: for example *EA
+ if ( $line =~ s/\*([\dABCDEF]{2})\s*$// ){
+ $checksumm=$1;
+ } else {
+ print "WARNING Checksumm is missing\n";
+ printf STDERR "Line: $full_line\n"
+ if $DEBUG>1;
+ next;
+ }
+
+ # Destinator Line: 160849.006,A,4606.6122,N,01819.4709,E,047.1,074.2,290705,003.1,E*6C^M
+ if ( $line =~ m/^\d+\.\d+,A,\d+\.\d+,[NS],\d+\.\d+,[EW],\d+\.\d+,\d+\.\d+,\d+,\d+\.\d+,(\S+)$/){
+ $type = "RMC";
+ } else {
+ ($type,$line) = split( /,/,$line,2);
+ }
+ $type =~ s/^\s*\$?//; # TomTom GO logger is missing the $ sign this is the reason for \$?
+ if ( $type !~ s/^GP// ){
+ print "WARNING Type is wrong: $type\n";
+ printf STDERR "Line: $line\n"
+ if $DEBUG>1;
+ next;
+ }
+ my $count_line=$line;
+ $count_line =~ s/[^,]//g;
+ my $elem_count = length($count_line);
+ printf STDERR "Type: $type, line: $line, checksumm:$checksumm, elem#: $elem_count\n"
+ if $DEBUG>4;
+
+ my $elem_soll ={
+ GGA => 13,
+ RMC => 10,
+ GSA => 16,
+ GSV => 18,
+ VTG => 7,
+ GLL => 5,
+ ZDA => 5,
+ };
+
+ if ( $type =~ m/RMC/ && ( $elem_count != 10 ) && ( $elem_count != 11 ) ){
+ print "!!!!!!! ERROR $elem_count is wrong Number of elements(should be $elem_soll->{$type}): $full_line\n";
+ next;
+ } elsif ( $type !~ m/GSV|GSA/ && $elem_count != $elem_soll->{$type} ){
+ print "!!!!!!! ERROR $elem_count is wrong Number of elements(should be $elem_soll->{$type}): $full_line\n";
+ next;
+ }
+
+
+ if ( $type eq "VTG" ) {
+ } elsif ( $type eq "GGA" ) {
+ # GGA - Global Positioning System Fix Data
+ # Time, Position and fix related data fora GPS receiver.
+ # 1 2 3 4 5 6 7 8 9 10 | 12 13 14 15
+ # | | | | | | | | | | | | | | |
+ # $--GGA,hhmmss.ss,llll.ll,a,yyyyy.yy,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx*hh<CR><LF>
+ # 1) Universal Time Coordinated (UTC)
+ # 2) Latitude
+ # 3) N or S (North or South)
+ # 4) Longitude
+ # 5) E or W (East or West)
+ # 6) GPS Quality Indicator, 0 - fix not available, 1 - GPS fix, 2 - Differential GPS fix
+ # 7) Number of satellites in view, 00 - 12
+ # 8) Horizontal Dilution of precision
+ # 9) Antenna Altitude above/below mean-sea-level (geoid)
+ # 10) Units of antenna altitude, meters
+ # 11) Geoidal separation, the difference between the WGS-84 earth
+ # ellipsoid and mean-sea-level (geoid), "-" means mean-sea-level below ellipsoid
+ # 12) Units of geoidal separation, meters
+ # 13) Age of differential GPS data, time in seconds since last SC104
+ # type 1 or 9 update, null field when DGPS is not used
+ # 14) Differential reference station ID, 0000-1023
+ # 15) Checksum
+ ($time,$lat,$lat_v,$lon,$lon_v,$quality,$dummy,$dummy,$alt,$alt_unit,
+ $dummy,$dummy,$dummy)
+ = split(/,/,$line);
+ printf STDERR "GGA: (time: $time, la: $lat,$lat_v, lo: $lon,$lon_v, Q: $quality, Alt: $alt,$alt_unit)\n"
+ if $DEBUG>4;
+ } elsif ( $type eq "RMC" ) {
+ # RMC - Recommended Minimum Navigation Information
+ # 1 2 3 4 5 6 7 8 9 10 11|
+ # | | | | | | | | | | | |
+ # $--RMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,xxxx,x.x,a*hh<CR><LF>
+ # 1) UTC Time
+ # 2) Status, V = Navigation receiver warning
+ # 3) Latitude
+ # 4) N or S
+ # 5) Longitude
+ # 6) E or W
+ # 7) Speed over ground, knots
+ # 8) Track made good, degrees true
+ # 9) Date, ddmmyy
+ # 10) Magnetic Variation, degrees
+ # 11) E or W
+ # 12) Checksum
+ ($time,$status,$lat,$lat_v,$lon,$lon_v,$speed,$dummy,$date,$mag_variation)
+ = split(/,/,$line);
+ printf STDERR "RMC: (Time: $time,Status: $status, la: $lat,$lat_v, lo: $lon,$lon_v, Speed: $speed)\n"
+ if $DEBUG >4;
+ } elsif ( $type eq "GSA" ) {
+ # GSA - GPS DOP and active satellites
+ # 1 2 3 14 15 16 17 18
+ # | | | | | | | |
+ # $--GSA,a,a,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x.x,x.x,x.x*hh<CR><LF>
+ # Field Number:
+ # 1) Selection mode
+ # 2) Mode
+ # 3) ID of 1st satellite used for fix
+ # ...
+ # 14) ID of 12th satellite used for fix
+ # 15) PDOP in meters
+ # 16) HDOP in meters
+ # 17) VDOP in meters
+ # 18) checksum
+ ($dummy,$dummy,$dummy,$dummy,$dummy,$dummy,$dummy,$dummy,$dummy,$dummy,
+ $dummy,$dummy,$dummy,$dummy,$pdop,$hdop,$vdop)
+ = split(/,/,$line);
+ $hdop = undef unless $hdop =~ m/[\d\-\+]+/;
+ $vdop = undef unless $vdop =~ m/[\d\-\+]+/;
+ $pdop = undef unless $pdop =~ m/[\d\-\+]+/;
+ $dop_time=$last_time;
+ next;
+ } elsif ( $type eq "GSV" ) {
+ # GSV - Satellites in view
+ #
+ # 1 2 3 4 5 6 7 n
+ # | | | | | | | |
+ # $--GSV,x,x,x,x,x,x,x,...*hh<CR><LF>
+ # Field Number:
+ # 1) total number of messages
+ # 2) message number
+ # 3) satellites in view
+ # 4) satellite number
+ # 5) elevation in degrees
+ # 6) azimuth in degrees to true
+ # 7) SNR in dB
+ # more satellite infos like 4)-7)
+ # n) checksum
+ my ($msg_anz,$msg_no,$rest);
+ ($msg_anz,$msg_no,$sat_count,$rest) = split(/,/,$line,4);
+ $msg_anz = 20 if $msg_anz>20;
+ $sat={} if $msg_no == 1;
+ #printf STDERR "# of Messages: $msg_anz; rest: '$rest'\n";
+ while ( defined $rest && $rest =~ m/,/) {
+ #printf STDERR "# $count: $rest\n";
+ my ($sat_no,$sat_ele,$sat_azi,$sat_snr);
+ ($sat_no,$sat_ele,$sat_azi,$sat_snr,$rest) = split(/,/,$rest,5);
+ #printf STDERR "($sat_no,$sat_ele,$sat_azi,$sat_snr)\n";
+ last unless defined ($sat_no) && defined($sat_ele) && defined($sat_azi) && defined($sat_snr);
+ $sat->{$sat_no}->{ele} = $sat_ele;
+ $sat->{$sat_no}->{azi} = $sat_azi;
+ $sat->{$sat_no}->{snr} = $sat_snr;
+ }
+ $sat_time = $last_time;
+ #printf STDERR Dumper(\$sat);
+ next;
+ } else {
+ printf STDERR "Ignore Line $type: $full_line\n"
+ if $DEBUG>6;
+ next;
+ };
+
+ next unless defined( $lat) && ($lat ne "" )&& defined( $lon) && ($lon ne "");
+ next if ($lat eq "0000.0000" ) && ($lon eq "00000.0000");
+ if ( $lat =~ m/(\d\d)(\d\d.\d+)/) {
+ $lat = $1 + $2/60;
+ } else {
+ printf STDERR "Error in lat: '$lat'\nLine: $full_line\n";
+ next;
+ }
+ if ($lon =~ m/(\d+)(\d\d\.\d+)/){
+ $lon = $1 + $2/60;
+ } else {
+ printf STDERR "Error in lon: '$lon'\nLine: $full_line\n";
+ next;
+ }
+ $lat = -$lat if $lat_v eq "S";
+ $lon = -$lon if $lon_v eq "W";
+ printf STDERR "type $type (time:$time lat:$lat lon:$lon alt:$alt speed:$speed)\n"
+ if $DEBUG>5;
+ if ( ( abs($lat) < 0.001 ) &&
+ ( abs($lat) < 0.001 ) ) {
+ printf STDERR "too near to (0/0) : type $type (time:$time lat:$lat lon:$lon alt:$alt speed:$speed)\n";
+ next;
+ };
+
+ $time =~ s/^(..)(..)(..)/$1:$2:$3/;
+ if ( defined($date)) {
+ $date =~ s/^(..)(..)(..)/20$3-$2-$1/;
+ } else {
+ $date = $last_date;
+ }
+ $last_date=$date;
+ $time = str2time("$date ${time}");
+ $last_time = $time if $time;
+
+ if ( defined $elem->{time} &&
+ defined $elem->{lat} &&
+ defined $elem->{lon} &&
+ ($elem->{time} != ($time||0)) ) { # We have a new Timestamp
+ bless($elem,"NMEA::gps-point");
+ push(@{$new_track},$elem);
+ $elem ={};
+ }
+
+ $elem->{lat} = $lat;
+ $elem->{lon} = $lon;
+ $elem->{alt} = $alt if defined $alt;
+ $elem->{time} = $time if defined $time;
+ $time ||=0;
+
+ my $dop_time_diff = $time - $dop_time;
+ #printf STDERR "time diff: %f\n ", $dop_time_diff;
+ if ( $dop_time_diff < 10
+ && defined($hdop)
+ && defined($vdop)
+ && defined($pdop)
+ ) {
+ $elem->{pdop} = $pdop if $pdop;
+ $elem->{hdop} = $hdop if $hdop;
+ $elem->{vdop} = $vdop if $vdop;
+ if ( $hdop > 30 or
+ $vdop > 30 or
+ $pdop > 30 ) {
+ #printf STDERR Dumper(\$elem);
+ next;
+ }
+ }
+
+ if (0) { # Currently we don't need these values
+ # So we save on local memory consumption
+ my $sat_time_diff = $time - $sat_time;
+ #printf STDERR "time diff: %f\n ", $sat_time_diff;
+ if ( $sat_time_diff < 10 ) {
+ $elem->{sat} = $sat_count;
+ for my $sat_no ( keys %{$sat} ) {
+ $elem->{"sat_${sat_no}_ele"} = $sat->{$sat_no}->{ele};
+ $elem->{"sat_${sat_no}_azi"} = $sat->{$sat_no}->{azi};
+ $elem->{"sat_${sat_no}_snr"} = $sat->{$sat_no}->{snr};
+ }
+ }
+ }
+ # More interesting Info might be:
+ # <course>52.000000</course>
+ # <ele>0.000000</ele>
+ # <fix>2d</fix>
+ # <fix>3d</fix>
+ # <sat>4</sat>
+ # <speed>0.000000</speed>
+ # <time>2035-12-03T05:42:23Z</time>
+ # <trkpt lat="48.177040000" lon="11.759786667">
+ }
+
+ # Write last element
+ if ( defined $elem->{lat} &&
+ defined $elem->{lon} ) {
+ bless($elem,"NMEA::gps-point");
+ push(@{$new_track},$elem);
+ $elem ={};
+ };
+
+ push(@{$new_tracks->{tracks}},$new_track);
+ if ( $VERBOSE >1 ) {
+ printf STDERR "Read and parsed $filename";
+ print_time($start_time);
+ }
+
+ return $new_tracks;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+NMEA.pm
+
+=head1 COPYRIGHT
+
+Copyright 2006, Jörg Ostertag
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+=head1 AUTHOR
+
+Jörg Ostertag (planet-count-for-openstreetmap@ostertag.name)
+
+=head1 SEE ALSO
+
+http://www.openstreetmap.org/
+
+=cut
diff --git a/scripts/osm/perl_lib/Geo/Tracks/TRK.pm b/scripts/osm/perl_lib/Geo/Tracks/TRK.pm
new file mode 100644
index 0000000..8577019
--- /dev/null
+++ b/scripts/osm/perl_lib/Geo/Tracks/TRK.pm
@@ -0,0 +1,143 @@
+##################################################################
+package Geo::Tracks::TRK;
+##################################################################
+
+use Exporter;
+@ISA = qw( Exporter );
+use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION);
+@EXPORT = qw( read_track_TRK );
+
+use strict;
+use warnings;
+
+use Data::Dumper;
+use IO::File;
+use Utils::Debug;
+use Utils::File;
+use Utils::Math;
+use Date::Manip;
+use Date::Parse;
+use Time::Local;
+
+# -----------------------------------------------------------------------------
+# Read GPS Data from TRK - File
+sub read_track_TRK($) {
+ my $filename = shift;
+
+ my $start_time=time();
+
+ my $new_tracks={
+ filename => $filename,
+ tracks => [],
+ wpt => []
+ };
+ printf STDERR ("Reading $filename\n") if $VERBOSE || $DEBUG;
+ printf STDERR "$filename: ".(-s $filename)." Bytes\n" if $DEBUG;
+
+ my ($fn_mtime) = (stat($filename))[9] || 0;
+ #print "$filename mtime: ".localtime($fn_mtime)."\n";
+ my $date ="01-01-2007";
+
+ my $fh = data_open($filename);
+ return $new_tracks unless $fh;
+ my $new_track=[];
+
+ while ( my $line = $fh->getline() ) {
+ chomp $line;
+
+ print "$line\n" if $DEBUG>10;
+
+ my ($dummy1,$time,$lon,$lat,$heading,$speed,$test1,$test2,$test3) = split(/\s*,\s*/,$line);
+ my $alt=0;
+ $time =~ s/^(..)(..)(..)/$1:$2:$3/;
+
+ $time = str2time("$date ${time}");
+ if ( $DEBUG >3) {
+ printf STDERR "".localtime($time)."\t, la: $lat, lo: $lon,";
+ printf STDERR "\tHeading: %6.2f",$heading;
+ printf STDERR "\tSpeed: %8.4f",$speed;
+ printf STDERR "\tTest1($test1)";
+ printf STDERR "\tdop?($test2)";
+ printf STDERR "\tSat#?: $test3";
+ printf STDERR "\tdummy1: $dummy1\n";
+ };
+
+
+ if ( $heading>360) {
+ print STDERR "Here something is wrong the heading ($heading) ".
+ "is larger than 360 degrees\n";
+ print STDERR "Line: $line\n";
+ }
+ my ($msg_anz,$msg_no,$rest);
+
+ unless ( defined( $lat) && ($lat ne "" )&& defined( $lon) && ($lon ne "")) {
+ print "ERROR in Line: $line\n";
+ next;
+ };
+
+ my $elem ={};
+ $elem->{pdop} = $test2;
+ $elem->{lat} = $lat;
+ $elem->{lon} = $lon;
+ $elem->{alt} = $alt if defined $alt;
+ $elem->{time} = $time if defined $time;
+ $time ||=0;
+
+ if ( defined $elem->{time} &&
+ defined $elem->{lat} &&
+ defined $elem->{lon} ) {
+ bless($elem,"TRK::gps-point");
+ push(@{$new_track},$elem);
+ $elem ={};
+ } else {
+ if ( @$new_track ) {
+ push(@{$new_tracks->{tracks}},$new_track);
+ }
+ $new_track=[];
+ }
+ }
+
+ push(@{$new_tracks->{tracks}},$new_track);
+ if ( $VERBOSE >1 ) {
+ printf STDERR "Read and parsed $filename";
+ print_time($start_time);
+ }
+
+ return $new_tracks;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+TRK.pm
+
+=head1 COPYRIGHT
+
+Copyright 2006, Jörg Ostertag
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+=head1 AUTHOR
+
+Jörg Ostertag (TRK.pm.openstreetmap@ostertag.name)
+
+=head1 SEE ALSO
+
+http://www.openstreetmap.org/
+
+=cut
diff --git a/scripts/osm/perl_lib/Geo/Tracks/Tools.pm b/scripts/osm/perl_lib/Geo/Tracks/Tools.pm
new file mode 100644
index 0000000..5008f71
--- /dev/null
+++ b/scripts/osm/perl_lib/Geo/Tracks/Tools.pm
@@ -0,0 +1,395 @@
+##################################################################
+package Geo::Tracks::Tools;
+##################################################################
+
+use Exporter;
+@ISA = qw( Exporter );
+use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION);
+@EXPORT = qw( copy_track_structure copy_track_wpt
+ tracks_only_good_point tracks_only_good_point_split
+ count_good_point
+ set_number_bad_points
+ enrich_tracks
+ track_point_speed
+ track_part_angle
+ track_part_distance
+ print_count_data
+ count_data
+ add_tracks
+);
+
+
+use strict;
+use warnings;
+use Carp;
+
+use Geo::Geometry;
+use Utils::File;
+use Utils::Math;
+use Utils::Debug;
+
+# Copy the track structure
+sub copy_track_structure($$){
+ my $tracks = shift;
+ my $new_tracks = shift;
+
+ Carp::confess "Must get Hashref to copy structure to\n"
+ unless ref($new_tracks) eq "HASH";
+
+ $new_tracks->{filename} = $tracks->{filename};
+ $new_tracks->{tracks} ||= [];
+ $new_tracks->{wpt} ||= [];
+}
+
+# Copy the track waypoints
+sub copy_track_wpt($$){
+ my $tracks = shift;
+ my $new_tracks = shift;
+
+ Carp::confess "Must get Hashref to copy structure to\n"
+ unless ref($new_tracks) eq "HASH";
+
+ # Keep WPT
+ for my $elem ( @{$tracks->{wpt}} ) {
+ next unless $elem;
+ push(@{$new_tracks->{wpt}},$elem);
+ }
+
+ return $new_tracks;
+}
+
+
+##################################################################
+# Copy only those trackpoints with the good_point Flag set
+# The Track Elements have Tags:
+# $elem->{good_point} : Ignore this point
+# $elem->{split_track} : Split track before this point
+# RETURN: Tracks Structure
+sub tracks_only_good_point($){
+ my $tracks = shift;
+
+ my $new_tracks={};
+ copy_track_structure($tracks,$new_tracks);
+ copy_track_wpt($tracks,$new_tracks);
+
+
+ Carp::Confess("Tracks to copy to musst be of Type Hash")
+ unless ref($new_tracks) eq "HASH";
+
+ for my $track ( @{$tracks->{tracks}} ) {
+ next if !$track;
+ my $new_track=[];
+
+ # Copy only those with good_point set to 1
+ for my $track_pos ( 0 .. $#{@{$track}} ) {
+ my $elem=$track->[$track_pos];
+
+ if ( $elem->{split_track} ) {
+ my $num_elem=scalar(@{$new_track});
+ if ( $num_elem >1 ) {
+ push(@{$new_tracks->{tracks}},$new_track);
+ }
+ $new_track=[];
+ }
+ next unless $elem->{good_point};
+ push(@{$new_track},$elem);
+ }
+ if ( scalar(@{$new_track} ) > 1 ) {
+ push(@{$new_tracks->{tracks}},$new_track);
+ }
+ }
+ return $new_tracks;
+}
+
+
+
+
+##################################################################
+# Set number of points in track to bad
+sub set_number_bad_points($$$){
+ my $track = shift; # reference to track
+ my $start_pos = shift; # position to start setting the tag
+ my $count = shift;
+
+ return unless $count;
+
+ my $max_pos = $#{@{$track}};
+ for my $i ( 0 .. $count-1 ){
+ last if $start_pos+$i > $max_pos;
+ $track->[$start_pos+$i]->{good_point}= 0;
+ }
+}
+
+##################################################################
+# Returns number of points with the tag ->{good_point} set
+sub count_good_point($){
+ my $tracks = shift; # A reference to a list of Tracks
+
+ my $count =0;
+ for my $track ( @{$tracks->{tracks}} ) {
+ next if !$track;
+ for ( my $track_pos=0; $track_pos <= $#{@{$track}};$track_pos++ ) {
+ $count++ if $track->[$track_pos]->{good_point};
+ }
+ }
+ return $count;
+};
+
+
+# ------------------------------------------------------------------
+# Enrich Track Data by adding:;
+# dist: Distance to next point in meters
+# angle_n: Angle to next point compared to north
+# angle_n_r: Angle to next point compared to north ignoring direction
+# angle: Angle between previous segment and following segment
+# compare_dist: is pdop or any other usefull distance in
+# meter we can later use for distance comparison
+sub enrich_single_track($){
+ my $track = shift;
+ my $last_track_point = $#{@{$track}};
+ my $compare_dist=30;
+ for my $track_pos ( 0 .. $last_track_point) {
+ my $elem0=$track->[$track_pos-1];
+ my $elem1=$track->[$track_pos];
+ my $elem2=$track->[$track_pos+1];
+
+ if ( ref($elem1) eq "ARRAY" ) {
+ print Dumper(\$track);
+ Carp::confess("enrich_single_track(): track_pos $track_pos has ARRAY instead of Hash");
+ }
+
+ $elem1->{good_point}= 1;
+
+ my $pdop = $elem1->{pdop};
+ if ( defined ( $pdop ) && ($pdop >0) ) {
+ $compare_dist= $pdop;
+ }
+ $compare_dist=10 if $compare_dist <10;
+ $elem1->{compare_dist} = $compare_dist;
+
+ if ( $track_pos < $last_track_point ) {
+ $elem1->{angle_n} = angle_north($elem1,$elem2);
+ $elem1->{angle_n_r} = angle_north_relative($elem1,$elem2);
+ } else {
+ $elem1->{angle_n} = -999999;
+ $elem1->{angle_n_r} = -999999;
+ }
+ if ( ($track_pos > 0) &&
+ ( $track_pos < $last_track_point ) ) {
+ $elem1->{angle} =
+ angle_north($elem0,$elem1) -
+ angle_north($elem1,$elem2);
+ } else {
+ $elem1->{angle} =0;
+ }
+ if ( ($track_pos > 0) &&
+ ( $track_pos < $last_track_point ) ) {
+ $elem2->{angle_to_last} =$elem1->{angle};
+ }
+ # Distance between line of segment($segment) to trackpoint $elem1
+ $elem1->{dist} = 1000*distance_point_point_Km($elem1,$elem2);
+
+ if ( defined($elem1->{time}) && defined($elem2->{time}) ) {
+ $elem1->{time_diff} = $elem1->{time} - $elem2->{time};
+ }
+ }
+}
+
+# ------------------------------------------------------------------
+# Enrich Tracks Data by doing enrich_singleTrack an all tracks
+sub enrich_tracks($){
+ my $tracks = shift;
+ for my $track ( @{$tracks->{tracks}} ) {
+ enrich_single_track($track);
+ }
+}
+
+
+# ------------------------------------------------------------------
+# Calculate Average Speed of track segment
+sub track_point_speed($$){
+ my $track = shift;
+ my $track_pos = shift;
+
+ my $elem = $track->[$track_pos];
+ return $elem->{speed} if defined $elem->{speed};
+
+ my $pos_start = $track_pos-10;
+ $pos_start = 0 if $pos_start<0;
+
+ my $pos_end = $pos_start+20;
+ my $max_pos = $#{@{$track}};
+ $pos_end = $max_pos if $pos_end> $max_pos;
+
+ return track_part_speed($track,$pos_start,$pos_end);
+}
+
+# ------------------------------------------------------------------
+# Calculate Average Speed of track segment
+sub track_part_speed($$$){
+ my $track = shift;
+ my $pos_start = shift;
+ my $pos_end = shift;
+ my $avg_speed = 0;
+
+ return 0 unless defined $track;
+
+ my $max_pos = $#{@{$track}};
+ $pos_start = 0 if $pos_start<0;
+ $pos_end = $max_pos if $pos_end> $max_pos;
+
+ my $dist = track_part_distance($track,$pos_start,$pos_end)/1000;
+ my $elem_s = $track->[$pos_start];
+ my $elem_e = $track->[$pos_end];
+
+ my $speed=0;
+ if ( defined($elem_s->{time}) && defined($elem_e->{time}) ) {
+ my $time_diff = $elem_s->{time} - $elem_e->{time};
+ if ( $time_diff ) {
+ my $speed = $dist/$time_diff*3600;
+ };
+ };
+ $avg_speed = $speed;
+
+ my $sum_speed=0;
+ for my $track_pos ( $pos_start .. $pos_end ) {
+ my $elem = $track->[$track_pos];
+
+ return $speed # Abort if any sub-speeds are not defined
+ unless defined $elem->{speed};
+
+ $sum_speed += $elem->{speed};
+ }
+ $avg_speed = $sum_speed/($pos_end-$pos_start+1);
+
+ return $avg_speed;
+}
+
+# ------------------------------------------------------------------
+# Summarize all angles between start and endpoint of a single track
+sub track_part_angle($$$){
+ my $track = shift;
+ my $pos_start = shift;
+ my $pos_end = shift;
+ my $sum_angle=0;
+
+ for my $track_pos ( $pos_start .. $pos_end ) {
+ $sum_angle += $track->[$track_pos]->{angle};
+ }
+ return $sum_angle;
+}
+
+# ------------------------------------------------------------------
+# Summarize distance between start and endpoint of a single track
+sub track_part_distance($$$){
+ my $track = shift;
+ my $pos_start = shift;
+ my $pos_end = shift;
+ my $sum_angle=0;
+
+ for my $track_pos ( $pos_start .. $pos_end ) {
+ $sum_angle += $track->[$track_pos]->{dist};
+ }
+ return $sum_angle;
+}
+
+# ------------------------------------------------------------------
+# count tracks and points
+sub count_data($){
+ my $tracks = shift; # reference to tracks list
+
+ my $start_time=time();
+
+ my $count_tracks=0;
+ my $count_points=0;
+
+ for my $track ( @{$tracks->{tracks}} ) {
+ next if !$track;
+ for my $elem ( @{$track} ) {
+ $count_points++;
+ }
+ $count_tracks++;
+ }
+
+ my $used_time = time()-$start_time;
+ if ( $DEBUG>5 || $VERBOSE>5 || ($used_time >5 )) {
+ printf STDERR "Counted ( $count_tracks Tracks,$count_points Points)";
+ print_time($start_time);
+ }
+
+ return ( $count_tracks,$count_points);
+}
+
+# ------------------------------------------------------------------
+# Print Number of points/tracks with a comment
+# and print them with a comment and the filename stored in the track
+sub print_count_data($$){
+ my $tracks = shift; # reference to tracks list
+ my $comment = shift;
+
+ my $filename = $tracks->{filename};
+
+ my ($track_count,$point_count) = GPS::count_data($tracks);
+ if ( $VERBOSE || $DEBUG) {
+ printf STDERR "%-35s: %5d Points in %d Tracks $comment",$filename,$point_count,$track_count;
+ }
+}
+
+
+# ------------------------------------------------------------------
+# add a list of tracks to another list of Tracks
+sub add_tracks($$){
+ my $dst_tracks = shift; # reference to tracks list
+ my $src_tracks = shift; # reference to tracks list
+
+ $dst_tracks ||= { filename => '',
+ tracks => [],
+ wpt => [],
+ };
+ $dst_tracks->{filename} .=",$src_tracks->{filename}";
+ for my $elem ( @{$src_tracks->{wpt}} ) {
+ next unless $elem;
+ push(@{$dst_tracks->{wpt}},$elem);
+ }
+ for my $elem ( @{$src_tracks->{tracks}} ) {
+ next unless $elem;
+ push(@{$dst_tracks->{tracks}},$elem);
+ }
+}
+
+1;
+
+
+__END__
+
+=head1 NAME
+
+Geo::Tracks::Tools
+
+=head1 COPYRIGHT
+
+Copyright 2006, Jörg Ostertag
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+=head1 AUTHOR
+
+Jörg Ostertag (planet-count-for-openstreetmap@ostertag.name)
+
+=head1 SEE ALSO
+
+http://www.openstreetmap.org/
+
+=cut