Documentation

Documentation

Introducción a las BotApps

En este documento analizaremos brevemente la función de cada una de las funciones del Aisoy 1 para el desarrollo de Botapps. Nos apoyaremos en código ya realizado para explicar cada una de las funciones.

Aprender las emociones jugando

En primer lugar, debemos realizar la importación de la clase Aisoy, situada dentro del SDK:

from airos.internal_sdk import Aisoy

Esta línea básicamente se añade para importar la clase Aisoy, la cual contiene todas las funciones relativas al robot (movimiento, habla, sonido…) y que vamos a utilizar posteriormente.

Objeto Aisoy

aisoy = Aisoy()

Con esta línea, creamos un objeto de la clase Aisoy. Este objeto representa al robot, y desde él se puede llamar a todos los atributos que veremos a continuación.

Atributos del Aisoy

tts

  • Este atributo de Aisoy, de la clase Tts, representa el habla. A través de la clase tts se llaman a funciones vinculadas a la capacidad de hablar del Aisoy.
  • aisoy.tts
  • La función say:
    • aisoy.tts.say(‘texto’, wait=True)
    • siendo el primer parámetro ‘texto’, lo que se quiera que diga Aisoy.
    • El segundo parámetro se utiliza para que no realice ninguna acción posterior hasta que no termine de hablar. Es muy importante, ya que si se quitara, podría desempeñar en un mal funcionamiento del robot.

asr

  • Este atributo de Aisoy, de la clase Asr, representa la capacidad de escuchar. A través de este atributo se llaman a funciones vinculadas con la escucha.
  • aisoy.asr
  • La función listen:
    • aisoy.asr.listen(tiempo)
    • Realiza la escucha por el micrófono, durante un tiempo indicado en el parámetro y devuelve lo que ha escuchado. Si no se le habla en ese tiempo, devuelve un vacío “” y continúa la ejecución.
    • Ejemplo: respuesta = aisoy.asr.listen(10) espera 10 segundos y almacena en respuesta lo que ha escuchado. Si dijese “Hola”, entonces respuesta valdría “Hola”
    • Si se pone tiempo –1, entonces espera hasta que escucha algo.

heart

  • Este atributo de Aisoy, de la clase Color representa el color del corazón de Aisoy. A través de este atributo se llaman a funciones vinculadas con el color de su corazón.
  • aisoy.heart
  • La función set:
    • aisoy.heart.set(r, g, b)
    • Esta función simplemente pone un color determinado al corazón de Aisoy. Se rige en función RGB (Red, green, Blue), en sus tres parámetros. Pudiendo variarse para conseguir otros colores.
    • Ejemplo aisoy.heart.set(255, 0, 0) → Color Rojo
    • Ejemplo aisoy.heart.set(0, 255, 0) → Color Verde
    • Ejemplo aisoy.heart.set(159, 0, 200) → Color Violeta

servo

  • Este atributo de Aisoy, de la clase Servo representa los movimientos de cabeza, párpados y cejas de Aisoy. A través de este atributo se llaman a funciones vinculadas con estos movimientos.
  • aisoy.servo
  • La función set:
  • aisoy.servo.set(‘parte_de_la_cabeza’, posición, tiempo)
  • Esta función realiza un movimiento del robot, sea de cabeza, cejas o párpados. Se mueve a una posición determinada, de 1 a 100. El tiempo representa lo que demora en realizar el movimiento, más lento o más rápido.
  • Ejemplo: aisoy.servo.set(‘head_h’, 40, 1) Movimiento de Cabeza
  • Ejemplo: aisoy.servo.set(‘eyebrows’, 100, 1) Movimiento de Cejas
  • Ejemplo: aisoy.servo.set(‘eyelids’, 60, 1) Movimiento de Párpados

audio

  • Este atributo de Aisoy, de la clase Audio representa los sonidos de Aisoy. A través de este atributo se llaman a funciones vinculadas a sonidos propios de Aisoy.
  • aisoy.audio
  • La función play:
    • aisoy.audio.play(‘beep’)
    • Esta función reproduce un sonido determinado por el altavoz del Aisoy. En el ejemplo anterior se trata de un pitido.
    • Otro ejemplo: aisoy.audio.play(‘loops-Garden’)

display

  • Este atributo de Aisoy, de la clase Display representa el display de la boca de Aisoy. A través de este atributo se llaman a funciones vinculadas al display mencionado.
  • aisoy.display
  • La función write:
    • aisoy.display.write(‘texto’)
    • Esta función simplemente mostrará el texto especificado en la display del Aisoy.

accel

  • Este atributo de Aisoy, de la clase Accel representa los valores del acelerómetro interno de Aisoy. A través de este atributo se llaman a funciones vinculadas al sensor mencionado.
  • aisoy.accel
  • La función get_position:
  • aisoy.accel.get_position()
  • Esta función devuelve la posición del Aisoy (yaw, roll, pitch)
  • Ejemplo: Pos = aisoy.accel.get_position() Pos almacena la posición.

performance

  • Este atributo de Aisoy, de la clase Performance representa el estado de ánimo de Aisoy. A través de este atributo se llaman a funciones vinculadas con el estado de ánimo.
  • aisoy.performance
  • La función set_emotion:
  • aisoy.performance.set_emotion(‘happy’)
  • Esta función establece el estado de ánimo del Aisoy

performance

  • Este atributo de Aisoy, de la clase Qr representa el sensor que capta códigos QR de Aisoy. A través de este atributo se llaman a funciones vinculadas con el sensor.
  • aisoy.qr
  • La función get_code:
  • aisoy.qr.get_code(tiempo)
  • Esta función devuelve el significado del código QR que se ha enseñado a Aisoy. El parámetro tiempo es el tiempo máximo que ha de esperar hasta que le enseñas el código.
  • Ejemplo: codigo = aisoy.qr.get_code(10)
  • Este ejemplo, almacena en “codigo” el significado del código QR que le enseñas al Aisoy, en un tiempo máximo de 10 segundos.

Resumen

Breve resumen de lo indicado anteriormente

  • Hablar → aisoy.tts.say(‘texto’, wait=True)
  • Escuchar → aisoy.asr.listen(10)
  • Mover cabeza → aisoy.servo.set(‘head_h’, 40, 1)
  • Mover cejas → aisoy.servo.set(‘eyebrows’, 40, 1)
  • Mover párpados → aisoy.servo.set(‘eyelids’, 60, 1)
  • Tocar → aisoy.touch.which_touched(10)
  • Color → aisoy.heart.set(255, 0, 0)
  • Sonido → aisoy.audio.play(‘beep’)
  • Posicion → aisoy.accel.get_position()
  • Escribir display → aisoy.display.write(‘texto’)
  • Poner emoción → aisoy.performance.set_emotion(‘happy’)
  • Codigo QR → aisoy.qr.get_code(10)

Proyecto de programación

¿Qué harás?

En esta actividad, vamos a aprender a programar, un juego muy sencillo para enseñar a contar.

Aisoy, por el número anterior o posterior a otro número, el niño responderá el número que crea que puede ser la respuesta. Al final del juegos se sumarán las respuestas acertadas y ese será el resultado obtenido por el niño.

¿Qué aprenderás?

Mientras programas con Python, vas a aprender a:

  • Utilizar diversas herramientas de python con Aisoy
  • Ofrecer diferentes posibilidades de resultado a partir de una resta
  • Crear diálogos coherentes con el juego para hacer dinámica cada partida
  • Cómo estructurar el código de una Botapp sencilla

Desarrollo

Tanto con un amigo como contra Aisoy, te damos los pasos para programar cada una de las partes necesarias para que Aisoy nos anime a jugar, y pasemos un rato agradable de diversión.

1

Crear el proyecto

Para crear vuestro primer proyecto os adjuntamos guía muy completa, sobre los métodos de crear un proyecto, para visualizarla clicka aquí.

2

¿Qué librerías vamos a usar?

import random
import time
import threading
from airos.helper import AirosHelper
from airos.sdk import Aisoy

Estos van a ser los módulos necesarios para desarrollar esta pequeña aplicación, conforme vayamos leyendo la documentación, veremos para qué van ser usados. Aun así esbozaremos lo que hace cada uno de estos import:

  • random: Se utilizará para generar números aleatorios.
  • time: Se usa para generar tiempos de espera en la ejecución.
  • threading: Se utiliza para ejecutar tareas de manera simultánea de una misma aplicación.
  • AirosHelper y Aisoy: Son librerías de Aisoy para las usar diferentes utilidades del robot.

3

Rutina inicial: Movements

Cuando iniciamos una botapp, el robot inicia el juego con una serie de movimientos, sea de párpados, cejas o cabeza, que perduran durante toda la partida. Esto se realiza a través de la clase Movements, la cual a través de su método run.

Primero, hay que crear  el inicializador, para iniciar el hilo de ejecución de los movimiento e inicializar los parámetros.

def __init__(self, name=’Movimientos‘):
threading.Thread.__init__(self)

self.name = name
self.daemon=True
self.aisoy = Botapp.aisoy

Además, necesitamos un método run que será el que contemple toda la funcionalidad de clase y que se ejecutará en el Thread.

def run(self):

print(‘Starting movement Thread’)
while playing:

rnd_mv = random.randint(1, 100) % 3
rnd_tm = random.randint(1, 100) % 15
if rnd mv is 0:

print(‘eyebrows’)
self.aisoy.servo.set(“eyebrows”, 0, 1, False)
self.aisoy.servo.set(“eyebrows”, 100, 1, False)
self.aisoy.servo.set(“eyebrows”, 50, 1, False)

elif rnd_mv is 1:

print(‘head’)
self.aisoy.servo.set(“head_v”, 40, 1, False)
self.aisoy.servo.set(“head_v”, 60, 1, False)
self.aisoy.servo.set(“head_v”, 50, 1, False)

elif rnd_mv is 2

print(‘eyelids’)
self.aisoy.servo.set(“eyelids”, 0, 1, False)
self.aisoy.servo.set(“eyelids”, 100, 1, False)
self.aisoy.servo.set(“eyelids”, 50, 1, False)

time.sleep(rnd_tm)

print(‘Exiting movement Thread’)

El método run ejecutará de forma aleatoria alternando movimientos de cabeza, ojos y párpados constantemente hasta que finalice el juego.

4

Funcionalidades del robot Aisoy

Crearemos la clase Botapp con un objeto estático Aisoy, para poder trabajar con nuestro robot. En esta clase todos sus métodos son estáticos, por ello, no es necesaria la instanciación de esta para su uso.

class Botapp():

aisoy=Aisoy()

Para repetir el juego

Dentro de la clase Botapp, utilizamos este sencillo código, para preguntarle al niño si quiere seguir jugando o no.

@staticmethod

def want_to_repeat():
Botapp.aisoy.tts.say(‘¿Quieres repetir el juego?’,wait=True)
Botapp.aisoy.tts.say(

‘Si quieres repetir el juego toca con tu mano mi derecha’,wait=True)

Botapp.aisoy.tts.say(

Si quieres salir toca con tu mano mi izquierda’,wait=True)
touched = Botapp.aisoy.touch.which_touched(-1)

if “right” in touched:

Botapp.aisoy.tts.say(‘Vamos a repetir el juego’,wait=True)
return Game.REPEAT

if “left” in touched:

return Game.EXIT

return Game.EXIT

Comprobar los resultados obtenidos

En este método estático de la clase Botapp, comprobaremos el porcentaje de respuestas acertadas por el niño y según este porcentaje, se le dirá que necesita o no mejorar dentro de este juego.

@staticmethod

def results(total_questions, correct_questions):

percentage_of_correct_answers = (

correct_questions * 100) / total_questions

Botapp.aisoy.tts.say(

‘Has acertado ‘ + str(correct_questions) + ‘ de ‘ +
str(total_questions),wait=True)

if total_questions is correct_questions:

Botapp.aisoy.performance.set_emotion(‘admiration’)
Botapp.aisoy.audio.play(‘loops-Triumph’, 0.1, False)
Botapp.aisoy.tts.say(‘Has acertado todo, ¡Muy
bien!’,wait=True)

elif percentage_of_correct_answers < 50:

Botapp.aisoy.performance.set_emotion(‘sad’)
Botapp.aisoy.tts.say(‘Necesitas mejorar
bastante’,wait=True)

else:

Botapp.aisoy.performance.set_emotion(‘surprise’)
Botapp.aisoy.tts.say(‘Necesitas mejorar un
poco’,wait=True)

Dar la enhorabuena por un resultado acertado

Realizamos un método para dar la enhorabuena por acertar una de las restas propuestas por Aisoy. Éste lo manifestará tanto por el habla como por la emoción que expresa.

@staticmethod

def congratulations():

Botapp.aisoy.performance.set_emotion(“happy”)
Botapp.aisoy.audio.play(‘effects-waterdrop’, False)
Botapp.aisoy.tts.say(‘Muy bien, has acertado’,wait=True)

Presentación inicial del juego

Al iniciar la Botapp, Aisoy hará una breve presentación propia, indicando quién es él y su intención de querer jugar. Asimismo, para que Aisoy sepa que queremos jugar con él, tendremos que tocarle la cabeza, por lo que tenemos que utilizar which_touched() para recoger los datos del sensor de la cabeza.

@staticmethod

def presentation():

Botapp.aisoy.performance.set_emotion(“happy”)
Botapp.aisoy.audio.play(‘loops-Garden’, 0.1, False)
Botapp.aisoy.tts.say(‘Hola!,’ +

‘Me llamo Aisoy y soy un robot.‘ +
‘Sí, soy un robot social que quiere ser amigo  tuyo’ +
‘Y jugar contigo!!’ +
‘¿Quieres jugar conmigo?’,wait=True)

Botapp.aisoy.tts.say(‘Si quieres jugar toca mi cabeza’,wait=True)

touched = Botapp.aisoy.touch.which_touched(15)
if “head” in touched:

Botapp.aisoy.display.write(Game.GAME_TITLE)
Botapp.aisoy.tts.say(‘Vamos a jugar a ‘ +

Game.GAME_TITLE, False,wait=True)

return

exit()

Explicación del juego

Este método estático explicara el juego si así lo desea el niño, según toque la parte izquierda o derecha de su cuerpo.

@staticmethod

def explanation():

Botapp.aisoy.tts.say(‘¿Quieres que te explique el juego?’,wait=True)
Botapp.aisoy.tts.say(

‘Si quieres que te explique el juego toca con tu mano a mi derecha’,wait =True)

Botapp.aisoy.tts.say(

‘Si quieres jugar ya. toca con tu mano a mi izquierda’,wait=True)

touched = Botapp.aisoy.touch.which_touched(20)
if “left” in touched:

Botapp.aisoy.tts.say(‘Vamos a empezar a jugar’,wait=True)
return

if “right” in touched:

Botapp.aisoy.tts.say(Game.GAME_EXPLANATION,wait=True)
Botapp.aisoy.tts.say(‘Vamos a empezar a jugar’,wait=True)
return

Despedida tras finalizar el juego

Cuando el juego finaliza, y no se quiere repetir, entonces Aisoy realiza una breve despedida, dando sus impresiones sobre el juego y cambiando sus emociones.

@staticmethod

def bye_bye():

Botapp.aisoy.performance.set_emotion(“happy”)
Botapp.aisoy.audio.play(‘loops-Medieval1’, 0.1, False)
Botapp.aisoy.tts.say(‘¿Te lo has pasado bien?’,wait=True)
Botapp.aisoy.tts.say(‘Yo me he divertido mucho contigo.’,wait=True)
Botapp.aisoy.tts.say(‘Te espero otro día para jugar.’,wait=True)
Botapp.aisoy.tts.say(‘Adios’,wait=True)

Decir las posibles opciones de resultado

Este método estático, dirá las posibles opciones de resultado y el resultado decidido será el parámetro devuelto.

@staticmethod

def say_options(options):

for (idx, option) in enumerate(options):

Botapp.aisoy.tts.say(“” + str(idx + 1) + “. “ + str(option),wait=True)

if Botapp.aisoy.asr:

answer = Botapp.aisoy.asr.listen(-1)

else:

answer = Botapp.aisoy.qr.get_code(10)
answer = answer.lower()
answer = AirosHelper.strip_accents(answer)

if answer == ‘1’ or answer == ‘uno’:

return options[0]

elif answer == ‘2’ or answer == ‘dos’:

return options[1]

elif answer == ‘3’ or answer == ‘tres’:

return options[2]

return answer

Recoger la respuesta del usuario

Para poder recoger la respuesta obtenida, necesitamos un método que llame a las funcionalidades del micrófono y recoja en una variable la respuesta, lo cual se hace empleando ASR y llamando a la función listen. Este además tendrá dos modos según el número aleatorio que toque, que serán ir hacia adelante o hacia atrás. También puedes cambiarlo a modo de opciones, aunque por defecto se encuentra desactivado.

@staticmethod

def ask_input():

tipo = random.randint(1, 50) % 2
numero = random.randint(1, 10)
correct_number = 0
print(“Tipo: “ + str(tipo))

if tipo is 1:

Botapp.aisoy.tts.say(‘El número siguiente a ‘ + str(numero) + ‘ es…’, False,wait=True)
correct_number = numero + 1
correct_answer = BotApp_Struct.integer_to_speak.get(numero + 1)

else:

Botapp.aisoy.tts.say(‘El número anterior a ‘ + str(numero) + ‘ es…’, False,wait=True)
correct_number = numero – 1
correct_answer = BotApp_Struct.integer_to_speak.get(numero – 1)
Botapp.aisoy.display.write(str(numero))

# Ask the input

if BotApp_Struct.WITH_OPTIONS:

options = BotApp_Struct.get_n_answers(3, correct_answer)
random.shuffle(options)
answer = Botapp.say_options(options)

else:

if Botapp.aisoy.asr:

answer = Botapp.aisoy.asr.listen(10)

else:

answer = Botapp.aisoy.qr.get_code(10)

print(“Answer: “ + answer + ” Correct answer: “ + correct_answer)
answer = answer.lower()
answer = AirosHelper.strip_accents(answer)

if correct_answer in answer or answer == correct_number:

return BotApp_Struct.CORRECT

else:

return BotApp_Struct.INCORRECT

return answer

5

Manejar las respuestas del usuario

Botapp_Struct es una clase que contiene dos variables estáticas que contienen un número que dice si un resultado es correcto o incorrecto además de varios métodos estáticos, para dar posibles respuestas al robot. Por último tenemos un diccionario con las preguntas y las respuestas del juego.

class BotApp_Struct():

CORRECT = 1
INCORRECT = -1
WITH_OPTIONS = False

integer_to_speak = {
0: ‘cero’,
1: ‘uno’,
2: ‘dos’,
3: ‘tres’,
4: ‘cuatro’,
5: ‘cinco’,
6: ‘seis’,
7: ‘siete’,
8: ‘ocho’,
9: ‘nueve’,
10: ‘diez’,
11: ‘once’
}
globaldictionary = {

}

También crearemos un inicializador de clase para manejar el el diccionario de las preguntas y las respuestas.

def __init__(self):

“””Create the questions dictionary, ready to be modified”””
self.dictionary = dict(self.globaldictionary)

6

Secuencia normal del Botapp

La clase Game, tiene como objetivo establecer la secuencia del juego, llamando a los métodos de las demás clases. 

Tenemos que inicializar algunas variables globales de clase, que representan la opción de salir, repetir un pregunta en concreto y continuar jugando. Además se define la explicación y el título del juego.

class Game():

EXIT = 0
REPEAT = 1
CONTINUE = 2
GAME_TITLE = ‘Contar hasta’
GAME_EXPLANATION = ‘En enste juego te voy a pedir que me digas el número siguiente o anterior de un número’

Inicializador de la clase

Cuando crea una instancia de esta clase, se llama automáticamente a este método, el cual inicializa algunas variables que se usarán en el transcurso del juego, como playing que indica que el juego se está ejecutando, por lo que cuando se quiere finalizar, pasa a valer False. Las demás son el número de cuestiones total en el juego, las preguntas acertadas hasta ahora y la opción de repetir el juego.

def __init__(self):

self.playing = True
“”” Not always have a number of questions, create the necessary variables”””
self.total_questions = 5
self.correct_questions = 0
self.repeat = Game.CONTINUE

Secuencia normal del juego


Es un trozo de código que a priori puede parecer más complicado que el resto de la Botapp, pero realmente tiene un procedimiento muy sencillo.

Primero presenta y explica en qué va consistir el juego, posteriormente inicializa siempre las respuestas acertadas a 0, y una vez hecho eso obtiene y realiza las pregunta el numero posterior o anterior a un numero.. En caso de acertar le da la enhorabuena y le suma un punto respuestas correctas y sino simplemente avisa de que la respuesta ha sido errónea esto un cierto. Esto lo hace un cierto número de veces establecidas en el constructor de la clase.

Una vez terminado el juego pregunta si quiere repetir el juego. En caso de que no, simplemente se despide, si es que si el robot seguirá jugando.

def main_loop(self):

“”” The main loop of the game “””
global playing
# Presentation and explanation of the game
Botapp.presentation()
Botapp.explanation()
# Continue if player wants to
while self.repeat is Game.CONTINUE:

# Select difficulty
self.repeat = Game.REPEAT
# Repeat always the player wants to
while self.repeat is Game.REPEAT:

# Restart the correct_questions in each game
self.correct_questions = 0
# Ask n questions
for _ in xrange(self.total_questions):

Botapp.aisoy.performance.set_emotion(“normal”)
# Ask input
player_answer = Botapp.ask_input()
if player_answer is BotApp_Struct.CORRECT:

Botapp.congratulations()
self.correct_questions += 1

else:

Botapp.oops()

Botapp.aisoy.performance.set_emotion(“normal”)
Botapp.results(self.total_questions, self.correct_questions)
self.repeat = Botapp.want_to_repeat()

playing = False
Botapp.bye_bye()

7

¿Donde ejecutamos todo el código que hemos escrito?

Lógicamente, debe existir un método main donde ejecutemos todas las clases y método escritas anteriormente. Desde este main se crea el Thread de Movements y se inicia, al terminar el juego (main.loop) entonces se debe parar el Thread.

if __name__ == ‘__main__’:


“””This is the main of class, here is where you execute the methods and classes.”””
# Create Movements thread and start it
mov = Movements()
mov.start()
# Wait three seconds to wait to mov starts
time.sleep(3)
# Create the game object and launch main loop
a = Game()
a.main_loop()
# Join movements thread to main thread
mov.join()