Vistas de página en total

jueves, 24 de noviembre de 2011

APRENDIENDO A VIAJAR SOLO!!

Aquí estoy una semana más para mostraros los avances que he realizado en la siguiente práctica. Como recordaréis, en la última entrada vimos la forma de trabajar con los sensores, cómo estos aportaban datos y cómo utilizarlos para realizar ciertos comportamientos (sigue pared, moverse por sonidos, chocar, etc). En esta nueva práctica se da por sentado que hemos adquirido estos conceptos y nos centramos en la navegación, concretamente navegación local, es decir, aquella que se caracteriza por utilizar los sensores para reconocer el entorno y moverse por él, al contrario de la global que hace uso de un mapa.

Bien, siguiendo con la estructura que siempre adopto para explicar cada una de las prácticas pasaré a explicar uno a uno los cuatro apartados que forman ésta:

BUMP & GO CON SENSORES DE CONTACTO

Supongo que este título ya os suena, sin embargo, no es exactamente igual al de la práctica anterior. En esta ocasión no sólo deberemos detectar cuando chocamos con un obstáculo, realizar un giro y continuar hasta chocar con otro, sino que el objetivo de este apartado es conseguir que Manué viaje de una posición a otra salvando los obstáculos que se encuentren a su paso.

Para conseguir este objetivo se ha hecho uso de la clase "Behavior" que ofrece ya el LEGO NXT implementado. La estructura es simple, existen dos comportamientos ("ir hacia la meta" y "chocar") que compiten por "entrar en acción", mientras que un "árbitro" es el que determina (por medio de unas condiciones) cual comportamiento debe ejecutarse en cada momento. El comportamiento "ir hacia la meta" tiene un objetivo bastante intuitivo, conseguir orientar al robot para que avance hacia el punto de destino, mientras que el comportamiento "chocar", determina lo que debe hacer el robot en caso de choque, que no será otra cosa que esquivar dicho obstáculo.

A continuación muestro unos vídeos sobre como Manué consigue realizar esta tarea con los obstáculos colocados de forma diferente y con situaciones distintas:



Aunque parece algo sencillo, hay que recordar que Manué no sabe en un principio donde se encuentran los obstáculos, solo sabe donde en que punto se encuentra la meta, con lo que siempre que esquiva un obstáculo debe orientarse para saber que paso ha hecho y saber donde está la meta en todo momento.

BUMP & GO CON SENSOR DE ULTRASONIDOS

"Sí, ahora hace lo mismo pero con el de ultrasonidos..." estareis pensando. Pues básicamente sí, el objetivo no es otro que el de llegar a un punto evitando los obstáculos que se encuentran en el camino. Pero en este caso tenemos algo más complejo, ya que he hecho uso del algoritmo VFF (o al menos eso he intentado). Este algoritmo se caracteriza por un vector atractivo que nos dirige continuamente hacia la meta, y varios vectores repulsivos, tantos como obstáculos haya en el camino.

Sin embargo, mi versión del programa no es completamente fiel a este algoritmo, ya que pienso (y esto es opinión mía) que la complejidad de realizar este algoritmo con las herramientas de las que disponemos supera con mucho a la eficiencia que éste puede dar, es decir, muy complicado para conseguir un resultado similar a otros más sencillos. El que yo propongo digamos que es una versión mucho más "light" puesto que no tengo en cuenta todos los obstáculos que ejercen fuerza repulsiva, sino que detecto si un objeto se encuentra al frente y, en este caso, giro para esquivarlo (aquí sí sumo del vector repulsivo de ese objeto con el atractivo de la meta), y finalmente vuelvo a orientar a Manué hacia la meta para que continúe su recorrido.

Bueno, mejor vemos el resultado, en este os adjunto un par de vídeos aumentando la distancia de la meta, siendo en uno de 1m y en el otro 2m:




PERSIGUE LA LUZ

PERSIGUE LA LUZ ESQUIVANDO

martes, 8 de noviembre de 2011

PRACTICA 3: Y AHORA...LOS SENSORES!

Bueno gente, aquí estoy una semana más para mostrar los avances que he realizado con Manué.

Antes de nada, voy a mostraros algunas fotos del nuevo diseño de Manué, que como veréis, será necesario para la ejecución de las aplicaciones que posteriormente mostraré:

Como se puede ver en las imágenes ha sido necesario añadir tres sensores (y un cuarto que muestro más adelante) .

Está bonico, eh? Bueno, al lío:

En la anterior entrada se vieron las primeras aplicaciones cuyo objetivo era aprender cómo se comportan los diferentes actuadores que posee un robot jugando con sus motores, con la odometría y una pequeña interfaz en el LCD que mostraba la trayectoria que realizaba éste. El objetivo de esta práctica es aprender a saber manejar los sensores, cómo procesan sus datos y cómo podemos usar éstos para definir un comportamiento concreto para nuestro robot. Bien, como es costumbre, explicaré uno a uno los apartados de los que se compone centrándome en aquellos aspectos más interesantes.

OBTENIENDO INFORMACIÓN

Información sensorial
Este primer apartado trata la visualización de cierta información que podemos obtener tanto internos, como de algunos sensores, concretamente lo que se muestra es lo siguiente:

- NOMBRE DEL ROBOT
- VALOR DEL SENSOR DE ULTRASONIDOS
- VALOR DEL SENSOR DE LUZ NORMALIZADO
- TENSIÓN DE LA BATERÍA EXPRESADA EN MILIVOLTIOS
- MEMORIA LIBRE EXPRESADA EN BYTES.
- VALOR DEL SENSOR DE LUZ EN CRUDO

He de comentar aquí, que para hacer este apartado hago uso de dos hilos (threads) por un lado uno que se encarga de mostrar los datos estáticos como son el nombre, la tensión y la memoria, y por  otro lado la visualización de los sensores de ultrasonidos y luz, cuyos valores varían en tiempo de ejecución.


CONTROL DEL ROBOT POR SONIDO

Este es el primer apartado donde ya definimos un comportamiento concreto para el robot utilizando los datos que nos ofrece un sensor, concretamente el de sonido. El objetivo es que el robot comience a moverse al escuchar una palmada y se pare al escuchar de nuevo una palmada.

Antes de realizar el comportamiento dicho es necesario realizar una calibración de sonido para que Manué sea capaz de ignorar el ruido ambiental, y no interprete un mínimo ruido como si de una palmada se tratara. Para ello el programa se inicia en modo calibración y estará tomando valores hasta que se presiona la tecla [ENTER], momento en el cual comienza su comportamiento. A continuación os dejo un vídeo para que veáis que obediente es:




BUM & GO CON SENSORES DE CONTACTO

Hemos visto como avanza Manué por medio del sonido, pero...y si se choca? bien, pues ese es el objetivo de este apartado, saber cuando se choca y tomar una decisión con respecto a ello.

El enunciado de la práctica simplemente pide que sepamos cuando se choca, y cuando lo haga, retroceda y gire un nº aleatorio de grados, pero en este caso he ido un poco más allá, porque no es lo mismo chocar, que chocar y tener una idea de por donde ha chocado. Para ello he incorporado dos botones al robot (en lugar de uno), cada uno orientado en una dirección como muestra la siguiente imagen:



De esta forma sabe por donde ha chocado y hacia que dirección debe girar un número aleatorio de grados, es decir, si se activa el izquierdo girará a la derecha y viceversa. Os muestro el vídeo para que veáis su comportamiento:




BUMP & GO CON SENSOR DE ULTRASONIDOS

Acabamos de ver cómo comandar a Manué qué debe realizar si se choca, pero y si podemos conseguir que esto no llegue a pasar? a nadie le gusta ir dando "trompicones"!

Para conseguir que no se choque vamos a hacer uso del sensor de ultrasonidos, el cual emite una onda de sonido y tras recibir el "rebote" de ésta con un obstáculo obtiene la distancia a la que se encuentra éste. A simple vista el comportamiento es sencillo, Manué irá enviando sonidos y cuando detecte que tiene un objeto a una distancia prudencial girará un número aleatorio de grados, veamos cómo lo consigue:




Pero aún hay más, y es que me he tomado la molestia de programar una segunda aplicación en la que Manué no sólo no se choca, sino que es capaz de determinar en cada momento cual es la mejor dirección que debe tomar ya que está libre de obstáculos (o el obstáculo está más lejos que en otras direcciones). En cuanto a implementación, la cosa se dificulta en relación al anterior, ya que como se puede ver el sensor va girando 180º para conocer el entorno y toma las distancias de los objetos en esas direcciones, luego simplemente toma la dirección adecuada como ya he explicado. Ahí tenéis el vídeo:



COMPORTAMIENTO SIGUE-PARED

Y aquí tenemos "la joya de la corona" y el comportamiento que más quebraderos de cabeza me ha dado...conseguir que Manué salga de un laberinto tomando siempre una pared como referencia, que parece fácil, pero no lo es.

Como de laberintos no dispongo, las pruebas las realizo en casa que paredes sí que tengo. Para la implementación me he basado en un sistema reactivo, concretamente en un módelo clásico PD. Lo que caracteriza a este modelo es que su comportamiento es iterativo y muy rápido, nada de pensar que pasará si... sino que continuamente Manué tomará datos para conocer la distancia de la pared y en relación a ésta hace uso de dos constantes que determinan cuánto debe girar para seguir estando al lado de la misma pared. Una de las constantes (el que le da la Proporcionalidad) simplemente es un número determinado de grados que marcan el ángulo de giro, para su ajuste es necesario realizar una gran cantidad de pruebas. La otra constante es la Derivativa y se encarga de decidir la proporción de P que debe aplicar en cada situación, no es lo mismo si estamos muy lejos de la pared (giro más grande  aplicando todo P), que si estamos en la distancia prudencial (un menor giro aplicando un 15% de P). El resto del comportamiento son ajustes como si Manué pierde de vista la pared, en cuyo caso se detendrá e irá girando poco a poco hasta encontrarla y continuar con su normal comportamiento, o si tiene un obstáculo de frente ya que tendrá que tener autonomía para esquivarlo sin perder nunca la pared.

Veamos el vídeo:



CALIBRACIÓN DEL SENSOR DE ULTRASONIDOS

Y aquí voy con el último apartado, la calibración del sensor de ultrasonidos, ya que siempre es bueno saber como se comporta un sensor ante determinadas situaciones.

Para calibrar el sensor el primer paso que pide la práctica es conocer la distancia mínima y máxima que este abarca, en mi caso estas distancias son:

Distancia mínima = 7cm.
Distancia máxima = 140 cm (a veces alcanzaba más, pero no era del todo regular)

El siguiente paso es conocer el ratio de acción, es decir, cuánto a la izquierda y derecha es capaz de ver:

Izquierda = 45ª
Derecha = 45ª

A continuación, se nos plantea la cuestión de, si a medida que alejamos el sensor de una pared el error (diferencia de la distancia real y obtenida) aumenta. Después de realizar diferentes pruebas se puede decir que sí, sin embargo el error no supera 0.5 cm a una distancia de 140 cm (su máximo alcance) con lo que se podría decir que tiene un error sistemático a medida que aumenta la distancia pero que este es mínimo.

El siguiente paso y último es conocer la incertidumbre del sensor en su eje X e Y.

Eje X: tras realizar las pruebas tal y como determina la práctica, he de decir que el error ha sido nulo, obteniendo siempre las distancias reales.

Eje Y: durante las pruebas he comprobado que el sensor tiene un cono de apertura en cuanto a su visión lateral, concretamente hasta que el objeto está a 80 cm el ángulo de visión va aumentando, cuando sobrepasa esta distancia el sensor sólo ve el objeto si una parte de éste se encuentra justo enfrente a él.

COMPORTAMIENTO SIGUE PARED V2

Dado que la anterior versión del programa sigue-pared era bastante lenta, tanto por la velocidad de navegación como por la manera de ejecutar el algoritmo, voy a mostraros un nuevo vídeo en el que se pueden apreciar algunas mejoras con respecto a la anterior versión para agilizar un poco el comportamiento del robot. Aunque la velocidad sigue siendo un tanto lenta, es el coste que tengo que pagar si quiero mantener la eficiencia que poseía Manué para no perder nunca la pared. Como se verá en el vídeo, el escenario utilizado es bastante "engorroso" ya que tiene numerosas esquinas de diferentes tipos (más anchas o estrechas, más largas, etc) para comprobar como consigue continuamente salir airoso de todas las situaciones:


lunes, 24 de octubre de 2011

PRACTICA 1: PRIMERAS APLICACIONES

En la última entrada terminé habiendo dejado todo el entorno de desarrollo listo y probando que toda la configuración del PC y el brick estaba correcta.

En esta práctica, tras configurar el entorno de programación, del cual explicaré un poco el proceso, mostraré las primeras aplicaciones que he desarrollado para el Lego NXT. La práctica está formada por varios apartados independientes y para explicar cada una de las partes seguiré la misma estructura: Explicación breve sobre lo que se desea conseguir, señalaré aquellas partes de código que, bajo mi punto de vista, son más creativas o interesantes, y por último mostraré un vídeo con la ejecución de la aplicación (porque una imagen vale más que mil palabras!).

Como he señalado, el paso previo ha sido instalar el IDE con el que vamos a programar todas las futuras aplicaciones, Eclipse (Gavab). El lenguaje elegido ha sido Java, me gustaría señalar que no domino este lenguaje pero gracias a C y a los conceptos de POO me está resultando (de momento) sencillo acoplarme a él. Sobre el IDE, unicamente comentar la necesidad de añadir todo el API de leJOS insertando el fichero "classes.jar" como "External JARs".

*****************************************************************************

Bien, pues vamos con la primera aplicación:

CONTROL BÁSICO DEL MOTOR

Este apartado tiene como objetivo iniciarnos con la clase "Motor" y los métodos que ésta ofrece para el manejo de los diferentes motores de Manué. Además, también se hace uso de algún método de la clase Button, que se utiliza para interactuar con los botones del brick. Para este primer apartado unicamente mostraré un vídeo ya que la ejecución es muy similar en todos. Concretamente se piden 3 clases:

BasicMotor1.java:
Con esta clase, la intención es aprender a utilizar el método forward
Motor.A.forward(); -> Hace avanzar el motor conectado a A.
y el método waitForPress()
Button.waitForPress(); -> Detiene  la ejecución hasta que se presiona un botón

BasicMotor2.java:
En este caso, la intención es hacer girar el motor en un ángulo determinado en grados:
Motor.A.rotate(x) -> Donde x es un integer que indica el nº de grados.

BasicMotor3.java:
Por último y muy similar al anterior, hay que girar el motor pero utilizando el método rotateTo, el cual hace girar al motor tomando como referencia una posición absoluta:
Motor.A.rotate(x+angle);
x=x+angle; -> de esta forma avanzará "angle" grados respecto a la última posición.




*****************************************************************************

VISUALIZACIÓN DE LA ODOMETRÍA DEL MOTOR

Una vez que hemos tomado nuestro primer contacto con la API de leJOS basándonos en los métodos de la clase Button y Motor, toca dar paso al LCD. La cuestión principal de esta práctica es aprender las herramientas y restricciones que ofrece la pantalla de Manué. Se puede decir que los mayores problemas que he tenido han sido, por un lado el hecho de que cuando mostramos algo en la pantalla ésta no se borra, con lo que a medida que añades cosas se pueden ir solapando unas a otras, y por otro lado el tamaño, ya que limita el tamaño del contenido que se quiere mostrar.

Lo que se pide concretamente es que la pantalla muestre, a medida que giramos un motor manualmente, los grados que éste lleva girado en todo momento en un rango [0-360º). La mayor complicación ha sido, como cito en el primer párrafo, controlar el hecho de pasar de mostrar un número de "x" cifras a un número con un número de cifras menor. Para ello simplemente he hecho uso de una función longitud, con la que recuerdo el número de cifras que tenía el último número mostrado para, si el siguiente número tiene menos, limpiar la pantalla antes de mostrar el nuevo, algo como:


if (longitud(num_anterior)>longitud(numero_nuevo))
    LCD.clearDisplay();
LCD.drawInt(numero_nuevo);



*****************************************************************************

CUADRADO DE CALIBRACIÓN DE MOVIMIENTO

Una vez aprendidos los conceptos básicos para el manejo de los motores y el LCD, el siguiente paso es comenzar a navegar. Para esta tarea la clase elegida es TachoPilot, ya que provee métodos para que realizar un recorrido sea más sencillo que ir comandando continúamente el movimiento de cada uno de los motores. El primer paso para utilizar estos métodos es instanciar un objeto definiendo la configuración del robot por medio del constructor, concrétamente la distancia que hay entre las ruedas y el diámentro de éstas.

Imagen 1
Con el método travel(arg1, arg2) podemos comandar al robot que avance una distancia de "x" centímetros a través del argumento "arg1" y puesto que el objetivo del apartado es realizar una aplicación que haga recorrer al robot un circuito en forma de cuadrado, este método y rotate(angle), donde angle son los grados a rotar, son suficientes para que desempeñe la tarea.

Para las pruebas de precisión, realicé un acople (imagen 1) con el quede precisar mejor el punto final donde finaliza y comienza la trayectoria. De tal modo que el robot pudiese sujetar un bolígrafo y de esta forma dejar marcado el recorrido que va siguiendo el robot a lo largo de los ejes "x" e "y", además de precisar mejor el punto final donde finaliza y comienza la trayectoria.


Aprovecharé este apartado para dar respuesta a dos cuestiones que se nos formulan en el enunciado de la práctica:

- ¿Cual es aproximadamente el rango de error cometido?
Para responder a la pregunta realicé un test de pruebas sobre una cartulina marcando, el propio robot, el recorrido que iba realizando (como se ve en el vídeo). Tras 10 ejecuciones, se podía comprobar que todas los intentos finalizaban en un rango de aprox. 1.5cm², siendo este el rango de error.


- ¿Existe un error sistemático?
Es complicado responder esta cuestión, ya que es me resultó muy difícil hacer que el robot comenzase siempre en exactamente la misma posición y con la misma orientación. Tras las 10 pruebas he de decir que no, ya que finalizaba con bastante precisión pero no fallaba siempre de una misma forma, sino que el error oscilaba en "+-x" y "+-y".



*****************************************************************************

MATRIZ DE COVARIANZA

Este apartado trata de mostrar, por medio de la covarianza, la dependencia que existe entre la distancia recorrida (eje y) y el error que se produce (eje x) al ejecutar un recorrido rectilíneo 20 veces. Ya que los cálculos son simplemente aplicar la fórmula que viene en el enunciado, prefiero omitir todos estos pasos y centrarme en responder la dos cuestiones que se nos plantean:


¿Cómo podr a generalizarse esta matriz para cualquier recorrido en línea recta?
Como ya he señalado, el objetivo de la covarianza es ver la dependencia existente entre dos variables estudiadas, es decir, si existe una relación directa que determine si a medida que aumenta un valor, también aumenta el otro, o bien si a medida que aumenta uno el otro disminuye. Por lo tanto, una vez que tenemos ese valor, podemos generalizar para cualquier otro recorrido, ya que sabemos la relación que tiene nuestro robot entre el error que comete y la distancia que recorre.

*****************************************************************************

VISUALIZACIÓN DE LA TRAYECTORIA

En esta última aplicación se combinan los métodos aprendidos para programar el recorrido de un robot con los vistos para mostrar en la pantalla determinada información.

El objetivo es conseguir mostrar en el LCD el recorrido (a escala) que realiza el robot. Para ello, he pensado hacer 2 tipos de recorridos, y así ver cómo el mostrado se relaciona directamente con el realizado por el robot. La aplicación queda entonces como un menú, en el que si seleccionamos el botón derecho el robot realizará la figura de un cuadrado, mientras que si seleccionamos el botón izquierdo realizará la figura de un rectángulo.

Para programar esta aplicación, parto del código implementado en el cuadrado de calibración y la base está en establecer dos estados, girando y avanzando, de tal forma que cuando avanza tenemos que saber en que dirección lo hace por medio de senos y cosenos del ángulo hacia el que está orientado, y si gira, debemos actualizar dicho ángulo. A continuación muestro un vídeo sobre como se va mostrando el recorrido que realiza el robot, he de decir que por comodidad lo mantengo sujeto en la mano ya que a medida que avanza sería más complicado poder mostrar la pantalla:

lunes, 17 de octubre de 2011

PRACTICA 0: PREPARANDO EL ENTORNO DE DESARROLLO

El título de esta entrada hace referencia al objetivo que se persigue en la práctica 0, instalar y configurar todo el software que necesitaremos para el robot, el firmware que contiene el ladrillo y aprender los conceptos básicos para poder comunicar al robot con el pc vía USB.

Para no repetir lo que ya dice el enunciado de la práctica, haré un resumen sobre los pasos que he realizado para conseguir configurar todo el sistema.

El primer paso fue descargar el entorno de programación leJOS para el robot Lego NXT, concretamente la versión 9.0. Una vez descomprimido y establecidas las variables de entorno necesarias el siguiente paso fue actualizar el firmware del brick (o ladrillo) a su versión más reciente, lo cual en mi caso no fue necesario puesto que ya se encontraba instalada la versión 8.5.

Tras esto, y a modo de prueba, utilicé algún ejemplo que trae el entorno leJOS ya programados y que sólo es necesario compilar y linkar para su ejecución. Sin embargo, aquí comienzan a surgir los primeros problemas ya que, una vez compilado y linkado el ejemplo HelloWorld.java y generado su ejecutable HelloWorld.nxj compruebo que no puedo enviar el ejecutable al brick por medio del USB puesto que me falta una librería relacionado con el mismo USB.
Después de navegar un rato, doy con el blog de otro alumno que había cursado la asignatura y que detalla las librerías que necesitó él para solucionar el problema. La solución no era más que ejecutar los comandos:

sudo apt-get install libusb-0.1-4
sudo apt-get install libbluetooth-dev

para instalar las librerías necesarias tanto para el USB como para el bluetooth (ya que además de vía USB la comunicación pc-brick se puede realizar por bluetooth).

El resto, y teniendo en cuenta que para transmitir el fichero ejecutable era necesario ejecutar el comando correspondiente con permisos administrativos (root user), fue tan sencillo como esperar el sonido de confirmación que lanza el ladrillo al finalizar la transferencia y ejecutar mi primer programa con el entorno leJOS.

Otra utilidad intersante, ya finalizando la práctica 0 es el comando:

nxjbrowse

ya que muestra una GUI desde la que podemos administrar los ficheros que están contenidos en el brick.

Y con esto finaliza la primera práctica dando paso a una siguiente en la que, tras configurar el entorno de programación, crearé mi primera aplicación.


CREANDO A MANUÉ

Mi primera experiencia con las prácticas de la asignatura fue asegurarme de que no faltaba ninguna de las piezas con las que tendríamos que dar forma a nuestro robot, algo sencillo.

Junto a la caja que nos daban y que contenía todas estas piezas venía un manual donde explica cómo crear un robot con un diseño standard, así que decidí que lo mejor sería montar éste y después realizar modificaciones en él, ya que en un principio no se me ocurría que forma darle con tanta pieza suelta.

Bien, pues es así como surje Manué, a quién podemos ver en las siguientes imágenes.



Si tuviésemos el manual a mano, se podría comprobar que faltan componentes (sensores principalmente) que sí trae el diseño que él muestra. En un principio he preferido prescindir de ellos por comodidad a la hora de manipular el robot, tanto para cuando necesito conectar el ladrillo al pc, como para transportarlo y realizar futuras pruebas, o simplemente cuando es necesario quitar y volver a poner la batería porque se ha quedado "colgado".

Con un primer diseño del robot ya montado, el siguiente paso fue comenzar la realización de la primera práctica, la práctica 0 que pasaré a explicar en la siguiente entrada.


EL INICIO

Se ha demorado más de lo previsto pero aquí comienza mi primer blog. 

La intención y el objetivo de este blog es poder reflejar mi andadura en la asignatura de Introducción a la Robótica mostrando los avances que tendré que ir realizando para crear lo que será mi primer robot. Para ello la asignatura consta de diversas prácticas en las que, de manera progresiva, intentaré dotar a un robot de cierta inteligencia artificial para que, de una forma autónoma, consiga tomar ciertas conductas ante estímulos concretos.

Siguiendo este objetivo, iré explicando de una forma genérica los pasos a seguir en cada práctica e incidiendo más en aquellas situaciones que, o bien me resultan más interesantes, o se ha tratado de algún tipo de problema para el que he necesitado investigar por mi cuenta y de esta forma que sirva, por ejemplo, para futuros alumnos.

Sin más que añadir, paso a explicaros la creación del robot Manué...