Robot buscador virtual con OpenRoberta

  • Nivel:
    • E.S.O.
  • Área del pensamiento computacional:
    • Programación
    • Robótica

Breve descripción:

El recurso consiste en programar un robot virtual que busca un objeto en un recinto limitado por paredes. Se utiliza para ello OpenRoberta, un simulador online de Robótica.

En su realización usaremos muchos elementos de programación y robótica (variables, bucles, condicionales, funciones, sensores, encoders, salidas de audio, texto y valores, etc.).

Nivel/niveles:

Desde 3º ESO en adelante (incluso un 2º avanzado).

Asignatura/s:

Asignaturas de Tecnología, TPR, TICO y similares.

¿Se requieren conocimientos previos? ¿Cuáles son?

Aunque el nivel es sencillo y se explica cada elemento (salvo los más básicos), sería interesante que ya hubieran tenido algún curso de programación básica en un entorno de bloques similar a Scratch.

Objetivos:

  • Practicar conceptos básicos de programación (variables, estructuras de control, funciones).
  • Avanzar en programación funcional: a) Llevar a cabo un programa de cierta complejidad en el que es imprescindible separar tareas. b) Ser capaz de identificar y separar esas tareas
  • Familiarizarse con el uso de sensores y actuadores de un robot en un entorno “realista” como es OpenRoberta para acercarnos a cómo sería la programación de un robot físico real.

¿Qué ventaja obtengo de utilizar este recurso en el aula?

  • No necesita inversión en robots físicos. Cada ordenador con un navegador será un “robot” y podemos individualizar el aprendizaje a un coste muy bajo.
  • OpenRoberta es un simulador “realista”. De esta forma tendremos los problemas con los que nos enfrentamos en entornos “físicos” (imprecisión de sensores y actuadores), algo muy importante para el aprendizaje de la robótica.
  • También puede usarse con entornos físicos reales. En el ejemplo hecho estamos simulando un robot de Lego al que podría cargarse el programa y verlo funcionar en el mundo real. OpenRoberta también sirve para programar otros robots físicos.

¿Qué habilidades de los estudiantes desarrollamos que no se pueden obtener de manera más tradicional?

El pensamiento computacional tiene mucho de pensamiento ordenado y este último puede conseguirse de múltiples formas usando estrategias y elementos tradicionales.

En este ejemplo se hace hincapié en la posibilidad de ir afinando y mejorando una tarea mediante la división del problema en tareas menores, algo imprescindible en cualquier actividad medianamente compleja (“Divide y vencerás”).

¿En qué consiste el recurso?

Este recurso usa el simulador online OpenRoberta. Requiere solamente de un navegador compatible para acceder a la página.

Se trata de programar un robot virtual para que busque una mancha de color en un entorno limitado por paredes. Se programa un algoritmo de búsqueda que recorre todo el espacio accesible rebotando entre paredes haciendo una figura similar a un “serpentín”. Usa programación funcional para ir separando la tarea global en tareas más pequeñas. Se va afinando el comportamiento gracias a los sensores del robot (distancia, encoders, etc.)

Finalmente se informa por audio y texto del encuentro con el objeto y su posición, o de no haberlo encontrado.

Desarrollo

Vamos a hacer un robot que vaya “barriendo” el lugar hasta que encuentre una “mancha” en el suelo.

Para ello, primero pensemos en cómo recorrer todo el espacio, ya que hay varias formas. Nosotros vamos a hacerlo en forma de serpiente. Empezaremos en la esquina inferior derecha. Subiremos hasta la pared de arriba, avanzaremos un poco a la izquierda, bajaremos hasta la pared de abajo, avanzaremos otro poco a la izquierda… hasta que lleguemos a la pared de la izquierda.

Nota: Vamos a recorrerlo en este sentido para evitar la dirección cero grados, ya que ahí hay una discontinuidad (359-0)

El programa

Para ver que traza bien el camino, vamos a usar el escenario en blanco donde el robot pinta al avanzar.

  • Arrastramos el robot con el ratón hasta la esquina inferior derecha.
  • El primer bloque es para ponerlo mirando hacia arriba (la espera es sólo para distinguir esa primera colocación de la “serpiente”).
  • Avanza 120 unidades y se desplaza diez.
Escenario programa OpenRoberta. Programación serpiente

Ahora haríamos un bucle para que recorriera toda la superficie. Como se puede ver, existen ciertos problemas con la precisión de los movimientos, en particular con los giros. Esto es algo bastante habitual en los entornos reales, vamos a ver cómo lo arreglamos, pero antes… introduzcamos algunas variables y otras mejoras en nuestro código.

Escenario programa OpenRoberta. Programación serpiente

Introduciendo variables

Las variables nos ayudarán a leer mejor el programa y cambiar más fácilmente los parámetros. Por ejemplo, creamos una variable “velocidad_avance” y la usaremos al avanzar.

Programación por bloques.

De esta forma, si queremos que vaya más despacio solo tenemos que cambiar el valor al principio y se usará en cuatro sitios diferentes. Además se lee y se entiende mucho mejor qué hace el programa y qué significa cada número.

Hagamos variables para las distancias que se avanzan (en horizontal y vertical), etc. Dejamos los 90º de los giros, porque ahora haremos un apaño. Y nos queda, así. Prueba a cambiar los parámetros, para ver las distintas “serpientes” que dibuja.

Programación por bloques.

Mejora del bucle

Intentemos optimizar nuestro código. Ahora mismo, el bucle tiene ocho bloques, en dos series de cuatro que se parecen bastante. La única diferencia es que en un caso hay que girar a la izquierda y en el otro a la derecha.

Si pudiéramos poner después de los cuatro primeros bloques, que cambiase el ángulo de giro de 90º a -90º, podríamos tener el bucle sólo con la mitad de bloques. Podemos hacerlo con una variable. La inicializamos a 90º y al final de cada iteración la cambiamos de signo. Quedaría así, y podéis comprobar que funciona.

Programación por bloques.

Este “truco” final es habitual en programación. Recuérdalo, te ayudará a simplificar tu código. Pero aún nos queda mejorar la precisión en los giros.

Corrección de giros.

Para corregir los giros vamos a crear una función que se ejecutará después de cada giro para que el robot quede apuntando en la dirección adecuada. Con eso bastará para nuestro proyecto, en otra situación podríamos plantearnos una corrección constante.

Programación por bloques.

La función se llama corregir_angulo. Hay que llamarla dando el valor del ángulo de la dirección en que queremos que queda (objetivo).

Va a repetir unos giros hasta que quede alineada. Bueno, en realidad le damos un margen de dos grados, en este ejemplo (El valor absoluto de la resta del ángulo real menos el ángulo objetivo tiene que ser menor que dos). En cada iteración

  • Primero mira el ángulo en el sensor (giroscopio).
  • Si es menor que el objetivo, gira a la derecha.
  • Si no es menor (será mayor), girará a la izquierda.
  • Cuando esté a menos de dos grados de distancia, saldrá del bucle.
  • Después hay una orden de paro para que deje de girar.

Vamos a empezar probándola sólo en los desplazamientos horizontales que son siempre en la dirección 180º. Añadimos la función después de ese giro.

Programación por bloques.

Vemos que las trayectorias horizontales ya son muy buenas. Las verticales siguen regular.

Escenario programa OpenRoberta. Programación serpiente

El problema de los movimientos verticales es que unos van hacia arriba y otros hacia abajo… pero podríamos usar el mismo truco de antes. Poner una variable que cambie en cada iteración.

En este caso no lo podemos hacer tan sencillo como un cambio de signo (el programa no entiende la dirección -90º como equivalente a 270º). Necesitamos otra variable al principio del programa: angulo_vertical. Así que hacemos una función que nos pasa de 90º a 270º en cada iteración.

Programación por bloques

Le pasamos un valor (el ángulo) que lo tomará como x. Compara ese valor con 270, si es igual lo cambia a 90, si no es igual (sería 90) lo convierte en 270. Una vez ejecutada la función, devuelve ese valor. En el programa principal, al final del bucle, lo pondríamos así.

Programación por bloques

Como verás no es una solución perfecta.

Ejemplo de fallo - juego de la serpiente

Puede que el problema sea que queramos corregir el giro a demasiada velocidad. Una cosa es a qué velocidad hacemos el giro grande de 90º y otra a qué velocidad corregimos el pequeño error que se haya producido. Mirad qué bien queda reduciendo esa velocidad a 5 (dentro de la función corregir_angulo).

Juego de la serpiente - OpenRoberta

Ya sabemos recorrer toda la superficie y podría pensarse que ya solo hay que añadir un condicional que mire el color del suelo… pero, tal y como está escrito, si añadimos el condicional al final del bucle o al final de algún movimiento, el robot hará todo el movimiento “sin mirar” a suelo.

Así que habrá que cambiar el bloque en el que avanza por una función que vaya comprobando todo el rato si hay un color en el suelo a la vez que avanza.

Avanzar MIRANDO

En estos sistemas en los que no se nos permite multihilo, debemos ir haciendo todas las “tareas” momento a momento. Para moverse teniendo en cuenta no chocar con la pared y ver si el suelo ha cambiado de color, tendré que hacerlo así:

  • Un paso, ¿estoy cerca de la pared? ¿Es el suelo de otro color?
  • Otro paso, ¿estoy cerca de la pared? ¿Es el suelo de otro color?
  • Otro paso…

Así que sustituiremos el primer bloque “avanzar una distancia” por una función que tenga dentro un bucle donde se vaya comprobando a cada momento todas las cosas a las que queramos estar atentos.

Programación por bloques

Como verás no hemos usado un bucle condicional (“repetir hasta”) porque hay varias razones para salir del bucle, según la cantidad de sensores que queramos comprobar en cada paso. Por eso ponemos un bucle infinito y en los casos que nos interese “rompemos el bucle” y nos salimos.

Antes de cada iteración tomamos medidas en todos los sensores.

Después le pasamos el dato de  la distancia al primer condicional para no chocarnos. Si estamos muy cerca, saldrá del bucle y pasará al bloque siguiente del programa principal (girar).

Si no estamos cerca de la pared, el robot recibe la orden de avanzar y pasa al siguiente condicional. Allí se comprueba si se ha encontrado la mancha. Si no se ha encontrado, volverá a hacer otra iteración… pero si se ha encontrado, pasaremos a ejecutar la función mancha_encontrada que definiremos en un momento.

Si queréis podemos hacer una prueba con una función sencilla, que simplemente toque un tono para ver si funciona adecuadamente.

Programación por bloques

Probadlo y veréis que funciona. Esto nos soluciona el problema cuando se mueve hacia arriba o hacia abajo, pero no cuando se está moviendo en horizontal.

Para el movimiento horizontal vamos a definir otra función. Así que cambiaremos el nombre a esta y la llamaremos avanzar_mirando_V, para distinguirla de la otra que será avanzar_mirando_H

Lo tentador pero incorrecto sería hacer una función igual pero que en lugar de decir “avanzar”, dijera avanzar 20 cm y después salir del bucle, pero entonces recorreríamos esa distancia sin mirar si nos chocamos o pisamos un color, que es justo para lo que estábamos haciendo esto. Así que, nuestro procedimiento debe ser otro.

Algo así como:

  • Un paso, ¿estoy cerca de la pared? ¿Estoy pisando un color? ¿Cuánto llevo andado?
  • Otro paso, ¿estoy ahora cerca de la pared? ¿Estoy ahora pisando un color? ¿Cuánto llevo andado ahora?

De forma que tenemos que añadir otra comprobación en cada paso para que, cuando lleguemos a la distancia que establecimos en la variable “paso”, parar.

Para la función fin hemos puesto un sonido (más grave que para la mancha). Para probar.

Programación por bloques

Así quedó.

Programación por bloques

Lo primero que hacemos es reiniciar el encoder de una de las ruedas. Es un sensor que nos da los grados que ha girado la rueda. Así es cómo vamos a saber cuándo hemos recorrido los veinte centímetros del “paso”.

Ese cálculo que queda tan difícil de leer es simplemente:

  • Dividir la distancia que quiero avanzar entre la longitud de la circunferencia de la rueda, a ver en cuántas vueltas la recorro (paso / π * diámetro) (el factor diez es porque está en mm)
  • Multiplicar luego por 360 para ver cuántos grados son esas vueltas.

Con nuestros datos sale una 1,137 vueltas, que en grados son, aproximadamente 409. Si os disgusta mucho esa operación, podéis sustituirla por un bloque de valor 409.

Después tomamos los datos de la distancia, el color y el encoder.

  • Si la distancia es mayor que diez, andamos. Si no, paramos y función fin.
  • Si el encoder ha pasado de 409 grados, salimos del bucle para ir al giro que hay después en el programa principal
  • Si encontramos la mancha, paramos y función mancha_encontrada

Buscador completo

Hasta aquí ya hemos conseguido que se mueva en una trayectoria bastante precisa, que no se choque con las paredes y que sea capaz de detectar la mancha tanto en el movimiento vertical como en el horizontal.

Juego de Serpiente - OpenRoberta

Ya que sabemos que funciona, quizá podríamos refinar un poco las funciones fin y mancha_encontrada. Función fin mejorada. Te habrás fijado que la función fin que pusimos para probar repetía una y otra vez el sonido, pero en la función no había una repetición. ¿Por qué se repite?

Si nos fijamos en qué lugar se llama a fin en la función avanzar_mirando_H, veremos que ocurre cuando la distancia a la pared izquierda es muy pequeña, dentro de un bucle infinito.

Programación por bloques

Así que el bucle sigue repitiéndose y, como el coche está parado, la distancia sigue siendo pequeña y se vuelve a llamar a la función fin una y otra vez.

Quizá sería más limpio que se llamase a la función fin una sola vez y que hiciésemos dentro de esa función un bucle infinito hasta apagar el aparato, que es lo que habíamos hecho en la función mancha_encontrada. También podríamos dar una respuesta más sutil que un bocinazo. Vamos a dar un mensaje de voz y mandemos un mensaje al “ladrillo” de Lego.

Programación por bloques

Este es el resultado

Juego de la serpiente - OpenOberta

Función mancha_encontrada mejorada

Lo primero que podemos hacer es algo parecido a la función fin, por ejemplo.

Programación por bloques

Pero sería interesante mandar también las coordenadas de la mancha. Vamos a mandar la posición del punto en el que se ha producido el encuentro. Otro ejercicio interesante sería estimar la posición del centro y enviar esas coordenadas.

Para saber dónde estamos, a primera vista se nos ocurren dos opciones.

  • Una sería: Volver al punto de origen (primero en la vertical y luego en la horizontal) y con los encoder estimar las distancias recorridas.
  • La otra consiste en mirar la distancia a las paredes y tomar esos valores como coordenadas. Vamos a implementar esta última.

Necesitamos a crear dos funciones.

  • x_final gira hasta que apunta hacia la izquierda (180º) con un error menor que dos grados y allí mide la distancia.
  • y_final gira hasta que apunta hacia arriba (270º) con un error menor que dos grados y allí mide la distancia.
Programación por bloques

Así quedaría la función mancha_encontrada

Programación por bloques

Llamando a las funciones x_final,  y_final conseguimos las coordenadas del punto de contacto con la mancha. Decimos esos resultados por voz y los mandamos al ladrillo.

Juego de la Serpiente - OpenRoberta

Y aquí damos por terminada esta implementación de robot buscador.

¿Cómo lo utilizo?

El documento está escrito para alguien con ligeras nociones de programación y robótica en entornos de bloques (alguna experiencia con Scratch podría bastar). Su lectura no debería ofrecer problemas a un docente que podría ir replicando el programa según fuera avanzando en el manual. De forma similar podría dárseles el mismo documento a estudiantes con experiencia en programación de bloques sin necesidad de mayor ayuda.

Para estudiantes nuevos en programación podría: dividirse el documento, añadir algunas explicaciones o reducir funcionalidades del robot. Aunque quizá en ese caso sería más interesante ir a algo menos “realista” como Scratch y aprender allí lo básico primero.

¿Qué materiales necesito para ponerlo en práctica en el aula?

Un ordenador con acceso a Internet y un navegador compatible para cada robot que se quiera usar.

¿Cómo evalúo las competencias adquiridas por los estudiantes con este recurso?

En mi opinión la mera realización guiada y envío del programa (o capturas) no sería suficiente garantía de aprendizaje.

En un entorno con una ratio reducida, la realización en el aula, responder a preguntas durante la práctica o exposición final de partes del algoritmo a los compañeros podrían ser buenos elementos de evaluación.

En un entornos de ratios altas (mucho más habituales) donde esa atención personalizada no resulta posible, podría hacerse una prueba objetiva final donde se presentasen pequeños trozos de código (relacionados con los elementos aprendidos) y se les preguntase por su funcionamiento. También podrían plantearse pequeños desafíos (de nuevo, relacionados con lo aprendido) y que hiciesen ellos, en ese momento, pequeños trozos de código que remitiesen como respuesta. Para que este segundo modo fuera “escalable” en su corrección, de nuevo habría que tener en cuenta el número de estudiantes del que estemos hablando.