Archivo de la categoría: Programación

Árboles monumentales de Cataluña en OpenStreetMap (1a parte)

Estas últimas semanas he renovado mi interés por el proyecto OpenStreetMap, y me he centrado en cómo contribuir en la actualización de los mapas.

Los mapas se pueden actualizar de forma manual, con el editor online iD, o mejor con el editor JOSM (basado en Java). Todo el mundo puede contribuir, e incluso puede ser divertido (y útil).

De todas maneras, mi interés es la programación de las APIs de OSM. Concretamente la OverpassAPI (orientada a hacer búsquedas), y la Osmapi (API v0.6) que es la que se puede utilizar para editar. Con las APIs he conseguido buscar, inserir, actualizar y editar nodos, com lo tengo documentado en la wiki.

Un vez se adquiere un poco de confianza, ya se puede afrontar el reto de actualizar con un script python la lista de los árboles monumentales de Catalunya, catalogados por la Generalitat. Todo ello está explicado en la part 2 del artículo.

OpenStreetMaps en rutesgps.joanillo.org

He actualizado la web de rutesgps.joanillo.org. Lo tenia con la API de Google Maps y hacia tiempo que no funcionaba debido a que la API KEY había caducado.

En la asignatura de Javascript, en el instituto, el curso pasado ya no utilizamos Google Maps, y sólo la API de OpenStreetMaps (OSM). Quizás los mapas no son tan chulos, pero son plenamente funcionales, y con el tiempo irá mejorando gracias a la colaboracion de la comunidad.

Además, he empezado a editar y colaborar en los mapas de OSM, hay mucho trabajo para la comunidad. Estos días estoy con temas de mapas porque me he comprado un GPS de ciclismo, el Bryton Rider 450, que me está dando muy buenos resultados. El sábado pasado fuimos a hacer una ruta por el macizo del Garraf, desde Garraf hasta Begues, y volver.

Conclusión: adios Google Maps, adelante OSM!

Experimentos de verano: modelo matemático de como decae la luz solar al atardecer

Me está rondando por la cabeza hacer una serie de experimentos captando dades amb sensors y procesando los datos en el ordenador. Espero hablar de ello pronto, hay bastantes ideas chulas que se pueden desarrollar. Aquí va una pequeña muestra. Y una de las técnicas clave para hacer todo esto que quiero hacer es enviar por el protocolo serie los datos de un sensor (arduino) a un programa C++ que se está ejecutando en el ordenador.

En la foto se puede ver cómo se recogen los datos del sensor en el ordenador. Los datos se van grabando en un fichero, y se pueden procesar a posteriori. En este caso tengo un sensor LDR que capta la luz solar, y se trata de ver cómo decae la iluminación a medida que se va haciendo oscuro. ¿Qué comportamiento tendrá? El estado inicial es asintótico (iluminación plena), y el estado final también (oscuridad). ¿Qué pasa en medio? Sabemos que a la naturaleza no le gustan los cambios bruscos. Hemos de unir las dos rectas con una curva. Esto nos puede dar una curva sigmoide, en la que habría un punto de inflexión de cambio máximo en el decrecimiento de la iluminación? ¿Será cierto este comportamiento, este modelo matemático? Vamos a comprobarlo.

Una vez tenemos el fichero con los datos, los procesaremos con las librerías científicas numpy y scipy de Python. Como podemos ver en el código, se propone una línea de máximo ajuste de tipo sigmoide. Y efectivamente obtenemos una buena solución y un buen ajuste como se puede ver en la gráfica. En este caso, la ecuación obtenida es:

y =987.24 * (1 / 1 + exp(-0.07*(x-393.87))) +-8.02

No hemos de hacer demasiado caso a los datos del eje X, son tan sólo puntso. Sencillamente tener en cuenta que la distancia entre puntos son 30 segundos.

Esta es una sencilla y buena demostración de verano (un divertimento) de que la Naturaleza se describe con funciones matemáticas. Las mates son una buena herramienta para describir el comportamiento de la Naturaleza. Y que los fenómenos exponenciales son inherentes a la Física.

Este último año he estado estudiando métodos numéricos y las librerías científicas de Python, y realmente le veo muchas posibilidades, que quiero ir explorando este curso que comenzará de aquí poco.

# -*- coding: utf-8 -*-
#cel·la LDR que ha gravat com decau la llum al capvespre.
#La funció que s’ajusta a les dades és una sigmoide

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

def sigmoid(x, a, b, c, d):
y = c / (1 + np.exp(-b*(x-a))) + d
return y

y = np.loadtxt(‘../dades/LDR_capvespre.txt’)
x = np.linspace(1,len(y),len(y))
#print (x)
#print (len(x))

popt, pcov = curve_fit(sigmoid, x, y, p0=[350, 0.001,1000, 2]) #és necessari ficar uns bons paràmetres inicials

print popt
print (‘y =c * (1 / 1 + exp(-b*(x-a))) +d ‘)
print (‘y =’ + ‘%.2f’%popt[2] + ‘ * (1 / 1 + exp(‘ + ‘%.2f’%popt[1] + ‘*(x-‘ + ‘%.2f’%popt[0] + ‘))) +’ + ‘%.2f’%popt[3] )

plt.figure()
plt.plot(x, y, ‘k’, label=»Original Noised Data»)
plt.plot(x, sigmoid(x, *popt), ‘r-‘, label=»Fitted Curve»)

plt.legend()
plt.show()

# Resultat:
#y =c * (1 / 1 + exp(-b*(x-a))) +d
#y =987.24 * (1 / 1 + exp(-0.07*(x-393.87))) +-8.02

Open Data BCN: World Data Viz Challenge 2018

Participo en la edición de este año del World Data Viz Challenge 2018 Barcelona-Kobe. Entre el catálogo de datos abiertos que publica el Ayuntamiento de Barcelona, he escogido los datos de paro en el periodo 2011-2018. Mi aplicación de visualización la puedes ver en http://aturbcn.joanillo.org/. Se presentan los datos desglosados por barrios y por distritos, y se puede ver la evolución del paro a través de los años, o a través de los meses.

He utilizado la API de Open Street Map, que es una novedad para mi pues siempre había utilizado la API de Google Maps. Los datos originales estaban en formato xls, y se han introducido a una base de datos MySQL para poder explotar los datos directamente con SQL.

La idea de participar vino porque, de hecho, en el instituto queremos participar en otra convocatoria: Repte Barcelona Dades Obertes, segona edició 2019 (http://opendata-ajuntament.barcelona.cat/ca/repte-barcelona-dades-obertes). Hay que ver cómo, dentro de la asignatura de Javascript (Ciclo Formativo de Desarrollo de Aplicaciones Web), podemos hacer alguna visualización para presentarla en esta convocatoria.

Referencias:

script cncboxparam: corte láser de cajas de madera

El noviembre pasado le regalé a Maria una cajita de luz para iluminar la habitación [1]. Estoy contento del resultado, pero se puede mejorar tanto en la parte de construcción de la cajita, como en la parte de la electrónica (un timer 555 que hace apagar la luz después de 20 minutos).

Aquí va el script cncboxparam para automatizar la creación de cajitas (con un texto en la cara frontal). Genera un fichero que se puede enviar directamente a una máquina de corte láser. La idea que me persigue desde hace tiempo es hacer este tipo de cajitas minimizando los costes y el tiempo. Sería una prueba de concepto de diseo industrial y fabricación digital, ver hasta qué punto con pocos recursos se puede automatizar hasta hacer rendible un pequeo proceso industrial. El curso que viene me gustaría adquirir una máquina de corte láser, pero ya me hago la idea de que ser una de las máquinas xines más pequeñas.

La parte de la electróncia también la tendría que mejorar de cara al curso que viene. La idea es diseñar una nueva placa PCB y utilizar sólo componentes SMD, pero esto ya es otro tema.

El script está programado en C++ y compila sin ninguna librería especial. Para generar el texto se ha de tener instalada la utilidad truetype-tracer-dxf. Las pruebas las he hecho con LibreCAD, que es el programa de CAD que utilizo habitualmente.

Enlaces:

Proyecto CNC: script para un juego de mesa Abalone

Abalone Bord Game and hexagonal gridAbalone Es un juego de mesa diseñado por Michel Lalet y Laurent Lévi en 1987. Es un tablero con agujeros donde colocamos 14 canicas por jugador, y se trata de hacer fuerta seis canicas del contrincante. De hecho nunca he jugado a este juego, pero de momento construiremos un tablero.

El problema consiste básicamente en hacer una red en formato de colmena de abejas, que de hecho son hexágonos y triángulos equiláteros. Para dibujar los puntos sobre un programa de CAD (yo utilizo LibreCAD), enseguida necesitamos el cos(60) y el sin(60). Partiendo de una parrilla ortogonal no es fácil hacer esta parrilla. Lo mejor es crear un script y generar los puntos de forma automática.

Partimos de un fichero vacío de LibreCAD, creamos la capa puntos, y meto tres puntos de prueba. Abrimos con un editor de texto (los ficheros de CAD tienen un formato de texto plano) y localizamos los puntos de referencia. Ahora ya sabemos el formato que han de tener los puntos que queremos generar programáticamente.

Mostramos el trozo de código más representativo que genera la geometría de mi parrilla, script bee_grid.cpp:

...
\tfor (j=0; j
El script genera un fichero de texto con las líneas que podemos inserir en nuestro fichero original, y el resultado lo podemos ver en la foto. Es una parrilla de puntos para el juego del Abalone. La otra foto, la del juego del Abalone, no es mía (la he encontrado por Internet), pero este es mi objetivo: construir un tablero de Abalone. Para hacerlo ya tengo el fichero de CAD, después tendré que generar el G-Code, y finalmente fresar todos los puntos sobre una madera. Ya enseñaré el resultado cuando lo tenga acabado.

Enlaces:

update 21/06/2018: Este es el resultado final. He aprovechado una madera de cocina, que estaba muy marcada, pero el resultado final me gusta.

Curso de Inteligencia Artificial CSMM.101x finalizado

Finalmente ya he finalizado el curso de Inteligencia Artificial. Estas últimas horas he hecho el examen final, tipo test. Cuando tenga un poco de tiempo me gustaría repasar algún concepto y volverme a mirar el proyecto del Sudoku y los algoritmos que allá hemos utilizado. Y de cara este verano releer el libro Computational Beauty of Nature, donde había algún capítulo sobre redes neuronales.

Me ha interesado sobretodo la parte del Machine Learning, y de cara el curs que viene me gustaría hacer algún curso en este campo. Ya veremos.

Curso de Inteligencia l’Artificial en edx.org

Estoy haciendo el curso ColumbiaX: CSMM.101x de Inteligencia Artificial de edx.org. De hecho. ya lo estoy acabando. Ya estamos en la última semana, y para mi suerte, el último proyecto ya lo tengo entregado y me ha llevado menos faena de lo que me pensaba, sin especiales contratiempos. Ahora sólo me falta hacer el examen final que será el 23 de abril, Sant Jordi.

Los proyectos que se han realizado, todos ellos en Python, son:

  • Proyecto 1: Search Algorythms. BFS, DFS,… Se ha resuelto el 8-puzzle
  • Proyecto 2: Adversarial Search and Games. Se ha resuelto el juego del 2048, que de hecho yo lo he jugado bastante. Este proyecto me costó bastante, y efectivamente llegué a 2048 en una ocasión combinando diferentes heurísticas.
  • Proyecto 3: Machine Learning. Había tres problemas diferentes: I. Perceptron Learning Algorithm; II. Linear Regression; III. Classification
  • Proyecto 4: Constraint Satisfaction Problems. Aquí resolvimos el juego del sudoku con los algoritmos del AC-3 y del backtracking.
  • Proyecto 5: NLP, Natural Language Processing. Un proyecto muy interesante. Había un train data de 25000 comentarios de películas, valoradas del 0 al 10. Y después también hi havía un test data de 25000 comentarios que se tenían que valorar después de entrenar el sistema.

El resumen de las semanas ha sido:

  • Week 1: Introduction to AI
  • Week 2: Intelligent Agents and Uniformed Search
  • Week 3: Heuristic Search
  • Week 4: Adversarial Search and Games
  • Week 5: Machine Learning I
  • Week 6: Machine Learning II
  • Week 7: Machine Learning III
  • Week 8: CSP
  • Week 9: Reinforcement Learning
  • Week 10: Logical Agents
  • Week 11: AI Applications: NLP

Por suerte el curso ya se está acabando porque me ha tomado más tiempo del que tenía y del que quería dedicarles. Pero realmente ha sido interesante y exigente, y me he tenido que poner las pilas con el Python. Realmente el tema de las estructuras de datos, y las diferentes librerías que se han utilizado con Python, son muy potentes.

Intentaré seguir leyendo cosas sobre Inteligencia Artificial (IA) y Machine Learning (ML).

NOTA: todavía no tengo acabado el proyecto de la máquina de dardos, y de hecho me doy cuenta de que el problema de acertar dónde ha tocado el dardo y qué puntuación tiene, a parte de un problema de CV (Computer Vision), también es un problema de ML (Machine Learning).

cnchollow script. Generador de G-Code para fresar diferentes tipos de cavidades

Hemos estado programando un script en C++ para hacer cavidades. Cavidades de diferente tipo: rectangulares, rectangulares con cantos redondeados, circulares y elípticas. Además, la profundidad de la cavidad puede ser constante (cavidad cilíndrica) o bien una cavidad esférica. Por tanto, hay 8 posibilidades de cavidades diferentes, como se ve en la imagen, con diversos parámetros que puedes controlar. El script genera el G-Code directo para ser fresado.

Si quieres utilizar el script, primero tendrás que mirar las ilustraciones que hay en la documentación, y así entender los diferentes parámetros. Básicamente tenemos que introducir el origen de coordenadas de la cavidad (allá donde está centrada); los semiejes en el caso de los rectángulos-elipse, o el radio en el caso del círculo; la profundidad final en el caso de cavidades cilíndricas; el radio esférico en el caso de cavidades esféricas, que dará lugar a más o menos profundidad esférica. En función de la broca que tengamos y de la resolución que queramos, también hemos de definir el paso lineal y el paso de profundidad (parámetros -m y -n).

Para las cavidades cilíndricas hay suficiente con utilizar brocas normales de fresar (las de 2mm de diámetro son las más pequeñas que he conseguido). Pero para las cavidades esféricas es interesante utilizar una broca tipo round nose bit, y así conseguimos un mejor acabado, como se puede apreciar en la foto.

El primer proyecto para utilizar mis cavidades es fresar el juego del mancala (o awalé o otros nombres), donde quiero fresar varias cavidades diferentes. Ya informaremos cuando esté acabado.

Es un proyecto escrito en C++, no requiere ninguna librería especial, por tanto su compilación es directa. Para la versión 1.0.6, la última versión:

$ g++ -o cnchollow cnchollow-1.0.6.cpp
Ex:
$ ./cnchollow -f rectangle -t cylindrical -x 100 -y 100 -r 30.23 -s 15.21 -z -10.3 -m 3.0 -n -1.0 -o ./cnchollow.ngc

Referencias:

script cncstroke: mejorando la conversión DXF a G-Code, II

Creo un proyecto con LibreCAD, creo la capa »stroke», y aquí metemos las polilíneas, tal como se ha explicado en el anterior artículo [1], y tal como se muestra en la imagen. Con lenguaje C++, lo primero que hacemos es leer el fichero dxf y detectar la capa stroke, con todos sus puntos. En el LibreCAD todas las líneas son iguales, tienen un origen y un final. Pero a mi me interesa detectar las polilíneas, que son las líneas enlazadas de manera que el punt final de una línea es el mismo que el punto de origen de la línea siguiente. Recordemos la estructura de datos que se utiliza:

struct linia {
\tint x0;
\tint y0;
\tint x1;
\tint y1;
\tdouble length;
};

struct polilinia {
\tstd::vector vlinia;
\tdouble length;
};

std::vector vpolilinia;
Recorremos todas las líneas, y vamos añadiendo elementos al vector polilínea, y dentro de cada polilínea vamos añadiendo elementos al vector línea. Para cada línea y para cada polilínea, tenemos calculada su longitud. Una vez tenemos rellenado el vector de polilíneas con sus líneas, ya podemos recorrer todas las polilíneas y generar la salida G-Code, de manera que el inicio de una polilínea está a profundidad -2mm, y el final de la polilínea está a profundidad 0mm, tal como se aprecia en este trozo del G-Code resultante, y en la imagen:

(* POLILINE #2 *)
G0 X 30 Y 30
G0 Z 3.000
F150
G1 Z -2.0
F400
G1 X 50 Y 40 Z -1.11
G1 X 60 Y 30 Z -0.55
G1 X 70 Y 40 Z 0
F150
G0 Z 5.000

Como se aprecia en el G-Code, posicionamos la broca en el punto (30,30), agujereamos hasta -2.0mm, y vamos pasando por tres puntos sucesivos mientras vamos levantando de forma proporcional la broca hasta llegar al punto (70,40), punto en que la broca deja de atacar la superficie. Así conseguimos un trazo variable, tal como se aprecia en la imagen. Con esta técnica podremos perfilar detalles en los trabajos CNC, como pueden ser los cabellos de un retrato, o el trazo en una caligrafía.

Como se aprecia en la imagen (extraída del proyecto de fresar el retrato de Albert Einstein en blanco y negro, en otra entrada mostraremos el resultado final), se ve el resultado de aplicar el script cncstroke para las polilíneas agrupadas en la capa stroke del proyecto LibreCAD. Vemos dos trazos que acaban en punta (en la part izquierda de la imagen, sobre madera), y otro trazo, donde no se ha aplicado el script, que no acaba en punta. En la parte derecha de la imagen vemos un trozo del proyecto LibreCAD donde se han definido estas líneas (dos que pertenecen a la capa cncstroke, y otra que se fresa normal). Así pues, con un uso correcto del proyecto LibreCAD, podemos aumentar la resolución del fresado CNC, consiguiendo un efecto más real y detallado.

Puedes descargar y estudiar el código del script cncstroke desde el siguiente enlace [2] .
Referències:

Nota aclarativa: En el proyecto cncstroke utilizamos el término polilínea como sucesión de líneas enlazadas. Ahora bien, para generar estas líneas enlazadas, en LibreCAD, utilizamos la herramienta línea (y no la herramienta polilínea) (En una futura versión se estudiará la posibilidad de utilizar la herramienta polilínea, o ambas).