sobota, 28 maja 2016

Wysyłanie śladów TCX na Endomondo/Strava z poprawioną wysokością

Ciąg dlaszy wpisu Rejestrowanie wysokości przez odbiorniki GPS

Ciąg dalszy bo ,,ciąg technologiczny'' FIT →TCX →GPX →srtm.py →lepszy_GPX→Endomondo/Strava pozbawia niestety przesyłany plik GPX danych, które nie są wspierane przez format GPX (takie jak tętno dla przykładu).

Problem można rozwiązać dodając do pliku TCX poprawione wysokości z pliku lepszy_GPX:

#!/usr/bin/perl
use XML::LibXML;
use XML::LibXML::XPathContext;
use Getopt::Long;

binmode(STDOUT, ":utf8");

my $Gpx_file; my $Tcx_file;

## gpx -- plik GPX z poprawionymi wysokościami
## tcx -- oryginalny plik TCX (w którym mają być poprawione wysokości)
GetOptions( "gpx=s" => \$Gpx_file, "tcx=s" => \$Tcx_file, ) ;

my $parser = XML::LibXML->new();

for my $file2parse ("$Gpx_file") {

  my $doc = $parser->parse_file($file2parse);
  my $root = $doc->documentElement();

  my $xc = XML::LibXML::XPathContext->new( $root );
  $xc->registerNs('gpx', 'http://www.topografix.com/GPX/1/0');

  foreach my $t ($xc->findnodes('//gpx:trkpt')) {

    my $xpe = XML::LibXML::XPathContext->new( $t );
    $xpe->registerNs('gpx', 'http://www.topografix.com/GPX/1/0');
    $node++;
    $gmttime = ($xpe->findnodes('gpx:time'))[0]->textContent();
    $altitude = ($xpe->findnodes('gpx:ele'))[0]->textContent();
    $GpxPoints{"$gmttime"} = $altitude;
  }
}

## for $e (keys %GpxPoints) { print "$e => $GpxPoints{$e}\n"; }

for my $file2parse ("$Tcx_file") {
  # http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2
  my $doc = $parser->parse_file($file2parse);

  my $root = $doc->documentElement();

  my $xc = XML::LibXML::XPathContext->new( $root );
  $xc->registerNs('tcx',
      'http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2');

  foreach my $t ($xc->findnodes('//tcx:Trackpoint')) {

    my $xpe = XML::LibXML::XPathContext->new( $t );
    $xpe->registerNs('tcx',
       'http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2');

    $gmttime = ($xpe->findnodes('tcx:Time'))[0]->textContent();

    foreach my $xpa ( $xpe->findnodes('tcx:AltitudeMeters') ) {
       $oldAltitude = $xpa->textContent();
       ## jeżeli istnieje w pliku GPX punkt z tym samym stemplem 
       ## czasu zmień zawartość elementu tcx:AltitudeMeters
       if (exists $GpxPoints{$gmttime} ) {
          ## replace content of tcx:AltitudeMeters
          $xpa->removeChildNodes();
          $xpa->appendText("$GpxPoints{$gmttime}");
          $changedNodesNo++;
       } else {
          ## jeżeli nie istnieje usuń cały węzeł
          my $parent = $t->parentNode;
          $parent->removeChild( $t );
          $droppedNodes .= "$gmttime;";
          $droppedNodesNo++;
       }
    }
  }

### ###
print "<?xml version='1.0' encoding='UTF-8' standalone='no' ?>\n";
print $root->toString;
### ###
}

print STDERR "Zmieniono: $changedNodesNo / Usunięto: $droppedNodesNo\n";
print STDERR "($droppedNodes)\n";

Ponieważ skrypt srtm.py nie tworzy pliku GPX zawierającego wszystkie punkty z pliku TCX (z jakiś powodów niewielka część jest pomijana); warunek exists $GpxPoints{$gmttime} sprawdza czy istnieje w pliku GPX punkt z podanym stemplem czasowym. Jeżeli istnieje zmieniana jest wysokość, jeżeli nie to punkt jest usuwany.

1 komentarz: