viernes, 18 de febrero de 2011

Entrega Final: Robot Rescatista

Para la cuarta y última entrega del robot rescatista debemos agregar las funciones que faltaban para realizar la tarea completa, es decir:

  •  Diferenciar a las diferentes tarjetas y actuar de acorde a cada una de ellas.
  • Mejorar la función de agarrar a las víctimas.
  • Diseñar la función de dejar a las víctimas una vez vuelva al Campo de primeros auxilios (Salida/Entrada del laberinto).
Debido a que los colores de las tarjetas no eran muy vivos y estábamos teniendo problemas con la calibración de los canales de color, editamos la imagen de la tarjeta para lograr que los colores fueran más intensos. A continuación imprimimos un total de 20 tarjetas de las cuales 7 son víctimas rojas, 7 víctimas amarillas, 3 son verdes y 3 más son fallecidos. 
Img 1. Tarjetas de las víctimas

Una vez calibrados los tres canales para captar los colores rojo, amarillo y verde se procedió a especificar qué hacer en cada caso. Todos los grupos acordamos en conjunto usar una pieza de Lego amarilla como víctima. En caso de encontrar a una víctima y no haber visto ninguna tarjeta antes, se supone que es el cuarto caso: se trata de un fallecido. Por tanto el robot lo evade dando una vuelta de 180°. 

Img 2. Víctima situada a un cuadro de su tarjeta.

En caso de encontrar una tarjeta roja, se inicia un DFS que busca  hacia todas las direcciones posibles a un cuadro de distancia. Al encontrar a la víctima en esa proximidad, la agarra y vuelve al lugar del laberinto donde vio a la tarjeta. Entonces prosigue con la navegación.
Si en cambio encuentra a una tarjeta amarilla, la evita y prosigue buscando a las rojas.
Una vez que haya recorrido todo el laberinto y dejado en el Campo de primeros auxilios a las víctimas en estado crítico (rojas), vuelve a entrar al laberinto pero en esta oportunidad en busca de las víctimas amarillas. Por tanto cuando las consiga las rescatará como hizo anteriormente con las rojas y al final las dejará también en el campo de primeros auxilios.

Img 3. Detalle del parachoques de calibración

Si encuentra una tarjeta verde en el primer recorrido, cuando está buscando a los rojos, inicia el DPS de búsqueda y cuando ubica a la víctima le hace un beep para “informarle hacia donde está la salida”. Durante el segundo recorrido, si encuentra una tarjeta verde, la evita dando una vuelta de 180° pues él ya sabe que le informó cómo escapar en el primero.

A pesar de que nuestro sistema de control para la navegación es satisfactoriamente bueno, va acumulando error y después de cierto tiempo (30 secs – 1 min) comienza a presentar oscilaciones de gran amplitud y por tanto a no ir en línea recta. Esto puede traer problemas impredecibles, como quedarse trancado contra alguna esquina. Como solución decidimos implementar una rutina de calibración que se ejecuta en ciertos eventos de frecuencia moderada. Dicha rutina consiste en avanzar a la mitad de la velocidad por un corto tiempo para chocar contra la pared y gracias a un parachoques, que además le evita cualquier daño, cuadrarse con ella para quedar derecho. A continuación retrocede un pequeño tiempo para quedar de nuevo en el centro del cuadro y proseguir con la navegación.

Para porder identificar la salida del laberinto, construimos en lego un indicador de colores verde y rojo. Elegimos éstos colores para que el programa no lo confundiera con ninguna tarjeta. Dicho indicador presenta una cruz roja para indicar que es el "campo de primeros auxilios". 

Img 4. Indicador de salida del laberinto (Campo de primeros auxilios).
 

A continuación una demostración del comportamiento del PROFETA DE LA DEVASTACIÓN realizando la tarea completa:






domingo, 6 de febrero de 2011

Tercera Entrega: Robot Rescatista

Para esta semana nuestro objetivo es lograr que nuestro robot sea capaz de recorrer el laberinto, reconocer los diferentes tipos de víctimas y rescatarlas en el orden establecido, es decir, primero a los rojos y luego a los amarillos, haciendo un beep a todos los verdes que consiga pero sin recogerlos.

También fué parte del trabajo de esta semana concretar el diseño y construcción del laberinto donde se van a desenvolver los robots de todos los grupos del curso.

Compramos las tablas que faltaban y con clavos las fijamos para formar el diseño de laberinto que decidimos todos los grupos en conjunto. 

Img 1 y 2. Construyendo el laberinto.










Un importante cambio que hicimos fue modificar el sistema de engranajes que transmite la potencia a las ruedas, pues el sistema anterior estaba haciendo mucho ruido, presentaba vibraciones y en general no cumplía con los patrones de calidad que deseamos. Por tanto decidimos transferir la energía a un engranaje más grande que el anterior y además cambiar las ruedas por unas más pequeñas. Para ello, fue necesario cambiar un poco la estructura de la base del robot, como se puede ver en la siguiente imagen.


Img 3. Última versión de los engranajes.



Se incorporó una "rueda loca" en la parte trasera, esta nos sirve de apoyo para sostener el peso del robot y al mismo tiempo eliminamos el problema de roce durante los giros. Se probaron una gran cantidad de ideas, pero nos encontrabamos con varios problemas como que la rueda era demasiado fragil, demasiado pequeña, demasiado grande o no giraba 360°. Finalmente conseguimos un modelo que cumplia con nuestras necesidades, el cual se presenta a continuación.


Img 4 y 5 "Rueda loca" en detalle.


Por último, agregamos una unas ruedas en la parte frontal del robot que nos sirven como protector contra los impactos y al mismo tiempo evitan el roce durante los mismos, permitiendo que el robot se continue moviendo con facilidad hasta que este corrija su rumbo. Así mismo, esta modificación brida al robot un aspecto más intimidante, por lo que decidimos agregarle algunos detalles decorativos que se pueden observar en las siguientes imágenes.
 
 Img 6. Parachoques anterior
Img 7. Parachoques nuevo




















Se implementó un algoritmo  de control PD (Proporcional Derivativo) que usa los sensores infrarojos laterales para ayudar a avanzar de forma recta. También de implementó un algoritmo de navegación en el que siempre sigue la "la mano izquierda" para recorrer el laberinto.




A continuación un video en dos partes (lo cortamos porque pensamos que no lograría seguir, pero al ver que si lo lograba, continuamos grabando en otro video) que demuestra el resultado del trabajo de esta semana ( nuevos engranajes, "rueda loca", control y navegación).

NOTA: La presentación amenazadora que adquirió nuestro robot para esta entrega nos inspiró en nombrarlo "EL PROFETA DE LA DEVASTACIÓN"

Parte 1:





Parte 2:


Actualizacion: Con algunas correcciones y entonación se logró recorrer todo el laberinto. A continuación un video:


martes, 1 de febrero de 2011

Segunda Entrega

Hola  a todos !

Para ésta se tenía que hacer que el robot recogiera una víctima (en consenso todos los grupos decidimos elegir unas fichas amarilla que hay en el laboratorio).

Primero que nada debemos mencionar que gran parte del carro fué remodelada. Se cambiaron las siguientes cosas:

- Ahora cada ruega funciona con dos engranajes, que van a lograr que el carro vaya mucho más rapido. Para lograr ésto se configuran de la siguiente forma: uno grande que esta pegado al motor para mover a otro pequeño, que está en el eje de las ruedas, de ese modo por cada vuelta que de el movimiento se traduce en varias vueltas de la rueda. En el siguiente link se puede ver mas información sobre esto: http://es.wikipedia.org/wiki/Engranaje

 Img 1. Sistema de engranajes para las ruedas.

- Se agrego un compartimiento para las víctimas. Éste consiste de una puerta que sube y baja mediante un servo motor. Además fueron agregadas dos piezas que sirven de parachoques y ayudan a ingresar a las víctimas, pues funcionan a modo de embudo.

 Img 2. Compuerta (color amarillo) controlada por el servomotor (a la derecha, azul). Parachoques con funcionalidad de embudo.

A continuación una explicación detallada de cómo sujetamos el servomotor de la compuerta:

 Img 3. Piezas necesarias para construir el soporte del servo motor.



- Se mejoró la estructura para que fuera más rígida.

- La base donde se encuentra el sensor infrarrojo fué mejorada y cambió para que se pudieran agregar dos más hacia los lados para detectar la distancia hasta las paredes del laberinto y así poder calibrar su avance. También serán útiles para detectar posibles caminos hacia los lados.

 Img 4. "Torreta" con los 3 sensores de distancia infrarojos Sharp.

Luego de esto se calibró la cámara y se programó al GBA para que reconociera el color de la víctima. Para ellos se ingresa en Vision->Color Model y se seleccionan los 3 "tipos de color" (canales) que se quieren reconocer. En nuestro caso configuramos el tercero para reconocer el color deseado: azul.

En cuanto al código que se uso, este hace lo siguiente además de si ve un obstáculo girar hacia la izquierda. Cuando detecte un blob de cierto tamaño del color de la víctima procede a llamar a agarrar_bloque().

Acá se hace lo siguiente:

1) Se paran los motores
2) Abre el servo
3) Hace un ciclo que va a ir alineando el carro con respecto a lo víctima. Para ello mueve una rueda más rápido que otra dependiendo si el objeto esta más de un lado u otro
4) Finalmente se sale del ciclo cuando lo deja de ver y simplemente es que lo tiene cerca por lo que se lo deja siguiendo cierto tiempo
5) Se cierra el servo de modo de empujar más para adentro a la víctima
6) Coloca el servo a 90 grados del suelo

He aquí el código:

#use "xbccamlib.ic"

void rotate_bot(float turns)
{
    float half_width, radius, pi, ticks_per_robot_rev;
    float ticks_per_wheel_rev, robot_rev_circum, wheel_circum;
    long ticks_to_turn;
    //put in pre-defined values
    half_width=100.; radius=50.; pi=3.1416; ticks_per_wheel_rev=2000.;
    //calculate circumferences and ticks
    wheel_circum=pi*radius*2.0;
    robot_rev_circum=half_width*pi*2.0;
    ticks_per_robot_rev=
      ticks_per_wheel_rev*robot_rev_circum/wheel_circum;
    ticks_to_turn=(long)(turns*ticks_per_robot_rev);
    mrp(0,RUEDAD,ticks_to_turn); //move left motor forward
    mrp(2,RUEDAI,-ticks_to_turn); //move right motor backwards
    bmd(0); bmd(2); //wait for both motors to complete moves
}

//Esquiva cuando consigue algo
void girar(float grados){
    rotate_bot(grados);
}

#define RUEDAD 380 
#define RUEDAI 345

void main() 
{
    init_camera();
    enable_servos();    
    set_servo_position(0,180);
    sleep(1.0);
    
    mav(0,RUEDAD);
    mav(2,RUEDAI);
    
    while(1){
        track_update();
        
        if (analog(0) > 120){
            ao();
            girar(0.05);
            mav(0,RUEDAD);
            mav(2,RUEDAI);
        }
        
        else if(track_count(2) > 0 && track_size(2,0)>500){
            printf("ENCONTRE UN BLOQUE\n");
            agarrar_bloque();
            mav(0,RUEDAD);
            mav(2,RUEDAI);
        }
        
    }
    
    
}

void agarrar_bloque()
{
    ao();
    set_servo_position(0,60);//abrir
    sleep(1.0);
    while(track_size(2,0)>500) {
        track_update();
        mav(2, RUEDAI-100+(track_x(2,0)-176));
        mav(0, RUEDAD-100+(3*(176-track_x(2,0)))/2);
        //mav(2, RUEDAI+2*(track_x(2,0)-176));//mav(0, RUEDAD);
        printf("%d\n", track_x(2,0));
        sleep(0.1);
    }
    mav(0,RUEDAD);
    mav(2,RUEDAI);
    sleep(4.0);
    set_servo_position(0,210);//empujar
    sleep(1.0);
    set_servo_position(0,180);//acomodar
    sleep(1.0);
    printf("Y LO AGARRE\n");
    
}

Seguiremos publicando el progreso!