Butialo: Ejemplo 2 - Seguidor de líneas con eventos, utilizando un sensor de grises

De Proyecto Butiá
Saltar a: navegación, buscar

Descripción

Se desea Implementar un seguidor de líneas básico que permite al robot Butiá seguir el rastro de una línea de color negro sobre el suelo, utilizando un sensor de grises.

El robot deberá avanzar mientras se encuentre en una zona oscura y en caso de salirse de la misma, girar para poder encontrar nuevamente una zona oscura.

La programación de la solución deberá usar los eventos que provee el lenguaje Lua.

Solución

Descripción

Al igual que en el ejemplo 1, es necesario calibrar el sensor antes de comenzar.

Una vez calibrado el sensor, 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 el color de la línea sea negro, en caso contrario deberá buscar dicho color realizando un movimiento en forma de abanico.

Para esto, se agrega un evento que si detecta que el Butiá está sobre la línea negra se llama a la función "avanzar", y si el robot encuentra una sola blanca significa que se desvió de la línea negra y por tanto es necesario buscarla, usando la función "buscar_negro".

events.add(Grey_1.getValue, '>=', COLOR_NEGRO, avanzar)

evento_blanco_encontrado = events.add(Grey_1.getValue, '<', COLOR_NEGRO, buscar_negro)

events.go()
  • avanzar

Si se estaba buscando la línea de color negro y se invocó esta función, es porque dicha línea fue encontrada, y por tanto se remueve el evento que tenía como objetivo "hacer un abanico" hasta encontrar la línea. Además, se vuelve a agregar el evento que activa la búsqueda de la línea negra cuando se encuentra el color blanco.

La variable TIEMPO_CENTRADO tiene como objetivo hacer que el Butiá, luego de encontrar la línea negra se mueve un poco más hacia el centro de la misma, para poder hacer el recorrido de forma más eficiente.

Por último, activa los motores haciendo que los mismos giren a una velocidad prefijada en la constante MOTOR_VEL.

local function avanzar()
    if buscando_negro then
        -- Remueve el evento para que se deje de buscar el color negro
        events.remove(evento_buscar_negro)
        -- Vuelve a agregar el evento que la funci\u00f3n buscar_negro removi\u00f3
        evento_blanco_encontrado = events.add(Grey_1.getValue, '<', COLOR_NEGRO, buscar_negro)
        
        buscando_negro = false
        tiempo = 0.5
        invertir_sentido()
        util.wait(TIEMPO_CENTRADO)
    end
    
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)
end
  • buscar_negro

Esta función tiene como objetivo "hacer un abanico" hasta encontrar nuevamente la línea negra.

Si es la primera vez que se invoca (o sea, el Butiá iba por la línea negra y encontró una zona blanca) se deshabilita el evento "evento_blanco_encontrado" para poder realizar la rutina de búsqueda sin que ambos eventos se "pisen". Esto es necesario porque simultáneamente se estarían dando las condiciones para que se ejecuten los 2 eventos (evento_blanco_encontrado y evento_buscar_negro) pero en este caso sólo es de interés que se ejecute la rutina de búsqueda haciendo el abanico (evento_buscar_negro).

Se usa la variable "tiempo" para incrementar el tiempo en el que gira en cada uno de los sentidos el Butiá.

Nótese que para poder realizar el abanico, es necesario deshabilitar el evento anterior "evento_buscar_negro" que consideraba un tiempo determinado, y agregar uno nuevo con el mismo nombre que considere el nuevo valor de la variable "tiempo".

local function buscar_negro()
	if not buscando_negro then
		buscando_negro = true
		-- Se deshabilita el evento de "color blanco encontrado" porque no tiene que "mezclarse" con el actual
		events.remove(evento_blanco_encontrado)
	else
		-- Se remueve el evento anterior para agregar uno nuevo con el nuevo valor de la variable tiempo
		events.remove(evento_buscar_negro)
	end
	last = util.get_time()
	-- Lo siguiente es para que se busque s\u00f3lo un determinado tiempo en cada sentido de giro
	evento_buscar_negro = events.add(get_elapsed, ">=", tiempo, buscar_negro)
	invertir_sentido()
	tiempo = tiempo * 2
	girar()
end
  • girar

Gira el robot en el sentido correspondiente, el cual estará definido por la variable sentido.

local function girar()
    if sentido == "I" then
        Motors.setvel2mtr(1,MOTOR_GIRO_VEL,0,MOTOR_GIRO_VEL)
    else
        Motors.setvel2mtr(0,MOTOR_GIRO_VEL,1,MOTOR_GIRO_VEL)
    end
    invertir_sentido()
end
  • get_elapsed

Esta función tiene como objetivo retornar el tiempo en segundos que pasó desde la última vez que se grabó la variable "last"

local function get_elapsed()
    return util.get_time() - last
end
  • invertir_sentido

Cambia el sentido de izquierda a derecha o viceversa.

local function invertir_sentido()
    if sentido == "I" then
        sentido = "D"
    else
        sentido = "I"
     end
end

Configuración

Se debe colocar un sensor de escala de grises lo más cercano al piso posible, pero siempre sin tocarlo, 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 del piso.

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

Configuración

Video

Código

Butialo: Ejemplo 2 - Seguidor de líneas con eventos, utilizando un sensor de grises - Código