Diferencia entre revisiones de «Butialo: Ejemplo 5 - Seguidor de líneas con dos sensores con eventos»

De Proyecto Butiá
Saltar a: navegación, buscar
(Página creada con '__TOC__ ==Descripción== Se desea implementar utilizando eventos un programa que permita al robot Butiá seguir el rastro de una línea de color negro sobre el suelo. El rob...')
 
(Configuración)
 
(No se muestran 4 ediciones intermedias del mismo usuario)
Línea 25: Línea 25:
 
* '''programa principal'''
 
* '''programa principal'''
  
Consiste en avanzar el robot hasta tanto no se encuentre en peligro de caer de la mesa, en caso contrario deberá retroceder de forma aleatoria. Luego de que se retrocede aleatoriamente, por un tiempo determinado, se utiliza la función girar_aleatorio() para que la siguiente vez que se avance, se haga en un sentido aleatorio.
+
Consiste en avanzar el robot hasta tanto no se cumpla alguna de las condiciones para cambiar de estado y en tal caso, se ejecutará la función asociada al evento correspondiente.
  
 
<syntaxhighlight lang="lua">
 
<syntaxhighlight lang="lua">
    events.add(Grey_2.getValue, '>=', COLOR_MESA,retroceder_y_girar_aleatorio)
+
events.add(obtener_estado, '==', NEGRO_IZQUIERDO, girar_izquierda)
    events.add(Grey_2.getValue, '<', COLOR_MESA, avanzar)
+
events.add(obtener_estado, '==', NEGRO_DERECHO, girar_derecha)
    events.go()
+
events.add(obtener_estado, '==', NEGRO_AMBOS, avanzar)
 +
events.add(obtener_estado, '==', BLANCO, detener)
 +
events.go()
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Línea 42: Línea 44:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
* '''retroceder_y_girar_aleatorio'''
+
* '''detener'''
Retrocede y luego gira de forma aleatoria.
+
Detiene los motores.
  
 
<syntaxhighlight lang="lua">
 
<syntaxhighlight lang="lua">
local function retroceder_y_girar_aleatorio()
+
local function detener()
     retroceder_aleatorio()
+
     Motors.setvel2mtr(0, 0, 0, 0)
    girar_aleatorio()
+
 
end
 
end
 
</syntaxhighlight>
 
</syntaxhighlight>
  
* '''chequear_giro_izquierda'''
+
* '''es_negro'''
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.
+
Retorna un valor booleano que indica si el robot está parado sobre la zona oscura, según el valor obtenido por el sensor de grises y su comparación con la constante COLOR_NEGRO.
  
 
<syntaxhighlight lang="lua">
 
<syntaxhighlight lang="lua">
local function chequear_giro_izquierda()
+
local function es_negro(valor)
     local sentido = math.random (0, 1)
+
     return (valor > COLOR_NEGRO)
    return sentido > 0.5
+
 
end
 
end
 
</syntaxhighlight>
 
</syntaxhighlight>
  
* '''girar_aleatorio'''
+
* '''girar_derecha'''
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.
+
Gira el robot hacia la derecha con una velocidad definida por la variable MOTOR_GIRO_VEL.
  
 
<syntaxhighlight lang="lua">
 
<syntaxhighlight lang="lua">
local function girar_aleatorio()
+
local function girar_derecha()
     local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)
+
     Motors.setvel2mtr(0,MOTOR_GIRO_VEL,0,0)
    local izquierda = chequear_giro_izquierda()
+
end
    if (izquierda) then
+
</syntaxhighlight>
Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)
+
 
 +
* '''girar_izquierda'''
 +
Gira el robot hacia la izquierda con una velocidad definida por la variable MOTOR_GIRO_VEL.
 +
 
 +
<syntaxhighlight lang="lua">
 +
local function girar_izquierda()
 +
    Motors.setvel2mtr(0,0,0,MOTOR_GIRO_VEL)
 +
end
 +
</syntaxhighlight>
 +
 
 +
* '''obtener_estado'''
 +
Retorna el estado correspondiente, dependiendo de los valores obtenidos en cada uno de los sensores de grises.
 +
 
 +
<syntaxhighlight lang="lua">
 +
local function obtener_estado()
 +
    negro_izquierda = es_negro(Grey_1.getValue())
 +
    negro_derecha = es_negro(Grey_2.getValue())
 +
    if (negro_izquierda and negro_derecha) then
 +
return NEGRO_AMBOS
 +
    elseif (negro_izquierda) then
 +
return NEGRO_IZQUIERDO
 +
    elseif (negro_derecha) then
 +
return NEGRO_DERECHA
 
     else
 
     else
Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)
+
return BLANCO
 
     end
 
     end
    util.wait(tiempo_giro)
 
 
end
 
end
 
</syntaxhighlight>
 
</syntaxhighlight>
Línea 80: Línea 101:
 
==Configuración==
 
==Configuración==
  
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.
+
Se deben colocar dos sensores de escala de grises lo más cercano al suelo, pero siempre sin tocarla, en la parte de adelante del Butiá.
  
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.
+
En nuestro caso encastramos piezas de forma de generar el soporte para adherir los sensores al Butiá, quedando dichos sensores a ras del suelo.
  
 
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.
 
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.
  
[[Archivo:config_butialo_problema_3.png|300px|thumb|center|Configuración]]
+
[[Archivo:config_butialo_problema_5.png|300px|thumb|center|Configuración]]
  
 
==Video==
 
==Video==

Revisión actual del 21:07 10 oct 2012

Descripción

Se desea implementar utilizando eventos un programa que permita al robot Butiá seguir el rastro de una línea de color negro sobre el suelo.

El robot deberá avanzar mientras se encuentre en una zona oscura y en caso de salirse de la misma se tendrán tres alternativas posibles para poder encontrar nuevamente una zona oscura, dependiendo de cuál sensor detectó que el robot se ha salido de la zona.

Solución

Descripción

Obtenemos el valor de la variable COLOR_NEGRO de la misma forma que lo hicimos en el Ejemplo 1.

Como podemos apreciar en el Ejemplo 1, el robot tiene un comportamiento que claramente se adapta al paradigma reactivo. Esto es, SENSAR - ACTUAR. Cambiará su estado dependiendo de una condición que le indica para cada sensor si el color sensado se corresponde con el color negro (COLOR_NEGRO).

Distinguimos entonces tres estados posibles: NEGRO_AMBOS, NEGRO_IZQUIERDO y NEGRO_DERECHO. Cuando ambos sensores detectan el color negro, el robot se encuentra en el estado NEGRO_AMBOS. Por lo cual el robot deberá avanzar. Si el sensor izquierdo detecta el color negro y el sensor derecho no, entonces el robot se encuentra en el estado NEGRO_IZQUIERDO. El robot aquí deberá girar en sentido izquierdo para tratar de no salirse de la línea. Si el sensor derecho detecta el color negro y el sensor izquierdo no, entonces el robot se encuentra en el estado NEGRO_DERECHO. Análogamente, el robot deberá girar en sentido derecho. En caso contrario, el estado será BLANCO y al perder la línea con ambos sensores el robot se detiene.

Finalmente se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:

  • programa principal

Consiste en avanzar el robot hasta tanto no se cumpla alguna de las condiciones para cambiar de estado y en tal caso, se ejecutará la función asociada al evento correspondiente.

events.add(obtener_estado, '==', NEGRO_IZQUIERDO, girar_izquierda)
events.add(obtener_estado, '==', NEGRO_DERECHO, girar_derecha)
events.add(obtener_estado, '==', NEGRO_AMBOS, avanzar)
events.add(obtener_estado, '==', BLANCO, detener)
events.go()
  • avanzar

Activa los motores haciendo que los mismos giren a una velocidad prefijada en la constante MOTOR_VEL.

local function avanzar()
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)
end
  • detener

Detiene los motores.

local function detener()
    Motors.setvel2mtr(0, 0, 0, 0)
end
  • es_negro

Retorna un valor booleano que indica si el robot está parado sobre la zona oscura, según el valor obtenido por el sensor de grises y su comparación con la constante COLOR_NEGRO.

local function es_negro(valor)
    return (valor > COLOR_NEGRO)
end
  • girar_derecha

Gira el robot hacia la derecha con una velocidad definida por la variable MOTOR_GIRO_VEL.

local function girar_derecha()
    Motors.setvel2mtr(0,MOTOR_GIRO_VEL,0,0)
end
  • girar_izquierda

Gira el robot hacia la izquierda con una velocidad definida por la variable MOTOR_GIRO_VEL.

local function girar_izquierda()
    Motors.setvel2mtr(0,0,0,MOTOR_GIRO_VEL)
end
  • obtener_estado

Retorna el estado correspondiente, dependiendo de los valores obtenidos en cada uno de los sensores de grises.

local function obtener_estado()
    negro_izquierda = es_negro(Grey_1.getValue())
    negro_derecha = es_negro(Grey_2.getValue())
    if (negro_izquierda and negro_derecha) then
	return NEGRO_AMBOS
    elseif (negro_izquierda) then
	return NEGRO_IZQUIERDO
    elseif (negro_derecha) then
	return NEGRO_DERECHA
    else
	return BLANCO
    end
end

Configuración

Se deben colocar dos sensores de escala de grises lo más cercano al suelo, pero siempre sin tocarla, en la parte de adelante del Butiá.

En nuestro caso encastramos piezas de forma de generar el soporte para adherir los sensores al Butiá, quedando dichos sensores a ras del suelo.

Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.

Configuración

Video

Código

Butialo: Ejemplo 4 - Butiá que no se cae de la mesa con un sensor sin eventos - Código