sábado, 12 de noviembre de 2011

Dribbler


Autor: Cristian Lara
Competencia: Aplica las Ciencias de la ingeniería.

Descripción de la actividad.


Diseñar y  construir un robot de competencia para el nuevo juego del verano “Dribbler”.

Reglas del juego:
  1. La idea de la competencia es que un robot autónomo encuentre la mayor cantidad de “zonas de puntaje” (círculo negro) en la pista, sin chocar con los obstáculos presentes (paredes, bloques, etc), ya que cuando pase esto, termina el juego.
  2. Cuando el robot vaya a chocar, el jugador debe indicarle que existe peligro de choque, a través de una señal audible (grito, pitazo, aplauso, etc), de modo que el robot no colisione.
  3. Cada vez que el robot encuentra una zona de puntaje (círculo negro), acumula puntos, pero también aumenta su velocidad.
  4. Gana el jugador que logre el mayor puntaje, antes de chocar con algún obstáculo.
Especificaciones:
  1. El robot debe iniciar su recorrido con una potencia de 20 e iniciar un timer en 0.
  2. Mientras el robot busca zonas de puntaje se emitirá constantemente una música ad-hoc.
  3. Cuando detecte una zona de puntaje (círculo negro), el robot:
 Emitirá una música de anotación de puntos
Registrará el puntaje obtenido en la posición correspondiente dentro de un arreglo (array)
Aumenta la potencia de movimiento en 10, hasta el máximo de 100.
Girará aleatoriamente sobre su eje
 Reiniciará el timer a 0.
 Seguirá su rumbo con la nueva velocidad.
  Volverá a su música de recorrido.
  1. El puntaje obtenido por el robot, estará dado por la siguiente función:
                P  =  - 5*t + 50              si t <= 10
                
                P = 0                        si t > 10
                Donde:
                        P= Puntaje.
                        t = Intervalo de tiempo (en segundos) para encontrar la zona de puntaje.

  1. Si el robot detecta una señal audible de 80 db (ud. puede ajustarla) girará en un ángulo apropiado (uds. lo definen) de modo de esquivar un obstáculo, o bien corregir su recorrido.
  2. Cuando el robot choque contra algún obstáculo se detendrá, finalizará todas las tareas y mostrará en el visor cada uno de los puntajes guardados en el arreglo y la suma total de los mismos.

Solución.

Primero, escribimos el psudocódigo que diera solución al problema

Umbral Sonido=80
Umbral=40
suma=0
contadorp=0
potencia=20
i=0
puntos[100]
tiempo = 0

mutex bandera
mutex música

Tarea música() 
{
Mientras (Siempre) 
{Adquirir recurso (música)
Tocar música
Liberar recurso (música) } // Cierre del Mientras
} // Cierre de la tarea música


Tarea avance ()
{ Registrar tiempo anterior 
Mientras (Siempre)
{Adquirir recurso (bandera);
Avanzar con el valor de Potencia 
Liberar recurso (bandera);

Si (Sensor de luz detecta negro)
{Registrar tiempo de demora al encontrar el punto negro
Tocar un Sonido indicando la detección de punto

Si(el tiempo de demora es mayor o igual a 10)
{tiempo=10 }

Calcular el puntaje obtenido y guardarlo en el arreglo, puntos[]
contadorp++
suma=suma+puntos[i]

Si (la potencia >=100)
{Potencia=100} 

sino
{Potencia=potencia+10 }

Adquirir recurso (bandera);
Girar sobre su eje en un ángulo aleatorio
Liberar recurso (bandera);

} // Cierre del Si
} // Cierre Mientras
}// Cierre Tarea Avance

Tarea peligro ()
{Mientras (Siempre)
{Si (Detecta un sonido sobre el Umbral de sonido)
{Adquirir recurso (bandera);
Girar en un ángulo leve 
Liberar recurso (bandera);
} //Cierre Si
} // Cierre Mientras
}// Cierre Tarea Peligro

Tarea final ()
{Mientras (Siempre)
{Si (Detecta pared)
{Mientras (contadorp<=15)
{Mostrar en pantalla los puntajes obtenidos y la suma total
contadorp++
} // Cierre del Mientras

Adquirir recurso (bandera);
apagar motores
Liberar recurso (bandera);
detener todas las tareas 
}// Cierre del Si
} // Cierre Mientras
}// Cierre Tarea final.


Tarea Principal ()
{Hacer correr todas las tareas
Encender Sensores de Luz, Tacto y Sonido
}


El código fuente correspondiente es el siguiente.


#define Umbral_Sonido 80 // Usado para que el sensor de Sonido detecte el aplauso
#define Umbral 40 // Declarado para ser usada como un punto negro por el Sensor de Luz
int suma=0; // Variable que representa el total del puntaje
int contadorp=0;// Variable usada que cuenta la cantidad de veces que detecta los puntos negros.
int potencia=20; // Potencia inicial que arranca el robot en la actividad.
long actual = 0; // Usado para registrar el tiempo hasta encontrar un punto negro
long anterior = 0; // Usado para registrar el tiempo desde el comienzo.
int i=0; // Marca la posición número 1 para el arreglo
int puntos[100]; // Arreglo que guarda el valor de los puntajes obtenidos al detectar un punto negro.
int giro=0; // Variable usada para realizar un giro en 180° al momento de detectar una señal auditiva
int tiempo = 0;// Variable usada para marcar lo que demoro en buscar un punto negro, lo que determina el puntaje obtenido(( actual - anterior)/1000)
int pos=0; // Usado para que al momento de Mostrar en pantalla avance lo guardado en el arreglo.
int altura=30; // Usado como coordenada Y en la muestra de la pantalla del ladrillo.

mutex bandera; // Con esto nos aseguramos que al mover de los motores no ocurra que resultados inesperados al tratar de funcionar
mutex musiquita; // Usado para la musica de fondo y el sonido de obtener puntaje.

task musica() // Tarea de la música de Fondo.
{
while(true) // Mientras sea verdadero
{ Acquire(musiquita); // Indica que el control en este caso de la musica la tiene esta tarea.
PlayTone (700,100); // Los 4 Playtone confeccionar la música de fondo gracias a sus diferentes frecuencias y tiempos.
Wait (200);
PlayTone (1000,100);
Wait (200);
PlayTone (1500,100);
Wait (200);
PlayTone (1200,100);
Wait (200);
Release(musiquita); // Esto quiere decir que libera el uso del sonido para que otra tarea la use.
} // Cierre del While
} // Cierre de la tarea musica


task avance()
{
anterior=CurrentTick(); // En esta variable guarda el tiempo desde el inicio del programa
while(true) // Mientras sea verdadero
{ Acquire(bandera); // Usado para que los motores tenga el control para avanzar
OnFwd(OUT_AC,potencia); // Avanzar con una potencia determinada en este caso 20.
Release(bandera); //Indica que los recursos del avance esten libres, lo puedan usar otra tarea.

if(Sensor(IN_3) <= Umbral) // Si el Sensor de Luz detecta un punto negro.
{
actual=CurrentTick(); // Guarda el tiempo que demoro en detectar un punto.
PlayTone (1000,100); // Los 2 Playtone marcan el hallazgo de un punto negro
Wait (250);
PlayTone (2000,200);
Wait (250);
tiempo=(actual-anterior)/1000; // La variable tiempo se guarda el tiempo exacto en segundo que demoro desde el inicio al encontrar un punto.
if(tiempo>=10) // Si el tiempo es mayor o igual a 10
{tiempo=10;} // El tiempo será 10 lo que en la ecuación de los puntos lo igual a 0 el puntaje.

puntos[i]= 50 - 5*tiempo; // Arreglo que determina el puntaje obtenido en relación al tiempo obtenido.
contadorp++; // Para contar el numero de veces que detecta un punto.
suma=suma+puntos[i]; // Marca el resultado total del puntaje que se obtienen
i++; // Usado para que se guarden valores una posición más allá de la inicial en el arreglo

if(potencia>=100) // Si la potencia es igual o mayor que 100
{potencia=100;} // La potencia es igual a 100.

else // Sino
{ potencia=potencia+10;}// La Potencia aumenta en 10

// Cierre Potencia

Acquire(bandera); // Lo mismo que en el inicio de la tarea en el uso de motores, ahora tienen el control.
OnFwd(OUT_A,75); // Las dos instrucciones usadas para que realice un giro aleatorio
OnRev(OUT_C,75); // para cambiar el rumbo que se lleva
giro=Random(400)+200;
Wait(giro);
Release(bandera); // Marca el final del uso del recurso del motor,
} // Cierre del if Punto Negro
} // Cierre While
} // Cierre Tarea Avance

task peligro() // Tarea de Peligro al momento de una advertencia ante un posible choque con una pared o obtáculo.
{
while(true) // Mientras sea verdadero
{
if(Sensor(IN_2) >= Umbral_Sonido) // Si el sensor de sonido detecte un sonido ( aplauso)
{
Acquire(bandera); // Usada para que tenga el control del robot mientras sucede lo anterior
OnFwd(OUT_A,75); // Instrucciones para que se realice un giro de 180° grados
OnRev(OUT_C,75);
Wait(200);
Release(bandera); // Marca el final del control de la tarea, de los recursos.
} //Cierre IF
} // Cierre While
} // Cierre Tarea Peligro

task final() // Tarea final es la que arranca al momento de detectar un golpe
{
while (true) // Mientras sea verdadero
{
if ((Sensor(IN_1)==1)) // Si el sensor de tacto es igual a 1, detecta un golpe
{ while(contadorp<=15) // Mientras el contador de los puntos sea menor o igual a 15
{
NumOut(0, altura, puntos[pos]); // Muestra en pantalla el valor de los puntajes obtenidos
TextOut(30,30,"Pje.Total"); // Muestra en pantalla el texto "Pje.Total"
NumOut(30,20, suma); // Muestra en pantalla el resultado de la suma de los puntajes obtenidos
contadorp++; // Le suma uno al contador de los puntos
pos++; // Suma uno a la variable de la posición usada para el arreglo
altura=altura+5; // Usado para que cada que muestre un valor se valla corriendo lugares en la pantalla.
} // Cierre del while

Acquire(bandera); // Con esto se asegura que al momento de ocurrir lo de arriba el control lo tenga esta tarea.
Off(OUT_AC); // Apaga los motores por 5 segundos
Wait(5000);
Release(bandera);// Se detiene los recursos, se liberan de la tarea, el uso de los motores.
StopAllTasks(); // Detiene todas las tareas
}// Cierre del If
} // Cierre While
} // Cierre Tarea final.


task main () // Tarea Principal.
{
Precedes(musica,avance,final,peligro);// Usado para que todas las tareas trabajen paralelamente
SetSensorTouch(IN_1); // Encender Sensor de Tacto, Puerto numero 1
SetSensorSound(IN_2); // Encender Sensor de Sonido, Puerto numero 2
SetSensorLight(IN_3); // Encender Sensor de Luz, Puerto numero 3

}





Reflexión 

De esta manera de realizar juegos como es el dribbler, se hace una forma mas cercana para interactuar con el robot, ademas de aprender y aplicar que los nombres de las tareas utilizadas,van dentro del comando Precedes, para que estas tareas funciones de una buena forma y que sean ejecutadas en paralelo.














No hay comentarios:

Publicar un comentario