Diferencia entre revisiones de «Butialo: Ejemplo 7 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises y uno de distancia»
(→Código) |
m (→Solución) |
||
(No se muestran 11 ediciones intermedias de 3 usuarios) | |||
Línea 2: | Línea 2: | ||
==Descripción== | ==Descripción== | ||
− | Se desea implementar un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma. | + | Se desea implementar utilizando eventos un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma. |
− | + | Inicialmente el robot sorteará hacia dónde desplazarse (avanzar o retroceder). En caso de detectar un color distinto al de la mesa o bien detectar una distancia mayor a la separación con la mesa el robot deberá volver al centro de la misma | |
− | + | para regresar al estado inicial y luego comenzar otra vez. | |
− | (avanzar o retroceder). En caso detectar un color distinto al de la mesa o bien detectar una | + | |
− | distancia mayor a la separación con la mesa el robot deberá volver al centro de la misma | + | |
− | para | + | |
==Solución== | ==Solución== | ||
Línea 15: | Línea 12: | ||
Obtenemos los valores de la variable COLOR_MESA, DISTANCIA_MESA, MIN_TIEMPO_RETROCESO, MAX_TIEMPO_RETROCESO, MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO de la misma forma que lo hicimos en el Ejemplo 6. | Obtenemos los valores de la variable COLOR_MESA, DISTANCIA_MESA, MIN_TIEMPO_RETROCESO, MAX_TIEMPO_RETROCESO, MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO de la misma forma que lo hicimos en el Ejemplo 6. | ||
− | |||
− | |||
− | |||
− | |||
+ | Como podemos apreciar en el ejemplo anterior, el robot tiene un comportamiento que claramente se adapta al paradigma reactivo. Esto es, SENSAR - ACTUAR. Cambiará su estado dependiendo de dos condiciones que le indican si el color sensado se corresponde con el de la mesa (COLOR_MESA) o si la distancia sensada es distinta a la distancia que hay entre el sensor y la mesa (DISTANCIA_MESA). | ||
+ | |||
+ | Distinguimos entonces tres estados posibles según las diferentes condiciones (ADELANTE_FUERA_MESA, ATRAS_FUERA_MESA, EN_LA_MESA) sean verdaderas o falsas. Si se cumple la condición ADELANTE_FUERA_MESA (ATRAS_FUERA_MESA), el robot deberá retroceder (avanzar) un tiempo aleatorio definido entre el rango MIN_TIEMPO_RETROCESO y MAX_TIEMPO_RETROCESO y luego girar de forma aleatoria también por un tiempo entre el rango MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO. En caso contrario, el robot deberá desplazarse en la mesa. | ||
+ | |||
+ | 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''' | * '''programa principal''' | ||
Línea 27: | Línea 25: | ||
<syntaxhighlight lang="lua"> | <syntaxhighlight lang="lua"> | ||
events.add(puedo_seguir, '==', ADELANTE_FUERA_MESA, volver_inicio) | events.add(puedo_seguir, '==', ADELANTE_FUERA_MESA, volver_inicio) | ||
− | events.add(puedo_seguir, '==', | + | events.add(puedo_seguir, '==', ATRAS_FUERA_MESA, volver_inicio) |
− | events.add(puedo_seguir, '==', | + | events.add(puedo_seguir, '==', EN_LA_MESA, moverse) |
− | + | ||
events.go() | events.go() | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | * '''moverse''' | ||
+ | Esta función permite que el robot avance o retroceda dependiendo del sentido que deba tomar. | ||
+ | |||
+ | <syntaxhighlight lang="lua"> | ||
+ | local function moverse() | ||
+ | local sentido = chequear_avance_o_retrocedo(); | ||
+ | if(sentido) then | ||
+ | Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL) | ||
+ | else | ||
+ | Motors.setvel2mtr(1, MOTOR_VEL, 1, MOTOR_VEL) | ||
+ | end | ||
+ | end | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* '''chequear_avance_o_retrocedo''' | * '''chequear_avance_o_retrocedo''' | ||
− | Retorna un valor booleano que indica si el robot debe avanzar. Para desplazarse de forma aleatoria, | + | Retorna un valor booleano que indica si el robot debe avanzar. Para desplazarse de forma aleatoria, adelante o atrás, 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 desplazamiento será hacia adelante, retornando True y en caso contrario deberá desplazarse hacia atrás retornando False. |
<syntaxhighlight lang="lua"> | <syntaxhighlight lang="lua"> | ||
local function chequear_avance_o_retrocedo() | local function chequear_avance_o_retrocedo() | ||
− | |||
local sentido = math.random (0, 1) | local sentido = math.random (0, 1) | ||
return sentido > 0.5 | return sentido > 0.5 | ||
Línea 44: | Línea 55: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | * ''' | + | * '''puedo_seguir''' |
− | Retorna un valor booleano que indica si el robot se encuentra en peligro de caerse, según el valor obtenido por el sensor de grises y su comparación con la variable COLOR_MESA y el valor obtenido por el sensor de distancia y su comparación con la variable DISTANCIA_MESA. | + | Retorna un valor booleano que indica si el robot se encuentra en peligro de caerse, según el valor obtenido por el sensor de grises y su comparación con la variable COLOR_MESA y el valor obtenido por el sensor de distancia y su comparación con la variable DISTANCIA_MESA. También define el valor de la variable debe_avanzar, la cual dependiendo de quién detecte que el robot se encuentra en peligro de caer definirá los valores para distinguir la acción a tomar: el valor será false si se detectó con el sensor de grises y será true si se detectó con el sensor de distancia. |
<syntaxhighlight lang="lua"> | <syntaxhighlight lang="lua"> | ||
local function puedo_seguir() | local function puedo_seguir() | ||
− | + | if Grey_2.getValue() > COLOR_MESA then | |
− | + | ret = ADELANTE_FUERA_MESA | |
− | + | else | |
− | + | if Distanc_6.getValue() < DISTANCIA_MESA then | |
− | + | ret = ATRAS_FUERA_MESA | |
− | + | else | |
− | + | ret = EN_LA_MESA | |
− | + | end | |
− | + | end | |
− | + | return ret | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Línea 94: | Línea 100: | ||
* '''volver_inicio''' | * '''volver_inicio''' | ||
− | Esta función se encarga de que el robot vuelva | + | Esta función se encarga de que el robot vuelva al centro de la mesa, que es su posición inicial. Para esto utiliza la variable debe_avanzar que indica si el robot debe avanzar o retroceder dependiendo su posición actual. |
− | Para esto utiliza la variable debe_avanzar que indica si el robot debe avanzar o | + | |
<syntaxhighlight lang="lua"> | <syntaxhighlight lang="lua"> | ||
local function volver_inicio() | local function volver_inicio() | ||
− | + | if (debe_avanzar) then | |
− | + | Motors.setvel2mtr(0, VELOCIDAD_RETROCESO, 0, VELOCIDAD_RETROCESO) | |
− | + | else | |
− | + | Motors.setvel2mtr(1, VELOCIDAD_RETROCESO, 1, VELOCIDAD_RETROCESO) | |
− | + | end | |
− | + | util.wait(TIEMPO_VOLVER_INICIO) | |
− | + | girar_aleatorio() | |
end | end | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Línea 111: | Línea 116: | ||
==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 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á. También se debe colocar un sensor de distancia en la parte trasera del Butiá, en nuestro caso a una altura de al menos 3 cm con respecto a la mesa. Esto último debe ser así pues el sensor de distancia utilizado devuelve valores incorrectos para distancias menores a 3cm. |
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 el sensor al Butiá, quedando dicho sensor a ras de la mesa. | ||
Línea 117: | Línea 122: | ||
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: | + | [[Archivo:config_butialo_problema_7.png|300px|thumb|center|Configuración]] |
==Video== | ==Video== | ||
− | <youtube> | + | <youtube>5SJudk4umpU</youtube> |
==Código== | ==Código== | ||
[[Butialo: Ejemplo 7 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises y uno de distancia - Código]] | [[Butialo: Ejemplo 7 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises y uno de distancia - Código]] |
Revisión actual del 16:48 15 oct 2012
Contenido
Descripción
Se desea implementar utilizando eventos un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma.
Inicialmente el robot sorteará hacia dónde desplazarse (avanzar o retroceder). En caso de detectar un color distinto al de la mesa o bien detectar una distancia mayor a la separación con la mesa el robot deberá volver al centro de la misma para regresar al estado inicial y luego comenzar otra vez.
Solución
Descripción
Obtenemos los valores de la variable COLOR_MESA, DISTANCIA_MESA, MIN_TIEMPO_RETROCESO, MAX_TIEMPO_RETROCESO, MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO de la misma forma que lo hicimos en el Ejemplo 6.
Como podemos apreciar en el ejemplo anterior, el robot tiene un comportamiento que claramente se adapta al paradigma reactivo. Esto es, SENSAR - ACTUAR. Cambiará su estado dependiendo de dos condiciones que le indican si el color sensado se corresponde con el de la mesa (COLOR_MESA) o si la distancia sensada es distinta a la distancia que hay entre el sensor y la mesa (DISTANCIA_MESA).
Distinguimos entonces tres estados posibles según las diferentes condiciones (ADELANTE_FUERA_MESA, ATRAS_FUERA_MESA, EN_LA_MESA) sean verdaderas o falsas. Si se cumple la condición ADELANTE_FUERA_MESA (ATRAS_FUERA_MESA), el robot deberá retroceder (avanzar) un tiempo aleatorio definido entre el rango MIN_TIEMPO_RETROCESO y MAX_TIEMPO_RETROCESO y luego girar de forma aleatoria también por un tiempo entre el rango MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO. En caso contrario, el robot deberá desplazarse en la mesa.
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(puedo_seguir, '==', ADELANTE_FUERA_MESA, volver_inicio)
events.add(puedo_seguir, '==', ATRAS_FUERA_MESA, volver_inicio)
events.add(puedo_seguir, '==', EN_LA_MESA, moverse)
events.go()
- moverse
Esta función permite que el robot avance o retroceda dependiendo del sentido que deba tomar.
local function moverse()
local sentido = chequear_avance_o_retrocedo();
if(sentido) then
Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)
else
Motors.setvel2mtr(1, MOTOR_VEL, 1, MOTOR_VEL)
end
end
- chequear_avance_o_retrocedo
Retorna un valor booleano que indica si el robot debe avanzar. Para desplazarse de forma aleatoria, adelante o atrás, 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 desplazamiento será hacia adelante, retornando True y en caso contrario deberá desplazarse hacia atrás retornando False.
local function chequear_avance_o_retrocedo()
local sentido = math.random (0, 1)
return sentido > 0.5
end
- puedo_seguir
Retorna un valor booleano que indica si el robot se encuentra en peligro de caerse, según el valor obtenido por el sensor de grises y su comparación con la variable COLOR_MESA y el valor obtenido por el sensor de distancia y su comparación con la variable DISTANCIA_MESA. También define el valor de la variable debe_avanzar, la cual dependiendo de quién detecte que el robot se encuentra en peligro de caer definirá los valores para distinguir la acción a tomar: el valor será false si se detectó con el sensor de grises y será true si se detectó con el sensor de distancia.
local function puedo_seguir()
if Grey_2.getValue() > COLOR_MESA then
ret = ADELANTE_FUERA_MESA
else
if Distanc_6.getValue() < DISTANCIA_MESA then
ret = ATRAS_FUERA_MESA
else
ret = EN_LA_MESA
end
end
return ret
end
- chequear_giro_izquierda
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.
local function chequear_giro_izquierda()
local sentido = math.random (0, 1)
return sentido > 0.5
end
- girar_aleatorio
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.
local function girar_aleatorio()
local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)
local izquierda = chequear_giro_izquierda()
if (izquierda) then
Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)
else
Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)
end
util.wait(tiempo_giro)
end
- volver_inicio
Esta función se encarga de que el robot vuelva al centro de la mesa, que es su posición inicial. Para esto utiliza la variable debe_avanzar que indica si el robot debe avanzar o retroceder dependiendo su posición actual.
local function volver_inicio()
if (debe_avanzar) then
Motors.setvel2mtr(0, VELOCIDAD_RETROCESO, 0, VELOCIDAD_RETROCESO)
else
Motors.setvel2mtr(1, VELOCIDAD_RETROCESO, 1, VELOCIDAD_RETROCESO)
end
util.wait(TIEMPO_VOLVER_INICIO)
girar_aleatorio()
end
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á. También se debe colocar un sensor de distancia en la parte trasera del Butiá, en nuestro caso a una altura de al menos 3 cm con respecto a la mesa. Esto último debe ser así pues el sensor de distancia utilizado devuelve valores incorrectos para distancias menores a 3cm.
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.
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.
Video