miércoles, 12 de octubre de 2011

Robotica - Proyecto Dribbler

El proyecto Dribbler consiste en construir un robot de competencia para el nuevo juego del verano. 

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. 

Solucion:

Segun las especificaciones que se dieron (que no las pondre aqui ya que son muchas) y las conclusiones que sacamos como grupo, entregamos la siguiente solucion de robot autonomo.

Este robot es ligeramente distinto a los demás ya que el contexto en el que supuestamente debe funcionar es distinto: un juego.
Anteriormente el robot había sido programado para responder mecánicamente a eventos, y cumplir objetivos educacionales. Ahora el objetivo es: “obtener el mejor puntaje”, mediante la reacción del jugador (aplauso o ruido), para evitar que el robot choque y pierda.
A continuación analizaremos los detalles del proceso de programación del robot y su funcionamiento final. 


Los problemas principales de esta actividad y sus soluciones fueron las siguientes:

1.- El puntaje, entregado por una función dependiendo si el tiempo desde el último punto es menor o mayor que 10. (Si t<=10, P=-5*t+50. Si t>10, P=0), donde t = es el tiempo que ha pasado entre el CurrentTick() producido en el último punto visto, hasta el CurrentTick() producido en el momento del nuevo punto negro detectado. P=Puntaje. [INSERTE FUNDAMENTACION] 

2.- Manejo de tareas simultáneas y subtareas, con uso de Precede() y ExitTo. No fue nuevo para nosotros, ya que por error (y con castigo de parte de ustedes por haber usado esta función anteriormente), ya habíamos utilizado exitosamente estas funciones, pudiendo ejecutar más de una tarea simultáneamente en el programa.

3.- Mutex, Acquire() y Release(). Así como ya habíamos utilizado múltiples tareas con Precede() y ExitTo, también teníamos conocimiento en el uso de Mutex, Acquire() y Release(), por lo que no nos presentó ninguna dificultad volver a aplicarlo. 



Pseudocódigo del código NXC
Tarea main{
                Encender sensores de luz, sonido y tacto.
                Definir constantes de umbral de sonido y color blanco para sensor de luz.
                Definir variables para las funciones de cálculo para puntaje, tiempo y otros.
                Velocidad inicial=20, Timer=0.}
Tarea PuntoNegro{
                Si sensor luz ve negro:
                               Música (Score music).
                               Esperar.
                               Registrar Puntaje en un Array.
                                               Si tiempo entre 1er y 2ndo punto es <=10
                                                              Puntaje=-5*t+50
                                               Si es mayor  a 10
                                                               Puntaje=0
                               Velocidad+10
                               Si velocidad > 100
                                               Velocidad = 100.
                               Giro random.
                               Wait(random)
                               Volver a música normal y seguir recorrido.
}
Tarea Moverse{
                Musica (background music.)
               
Avanzar indefinidamente}
Tarea Aplauso{
                Si sensor sonido siente aplauso{
                               Giro definido para esquivar objeto.
                               Esperar.}
}
Tarea Choque{
                Si sensor touch == 1
                               Detener robot y música.
                               Música (GAME OVER music).
                               Contar puntaje desde array de puntajes acumulados.
                               Mostrar puntajes acumulados
                               Mostrar resultado final de puntajes acumulados
                               Terminar programa después de 20 segundos.
}



Código del programa NXC

//Universidad Católica de Temuco
//Ing. Civil Informática
//Grupo MISSINGNO
//Robot DRIBBLER
//02-10-2011
//ultima revisión: 04/10/2011 por pablo

//constantes
#define CLAP 80         //umbral para sensor sound
#define UMBRAL 50         //UMBRAL sensor luz
#define __NOTETIME   10
#define __WAITTIME   12

//variables
int luz,tiempo_dif,puntaje;
long tiempo_actual,tiempo_ini;
int vel_var=20;
int puntos=0;
int t=500;
int i[100]; //array
int c=0;
int x=0;
int total=0;
mutex motor;

//tareas
task PuntoNegro(){
  while(true){
  if(SENSOR_2<UMBRAL){
           vel_var=vel_var+10;          //(velocidad variable)
           t=t+Random(100);             //t random
           tiempo_actual=CurrentTick(); //adquirir tiempo actual.
           tiempo_dif=(tiempo_actual-tiempo_ini)/1000;
           Acquire(motor);
           PlayTone(300,400);           //PuntoNegro!

  PlayTone(1568,4*10);
  Wait(4*12);
  PlayTone(1568,4*10);
  Wait(4*12);
  PlayTone(1568,4*10);
  Wait(4*12);

           Off(OUT_AC);
           Wait(600);
           if(tiempo_dif<=10){
              puntaje=-5*tiempo_dif+50;     //aplicación formula para puntaje1
              i[puntos]=puntaje;}
           else{
              puntaje=0;                    //aplicacion formula para puntaje2
              i[puntos]=puntaje;}
           puntos++;
           OnRev(OUT_C,50);                 //giro realizado en su propio eje
           OnFwd(OUT_A,50);
           Wait(t);
           OnFwdReg(OUT_AC,vel_var,OUT_REGMODE_SPEED);
           Release(motor);}
  }//while
}//fin tarea puntonegro

sub Melodia(){                   //MELODIA
  PlayTone(247,2*__NOTETIME);
  Wait(2*__WAITTIME);
  PlayTone(349,2*__NOTETIME);
  Wait(2*__WAITTIME);
  PlayTone(523,2*__NOTETIME);
  Wait(2*__WAITTIME);
  PlayTone(196,2*__NOTETIME);
  Wait(2*__WAITTIME);
  PlayTone(262,2*__NOTETIME);
  Wait(2*__WAITTIME);
  PlayTone(349,2*__NOTETIME);
  Wait(2*__WAITTIME);
  PlayTone(988,2*__NOTETIME);
  Wait(2*__WAITTIME);
  PlayTone(175,2*__NOTETIME);
  Wait(2*__WAITTIME);
  PlayTone(568,2*__NOTETIME);
  Wait(2*__WAITTIME);
  PlayTone(046,2*__NOTETIME);
  Wait(2*__WAITTIME);
  PlayTone(568,2*__NOTETIME);
  Wait(2*__WAITTIME);
  PlayTone(093,2*__NOTETIME);
  Wait(2*__WAITTIME);}
 
task Sonido(){
  while(true){
  if(SENSOR_3>CLAP){
           Acquire(motor);
           Off(OUT_AC);
           Wait(500);
           OnRev(OUT_AC,50);        //retrocede con ambos motores
           Wait(500);
           OnFwd(OUT_C,vel_var);
           OnRev(OUT_A,vel_var);
           Wait(600);
           OnFwd(OUT_AC,vel_var);   //avanza con ambos motores
           Release(motor);}
           }//while
}//fin tarea sonido



task Musica(){//tarea Musica
  while(true){
           Acquire(motor);
           Melodia();
           Release(motor);
           }//while
}//fin tarea musica.

task Choque(){                               //tarea para choque
  while(true){
    if(SENSOR_1==1){
           Acquire(motor);
           Off(OUT_AC);
           TextOut(5,60,"Puntajes");         //muestra "circulo numero" por pantalla
           while(c<=puntos){
                x=x+15;
                NumOut(x,50,i[c]);
                total=total+i[c];
                c++;}//while
           TextOut(5,30,"Puntaje Total");
           NumOut(5,20,total);               //no. de puntos
           NumOut(5,10,puntos);
           Wait(10000);
           StopAllTasks();
           Release(motor);}//if
           }//1er while
}//fin tarea choque

task main(){                              //tarea main
   SetSensorTouch(IN_1);                  //sensor touch
   SetSensorLight(IN_2);                  //sensor light
   SetSensorSound(IN_3);                  //sensor sound
   tiempo_ini= CurrentTick();             //adquirir tiempo inicial
   Acquire(motor);
   OnFwdReg(OUT_AC,vel_var,OUT_REGMODE_SPEED);
   Release(motor);
   Precedes(Sonido,Musica,PuntoNegro,Choque);
}//fin tarea main

//Fin programa, grupo MissingNo.
 
Conclusión

Gracias a que siempre podemos reutilizar trozos de código anterior, las actividades se van realizando de manera más simple, solo agregando pequeñas nuevas funcionalidades como lo son el uso de múltiples tareas y uso inteligente de motores.
Con el  uso de tares que se ejecutan simultáneamente podemos programar al robot para que ejecute varias acciones al mismo tiempo y así sea más eficiente, lo que nos abre mas posibilidades de programación.
Con las variable mutex podemos prevenir que se produzcan fallos en los procesos  del robot debido a que dos procesos o tareas quieran tener acceso al mismo recurso al mismo tiempo ya que con el mutex podemos  proteger  los recursos que pueden causar .

No hay comentarios:

Publicar un comentario