diff options
Diffstat (limited to 'scripts/osm/perl_lib/Geo/Tracks')
-rw-r--r-- | scripts/osm/perl_lib/Geo/Tracks/GpsBabel.pm | 82 | ||||
-rw-r--r-- | scripts/osm/perl_lib/Geo/Tracks/Kismet.pm | 125 | ||||
-rw-r--r-- | scripts/osm/perl_lib/Geo/Tracks/NMEA.pm | 373 | ||||
-rw-r--r-- | scripts/osm/perl_lib/Geo/Tracks/TRK.pm | 143 | ||||
-rw-r--r-- | scripts/osm/perl_lib/Geo/Tracks/Tools.pm | 395 |
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 |