Diferencia entre revisiones de «Butialo: Ejemplo 6 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia»

De Proyecto Butiá
Saltar a: navegación, buscar
(Solución)
m (Solución)
 
(No se muestran 19 ediciones intermedias de 3 usuarios)
Línea 4: Línea 4:
 
Se desea implementar un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma.  
 
Se desea implementar un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma.  
  
Implementamos lógica de nivel intermedio que permite que el robot Butiá pueda desplazarse
+
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
en una mesa sin caerse de la misma. Inicialmente el robot sorteará hacia dónde desplazarse
+
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 volver al estado inicial y luego comenzar otra vez.
+
  
 
==Solución==
 
==Solución==
Línea 19: Línea 16:
 
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.
 
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, debemos calibrar el valor de la variable DISTANCIA_MESA que refiera a la distancia a partir de la cual el robot detecta la presentacia de la mesa, si esta distancia es mayor el robot debe detectar que esta por caerse de le mesa, entonces deberá evitar la caida .
+
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.
  
El robot deberá retroceder en un tiempo aleatorio, dicho valor deberá ser calibrado en las variables MIN_TIEMPO_RETROCESO y MAX_TIEMPO_RETROCESO de forma de contemplar que no se caiga de la mesa en caso de que el tiempo sea muy grande. Para ello el robot se colocará en el centro de la mesa. De la misma forma, se calibrará los valores de MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO, considerando aquí los posibles valores entre 1° y 90° aproximadamente.
+
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:
 
+
Una vez calibrado el sensor 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'''
 
* '''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 desplazar el robot de forma aleatoria, para adelante o para atrás, hasta tanto no se encuentre en peligro de caer de la mesa. En caso contrario, deberá retroceder o avanzar dependiendo de cuál sensor detectó que el robot se encuentra en peligro de caer 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 que el siguiente movimiento del mismo se realice en una dirección aleatoria.
  
 
<syntaxhighlight lang="lua">
 
<syntaxhighlight lang="lua">
 
while true do
 
while true do
     avanzar()
+
     moverse()
 
     while (puedo_avanzar()) do
 
     while (puedo_avanzar()) do
util.wait(INTERVALO_CHEQUEO)
+
        util.wait(INTERVALO_CHEQUEO)
 
     end
 
     end
     retroceder_aleatorio()
+
     volver_inicio()
    girar_aleatorio()
+
 
end
 
end
 
</syntaxhighlight>
 
</syntaxhighlight>
  
* '''avanzar'''
+
* '''moverse'''
Activa los motores haciendo que los mismos giren a una velocidad prefijada en la constante MOTOR_VEL.
+
Esta función permite que el robot avance o retroceda dependiendo del sentido que deba tomar.  
  
 
<syntaxhighlight lang="lua">
 
<syntaxhighlight lang="lua">
local function avanzar()
+
local function moverse()
     Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)
+
     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>
 +
 
 +
* '''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.
 +
 
 +
<syntaxhighlight lang="lua">
 +
local function chequear_avance_o_retrocedo()
 +
    local sentido = math.random (0, 1)
 +
    return sentido > 0.5
 
end
 
end
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
* '''puedo_avanzar'''
 
* '''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.
+
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_avanzar()
 
local function puedo_avanzar()
     return (Grey_2.getValue() < COLOR_MESA)
+
     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
 +
          debe_avanzar = false
 +
        else
 +
          debe_avanzar = true
 +
        end
 +
    end   
 +
    return ret
 
end</syntaxhighlight>
 
end</syntaxhighlight>
  
Línea 81: Línea 104:
 
     end
 
     end
 
     util.wait(tiempo_giro)
 
     util.wait(tiempo_giro)
 +
end
 +
</syntaxhighlight>
 +
 +
* '''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. 
 +
 +
<syntaxhighlight lang="lua">
 +
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 86: Línea 125:
 
==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 92: Línea 131:
 
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_6.png|300px|thumb|center|Configuración]]
  
 
==Video==
 
==Video==
  
<youtube>H3Ri7VNSrM8</youtube>
+
<youtube>OsuOKwmCiqs</youtube>
  
 
==Código==
 
==Código==
 +
 +
[[Butialo: Ejemplo 6 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia - Código]]

Revisión actual del 16:39 15 oct 2012

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 desplazar el robot de forma aleatoria, para adelante o para atrás, hasta tanto no se encuentre en peligro de caer de la mesa. En caso contrario, deberá retroceder o avanzar dependiendo de cuál sensor detectó que el robot se encuentra en peligro de caer 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 que el siguiente movimiento del mismo se realice en una dirección aleatoria.

while true do
    moverse()
    while (puedo_avanzar()) do
        util.wait(INTERVALO_CHEQUEO)
    end
    volver_inicio()
end
  • 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_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. 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_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
           debe_avanzar = false
        else
           debe_avanzar = true
        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.

Configuración

Video

Código

Butialo: Ejemplo 6 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia - Código