Editar o consultar tracks en python - Añadir Waypoints

Todos los track que utilizo los creo, preparo o modifico con QMapShack, aplicación de código libre con la que podemos planificar rutas o visualizar y archivar todos los registros que creamos con el GPS. En algunos casos puede ser interesante modificar los track directamente para realizar tareas a muchos track o modificaciones que sigan algún tipo de patrón. En este caso lo que necesitaba es generar puntos (waypoints) en un track cada ciertos metros, y eso es exactamente lo que vamos a hacer en python.

Para trabajar con ficheros GPX podemos usar una librería en python, concretamente gpxpy, un parser que nos va a facilitar mucho todo el trabajo.

Como ejemplo del uso de esta librería, voy a mostrar una pequeña aplicación en python que hice hace tiempo y que utilizo habitualmente cuando creo los track. Concretamente lo que quiero es generar puntos en un track cada ciertos metros de forma automática. A la aplicación le pasamos el fichero o ficheros GPX y lo que hace es seguir las rutas que tenga el fichero y generar waypoints cada ciertos metros, por defecto 500m, pero podemos seleccionar cada cuanto queremos que nos cree los waypoints.

Lo primero es instalar la librería. Para instalar las librerías vamos a usar pip, voy a utilizar ubuntu 20.04LTS pero es similar en otras distros. Instalamos pip si no lo tenemos todavía en el equipo:

sudo apt install python3-pip

y ahora instalamos la librería:

sudo pip3 install gpxpy

Ahora vamos a ver el código del programa:

#!/usr/bin/env python3  
# -*- coding: utf-8 -*-  
# ***************************************************************  
# *  
# * (c) Author: David Quiroga  
# * e-mail: david (at) clibre (dot) io 
# *  
# ****************************************************************  
# * Description:  
# *  
# * Program to read the tracks of a gpx file and create points  
# * every nnn meters  
# *  
# 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 3 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, see <http://www.gnu.org/licenses/>.  
  
import gpxpy  
from pathlib import Path  
import sys as mod_sys  
import logging as mod_logging  
import argparse as mod_argparse  
  
def create_Waypoints(gpx, cdistancia, nfich):  
    gpx_file = open(nfich, 'w')  
    wpf_gpx = gpxpy.gpx.GPX()  
  
    wpf_gpx.creator = 'ComunidadLibre'  
    wpf_gpx.name = 'Waypoints (%s)' % gpx.name  
    wpf_gpx.description = 'Puntos creados cada %d metros' % cdistancia  
    #wpf_gpx.time = mod_datetime.datetime(2014, 4, 7, 21, 17, 39)  
    #wpf_gpx.bounds = gpxpy.gpx.GPXBounds(1, 2, 3, 4)  
    wpf_gpx.author_name = 'david'  
    #wpf_gpx.author_email = 'david[at]comunidadlibre[dot]org'  
    wpf_gpx.link = 'comunidadlibre.org'  
    wpf_gpx.link_text = 'Comunidad Libre - Software Libre'  
    wpf_gpx.keywords = ''  
  
    for track in gpx.tracks:  
        for segment in track.segments:  
         previous_point = None  
         tot_distancia = 0  
         ttt_distancia = 0  
         cont=0  
         for point in segment.points:  
            if previous_point:  
                distancia = point.distance_2d(previous_point)  
                tot_distancia = tot_distancia + distancia  
                if tot_distancia >= (cdistancia*(cont+1)):  
                    d_waypoint = gpxpy.gpx.GPXWaypoint()  
                    d_waypoint.latitude = point.latitude  
                    d_waypoint.longitude = point.longitude  
                    d_waypoint.elevation = point.elevation  
                    d_waypoint.name = 'Km %0.02f' % (tot_distancia/1000)  
                    d_waypoint.symbol = 'Waypoint'  
                    d_waypoint.comment = 'cm'  
                    d_waypoint.description = 'des'  
                    d_waypoint.dgps_id = str(cont+1)  
                    wpf_gpx.waypoints.append(d_waypoint)  
                    cont=cont+1  
            else:  
                # Grabamos el primer punto  
                d_waypoint = gpxpy.gpx.GPXWaypoint()  
                d_waypoint.latitude = point.latitude  
                d_waypoint.longitude = point.longitude  
                d_waypoint.elevation = point.elevation  
                d_waypoint.name = 'Km '+ '0.00'  
                d_waypoint.symbol = 'Waypoint'  
                d_waypoint.comment = 'cm'  
                d_waypoint.description = 'des'  
                d_waypoint.dgps_id = '0'  
                wpf_gpx.waypoints.append(d_waypoint)  
  
            previous_point = point  
         print (' - Created Waypoints for track [%s]: %d' % (track.name, cont))  
  
    gpx_file.write(wpf_gpx.to_xml())  
      
def print_gpx_info(gpx, gpx_file):  
    print('[+] File: %s' % gpx_file)  
  
    if gpx.name:  
        print(' - GPX name: %s' % gpx.name)  
    if gpx.description:  
        print(' - GPX description: %s' % gpx.description)  
    if gpx.author_name:  
        print(' - Author: %s' % gpx.author_name)  
    if gpx.author_email:  
        print(' - Email: %s' % gpx.author_email)  
  
    print(' - Waypoints every: %d meters' % args.distancia)  
      
    nfich = replace_last (gpx_file.name, '.gpx', '')  
    nfich += '-points%dm.gpx'%args.distancia  
    print(' - File for write Waypoints: %s' % nfich)  
  
    existe_file = Path(nfich)  
    if existe_file.exists() and args.remplazar == 'false':  
        print(' the file already exists, it will not be modified '  
                '(to overwrite use: -r true)')  
        return  
    else:  
        create_Waypoints(gpx, args.distancia, nfich)  
  
def replace_last(string, find, replace):  
    reversed = string[::-1]  
    replaced = reversed.replace(find[::-1], replace[::-1], 1)  
    return replaced[::-1]  
  
def run(gpx_files):  
    if not gpx_files:  
        print('No GPX file has been selected')  
        mod_sys.exit(1)  
  
    for gpx_file in gpx_files:  
        try:  
            gpx = gpxpy.parse(open(gpx_file))  
            print_gpx_info(gpx, gpx_file)  
        except Exception as e:  
            mod_logging.exception(e)  
            print('Error processing %s' % gpx_file)  
            mod_sys.exit(1)  
  
def range_type(astr, min=50, max=20000):  
    value = int(astr)  
    if min<= value <= max:  
        return value  
    else:  
        raise mod_argparse.ArgumentTypeError('Value out of range: %sm-%sm'%  
                (min,max))  
  
def check_files(astr):  
    gpx_file = Path(astr)  
    if gpx_file.exists():  
        return gpx_file  
    else:  
        raise mod_argparse.ArgumentTypeError('file not found [%s]'  
                % astr)  
  
def make_parser():  
    parser = mod_argparse.ArgumentParser(usage='%(prog)s [-d nnn] file1.gpx '  
                'file2.gpx ..', description='Program to create Waypoints '  
                'from a track every [nnn] meters')  
    parser.add_argument('gpxfiles', metavar='files.gpx',  
                type=check_files, nargs='+', help='gpx files with tracks')  
    parser.add_argument('-d', '--distance', type=range_type, default=500,  
                dest='distancia', metavar='nnn',  
                help='Waypoints distance (from 50m to 2000m), '  
                'default 500 meters')  
    parser.add_argument('-r', '--replace', choices={'true', 'false'},  
                default='false', dest='remplazar', metavar='true/false',  
                help='replace output files if they already exit, default false')  
    return parser  
  
if __name__ == '__main__':  
    args = make_parser().parse_args()  
    run(args.gpxfiles)  
    mod_sys.exit(0)  

Solo lo tenemos que guardar en nuestro equipo, yo lo he llamado createwaypoints, y darle permisos de ejecución como vimos en la entrada sobre los permisos en GNU/Linux:

sudo chmod +x createwaypoints

Para poder ejecutarlo desde cualquier sitio lo guardamos en /user/local/bin:

sudo cp createwaypoints /usr/local/bin/

y ya podemos usarlo:

$ createwaypoints -h
usage: createwaypoints [-d nnn] file1.gpx file2.gpx ..

Program to create Waypoints from a track every [nnn] meters

positional arguments:
files.gpx gpx files with tracks

optional arguments:
-h, --help show this help message and exit
-d nnn, --distance nnn
Waypoints distance (from 50m to 2000m), default 500 meters
-r true/false, --replace true/false
replace output files if they already exit, default false
david@clibre:~/tracks$ createwaypoints TejoMilenario-Pozas.gpx 
[+] File: TejoMilenario-Pozas.gpx
- GPX name: TejoMilenario-Pozas
- Waypoints every: 500 meters
- File for write Waypoints: TejoMilenario-Pozas-points500m.gpx
- Created Waypoints for track [2017-08-23 00:18:52]: 23
david@clibre:~/tracks$ ls
TejoMilenario-Pozas.gpx TejoMilenario-Pozas-points500m.gpx

El programa no modifica el .gpx original sino que crea un nuevo fichero .gpx que deriba del nombre original añadiendo '-pointsXXXm' (donde XXX son los metros).

Por defecto nos crea los waypoints cada 500 metros. Podemos crearlos, por ejemplo cada 100m:

$ createwaypoints TejoMilenario-Pozas.gpx -d 100
[+] File: TejoMilenario-Pozas.gpx
- GPX name: TejoMilenario-Pozas
- Waypoints every: 100 meters
- File for write Waypoints: TejoMilenario-Pozas-points100m.gpx
- Created Waypoints for track [2017-08-23 00:18:52]: 118

Es posible crear los waypoints a varios ficheros, por ejemplo a todos los de una carpeta con extensión gpx:

david@clibre:~/tracks$ ls
ascension-pico-del-oso.gpx LaCabrera-PicoMiel-CanchoGordo.gpx raquetas-picodeloso.gpx
Canon-Rio-Dulce.gpx las-torres-de-la-pedriza.gpx sierra-de-ayllon.gpx
carro-del-diablo.gpx loschorrosdelapedri.gpx silla-del-rey-cascadas-la-chorranca.gpx
el-trabuquete.gpx pozas-del-aljibe.gpx tres-cestos.gpx
david@clibre:~/tracks$ createwaypoints *.gpx
[+] File: ascension-pico-del-oso.gpx
- GPX name: ascension-con-raquetas-al-pico-del-oso-desde-Ortigosa
- Waypoints every: 500 meters
- File for write Waypoints: ascension-pico-del-oso-points500m.gpx
- Created Waypoints for track [Mujer Muerta. Ascensión con raquetas al pico del Oso desde O...]: 21
[+] File: Canon-Rio-Dulce.gpx
- GPX name: Canon Rio Dulce - New
- Waypoints every: 500 meters
- File for write Waypoints: Canon-Rio-Dulce-points500m.gpx
- Created Waypoints for track [Canon del Rio Dulce - New]: 5
- Created Waypoints for track [Canon del Rio Dulce - New]: 6
[+] File: carro-del-diablo.gpx
- Waypoints every: 500 meters
- File for write Waypoints: carro-del-diablo-points500m.gpx
[+] File: el-trabuquete.gpx
- GPX name: el-trabuquete
- Waypoints every: 500 meters
- File for write Waypoints: el-trabuquete-points500m.gpx
- Created Waypoints for track [El Trabuquete]: 28
- Created Waypoints for track [El Trabuquete_rev]: 28
[+] File: LaCabrera-PicoMiel-CanchoGordo.gpx
- GPX name: LaCabrera-PicoMiel-CanchoGordo
- Waypoints every: 500 meters
- File for write Waypoints: LaCabrera-PicoMiel-CanchoGordo-points500m.gpx
- Created Waypoints for track [2016-11-01 16:39:41]: 23
[+] File: las-torres-de-la-pedriza.gpx
- Waypoints every: 500 meters
- File for write Waypoints: las-torres-de-la-pedriza-points500m.gpx
- Created Waypoints for track [Las Torres de la Pedriza Circular por Collado de la Ventana ...]: 27
[+] File: loschorrosdelapedri.gpx
- GPX name: loschorrosdelapedrizaedit2
- Waypoints every: 500 meters
- File for write Waypoints: loschorrosdelapedri-points500m.gpx
- Created Waypoints for track [Los Chorros de la Pedriza]: 19
[+] File: pozas-del-aljibe.gpx
- Waypoints every: 500 meters
- File for write Waypoints: pozas-del-aljibe-points500m.gpx
[+] File: raquetas-picodeloso.gpx
- GPX name: raquetas-picodeloso
- Waypoints every: 500 meters
- File for write Waypoints: raquetas-picodeloso-points500m.gpx
- Created Waypoints for track [Track actual: 12 MAR 2016 10:09 (2 - 624) & other]: 22
[+] File: sierra-de-ayllon.gpx
- Waypoints every: 500 meters
- File for write Waypoints: sierra-de-ayllon-points500m.gpx
- Created Waypoints for track [Sierra de Ayllón, Matallana - Pozas del Aljibe]: 23
[+] File: silla-del-rey-cascadas-la-chorranca.gpx
- GPX name: silla-del-rey-cascadas-la-chorranca-cueva-del-monje
- Waypoints every: 500 meters
- File for write Waypoints: silla-del-rey-cascadas-la-chorranca-points500m.gpx
- Created Waypoints for track [Silla del Rey - Cascadas La Chorranca - Cueva del Monje y Ce...]: 27
[+] File: tres-cestos.gpx
- Waypoints every: 500 meters
- File for write Waypoints: tres-cestos-points500m.gpx
david@clibre:~/tracks$

Nos crea un fichero con los waypoints por cada fichero que le pasemos. Dentro del fichero crea los waypoints de todos los track o secciones que hay. Si no hay ninguno crea el fichero .gpx sin datos.

Los ficheros .gpx con los waypoints los podemos usar en QMapShack o cargarlo al GPS. Espero que sea de utilidad!

 

 

Modificado por última vez enViernes, 14 Agosto 2020 19:57
(1 Voto)
Etiquetado como :

Deja un comentario

Asegúrese de introducir toda la información requerida, indicada por un asterisco (*). No se permite código HTML.