Butialo: Ejemplo 6 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia
Contenido
Descripción
Se desea implementar 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
Como fue explicado en ejemplos anteriores, el sensor de escala de grises (en este caso, se conectó el sensor al puerto 2, por eso su nombre es “Grey_2”) debe ser calibrado previamente a la ejecución del programa a desarrollar para poder obtener los respectivos valores límites a partir del cual definimos que el robot se encuentra sobre la mesa.
Calculando el valor medio, obtuvimos el valor de la variable COLOR_MESA (55000 para las pruebas realizadas). Determinamos entonces que si el valor arrojado por el sensor es menor a 55000, el robot puede continuar avanzando sin peligro de caer de la mesa, en caso contrario se deberá evitar la caída.
Además usaremos un sensor de distancia, el cual debe ser calibrado previamente también. Para ello, colocamos el sensor sobre la mesa y utilizamos la función Distanc_6.getValue() que nos brinda el entorno Butialo (en este caso se colocó el sensor de distancia en el puerto 6, por eso su nombre es Distanc_6). Nos arrojará un valor que tendremos identificado como “DISTANCIA_MESA”.
Posteriormente, colocamos el sensor fuera de la mesa y obtenemos un nuevo valor. Con dicho valor y el anterior, calculamos el valor medio (21000 para las pruebas realizadas). De esta forma obtenemos el valor de la variable DISTANCIA_MESA que refiere a la distancia a partir de la cual el robot detecta la presencia de la mesa. Determinamos entonces que si el valor arrojado por el sensor es menor a 21000, el robot puede continuar avanzando sin peligro de caer de la mesa, en caso contrario se deberá evitar la caída.
Una vez calibrados los sensores y obtenidos los respectivos valores de tiempo máximo y mínimo de giro y retroceso, 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 desplazarse el robot de forma aleatoria, para adelante o para atras, hasta tanto no se encuentre en peligro de caer de la mesa, en caso contrario deberá retroceder o avanzar, dependiendo de con cual sensor se detecto que el robot se esta por salir de la mesa. Luego de que el robot se encuentra lo más cercano a su posición inicial, el centro de la mesa, se utiliza la función girar_aleatorio() para el siguiente movimiento de este, se haga en un sentido aleatorio.
while true do
moverse()
while (puedo_avanzar()) do
util.wait(INTERVALO_CHEQUEO)
end
volver_inicio()
end
- chequear_avance_o_retrocedo
Retorna un valor booleano que indica si el robot debe avanzar. Para desplazarse de forma aleatoria, para adelante o atras, 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 hacia adelante, retornando True y en caso contrario deberá dsplazarse hacia atras retornando False.
local function chequear_avance_o_retrocedo()
-- Avanzar = true, Retroceder = false
local sentido = math.random (0, 1)
return sentido > 0.5
end
- puedo_avanzar
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. Define el valor de la variable debe_avanzar que será false si se detectó con el sensor de grises (sensor se encuentra en la parte de adelante del robot) peligro de caerse de la mesa, entonces este debera retroceder o en caso de que detectó peligro de caerse con el sensor de distancia (sensor se encuentra en la parte de atras del robot), este debe avanzar.
local function puedo_avanzar()
local ret
if Grey_2.getValue() < COLOR_MESA and Distanc_6.getValue() >= DISTANCIA_MESA then
ret = true
else
ret = false
end
if(not ret) then
if(Grey_2.getValue() > COLOR_MESA ) then
--se esta por caer desde la parte de adelante
debe_avanzar = false
else
debe_avanzar = true
end
end
return ret
end
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 la 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 retoceder 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 debemos colocar un sensor de distancia a una distancia de la mesa mayor a 3cm pero no mucho más, debido que a una distancia menor el sensor no sensa correctamente.
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