L’esperienza con NAO

Le applicazioni che ho sviluppato per NAO sono parte di un progetto internazionale di più ampia portata volto a migliorare l’interazione dei bambini affetti da autismo. Sembra banale, ma quello che un robot fa egregiamente è ripetere più e più volte lo stesso task senza variazioni nel tono di voce o nell’atteggiamento. Il bambino si trova così in un clima ideale e rassicurante, riuscendo ad uscire dall’isolamento che caratterizza questo disturbo.

Rivolto principalmente a scuole e centri di ricerca, NAO ha un costo di circa 8 mila euro, troppo per un semplice hobbista. Entrare nel gruppo degli sviluppatori mi ha permesso di avere accesso ad un esemplare ad una frazione del suo costo e a tutto il codice attualmente esistente.

Attingendo a memorie di un’infanzia ormai lontana, ho pensato a quello che mi incuriosiva e cercato di portarlo in forma di app.

Nel 2016, a causa di impegni professionali sempre più invadenti, ho cessato ogni collaborazione con Aldebaran Robotics e venduto NAO ad uno sviluppatore di Madrid che sta continuando il progetto.

 

Tracker

Più difficile di quello che possa sembrare dato che il riconoscimento cromatico è fortemente condizionato dalla luce ambientale mentre il potere di elaborazione di NAO un po’ troppo limitato. Funziona e mi ha permesso di studiare un po’ di tecnica, ma quando ho applicato la stessa routine su di un computer ROS ho ottenuto effetti ben più soddisfacenti.

 

Silly Animal Recognitions

Esplorando le tecniche di riconoscimento immagini ho applicato a NAO un semplice algoritmo che gli permettesse di riconoscere le figure da un set di carte precedentemente memorizzate. Il bambino giocando con il Robot può facilmente imparare il nome degli animali. Interessante la parte di codice che si occupa di orientare l’immagine nel modo corretto nella mente del robot a prescindere dalla sua posizione reale (ad es. sottosopra).

 

Tabelline

NAO interroga il bambino sulle tabelline secondo due modalità:

  • 10 domande in ordine casuale da una tabellina scelta (es: 7X6, 7X3, 7X8..)
  • 10 domande su tutte le tabelline

Il livello di interazione è perfetto dato che ho implementato tutto tramite riconoscimento vocale, compreso il menu di selezione modalità. In caso di risposta errata NAO riformula ad oltranza la stessa domanda fino ad una richiesta di interruzione.

 

Indovina chi?

Era tra i miei giochi preferiti e la programmazione si è rivelata piuttosto complessa nella fase di studio e pianificazione delle sequenze. Una volta che il bambino ha scelto il personaggio,  NAO gli pone cinque domande casuali ma senza ripetizione (“ha il cappello?”, “ha gli occhi blu?”, “è una donna?”,…) atte ad arrivare all’identificazione finale. Ecco il codice Python:

 

# -*- coding: utf-8 -*-
__author__ = 'Andrea'

from random import randint

# Definizione funzione rimuovi se in lista

def remove_if(lista, valore):
try:
lista.remove(valore)
except ValueError:
pass

# Definizione personaggi e loro caratteristiche

nr1 = ['Hans', 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1]
nr2 = ['Inga', 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0]
nr3 = ['John', 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1]
nr4 = ['Katrin', 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0]
nr5 = ['Markus', 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1]
nr6 = ['Jane', 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0]
nr7 = ['Paul', 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1]
nr8 = ['Claudia', 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0]
nr9 = ['Stefan', 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1]
nr10 = ['Nelli', 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0]
nr11 = ['Ahmed', 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1]
nr12 = ['Sabrina', 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
nr13 = ['Theo', 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1]
nr14 = ['Maria', 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0]
nr15 = ['George', 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1]
nr16 = ['Sophia', 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0]
nr17 = ['Ivan', 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1]
nr18 = ['Sara', 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]
nr19 = ['Jose', 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1]
nr20 = ['Anna', 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0]

# Composizione del mazzo

mazzo = [nr1, nr2, nr3, nr4, nr5, nr6, nr7, nr8, nr9, nr10, nr11, nr12, nr13, nr14, nr15, nr16, nr17, nr18, nr19, nr20]

# Elenco frasi

fra0 = 'Si chiama'
fra1 = 'Ha il cappello?'
fra2 = 'Ha i capelli biondi?'
fra3 = 'Ha i capelli neri?'
fra4 = 'Ha i capelli marroni?'
fra5 = 'Ha i capelli bianchi?'
fra6 = 'Ha i capelli rossi?'
fra7 = 'Ha i baffi?'
fra8 = 'Ha gli occhiali?'
fra9 = 'Ha gli occhi azzurri?'
fra10 = 'Ha gli orecchini?'
fra11 = 'è un maschio?'

# Ventaglio domande

listaDom = [fra1, fra2, fra3, fra4, fra5, fra6, fra7, fra8, fra9, fra10, fra11] # lista tot domande
dom = listaDom[:] # lista clonata da cui tolgo le domande già fatte
domCap = [fra2, fra3, fra4, fra5, fra6] # lista domande che riguardano il colore dei capelli

# Programma

print ''
print '--INIZIO PROGRAMMA--'
print ''

# Main routine

while len(mazzo) > 1:

# Routine scelta domanda

indiceCasuale = randint(0, len(dom) - 1) # l'ultima frase nella lista domande ha pos 10

domScelta = dom[indiceCasuale] # la domanda vera e propria (sottolista)

posDom = listaDom.index(domScelta) + 1 # posizione nella lista domande tot (la lista 'dom' si accorcia)

print domScelta, 's/n'
risp = raw_input('> ')

if risp == 's':
for i in reversed(range(0, (len(mazzo)))):
if mazzo[i][posDom] == 0: # è la caratteristica 0/1
del mazzo[i] # è la carta

if domScelta in domCap: # routine per scartare ulteriori domande sui capelli se già individuato il colore
for j in domCap:
remove_if(dom, j)

elif risp == 'n':
for i in reversed(range(0, (len(mazzo)))):
if mazzo[i][posDom] == 1:
del mazzo[i]

del dom[indiceCasuale]

try:
guess = mazzo[0][0]
print ''
print 'Credo sia', guess

except IndexError:
print 'No, nessuno ha queste caratteristiche!'

print '--FINE PROGRAMMA--'