jueves, 1 de octubre de 2015

¿Llevan todos los caminos a Roma?

Qué encontrarás en esta entrada?
  • Script Linux para unir GPX.
  • Ver en un mapa la superposición de de todos los caminos.

Como sabéis, en Astaroth's World somos muy fans de los GPS y de Linux. Una cosa que siempre he tenido curiosidad por ver es la superposición de todos los caminos que he seguido en mi vida. No recuerdo exactamente cómo era aquello que leí una vez, pero venía a decir algo así como que nuestros pies eran como bolígrafos que iban escribiendo nuestra historia según nos íbamos moviendo.

Los puntos que forman una línea más gruesa representan mis pasos por Los Cerros de Alcalá

Evidentemente, no registro mi vida continuamente con el GPS (si bien es verdad Google sí que lo hace por nosotros...). Al menos no por ahora. Lo que sí registro son muchas de mis excursiones, en archivos con formato ".gpx".

Un archivo ".gpx", como podemos ver en Wikipedia, es un archivo XML que contiene las coordenadas de una ruta, los puntos de interés ("waypoints"), la altitud y otros datos. Mi objetivo es partir de varios archivos ".gpx", extraer sólo la latitud y longitud de los puntos que construyen la ruta, y crear un nuevo archivo con todos ellos.

Para ello, he realizado un script en shell de Linux. Seguro que hay millones por Internet más eficientes que éste, pero éste es el mio, y es lo que se me ha ocurrido a mi en el momento.

#!/bin/bash
#
# Este script recopila datos sobre la longitud y latitud de varios archivos ".gpx" ó
#".GPX" y los une un un sólo archivo.
#
# Es necesario para su correcto funcionamiento que los archivos de entrada estén en la
#carpeta "GPX", un nivel por debajo del script.
#
# Creado por Astaroth (O.R.G.).
# 30/09/2015

clear

#************************************************************************************
# RENOMBRAR: se intenta evitar problemas con los espacios en los nombres de archivos.
#************************************************************************************
echo "Renombrando archivos para evitar problemas al procesarlos..."
mkdir .renombrado

# Se hace un primer indexado de los archivos de entrada:
ls GPX/*.gpx > .lista.txt
ls GPX/*.GPX >> .lista.txt

# Primero se renombran las extensiones para homogenizar:
cat .lista.txt | sed 's/.GPX/.gpx/g' > .Lista2.txt

maxl=`wc .lista.txt | awk '{print $1}'`

# Después se renombran los archivos, copiándolos a una carpeta con nombres no problemáticos:
for i in $(seq $maxl) ; do
    nomorg=`cat .lista.txt | sed -n ''$i'p' | sed 's/\ /\\ /g'`
    renom=`cat .Lista2.txt | sed -n ''$i'p' | sed 's/GPX\///g' | sed 's/\ /_/g'`
    cp "$nomorg" .renombrado/$renom
done

# Por último, se indexan los archivos con el nombre que no dará problemas:
echo "Indexando archivos"
lista=`ls .renombrado/*.gpx`

#************************************************************************************
# UNIÓN: es el script propiamente dicho, se extraen los datos de cada archivo y se
#unen en uno solo.
#************************************************************************************

echo "Escribiendo GPX de la unión..."

# CABECERA: se escribe parte fija inicial.
#------------------------------------------------------------------------------------
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" > Union.gpx
echo "<gpx>" >> Union.gpx
echo "<trk>" >> Union.gpx
echo "<trkseg>" >> Union.gpx

echo "Extrayendo coordenadas..."

# CUERPO: la parte en la que van los datos.
#------------------------------------------------------------------------------------

# Extracción de las latitudes y longitudes:
for archivo in $lista; do
    cat $archivo | grep -o "lat=\"[0-9]*.[0-9]*\" lon=\"[,-][0-9]*.[0-9]*\"" >> .latlong.txt
done

# Escribiendo los datos en el archivo de la unión:
cat .latlong.txt | sed 's/lat/<trkpt lat/g' | tr '\n' '*' | sed 's/*/>\n<\/trkpt>\n/g' >> Union.gpx

# COLA: Parte fija al final del documento (cierre de etiquetas XML)
#------------------------------------------------------------------------------------
echo "Cerrando archivo GPX de la unión..."
echo "</trkseg>" >> Union.gpx
echo "</trk>" >> Union.gpx
echo "</gpx>" >> Union.gpx

#************************************************************************************
# BORRADO DE ARCHIVOS TEMPORALES: se limpian los archivos que ya no son necesarios.
#************************************************************************************
echo "Borrando archivos temporales..."
rm .lista.txt
rm .Lista2.txt
rm -R .renombrado
rm .latlong.txt

echo ""
echo "¡¡EJECUCIÓN FINALIZADA!!"

Uno de los puntos delicados era que tomara correctamente el nombre de los archivos (muy heterogéneo entre mis documentos), por lo que parte importante del script es indexar los elementos involucrados y renombrarlos para que no den problemas (prestando especial cuidado a los espacios, que podrían ocasionar errores).

Una vez hecho esto, se escribe la cabecera (una parte genérica fija). Luego se extraen las coordenadas (longitud y latitud, obviando otros datos, como pudieran ser los de elevación) y se insertan en el cuerpo del archivo final. Por último, se cierra el archivo con una parte fija final (el cierre de las etiquetas del XML que se abrieron en la cabecera).

Pantalla de la salida del script

Con esto tenemos un único archivo ".gpx" con la información de todos, pudiéndolo visualizar con casi cualquier herramienta cartográfica como, por ejemplo, GpsPrune.

Unión de varias rutas que he registrado con el GPS. Se ve mi recorrido por La Alcarria de Alcalá (Los Santos de la Humosa, Santorcaz, Anchuelo, Villalbilla, Valverde de Alcalá, Torres de la Alameda, Loeches...).

Visión global de la unión de todas las rutas que he registrado con el GPS. Se incluyen algunas rutas no hechas a pie.

Algún día espero cubrir gran parte del mapa con estas líneas, y dejar una historia llena de recorridos, pueblos, monumentos y curiosidades que poder contar.

ACTUALIZACIÓN 


Una sencilla modificación en el script nos permite, de una manera más limpia, recuperar además los puntos de interés, las altitudes, las fotos, etc. En lugar de quedarnos sólo con la longitud y la latitud, el scrpt ahora selecciona todo lo que esté entre las etiquetas "<gpx ...>" y "</gpx>", y lo incluye en bloque en el archivo final. El resultado, el que podéis ver bajo estas líneas.

Caminos que he seguido por Los Cerros. Con esta actualización se incluyen puntos de interés que fui marcando, así como fotos y elevaciones, y desaparecen las líneas que unían una ruta con la siguiente, emborronando el resultado final.

El script definitivo sería el siguiente:

#!/bin/bash
#
# Este script recopila datos sobre la longitud y latitud de varios archivos ".gpx" ó
#".GPX" y los une un un sólo archivo.
#
# Es necesario para su correcto funcionamiento que los archivos de entrada estén en la
#carpeta "GPX", un nivel por debajo del script.
#
# Creado por Astaroth (O.R.G.).
# 01/10/2015

clear

#************************************************************************************
# RENOMBRAR: se intenta evitar problemas con los espacios en los nombres de archivos.
#************************************************************************************
echo "Renombrando archivos para evitar problemas al procesarlos..."
mkdir .renombrado

# Se hace un primer indexado de los archivos de entrada:
ls GPX/*.gpx > .lista.txt
ls GPX/*.GPX >> .lista.txt

# Primero se renombran las extensiones para homogenizar:
cat .lista.txt | sed 's/.GPX/.gpx/g' > .Lista2.txt

maxl=`wc .lista.txt | awk '{print $1}'`

# Después se renombran los archivos, copiándolos a una carpeta con nombres no problemáticos:
for i in $(seq $maxl) ; do
    nomorg=`cat .lista.txt | sed -n ''$i'p' | sed 's/\ /\\ /g'`
    renom=`cat .Lista2.txt | sed -n ''$i'p' | sed 's/GPX\///g' | sed 's/\ /_/g'`
    cp "$nomorg" .renombrado/$renom
done

# Por último, se indexan los archivos con el nombre que no dará problemas:
echo "Indexando archivos"
lista=`ls .renombrado/*.gpx`

#************************************************************************************
# UNIÓN: es el script propiamente dicho, se extraen los datos de cada archivo y se
#unen en uno solo.
#************************************************************************************

echo "Escribiendo GPX de la unión..."

# CABECERA: se escribe parte fija inicial.
#------------------------------------------------------------------------------------
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" > Union.gpx
echo "<gpx>" >> Union.gpx
echo "<trk>" >> Union.gpx
echo "<trkseg>" >> Union.gpx


# CUERPO: la parte en la que van los datos.
#------------------------------------------------------------------------------------

# Extracción de las latitudes y longitudes:
echo "Escribiendo datos..."
for archivo in $lista; do
    inic=`cat $archivo | grep -n "<gpx" | awk -F\: '{print $1}' | sed -n '1p'`
    fini=`cat $archivo | grep -n "</gpx" | awk -F\: '{print $1}'| sed -n '$p'`
    inic=`echo "$inic + 1" | bc`
    fini=`echo "$fini - 1" | bc`
    cat $archivo | sed -n ''$inic','$fini'p' >> Union.gpx

done

# COLA: Parte fija al final del documento (cierre de etiquetas XML)
#------------------------------------------------------------------------------------
echo "Cerrando archivo GPX de la unión..."
echo "</trkseg>" >> Union.gpx
echo "</trk>" >> Union.gpx
echo "</gpx>" >> Union.gpx

#************************************************************************************
# BORRADO DE ARCHIVOS TEMPORALES: se limpian los archivos que ya no son necesarios.
#************************************************************************************
echo "Borrando archivos temporales..."
rm .lista.txt
rm .Lista2.txt
rm -R .renombrado

echo ""
echo "¡¡EJECUCIÓN FINALIZADA!!"

Espero que os sea de utilidad.

No hay comentarios:

Publicar un comentario

Querido astarothista!,

Si te ha gustado la entrada y quieres dejar constancia de ello, tienes alguna sugerencia para completarla o corregirla, quieres mostrar tu opinión respecto a algo de lo que se haya hablado en esta entrada (con respeto) o simplemente quieres dejarme un mensaje a mi o a la comunidad, no dudes en comentar ;)!

Recuerda que también estamos en Facebook y en Google+.