sábado, 27 de febrero de 2010

Laberintos (V): ROBOREALM

Roborealm es, hablando muy por encima, una aplicación de visión artificial y procesamiento de imagenes. Roborealm podría llenar por sí sólo blogs y blogs, así que lo que voy a contar aquí, no hace más que arañar la superficie de la cantidad de cosas que se pueden hacer con él.

En este ejemplo vamos a proporcionar sentido de la vista a nuestro robot. Y hablando más técnicamente, vamos a transformar una imagen de un laberinto, en información que pueda entender el robot. En este caso, una matriz de dos dimensiones, que indique si hay pared o hay camino libre para moverse.



Como se puede ver, lo que voy a intentar conseguir en que posiciones de la matriz habrá pared o no. Que podría ser perfectamente una matriz de booleanos.

Empecemos a trabajar con RoboRealm. Recordar que tenéis que jugar con ello para obtener buenos resultados y que yo disto mucho de ser un experto en su uso. seguro que se os ocurren muchas y mejores maneras de hacer lo mismo que yo.

Información en bruto

El punto de partida en RoboRealm es un dispositivo capturador de imagenes, como puede ser una cámara web, o una imagen, como es el caso que nos ocupa.



Sobre estas imágenes se aplican una serie de filtros de manera consecutiva que van filtrando, extrayendo, modificando ... de modo que podamos extraer información útil de la misma.

Lo primero que vamos a realizar sobre la imagen es aplicar el filtro Affine. Este filtro modifica los límites de la imagen para cuadrarla. Y fingir que estamos mirando el laberinto desde arriba. De este modo queda mucho mejor delimitado el laberinto.



De todo lo que aparece en la foto, sólo nos interesa los papeles verdes. Vamos a filtrar utilizando el RGB Filter.





Ahora ya sólo tenemos en la imagen información interesante. Vamos a centrarnos en obtener tres cosas: dónde está la meta, dónde está la salida y dónde están las paredes.

Obtener la meta
Como se puede ver en la imagen inicial, la meta está representada con un triángulo. Luego deberemos buscar en la imagen objetos con forma de triángulo. Yo lo he resuelto de la siguiente manera.

Utilizando el Blob Filter, podemos buscar formar en la imagen. En este caso queremos sólo buscar formas que tengan un área triangular y pulsamos CREATE BLOBS VARIABLE. Esta variable almacena el centro de gravedad de todos los objetos devueltos por el filtro. De este modo tenemos el punto donde está la salida dentro de la imágen.



Y ahora con el lenguaje de script que tiene roborealm, introducimos la variable BLOBS en la variable TRIANGULO.



Tras esta serie de pasos, tenemos en la variable TRIANGULO de RoboRealm la posición de la salida.

Obtener la salida

El procedimiento es similar. Volvemos a la posición de partida, con el marcador de inicio. Aplicamos un nuevo Blob Filter, pero esta vez buscamos objetos que tengan forma circular. Marcamos "CREATE BLOBS ARRAY VARIABLE"

De forma similar a antes introducimos la variable BLOBS en una nueva variable CIRCULO. Tenemos que hacer esto, porque si no, la llegada, habría sobrescrito el valor de la llegada.



Tras esta serie de pasos, tenemos en la variable CIRCULO de RoboRealm la posición de la meta.

Obtener las paredes

Las paredes se obtienen de manera similar. La única salvedad es que ahora tendremos no sólo un punto, sino un array de los mismos. Esto es importante de cara a recuperar los valores desde aplicaciones fuera de roborealm.

Aquí podemos ver los pesos que tienen las figuras, el triángulo y el círculo han desaparecido porque hemos ajustado un valor muy alto. De este modo podemos ajustar los objetos "más cuadrados", "más redondos" ... Este filtro es muy interesante y creo que es el que más juego puede ofrecer.





Tras esta serie de pasos, tenemos en la variable PAREDES de RoboRealm la posición de las paredes.

Comunicación con otros sistemas

Ahora voy a mostraros otra característica bastante interesante de RoboRealm, que es la comunicación con otros sistemas a partir de su API. Vamos a facilitar toda la información que ha extraído RoboRealm a la imagen, a un pequeño programa escrito en java. Este programa será el encargado de encontrar una salida al laberinto. Pero eso será en otra entrada.

De este modo estoy separando el procesado de la imagen, con el procesado de la información extraida de la imagen. Así, detrás de RoboRealm, podemos tener cualquier otro sistema de resolución de problemas, más apropiado al caso que nos concierna.

El uso de la API es bastante sencillo. Roborealm disponibiliza un servidor de telnet al que podemos atacar, por ejemplo, solicitando variables con

 
<request>
<get_variables>VAR_1_NAME, VAR_2_NAME, etc.</get_variables>
</request>



y aquí podemos ver como Roborealm nos ha devuelto los puntos donde estaban las paredes.

Y con esto he dado una pequeña introducción a RoboRealm. Espero que haya quedado relativamente claro, y animaros una vez más a trastear por vuestra cuenta, porque con la visión artificial se amplían bastante los límites de los proyectos que podemos emprender con nuestro robot.

laberintos (IV): ¿Qué vamos a utilizar?

Todo esto está muy bien: tenemos un lego, un laberinto en el suelo ... pero nos falta algo. ¿Cómo vamos a hacer a lego inteligente para encontrar la salida? ¿Cómo va a ver el lego el laberinto? ... hay muchas preguntas, así que vamos a contestarlas por partes.

¿Cómo va el lego a interpretar el laberinto?
Vamos a utilizar Roborealm. Es un software de visión artificial. De este modo, podemos hacer que el lego "vea" a través de roborealm (mediante una foto del laberinto o una cámara web enfocada al laberinto), dónde está metido.

Una vez que ya sabe dónde está metido ¿Cómo va a saber salir?
Para esto vamos a usar inteligencia artificial. Vamos a aplicar algoritmos de búsqueda de soluciones sobre lo que ve Roborealm y dar una solución al problema.

Chuck Norris una vez tuvo un Lego Mindstorms. La televisión hizo documental sobre él, le llamó The Terminator.

Uff, muchas cosas ¿Cómo lo vamos a unir todo?
Es un poco lio la verdad, pero lo voy a intentar explicar lo mejor que pueda.

Roborealm va a reconocer la información del laberinto.

Esa información va a ser procesada por un algoritmo de búsqueda de soluciones implementado en java. De este algoritmo se obtienen una serie de movimientos que son los que tiene que hacer el robot para salir del laberinto.

Mediante matlab vamos a enviar esa serie de movimientos al robot para que salga del laberinto.

Es importante resaltar que no es el bloque el que sabe salir del laberinto, si no que se limita a escuchar los movimientos que le llegan.

Hay una entrada para cada una de estas partes, así que allí intentaré explicarlo un poco mejor

Vamos al lío !!!

Laberintos (II): el laberinto

Vamos a hablar de las partes de las que va a constar este experimento: un lego saliendo de un laberinto. Creo que a estas alturas todos sabemos lo que es un lego, así que no queda otra que hablar del laberinto.

Recortando trozos de papel cuadrados he dibujado en el suelo de mi habitación un laberinto cuadrado 5x5 como puede ver en la siguiente imagen. Los bordes no están limitados por otros cuadrados, si no por las dimensiones.




El robot se puede mover por el suelo que no está ocupado por cuadrados verdes.

La salida estará representada por un triángulo y el punto de llegada con un círculo.



Y aquí diferentes laberintos.








Si mi habitación fuera más grande ... pues podría hacer un laberinto enorme.


Lo que pretendo es que el robot situado en la entrada, vaya hacía la salida.


Con esto creo que ya está explicado el dominio del problema.

Laberintos (I)

Hola a todos,

Hace bastante bastante tiempo que no publico nada. No es que haya estado sin tocar estos temas, pero nada de lo que he intentado me ha salido bien.

Aunque hoy escribo porque tengo un nuevo tema, y he obtenido un bonito resultado. A lo largo de las siguientes entradas podréis ver como mi lego escapa de un laberinto dibujado en el suelo.

Un saludo y espero que la espera haya merecido la pena.

sábado, 27 de junio de 2009

Vehiculo que aparca sólo (SPC, Self Parking Car)

Uno de los robotos hechos con el nxt más recurrentes que podemos encontrar por youtube (fuente inagotable de inspiración), son los llamados SPC.

He modificado un poco el siguiente diseño de nxtPrograms, y he obtenido lo siguiente, un pequeño coche con dirección.

Lo importante de este diseño es la dirección, que nos permitirá girar para aparcar el coche. Además de ya por fin ver cumplido mi sueño de construir un vehículo con dirección)


Y el sensor de ultrasonidos, que nos permitirá encontrar huecos en la carretera o sobre una mesa con libros, donde podamos aparcar el lego.


El resultado que he obtenido es el siguiente.


El resultado es medianamente aceptable. He tenido que recordarme a mi mismo que tengo que hacer prácticas de aparcar con el coche de nuevo, y comprarme coche ya de una vez también.

El sensor de ultrasonidos, tan sólo se usa para encontrar un hueco para aparcar, los demás giros que hace el lego, están metidos a capón en el código del programa. Ha sido un caso de programación por prueba y error. Como veis no entra mucho en el hueco, se queda más bien fuera, sospecho que es probelma de que la dirección no gira tanto como debería.

Esto es un modelo muy sencillo, pero ya que estamos, voy a ver si lo mejoro un poco. He visto en youtube dos videos realmente interesantes.

Este lego me ha gustado mucho porque creo que se asemeja mucho a lo que hace un conductor real cuando aparca, una vez que el coche está medio metido, avanza hacia delanta y atrás mirando hasta que el coche esté bien encajado.

No parece muy complicado añadir esta modificación al lego que tenemos entre manos, aunque eso será otro día.

Este video se lleva la palma, especialmente los últimos segundos, cuando se vé quien hace realmente toda la chicha. El autor no da ninguna información sobre el proceso o que usa para hacer ese gráfico tan bonito que da la ruta que debe tomar el robot. Sólo que está hecho con .net.

Parece un caso para matlab y alguna de sus toolbox. Investigaré un poco y veré que puedo encontrar.

Me he puesto dos objetivos de tarea, a ver si cumplo alguno.

lunes, 9 de marzo de 2009

Rotar 360 grados sobre si mismo

Hoy voy a dar una solución a un problema que creo que todos los que jugamos con nuestro lego nos hemos encontrado alguna vez. Hacer una rotación completa en el sitio.

Es una situación bastante común
  • Un robot que analice el entorno para detectar algo. Como el ball hunter de nxtprograms, o mi fallido intento de hacer un mapa del entorno.
  • Un robot que vea algo que no le guste y de media vuelta. Como por ejemplo la demo del nxt.
Para hacer que el tribot gire sobre si mismo, lo que todos hemos hecho alguna vez ha sido poner que los motores giren 360º cada uno, pero en sentido contrario. Pero ... ¡¡¡ se queda corto, no gira más !!! ... ¿Nos suena esto verdad? algo no cuadra.


Un poco de geometría, nos dará no sólo la solución sino que nos ayudará a comprender el problema. Lo principal es recordar que el perímetro de una circunferencia es pi * diámetro ó pi * 2 * diámetro.


Pongamos de ejemplo la vuelta de una rueda de bicicleta (el reflectante empiece en el punto más bajo y vuelva a estarlo). La distancia que ha recorrido la bicicleta es pi*diámetro. También, la rueda de la bicicleta, ha girado 360 grados. Es decir, para girar 360º hace falta recorrer el perímetro completo.


Ahora mirad el siguiente dibujo. Es nuestro tribot visto desde arriba y dibujado por un pintor abstracto. Los rectángulos de los lados son las dos ruedas del tribot y la circunferencia sobre las que están, es lo que tienen que girar para hacer un giro completo. Para que el tribot gire completamente sobre sí mismo, cada rueda tiene que girar volviendo a su posición original.



Nuestro fallo, es que hacemos que cada rueda gire 360º, es decir, pi*diámetro, cuando en realidad lo que tienen que recorrer es pi*distancia entre las dos ruedas,que es el diámetro de la circuferencia grande.

Ahora unas fórmulas que nos harán la vida más fácil y también la correspondencia entre grados, radianes y coordenadas polares.

Las veces que tiene que girar la rueda para volver al origen, o para recorrer 360º pi*distancia entre ruedas / pi * diametro rueda = distancia entre ruedas / diametro rueda.

Si queremos que el giro no sea de 360º sino de un número de grados en concreto, pues una regla de tres. Dividimos entre 360º para sacar lo que recorre en un grado y multiplicamos por n, número de grados. (distancia entre ruedas * número de grados) / (diámetro ruedas * 360º)

Sobre radianes y grados. En este enlace de la wikipedia, os lo contarán mucho mejor que yo. Pero recordad que pi radianes son 180º.

viernes, 30 de enero de 2009

derrotado otra vez

Retomando mi última creación.

Estaba totalmente seguro de que el problema era que las paredes estaban muy lejos, por lo que situaba al nxt en un entorno mucho más reducido (un "corral" hecho con libros), obtendría mejores resultados. También incluí algunas mejoras en el programa, como por ejemplo la normalización de datos

Nada más lejos de la realidad.

Esto es lo que detectaba si el robot estaba totalmente encerrado dentro de un cuadrado hecho de libros. Hay puntos repartidos por todo el contorno. ¡¡¡ Pero no equidistantes del centro !!!



Y esto lo que detectaba si quitaba una pared del cuadrado. En la parte de abajo de la gráfica no hay ningún punto detectado.



Como veis con mucha mucha imaginación ... algo se puede sacar. Pero visto que rodeando al robot con libros tampoco obtengo buenos resultados, voy a desistir de este modelo y cambiar la construcción del robot.

Lo único que girará será el sensor de rotación y extremadamente lento.

No obstante, esto me ha servido para probar la facilidad con que en matlab puedo representar gráficas, eliminar ruido, calcular medias ...

A ver si tengo tiempo y pongo un pequeño video del robot dando vueltas ... no hace nada, casi me da verguenza enseñarlo.



domingo, 18 de enero de 2009

primera aproximación a un robot que detecta su entorno

En este nuevo proyecto, quiero abordar la construcción de un robot que "vea" el entorno en el que se encuentra, e intente alejarse lo más posible de su punto de partida. Para ello aprovecharé el modelo de robot que presenté en este mismo blog y sustituiré el sensor de intensidad de luz por el sensor de ultrasonidos. El modelo resultante lo podeis ver aquí mismo.




El funcionamiento que tengo en mente es el siguiente: que el robot gire 360º sobre sí mismo a la vez que recopila información sobre su entorno mediante el sensor. Esta información es la distancia a los objetos que existen a su alrededor. 

Lo que pretendo es averiguar el punto que más alejado esté del origen y desplazar el robot hacía allí, y repetir el proceso otra vez. Teniendo en cuenta de que no vuelva por donde haya venido.

Este proyecto en nxtprograms hace algo muy similar a lo que yo quiero, por lo que bajaré el programa para el nxt-g y estudiaré las partes que me puedan venir bien.

Lo más interesante del programa es lo siguiente. Se puede ver que si se encuentra un objeto, a una distancia menor que un objeto que ya tuvieramos localizado, guardamos este nuevo objeto como el más cercano, a la vez que también guardamos la nueva posición.

Es interesante ver como la posición se guarda reseteando la cuenta de grados recorridos por el motor, de este modo al rotar el motor a su posición inicial tendremos el objeto más cercano delante.

También se puede ver como no hay ninguna medida estándar para que el robot gire 360º sobre si mismo. Haciendo pruebas he calculado que unos 600º de giro de una rueda equivalen a 360º del robot.





A continuación esbozo un pseudocódigo de lo que hace el robot mientras gira

variable distanciaMasLejana <- 0
variable gradosDistanciaMasLejana <- 0 

mientras el robot gira
variable valorRecogido <- recojo medición del sensor de ultrasonidos
si valorRecogido > distanciaMasLejana // es decir, hay un punto más lejano al que puedo ir que el que tenía almacenado
distanciaMasLejana <- valorRecogido
reseteamos motor
fin si
fin mientras el robot gira

Una vez que haya finalizado el giro del robot, en la posición inicial de giro tendremos el camino más largo para andar.

Teniendo en cuenta todo lo anterior ... vamos a entrar en harina. Un poco de matlab por aquí y por allá, un par de maldiciones ... y más o menos ya lo tengo. Antes de todo unas consideraciones

  • Como he hecho en robots anteriores, tomar varias medidas y luego hacer la media, no funciona aquí. Se podría pensar que si el robot en vez de dar una vuelta, diera cinco se tendría mucha más precisión. Se obtiene todo lo contrario. Como los grados que se recorren no son exactamente múltiplos de 360º, y el sensor está moviéndose contínuamente mientrasa hace mediciones ... a más vueltas, lo que se obtiene el que es robot está rodeado de todos los obstáculos.



  • Es bastante complicado interpretar el dibujo resultante. El que se ve a continuación es el del robot situado en medio de un pasillo. Con paredes cerca a los lados y paredes al principio y al final del pasillo que no se ven. Se puede ver que con cada ejecución del programa, obtenemos un resultado bastante diferente.




  • Voy a filtrar en el resultado los valores muy altos, para ello no voy a mostrar en el resultado aquellos valores que estén muy por encima de la media. Se puede ver como ahora el resultado es un poco más intuitivo.



  • Aqui vemos el resultado con una botella. La verdad es que no se ve nada ... por lo que deduzco que sólo podrá detectar objetos pequeños.



Más que suficiente para una entrada en el blog. Voy a titularla primera aproximación a un robot que detecta su entorno. Es una primera aproximación por que intuyo que esto no va a funcionar realmente.

  • Es incapaz de localizar objetos pequeños en distancias medias.
  • Los gráficos resultantes son extremadamente dificiles de interpretar.
  • A parte que hay como dos tipos de gráficos: unos con los puntos bien delineados y otros con grupitos curvados. Ignoro a qué se debe eso todavía.
  • El robot no puede girar excesivamente lento, ya que necesita algo de potencia para mover todo su peso. Esa es la razón de los gráficos tan extraños.

La solución podría ser cambiar totalmente el diseño del robot. Montando el sensor sobre un servo, que gire extremadamente lento y consiga unos resultados más precisos con muchas más mediciones por giro. Pero eso ya será en otra ocasión.

También este robot podría tener otro ámbito de actuación, como por ejemplo un laberinto de paredes estrechas. Sería interesante probar su desarrollo en un campo de esas características.

En la próxima entrada acabaré el programa, probaré el robot en varios entornos y subiré algún video.

Un saludo a todos.

domingo, 14 de diciembre de 2008

Clasificación First Lego League Madrid 2008

Hoy he tenido la oportunidad de trabajar como voluntario en la ronda clasificatoria de la First Lego League 2008 española que ha tenido lugar en Madrid. Mi colaboración ha sido más bien escasa al ser mi primer año y se ha reducido a vigilar a los chavales en el PIT o área de entrenamiento, en la lengua del Cantar del Mio Cid.

En el área de entrenamiento los chavales disponen de una réplica del tapete de juego donde se hacen las eliminatorias oficiales, y les sirve para hacer los últimos retoques a los robots.



Los chavales parecen ser igual que los mayores, porque salvo un grupo al que no le he visto entrenar casi nada (los ganadores finales he de añadir), los demás han dado buena cuenta de su tiempo de práctica.

Esto me ha dado la oportunidad de ver un montón de robots interesantes. La verdad es que me han sorprendido varios de los robots, para estar hechos por chavales. Había mecanismos muy ingeniosos. Muchos de ellos programaban con labview dejando de lado al nxt-g.

A título personal diré que me hubiera gustado poder echar un ojo a los proyectos más en profundidad, puede que al próximo año si sigo de voluntario, intente hacer de juez de proyecto técnico. O tal vez se podría sugerir que los proyectos ganadores se alojen en una especie de repositorio al más puro estilo nxtLog (un modelo lxf y un documento con su documento técnico )

La final española será en el Cosmo Caixa de Barcelona el día uno de febrero de 2009.

Enhorabuena a los ganadores, y mucha suerte en la ronda final española.

Ya por último, otro pequeño evento de robótica usando lego. El viernes se celebró el V Certamen de Robótica Educativa, la complubot. Podeis ver el evento, que fué retransmitido en directo aquí. Unos combates de sumo, laberitnos, y seguidores de líneas, y se presentó lo que puede ser un nuevo sensor de movimiento: wedo

sábado, 13 de diciembre de 2008

vehículo para muchos propósitos

Hola a todos, hoy me gustaría presentaros un modelo de vehículo que pretendo usar para varios modelos como base. 



Es un pequeño vehículo capaz de ir en cuatro direcciones a ras de suelo, pero con la peculiaridad que se deja poner en la parte adelantada cualquier sensor, apuntando al frente o al suelo. Esto nos permite hacer con él, dependiendo del sensor que coloquemos, robots con propósito totalmente diferente.

Con este diseño consigo que robot y sensor giren a la vez, haciendo posible recopilar datos de los 360 grados. Si sólo girara el sensor, quedando el resto del robot fijo. El cable que une sensor-bloque, se enrollaría sobre si mismo quitando maniobrabilidad al conjunto.

El procedimiento para colocar los sensores, va a la imaginación de cada uno, pero viendo el modelo, creo que lo tendreís bastante fácil.

Este modelo en concreto con el sensor de luz apuntando hacia el suelo, lo he utilizado para programar el típico robot que sigue la línea del tapete. Lo he programado en matlab, para variar y la verdad es que he tenido buenos resultados. 

No he conseguido que sea tan rápido como mi anterior intento usando el nxt-g. Creo que al tema motores, sensores ... no le acabo de coger bien el truco con la toolbox. También cabe la posibilidad, de que todo sea debido a que he usado bluetooth, y tiene un retardo mayor que el usb, o el programa embebido. No he hecho ningún video porque no he aportado nada distinto al que ya tenía hecho.

Ahora quiero usar este modelo de coche con el sensor de ultrasonidos para hacer un robot que salga de laberintos o alguna cosa similar. Ese es mi próximo proyecto.

Aunque siguiendo con el tema de seguir líneas ... tengo otro proyecto en la trastienda. Mirad que video más espectacular.



He hablado con el autor y muy amablemente me cedió el lxf y el rbt asociado, así que creo que intentaré repetir su proyecto y programarlo con matlab. Ya os contaré. Muchas gracias cesky79. Youtube es sinduda una fuente inagotable de sabiduría

Voy a volver a casa por navidad, como el turrón, así que estaré un poco aislado de mi lego. Tendreís noticias mías a la vuelta de vacaciones.

¡ Felíz navidad a todos !