lunes, 22 de febrero de 2010

Práctica 2- Obteniendo información sensorial

Hola a todos.

Esta semana nuestro robot ha crecido, ha echado cuerpo y ha aprendido a extraer información del entorno gracias a sus sensores: desde la iluminación de la habitación, hasta la carga de la bateria.

Para ello hemos tenido que implantarle estos sensores y luchar un poco con Cigarro para encontrar la forma de colocarlos todos de la mejor forma posible. La mayoría de ellos no fueron difíciles de ubicar, pero con el de ultrasonidos tuvimos que ejercitar la imaginación para conseguir que pueda apuntar hacia delante o hacia el lado. Tras gastar más de la mitad del celo decidimos optar por crear esa especie de plataforma circular que permite enforcar el sensor hacia donde nosotros queramos.




OBTENIENDO INFORMACIÓN


En este apartado había que sacar por pantalla cierta información como el nombre del robot, los valores del sensor de luz y del de ultrasonido, la memoria RAM disponible y la información de la batería.

Para obtener la información del ultrasonido utilizamos getDistance(), para la luz readValue() y getNormalizedLightValue(), para la batería getVoltageMilliVolt(), y por último para la memoria libre tuvimos que hurgar bastante en la documentación de la API hasta encontrar, bajo la clase Runtime el método freeMemory().






CONTROL DEL ROBOT POR SONIDO

Este apartado trata de hacer ruidos raros y asustar mucho a Cigarro. Para ello hay que elegir el porcentaje de decibelios a partir del cual el robot debía reaccionar.

En principio el robot permanece parado, recogiendo mediciones del micrófono con readValue(). Cuando se de la palmada el microfono la recogerá y el robot empezará a andar. Con la segunda palmada el robot vuelve a su estado inicial de espera (parado). Hemos incluído también un par de sleeps estratégicamente situados para dejar al sensor reestablecer su valor, si no salía de los bucles demasiado rápido y la ejecución tenía muchísimos problemas.






BUMP & GO! USANDO SENSORES DE CONTACTO

Para esta sección hay que poner a andar el robot en cualquier dirección con el sensor de contacto conectado. Cuando el sensor se pulsa ( sensor.isPressed()) el robot se para y ejecuta un método al que hemos llamado pasoAtrás. Como su nombre indica el robot realiza un pequeño movimiento hacia atrás para retirarse del obstáculo que ha detectado, y luego realiza un giro aleatorio gracias a la función random().






BUMP & GO! USANDO SENSORES DE ULTRASONIDO

El código para este apartado es muy similar al anterior, de hecho, se puede usar el mismo procedimiento de pasoAtrás, solo que esta vez usamos el sensor de ultrasonido, y por tanto, evitamos el obstáculo antes de la colisión. De nuevo volvemos a usar getDistance().






COMPORTAMIENTO SIGUE-PARED PARA SALIR DE UN LABERINTO

Como su nombre indica se trata de hacer un programa para el robot con el fin de que este pueda seguir la pared de una habitación sorteando esquinas, objetos apoyados, etc.

Para ello hay que ir tomando mediciones con el sensor de ultrasonido dirigido hacia la pared con un ángulo aproximado de 45º, y ir obteniendo datos del mismo para ir corrigiendo la ruta del robot.


Como podéis ver, el robot campa a sus anchas por nuestras casas como uno más yendo a la cocina a por algo de picoteo.




CALIBRACIÓN DEL SENSOR DE ULTRASONIDOS

Aquí el reto consiste en medir experimentalmente las características de nuestro sensor de ultrasonidos.

Primero comprobamos el rango de distancias para las que el sensor da una señal fiable.
El resultado es [5cm, 240cm]. El rango de ángulos para el que las mediciones son válidas es [-45, 45] aproximadamente.

La siguiente comprobación es saber si el sensor tiene un error sistemático o no. Para ello tomamos medias perpendicularmente a una pared, los resultados son en cm:

Distancia en X
20
30
40
50
60
70
80
90
100
Distancia medida
23
32
42
52
62
72
81
92
101

Existe un error sistemático de media 1.8cm en las medidas del sensor de ultrasonidos.


El siguiente paso es calcular la incertidumbre de la medida en el eje X y en el eje Y independientemente. Para el eje X colocamos el robot a distintas distancias respecto a la pared y medimos, todas las medidas están en cm:

Distancia X
x1
x2
x3
x4
x5
x6
x7
x8
x9
x10
Media del error
40
42
42
42
42
42
43
42
42
42
43
2,2
50
52
53
52
52
52
52
52
52
52
52
2,1
60
62
62
62
62
62
62
62
62
62
62
2
70
72
72
72
72
72
72
73
72
72
72
2,1
80
81
81
81
82
81
82
82
82
82
81
1,5
90
92
92
92
91
92
92
92
92
91
92
1,8
100
102
102
101
102
102
102
102
101
102
102
1,8
110
112
112
113
112
112
112
113
112
112
112
2,2
120
122
122
123
122
122
122
122
123
122
122
2,2

Podemos deducir que el error no depende de la distancia ya que el error medio no cambia respecto a la misma.

Para la incertidumbre en el eje y colocamos un objeto a distintas distancias en el eje x y lo fuimos desplazando por el eje y hasta que dejabamos de recibir una medida válida. Los resultados han sido:


Distancia X
40
10
11
11
11
11
13
10
12
12
10
50
13
13
13
13
13
13
12
14
13
13
60
15
16
16
17
15
15
16
16
17
17
70
20
20
20
20
19
20
20
19
20
19
80
12
14
14
14
13
13
13
12
13
13
90
8
8
8
8
9
9
8
9
9
9
100
10
10
10
10
10
10
10
9
10
10
110
7
7
7
8
8
7
8
7
8
7
120
5
6
5
5
5
5
5
5
6
5


En este caso puede comprobarse que tiene una fuerte dependencia respecto a la distancia al robot. Las distancias en teoría deberían mostrar una figura elíptica aunque en nuestro caso hay que echarle imaginación para verla pero la elipse estar está, creednos. La culpa de este error se la echamos al sensor que el pobre no puede defenderse.
Matrices de covarianza a distintas distancias del robot:

A 40cm:
5
24,5
24,5
124,1

A 50cm:
4,5
27,3
27,3
169,2

A 60cm:
4
32
32
256,6

A 70cm:
4,5
41,4
41,4
388,3

A 80cm:
2,5
19,6
19,6
172,1

A 90cm:
3,4
15,3
15,3
72,5



A 100cm:
3,4
17,9
17,9
98,1

A 110cm:
5
16,3
16,3
55

A 120cm:
5
11,4
11,4
27,2

miércoles, 17 de febrero de 2010

Práctica 1- Primeros Pasos

En esta semana lo más destacable fue, sin duda, el bautizo de nuestro robot con el noble nombre de Cigarro. ¿Cambiaremos su nombre la semana que viene? sólo Dios sabe.

En cuanto a la práctica 1, ésta podría dividirse en dos etapas. La primera correspondiente a la instalacion y uso de eclipse, y la segunda destinada a la creación de pequeñas aplicaciones para el robot.

En lo que se refiere a la parte de uso del eclipse no hay mucho que añadir, unicamente hay que tener cuidado en la configuración de los "external tools" (que nos ayudan a compilar, enlazar y enviar programas al robot desde eclipse). Aseguraos de rellenar bien los campos, y cuidado con VMware, parece que la versión 6.0 tiene algunos problemas a la hora de reconocer el robot.

En cuanto a la descarga de eclipse, solo es necesario acceder a la sección de descargas de la propia página de eclipse para conseguir la ultima versión. (Si introducís eclipse en la shell y lo descargáis del enlace recomendado obtendréis una versión anterior y que no se puede actualizar).

PRÁCTICAS:



CONTROL BÁSICO DEL MOTOR

Lo primero era enseñarle a Cigarro a moverse como Dios manda para lo que tuvimos que aprender a manejar los motores. Esta parte se divide en tres programas:

BASIC MOTOR 1:

Al pulsar el boton el motor conectado al puerto A empieza a girar.
Button.waitForPress();
Motor.A.forward();
Cuando se pulsa el boton de nuevo el motor para.
Button.waitForPress();
Motor.A.stop();





BASIC MOTOR 2:

Al pulsar el botón derecho el motor conectado al puerto A gira 45º a derecha, y viceversa con el botón izquierdo. Para ello hacemos uso de Motor.A.rotate() y Button.waitForPress().





BASIC MOTOR 3:

En este caso hay que obtener el mismo resultado que en el apartado anterior pero
usando la funcion rotateTo(). Hay que tener en cuenta que la función rotateTo() gira hasta que la odometría del robot marca el ángulo pedido, es decir, que si la ejecutamos dos veces seguidas con el mismo ángulo, la segunda no producirá ningún cambio, ya que la odometría ya marca los grados solicitados. Por ello hay que usar la función resetTachoCount() para resetear la odometría.







VISUALIZACIÓN DE LA ODOMETRÍA DEL ROBOT:

En la solución de este problema mostramos por pantalla la odometría del motor B. El giro del motor lo consegimos con la función getTachoCount(). Para que los giros esten siempre comprendidos entre 0 y 360º acotamos el rango de valores haciendo uso de resetTachoCount() cada vez que se exceden estos valores.







CUADRADO DE CALIBRACIÓN DE MOVIMIENTO:



Al ejecutar la aplicación el robot realiza una trayectoria en forma de cuadrado.
Las funciones necesarias para este apartado son navegador.travel() y navegador.steer().
Este apartado esta vinculado con el siguiente. Para poder realizar la matriz de covarianzas pusimos un rotulador al robot para que pintara sus trayectorias. Luego hay que anotar el error cometido en cada vuelta.





Como puede verse el cuadrado no es perfecto, trasteamos con los parámetros del constructor de la clase TachoPilot, variando un poco el ángulo de giro y reduciendo la velocidad pero de ninguna manera esto se solucionaba, no pasa nada, lo importante es tener salud. Como siempre se produce el mismo error, sobre todo en los giros, pensamos que podría fallar la rueda trasera giratoria así que mandamos a Cigarro a boxes para probar con varios tipos de ruedas fijas:





Tampoco sirvió de nada. Acabamos dándonos por vencidos y dejamos la que viene en el manual y es que en cuanto a ruedas al tío Lego no hay quien le tosa.

Por ello podemos concluir que este error en el giro es sistemático, y ante eso poco podemos hacer...



CÁLCULO DE LA MATRIZ DE COVARIANZAS:

Para hallar la matriz de covarianza no hay mas que seguir la fórmula indicada en el enunciado.

Nosotros hemos tomado como origen de coordenadas el punto (0,0). Tras realizar el experimento 10 veces, las coordenadas de llegada obtenidas han sido : (2.6,-3.4),(2.9,-3.1),(2.3,-2.6),(3.0,-2.8),(2.9,-3.6),(2.9,-3.9),(3.1,-3.8),(3.3,-2.8),(3.7,-3.1),(3.1,-3.1), por lo que la matriz de covarianzas ha quedado de la siguiente manera:

[ 1.276 -0.023 ]
[ -0.023 1.756 ]



VISUALIZACIÓN DE LA TRAYECTORIA:
Aquí el reto es que, a medida que el robot se desplaza por el mundo, vaya dibujando su trayectoria en pantalla con escala píxel/cm. Este punto fue el más difícil de implementar ya que este trazado ha de ser en tiempo real.
Al final, superándonos a nosotros mismos, lo hemos conseguido y puede mostrar todo tipo de pirueta que pueda realizar Cigarro. Ved el vídeo en el que traza el cuadrado del punto anterior en pantalla:


Quisimos ir más allá y probamos con una trayectoria curvilínea a ver si funcionaba igual de bien poniendo un humilde menú para elegir entre embos trayectos, el resultado nos dejó con las patas vueltas, véanlo:




(* Para resolver las dudas sobre los comando a utilizar recomendamos mirar el NXJ Tutorial. A nosotros nos ha sido de gran ayuda.)

jueves, 4 de febrero de 2010

Práctica 0- Introducción al entorno NXJ


Hola.

Hoy hemos tenido la primera práctica con nuestro robot Lego mindstorms NXT. Se trataba solo de instalar el entorno de desarrollo leJOS y probar un par de aplicaciones.

En cuanto al desarrollo de la práctica en el ordenador del laboratorio no hemos tenido ningún problema. El leJOS NXJ 0.8.5 ya estaba instalado en los ordenadores, por lo que solo hemos tenido que seguir los pasos indicados en el enunciado para probar las aplicaciones HelloWorld, LCDUI, y por último nxjbrowse que permite gestionar los archivos del robot desde el ordenador de forma gráfica.

Si hablamos ahora de nuestro ordenador personal, aquí la cosa se complica. Aconsejamos antes de empezar echar un vistazo a su web y prestar especial atención a los prerrequisitos que se pueden encontrar en la sección tutorial y dependen de tu sistema operativo.

No es extraño que no se cumpla algún prerrequisito en nuestro caso, que vamos a instalarlo en una ubuntu, tuvimos que instalar varios paquetes que faltaban, estos son: ant, sun-java6-jdk, libusb-dev y libbluetooth-dev.

Una vez cumplidos los prerrequisitos ya podemos descargar el software desde aquí e instalarlo siguiendo las instrucciones. Y eso es todo, al menos en teoría ya que en nuestra ubuntu corriendo en VMware Player sobre un Windows XP a la hora de 'flashear' el firmware con nxjflash borraba el actual pero no instalaba el nuevo dejando el ladrillo en lo que se llama 'modo de actualización de firmware' en el que no se muestra nada en pantalla y se emite un 'click' periódicamente. La salida de nxjflash era la siguiente:

>: sudo nxjflash
Building firmware image.
VM file: /home/jmoral/lejos_nxj/bin/lejos_nxt_rom.bin
Menu file: /home/jmoral/lejos_nxj/bin/StartUpText.bin
VM size: 52752 bytes.
Menu size: 38016 bytes.
Total image size 91008/94208 bytes.
Locating device in firmware update mode.
Found NXT: %%NXT-SAMBA%% 1
an error occurred: Failed to open device in SAM-BA mode.

Como todos los pasos anteriores se habían ejecutado con éxito no conseguíamos averiguar el por qué del error que al final parece ser de cómo el VMware Player reconoce el ladrillo conectado por USB, actualizando el VMware a su versión Workstation el problema queda solucionado.