lunes, 10 de octubre de 2011

Actividad #1 Proyectos de Robots

Autor: Manuel Vidal Jaque 
Competencia: Desarrollo de Software (Nivel 1): Desarrolla soluciones de software aplicando procesos de análisis, diseño y prueba a problemas simples; centrados en la programación, los datos y las Interfaces Humano/Computador (IHM).
Palabras Clave: Programación, NXC, robótica, lego.


Descripción de la Actividad
En esta entrada de mi blog le contare sobre mi primera actividad del ramo Proyecto de Robótica, esta actividad consistió en un repaso del contenido del primer semestre, agregando la funcionalidad del uso de parámetros dentro de las subtareas. Para practicar esto se nos pidió programar un robot que se desplace por una superficie blanca delimitada por paredes, y con puntos negros en su superficie. El robot debía reaccionar a los puntos negros y las paredes, haciendo giros aleatorios y aumentando su velocidad si pasaba por un punto negro y disminuyendo su velocidad si chocaba con una pared. En detalle las instrucciones eran las siguientes:

Cada vez que el robot chocaba con una pared debía:
Retroceder un poco,
Girar 180° a la izquierda o derecha,
Disminuir su potencia en 10,
Contar los choques con las paredes,
Y seguir su recorrido con la nueva potencia
 Al pasar por un punto negro debía:
Contarlo,
Girar en un ángulo aleatorio menor a 180° a la izquierda o derecha,
Aumentar su potencia en 10,
Y seguir su recorrido con la nueva potencia.
El robot se desplazaba por tiempo indefinido, deteniendo su recorrido ante una señal auditiva sobre 80 db.
Al final del recorrido, informaba atreves de su visor el n° de choques y el n° de puntos negros detectados.

Solución
Para resolver el problema que se nos planteo primero que nada desarrollamos el pseudocódigo, luego diseñamos el robot de manera que cumpliera con los requisitos para poder cumplir con la actividad y finalmente implementamos el código en NXC.

Pseudocódigo del código NXC


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.

Subtarea GiroPotencia
Si el evento es “choque”
 Retroceder 8 segundos.
Potencia total disminuir en 10.
Contador choque++
Si la potencia era inferior a 30, la potencia vuelve a 30.
Si la dirección es “izquierda”
Girar hacia la izquierda por t segundos (t random).
Volver al avance hacia adelante con potencia modificada.
Si la dirección es “derecha”
Girar hacia la derecha por t segundos.
 Volver al avance hacia adelante con potencia modificada.
Si el evento es “puntos negros”
Potencia total aumentar en 10.
Si la potencia es mayor que 100, volver a 100.
Contador puntos++.
Si la dirección es “izquierda”
Girar hacia la izquierda por t segundos. (random)
Seguir avance hacia adelante con nueva potencia.
Si la dirección es “derecha”
 Girar hacia la derecha por t segundos (random)
Seguir avance con nueva potencia.

Subtarea para cambio de dirección.
Si un numero random es mayor que 100 -> return “d”
                Si un numero random es menor que 100 -> return “i”

Tarea main
 Ejecutar mientras el ruido sea menor de 80 dB lo siguiente:
 Avanzar a velocidad x.
si el sensor tacto es presionado…
 evento = choque
 subtarea GiroPotencia
si el sensor de luz detecta color negro…
evento = punto negro
subtarea GiroPotencia
 Si el sonido supera el umbral de 80 db.
 Imprimir contador choques y puntos negros.
 Esperar.
                        Terminar programa



Código fuente final del robot

//UC Temuco
//Ing Civil Informatica
//PROYECTO ROBOTICA
//Grupo MISSING NO
//Pablo Hernandez, Nicolas Miranda y Manuel Vidal.
//Actividad #1

#define UMBRAL 80
#define BLANCO 50

//VARIABLES
int t=0;                      //variable que contendrá los tiempos para los giros
int potencia= 30;             //variable que contendrá el valor de la potencia de los motores
int azar=0;                   //variable que contendrá valores enteros al azar
int cuentaChoque =0;          //contador de choques
int cuentaCirculo=0;          //contador de círculos negros
string direccion, evento;     //variables que contendrán los string que se usaran como parámetros


//SUBRUTINAS

sub GiroPotencia(int t, string direccion, string evento)   //subrutina que funcionara con 3 parámetros
    {
    if(evento == "choque")                                 //si la variable evento contiene el string "choque"
      {
      OnRevReg(OUT_AB,75,OUT_REGMODE_SPEED);               //retroceder
      Wait (800);
      if(direccion == "i" )                                //si la variable direccion contiene "i"
                  {
        OnFwdReg(OUT_B, 75,OUT_REGMODE_SPEED);             //giro a la izquierda
                  OnRevReg(OUT_A, 75,OUT_REGMODE_SPEED);
                  Wait (t) ;                                         //tiempo para el giro
        OnFwdReg(OUT_AB, potencia,OUT_REGMODE_SPEED);      //avanzar
                  }
      if(direccion == "d")                                 //si la variable direccion contiene "d"
                  {
                  OnFwdReg(OUT_A, 75,OUT_REGMODE_SPEED);             //giro a la derecha
                  OnRevReg(OUT_B, 75,OUT_REGMODE_SPEED);
                  Wait (t) ;                                         //tiempo para el giro
        OnFwdReg(OUT_AB, potencia,OUT_REGMODE_SPEED);      //avanzar
                  }
      potencia= potencia-10;                               //disminución de la potencia
      if( potencia<30){                                    //condición que impide que la potencia sea inferior a 30
         potencia=30;}
      cuentaChoque++;                                      //se aumenta el contador de choques
      }
     
    if(evento == "circulo")                                //si la variable evento contiene el string "circulo"
      {
      if(direccion == "i" )                                //si la variable direccion contiene "i"
                  {
        OnFwdReg(OUT_B, 75,OUT_REGMODE_SPEED);             //giro a la izquierda
                  OnRevReg(OUT_A, 75,OUT_REGMODE_SPEED);
                  Wait (t) ;                                         //tiempo para el giro
        OnFwdReg(OUT_AB, potencia,OUT_REGMODE_SPEED);      //avanzar
                  }
      if(direccion == "d")                                 //si la variable direccion contiene "d"
        {
                  OnFwdReg(OUT_A, 75,OUT_REGMODE_SPEED);             //giro a la derecha
                  OnRevReg(OUT_B, 75,OUT_REGMODE_SPEED);
                  Wait (t) ;                                         //tiempo para el giro
        OnFwdReg(OUT_AB, potencia,OUT_REGMODE_SPEED);      //avanzar
                  }
      potencia= potencia+10;                               //se aumenta la potencia
      if( potencia>100){                                   //condición que impide que la potencia sobrepase 100
         potencia=100;}
      cuentaCirculo++;                                    //se aumenta el contador de círculos
           }
    }


inline string direccionador()                    //función que retorna al azar un string
{
azar=random(200);
if(azar<100){
       return "d" ;}                                  //retorna "d" indicando giro a la derecha
if(azar>100){
       return "i";}                                   //retorna "i" indicando giro a la izquierda
}


task main()                                      //Tarea principal
{
SetSensorTouch(IN_1);                            //se encienden los sensores
SetSensorLight(IN_2);
SetSensorSound(IN_3);

while(SENSOR_3<UMBRAL)                           //ciclo que se ejecuta mientras el sensor de sonido no detecte 80 db
  {
       OnFwdReg(OUT_AB, potencia, OUT_REGMODE_SPEED); //avanzara según la potencia que contenga la variable potencia
       if(SENSOR_1==1)                                //si es detectado un choque
    {
    t=400;                                       //se asigna a t el tiempo necesario para realizar el giro de 180 grados
    direccion =direccionador();                  //se asigna a la variable direccion el string retornado por la función inline
    evento="choque";                             //se asigna a la variable evento el string "choque"
    GiroPotencia(t,direccion,evento);            //se llama a la subrutina y se le pasan los parametros
    }
  if(SENSOR_2<BLANCO)                            //si es detectado un círculo negro
    {
    t =random(400);                              //se asigna a la variable t un int al azar
    direccion =direccionador();                  //se asigna a la variable direccion el string retornado por la función inline
    evento="circulo";                            //se asigna a la variable evento el string "circulo"
    GiroPotencia(t,direccion,evento);            //se llama a la subrutina y se le pasan los parámetros
    }
  }
Float(OUT_AB);                                   //se detienen los motores
ClearScreen();                                   //se limpia e imprime en pantalla la cantidad de choque y círculos
TextOut(6,10,"Choques" );
NumOut(51,10, cuentaChoque);
TextOut(7,30, "Circulos" );
NumOut(50,30, cuentaCirculo);
Wait(10000);
}                                                //FIN


Este es el vídeo que documenta esta actividad



Reflexión

Con esta actividad fui capaz de comprender como programar funciones que trabajen con parámetros, ya sean ingresados o retornados por otras funciones o sub rutinas.

Les invito a que dejen sus comentarios sobre esta entrada.




No hay comentarios:

Publicar un comentario