Sviluppo di un sistema per l'interpretazione dei comandi basati sul riconoscimento vocale per l'interazione uomo-robot

Pagina creata da Nicola Bellini
 
CONTINUA A LEGGERE
Sviluppo di un sistema per l'interpretazione dei comandi basati sul riconoscimento vocale per l'interazione uomo-robot
Scuola Politecnica e delle Scienze di Base
Corso di Laurea in Ingegneria Informatica

Elaborato finale in Fondamenti di sistemi dinamici

Sviluppo di un sistema per
l'interpretazione dei comandi basati sul
riconoscimento vocale per l'interazione
uomo-robot

Anno Accademico 2016/17

Candidato:

Davide Russo

matr. N46002152
Sviluppo di un sistema per l'interpretazione dei comandi basati sul riconoscimento vocale per l'interazione uomo-robot
[Dedica]
Sviluppo di un sistema per l'interpretazione dei comandi basati sul riconoscimento vocale per l'interazione uomo-robot
Indice

Indice..................................................................................................................................................III
Introduzione..........................................................................................................................................4
Capitolo 1: Stato dell’arte.....................................................................................................................6
Capitolo 2: Implementazione.............................................................................................................15
   2.1 Verifica della raggiungibilità del server....................................................................................16
   2.1 Richiesta HTTP al server..........................................................................................................17
   2.2 Interpretazione dei comandi.....................................................................................................18
   2.3 Codifica dei comandi................................................................................................................21
   2.4 Creazione del messaggio..........................................................................................................23
   2.5 Visualizzazione dei comandi....................................................................................................24
Capitolo 3: Casi di test.......................................................................................................................25
   3.1 Primo: comando singolo semplice............................................................................................25
   3.2 Secondo: comando singolo articolato.......................................................................................26
   3.3 Terzo: comando fuori dal dominio delle funzioni eseguite dal robot.......................................27
   3.4 Quarto: due comandi semplici..................................................................................................28
   3.5 Quinto: comandi multipli.........................................................................................................29
   3.6 Sesto: interazione sociale.........................................................................................................30
Conclusioni.........................................................................................................................................31
Bibliografia.........................................................................................................................................32
Sviluppo di un sistema per l'interpretazione dei comandi basati sul riconoscimento vocale per l'interazione uomo-robot
Introduzione
     Il lavoro svolto in questa tesi ha lo scopo di implementare un sistema per l'interpretazione

     dei comandi inviati a un robot da un utente espressi in linguaggio naturale.

     Tale sistema estende un lavoro già presentato nella tesi di laurea [1], al quale abbiamo

     aggiunto diverse funzionalità in modo da superarne alcuni limiti, tra cui:

         •   l’analisi della frase pronunciata dall’utente era eseguita in maniera statica nel senso

             che le parole della frase vengono analizzate senza eseguire alcuna analisi sintattica

             delle stesse, ma semplicemente confrontando le radici di queste basandoci su un

             dizionario interno all’applicativo e implementato dagli sviluppatori;

         •   la possibilità di esprimere un solo comando per volta;

         •   l’assenza di modulartità dell’algoritmo che comportava una particolare difficoltà

             nell’aggiunta di comandi.

     Quindi, gli obiettivi di questo lavoro di tesi sono:

         •   utilizzare un motore di Natural Language Processing in cloud per interpretare un

             insieme di comandi richiesti da un operatore umano, in modo da permettere a questi

             di richiedere un’azione interagendo attraverso il linguaggio naturale;

         •   implementare un sistema che permetta controllo e interazione sociale tra l'utente ed

             il robot;

         •   implementare un sistema modulare, indipendente sia dalla piattaforma robotica

             utilizzata (nel nostro caso RoDyMan sviluppato dal PRISMA Lab dell’Università

             degli Studi di Napoli “Federico II”) che dal Natural Language Processor utilizzato;

     Tale lavoro di tesi si divide in tre parti: inizialmente verranno introdotte le tecnologie

     utilizzate, considerando sia il cuore dell’applicativo ovvero il Natural Language Processor,

     sia l’area di applicazione di quest’ultimo cioè il Natural Language Processing. Verranno

     descritte le soluzioni già esistenti in letteratura e quella utilizzata in questo lavoro di tesi,

     motivandone la scelta. In una seconda parte verranno descritte le tecniche implementative

     seguite durante lo sviluppo del sistema, e infine verranno discussi alcuni casi di test per

     dimostrare come funziona il sistema implementato e gli obiettivi raggiunti.

                                                4
Sviluppo di un sistema per l'interpretazione dei comandi basati sul riconoscimento vocale per l'interazione uomo-robot
Per quanto riguarda l’implementazione di tale sistema, esso è basato su tecnologia

Android, attraverso la programmazione in linguaggio Java e prevedendo un terminale

mobile (cellulare, tablet, etc…) che permette l’interazione tra l’utente la piattaforma

robotica.

Per quanto riguarda la lingua scelta per l’interazione tra l’uomo e il sistema implementato,

esso è l'inglese, a differenza di quello utilizzato nella precedente tesi, che era basata

sull’italiano. Questa scelta nasce principalmente dal fatto che la lingua utilizzata dal

Natural Language Processor utilizzato nel sistema implementato è appunto l’inglese.

In ogni caso il sistema implementato produce comunque lo stesso risultato in quanto

l’analisi del testo viene effettuata tramite l’analisi degli elementi sintattici del testo inserito

dall’utente e non delle parole stesse del testo.

                                            5
Sviluppo di un sistema per l'interpretazione dei comandi basati sul riconoscimento vocale per l'interazione uomo-robot
Capitolo 1: Stato dell’arte
     Natural Language Processing si riferisce al trattamento informatico (computer

     processing) del linguaggio naturale, per qualsiasi scopo, indipendente dal livello di

     approfondimento dell’analisi. Per linguaggio naturale si intende la lingua che usiamo nella

     vita di tutti i giorni, come l’inglese, il russo, il giapponese, il cinese, ed è sinonimo di

     linguaggio umano, principalmente per poterlo distinguere dal linguaggio formale, incluso

     il linguaggio dei computer. Così com’è, il linguaggio naturale è la forma di comunicazione

     più naturale e più comune, non solo nella sua versione parlata, ma anche in quella scritta.

     Rispetto al linguaggio formale, il linguaggio naturale è molto più complesso, contiene

     spesso sottintesi e ambiguità, il che lo rende molto difficile da elaborare.

     Le teorie dietro l’area chiamata Natural Language Processing è la linguistica

     computazionale che si focalizza su come diminuire il gap tra linguaggio naturale e

     linguaggio formale, attraverso dei formalismi descrittivi di un linguaggio naturale.

     Il Natural Language Processing si divide in due macro aree: il Natural Language

     Understanding e il Natural Language Generation. Queste due macro aree sono una

     l’opposta dell’altra: la prima ha come obiettivo lo studio delle comprensione da parte delle

     macchine del linguaggio naturale; la seconda ha come obiettivo quello di studiare come le

     macchine possono generare frasi in linguaggio naturale.

     In generale il Natural Language Processing prevede diverse fasi nell’analisi di un testo che

     ne fanno di esso una struttura su livelli. I livelli fondamentali su cui si basa l’elaborazione

     dell’analisi di una frase sono [2]:

        •   lessico e morfologia, si occupa di effettuare l’analisi lessicale del testo posto in

            input. Il testo viene “spezzettato” attraverso un processo di tokenizzazione,

            formado una serie di token. In un Natural Language Processing ogni token è

            associato ad una parola del testo. Per ogni token, tramite i processi di

            Lemmatization e Morphological segmentation, vengono individuate tutte le parole

            con significato, detti lemmi, che compongono il testo in input e ne fa l’analisi

            morfologica, cioè individua il modo e il tempo dei verbi, se un nome è singolare o

                                               6
Sviluppo di un sistema per l'interpretazione dei comandi basati sul riconoscimento vocale per l'interazione uomo-robot
plurale, etc.;

•   sintassi, si occupa di effettuare l’analisi sintattica del testo posto in input. Vengono

    cioè individuate tutte le parti del discorso, intesi come verbi, nomi, aggettivi,

    avverbi, preposizioni, pronomi. Il processo che si occupa di marcare ogni parola

    con la propria parte del discorso si chiama Part-of-speech tagging. Il processo, si

    divide in due sotto-processi: il primo, detto shallow parsing, produce un albero

    binario in cui vengono individuate le parti elementari cioè la parte nominale (NP) e

    la parte verbale (VP), mentre il secondo, detto full parsing, produce un albero

    sintattico in cui ogni parola viene marcata con il suo ruolo sintattico all’interno

    della frase. Di seguito viene fatto un esempio, supponendo che il testo in ingresso

    sia “Martina mangia la pizza”. Nell’esempio la stringa in ingresso è identificata con

    S.

•   semantica, si occupa di individuare il significato del testo. Non ci si spinge oltre

    nella spiegazione, ma vale la pena citare il processo Named Entity Recognition che

    è utilizzato per ricercare ed individuare gruppi di parole che possono formare

    un’entità, intesa come nomi di persona, paesi, eventi, etc.;

                                      7
•   pragmatica, si occupa di individuare il contesto in cui è posto il testo e di elaborarlo

       e utilizzarlo in funzione di esso.

Il Natural Language Processing è implementato con un Natural Language Processor, che è

un framework che racchiude tutti i processi utilizzati nei vari livelli.

Allo stato attuale della teconologia, un Natural Language Processor è presente in rete

come servizio cloud.

Il cloud computing è un paradigma di erogazione di risorse informatiche caratterizzate

dal fatto che queste risorse non sono collocate sul computer dell’utente ma su un server

remoto e sono accessibili dall’utente attraverso la rete. Questo paradigma è offerto a

partire da risorse che non vengono configurate e messe in opera dal fornitore apposta per

l'utente, ma gli sono assegnate, grazie a procedure automatizzate, a partire da un insieme

di risorse condivise con altri utenti lasciando all'utente la configurazione della risorsa.

Quando l'utente rilascerà la risorsa, essa verrà riconfigurata nello stato iniziale e rimessa a

disposizione nell’insieme condiviso delle risorse.

I servizi fondamentali messi a disposizione dal cloud computing sono:

         •   SaaS (Software as a Service), offre l’utilizzo di un software, installato su un

             server remoto, usufruibile tramite API (Application Programming Interface)

             accessibili via web;

         •   DaaS (Data as a Service), offre le funzionalità di una memoria di massa,

             mettendo a disposizione dell’utente la gestione di dati disponibili in vari

             formati, come se fossero in locale;

         •   HaaS (Hardware as a Service), offre l’utilizzo di risorse hardware atte

             all’elaborazione di dati collocate, di solito, in un centro elaborazione dati

             (CED) o data center cioè una struttura in cui sono presenti apparecchiature

             fisiche come i server, per la gestione dell’elaborazione dei dati, e tutti gli

             strumenti utili per il funzionamento di essi, come per esempio gruppi di

             continuità e sistemi di raffreddamento;

Attualmente questi servizi sono raggruppati in due macro-servizi che sono:

                                            8
•   PaaS (Platform as a Service), offre, a differenza di Saas e Daas, una piattaforma

           costituita da una serie di programmi e librerie utilizzabili dall’utente che

           comprendono sia software che sistemi per la gestione di dati;

       •   IaaS (Infrastructure as a Service), offre risorse hardware, non solo in termini di

           unità di elaborazione, ma anche in termini di dischi locali e infrastrutture di

           rete.

L’applicazione del cloud computing alla robotica comporta una serie di vantaggi al punto

da creare una nuova branca della robotica, detta cloud robotics. I vantaggi ottenuti sono in

termini di potenza di calcolo e riduzione dei costi. Infatti è possibile creare dei robot a

basso costo, dotati però di un “cervello” costituito dai servizi del cloud compunting di cui

si cita il Machine Learning, Data Mining, Information Extraction, e altri. Questi servizi

sono utili nel campo della robotica per:

   •   la creazione di sistemi per la Human-Robot Interaction;

   •   utilizzare di Big Data, cioè dati raccolti e/o diffusi su reti accessibili e di grandi

       dimensioni che possono consentire decisioni per problemi di classificazione o

       rivelare modelli;
   •   Internet of Things per la robotica.
Questi sistemi sono utilizzati per realizzare servizi del tipo:

   •   Autonomous mobile robots, cioè la possibilità di creare auto che “si guidano da

       sole” in base alle immagini ricevute da GPS e comparate con quelle catturate

       dall’auto tramite fotocamere, sensori;

   •   Cloud medical robots, un cloud che fa da assistenza ai medici attraverso l’accesso a

       vari servizi come un archivio di malattie, cartelle cliniche elettroniche, un sistema

       di gestione della salute del paziente, servizi di pratica, servizi di analisi, soluzioni

       cliniche, sistemi esperti;

   •   Industrial robots, cioè robot utilizzati per la produzione di prodotti.

Un’azienda che si occupa di offrire il cloud computing è detta cloud provider. I maggiori

cloud provider esistenti al mondo sono, per esempio, Google, Amazon, IBM, Microsoft.

Tra i software offerti dal cloud compunting di queste aziende, troviamo anche il Natural

Language Processing. In particolare i prodotti che offrono questo tipo di servizio sono

                                           9
Google Cloud Platform Natural Language API [3], Amazon Comprehend [4], IBM Watson

Natural Language Understanding [5], Microsoft Azure Cognitive Services Language

Understanding (LUIS) [6]. Di seguito si riporta una tabella contenente le peculiarità dei

diversi sistemi offerti.

     Nome
                               Servizi offerti         Lingue supportate          Peculiarità
  piattaforma
                           •     analisi sintattica;
                           •     analisi delle           Inglese, sagnolo,
 Google Cloud
                                 relazioni;            giapponese, cinese,    •   Analisi delle
   Platform
                           •     analisi delle          francese, tedesco,        opinioni relative
    Natural
                                 opinioni;              italiano, coreano,        alle entità.
 Language API
                           •     analisi delle         portoghese, e altre.
                                 entità.
                                                                              •   Rilevamento
                                                                                  della lingua;
                                                                              •   possibilità di
                           •     analisi sintattica;
                                                                                  tradurre e poi
                           •     analisi delle
   Amazon                                                                         analizzare;
                                 opinioni;             Inglese, spagnalo.
  Comprehend                                                                  •   analisi di termini
                           •     analisi delle
                                                                                  o argomenti
                                 entità.
                                                                                  collezione di
                                                                                  documenti (topic
                                                                                  modeling)
                           •     analisi sintattica;
                                                         Inglese, arabo,
                           •     analisi delle
  IBM Watson                                           francese, tedesco,
                                 relazioni;                                   •   Analisi delle
    Natural                                                 italiano,
                           •     analisi delle                                    emozioni di un
   Language                                               giapponese,
                                 opinioni;                                        testo.
 Understanding                                             portoghese,
                           •     analisi delle
                                                       coreano, spagnolo.
                                 entità.
                                                                              •   Analisi delle
                                                       Inglese americano,
                                                                                  intent, cioè
  Microsoft                                            francese canadese,
                                                                                  azioni che
  Cognitive                                            cinese, giapponese,
                           •     analisi sintattica;                              l’utente vuole
   Services                                             coreano, francese,
                           •     analisi delle                                    fare;
   Language                                              tedesco, italiano,
                                 entità.                                      •   analisi di testi
 Understanding                                              portoghese,
                                                                                  malformati che
    (LUIS)                                             spagnolo, spagnolo
                                                                                  devono essere
                                                            messicano.
                                                                                  capiti.

                                                 10
Di seguito segue una lista di tabelle di costi per ogni cloud provider.

                     Google Cloud Platform Natural Language API
          Servizio               0 → 5K           5K+ → 1M       1M+ → 5M      5M+ → 20M
    Analisi delle entità          Gratis             $1.00          $0.50             $0.25
   Analisi delle opinioni         Gratis             $1.00          $0.50             $0.25
     Analisi sintattica           Gratis             $0.50          $0.25         $0.125
   Analisi delle opinioni
                                  Gratis             $2.00          $1.00             $0.50
    relative alle entità

Il costo si riferisce a una spesa mensile per unità detta text record e rappresenta 1000

caratteri Unicode. Per oltre 20 milioni di text record, Google propone dei contratti

commerciali ad-hoc per il cliente.

                                     Amazon Comprehend
        Tipo di servizio               0 → 10M               10M → 50M         Over 50M
              NLP                       $0.0001               $0.00005         $0.000025

                                     Amazon Comprehend
        Tipo di servizio                   First 100 MB            For every MB over 100
        Topic modeling                           $1.00                       $0.004

Il costo fa riferimento a una singola unità che consiste in 100 caratteri Unicode. Il minimo

di unità per poter usufruire dei servizi di Amazon è 3.

                     IBM Watson Natural Language Understanding
              Tipo di contratto                                    0 → 30K
                     Lite                                           Gratis

                     IBM Watson Natural Language Understanding
          Tipo di contratto                0 → 250K           250K+ → 5M        Over 5M
              Standard                          $0.003          $0.001           $0.0005

                                           11
Il costo fa riferimento a un canone mensile per unità della NLU che rappresenta 10000

caratteri. La Microsoft permette anche di stipulare contratti commerciali personalizzati.

              Microsoft Cognitive Services Language Understanding (LUIS)
                                                                           Every 1000 transaction
              Servizio                               0 → 10K
                                                                                 over 10K
               LUIS                                   Gratis                       $1.50

Il costo fa riferimento ad un costo mensile. Per transaction s’intende una chiamata alle

API del sistema con query che contengono fino a 500 caratteri.

Il più idoneo per questo lavoro di tesi è Google Cloud Natural Language API in quanto le

API offerte si adattano perfettamente alla stesura di un’applicazione Android, ma a causa

dei costi, che si basano sul numero di query inviate e sul fatto che per accedere al servizio

serve una partita IVA, la scelta è ricaduta su una soluzione open-source chiamata

StanfordNLP. Questo Natural Language Processor è stato sviluppato da un team di

ricercatori della Stanford University. Di seguito si riportano in tabella le caratteristiche del

Natural Language Processor in esame.

     Nome
                             Servizi offerti          Lingue supportate            Peculiarità
  piattaforma
                         •     analisi sintattica;
                         •     analisi delle            Inglese, arabo,
   StafordNLP                  opinioni;               cinese, francese,       •   Open-source
                         •     analisi delle          tedesco, spagnolo.
                               entità.

Il servizio di Natural Language Processing è offerto in modo tale da poter installare un

server privato al fine di creare un’architettura client-server, dove il client fa delle richieste

al server, che vengono effettuate tramite protocollo HTTP e il server risponde con le

informazioni legate al testo messo in ingresso in formato JavaScript Object Notation

(JSON) [7].

JavaScript Object Notation è un formato dati adatto all’interscambio di essi

nell’architettura client-server. JSON prende origine dalla sintassi degli oggetti letterali in

                                               12
JavaScript. Un oggetto letterale può essere definito così:

                    var JSON = {
                                            proprieta1: 'Valore',
                                            proprieta2: 'Valore',
                                            proprietaN: 'Valore'
                                            }

Si tratta di coppie di proprietà/valori separate dalla virgola a eccezione dell’ultima.

L’intero oggetto viene racchiuso tra parentesi graffe. A differenza di JavaScript, che può

contenere anche funzioni e valori complessi, JSON ammette solo valori semplici e

atomici, tra cui:

      •   stringhe;

      •   numeri;

      •   array;

      •   oggetti letterali;

      •   true, false;

      •   null.

La caratteristica principale di StanfordNLP che più salta all’occhio è che la lingua
utilizzata dal servizio è l’inglese, quindi tutti i comandi sono dati in lingua inglese.

Particolare attenzione vale la pena darla al servizio Part-of-speech tagging di StanfordNLP

utilizza il Penn Treebank tag set [8]. Questo set di tag è una legenda che esplicita la

semantica di ogni tag utilizzato dal servizio Part-of-speech. Di cui di seguito viene

mostrata la tabella.

                     Tag                      Description
                     CC        Coordinating conjunction
                     CD        Cardinal number
                     DT        Determiner
                     EX        Existential there
                     FW        Foreign word
                       IN      Preposition or subordinating conjunction

                                            13
JJ       Adjective
                   JJR       Adjective, comparative
                   JJS       Adjective, superlative
                   LS        List item marker
                   MD        Modal
                   NN        Noun, singular or mass
                  NNS        Noun, plural
                  NNP        Proper noun, singular
                 NNPS        Proper noun, plural
                  PDT        Predeterminer
                  POS        Possessive ending
                  PRP        Personal pronoun
                  PRP$       Possessive pronoun
                   RB        Adverb
                  RBR        Adverb, comparative
                  RBS        Adverb, superlative
                   RP        Particle
                  SYM        Symbol
                   TO        to
                   UH        Interjection
                   VB        Verb, base form
                  VBD        Verb, past tense
                  VGD        Verb, gerund or present participle
                  VBG        Verb, past participle
                  VBN        Verb, non-3rd person singular present
                  VBZ        Verb, 3rd person singular present
                  WDT        Wh-determiner
                   WP        Wh-pronoun
                  WP$        Possessive wh-pronoun
                  WRB        Wh-adverb

Di seguito verrà mostrato un esempio di applicazione di questa tabella supponendo di

avere in ingresso il testo “Take the bottle and take the glass”.

                                            14
Capitolo 2: Implementazione
     In questo capitolo verrà illustrato come l’applicazione Android realizza le funzionalità al

     fine di raggiungere gli obiettivi richiesti.

     Prima di analizzare l’algoritmo, verrà discussa l’architettura completa del sistema che

     permette l’interazione tra l’operatore e la piattaforma robotica. Tale architettura è proposta

     nella seguente figura.

     Di seguito si descrive il funzionamento del sistema. L’utente inserisce il comando tramite

     linguaggio naturale. L’applicativo trasforma in stringa il comando dell’utente e, attraverso

     un’interfaccia di comunicazione, invia la stringa al Natural Language Processor. Dopo

     l’elaborazione, la risposta del servizio ritorna all’applicativo, che, attraverso opportune

     elaborazioni, individua i comandi espressi dall’operatore e crea un messaggio per il robot.

     Successivamente quest’ultimo viene inviato al robot tramite su una rete che collega

     l’applicativo al robot.

                                                15
L’algoritmo utilizzato precedentemente per decidere quali comandi dovesse svolgere il

       robot era statico, nel senso che l’analisi della frase dell’operatore non era fatta tramite

       un’analisi sintattica ma attraverso la comparazione delle parole della frase con un

       dizionario interno. Inoltre, come detto precedentemente prevedeva, l’interpretazione di un

       singolo comando alla volta. Con questo lavoro di tesi si è voluto rivoluzionare l’algoritmo

       di interpretazione dei comandi lasciando inalterati il modo in cui l’applicativo invia i

       comandi al robot (un apposito thread che apre una comunicazione con il robot tramite una

       socket di tipo UDP) e il modo in cui l’utente fornisce il comando all’applicativo (speech-

       to-text fornito da Google come API per Android). In particolare quest’ultima funzionalità

       dell’applicazione fornisce come output, sotto forma di stringa, il comando immesso

       dell’utente. Si vuole far notare che il servizio speech-to-text non è esente da errore di

       interpretazione. Da questo momento in poi si farà riferimento a questo risultato con il

       termine “stringa”.

       In particolare, si ricorda, che la stesura di questo nuovo algoritmo prevede che si possono

       dare più comandi al robot e che ci sia una forma di conoscenza con esso.

       L’algoritmo di interpretazione comandi si basa su cinque sotto-funzionalità:

           1. verifica della raggiungibilità del server;

           2. richiesta HTTP al server del Natural Language Processor;

           3. interpretazione dei comandi;

           4. codifica dei comandi;

           5. creazione del messaggio;

           6. visualizzazione dei comandi.

      Ogni sottofunzionalità è implementata come metodo della classe MainActivity, tranne la

      richiesta HTTP che è implementata con una classe apposita.

      Nelle sezioni seguenti verranno descritte in dettaglio ogni sotto-funzionalità.

2.1 Verifica della raggiungibilità del server
       Questa prima sotto-funzionalità si occupa di contattare il server tramite il comando da

       terminale ping. Infatti in Java sono presenti particolari tipi e metodi che permettono di

                                                16
richiamare i comandi della Shell durante l’esecuzione di un programma. In particolare si

      utilizzano il tipo Process e il metodo Runtime.getRuntime().exec(String command) della

      libreria java.lang per adempiere all’obiettivo della sotto-funzionalità.

      Il comando è utilizzato in modo tale che se esso va a buon fine, allora l’utente può dare il

      comando al robot (in sostanza si apre la RecognizerIntent di Google), altrimenti viene

      visualizzato un Toast, che è un tipo di notifica di Android che appare sotto forma di

      riquadro in basso dello schermo, che dice all’utente che il server non è raggiungibile.

      Il codice per implementare la sotto-funzionalità è presentato di seguito:

         public boolean ping() throws IOException, InterruptedException {
           Process p1 = java.lang.Runtime.getRuntime().exec("ping -c 1 corenlp.run");
           int returnVal = p1.waitFor();
           return (returnVal==0);
         }

2.1 Richiesta HTTP al server
      L’utente inserisce il proprio comando se la verifica della raggiungibilità va a buon fine, e,

      tramite un processo di speech-to-text, quest’ultimo viene trasformato in stringa. La

      seconda sotto-funzionalità si occupa di contattare il server, inviando la stringa appena

      trasformata. Essa, come già detto, è implementata in una apposita classe Java, chiamata
      HTTPRequest, che estende la classe AsyncTask, che permette l’esecuzione di operazioni in

      background [9]. Il funzionamento è simile a un Thread, ma viene scelto AsyncTask perché,

      a differenza di Thread, viene utilizzato per l’esecuzione di brevi task asincroni che devono

      comunicare con un task principale.

      La classe AsyncTask possiede un metodo Abstract chiamato doInBackground(Params…

      params). Questo metodo viene sovrascritto con le istruzioni atte alla creazione di una

      comunicazione HTTP. Ciò avviene tramite i costrutti URL e HttpURLConnection. Il primo

      permette di dichiarare un puntatore ad una risorsa del World Wide Web intesa come

      Uniform Resource Locator a partire da un indirizzo passato come parametro di tipo String

      [10]. Il secondo permette di aprire una comunicazione con la URL dichiarata utilizzando il

      protocollo HTTP [11]. Entrambi i tipi sono contenuti nella libreria java.net.

                                               17
La caratteristica principale di HttpURLConnection è quella di poter utilizzare diversi

      parametri per caratterizzare la connessione, come per esempio il comando da utilizzare

      nella connessione HTTP, che nel nostro caso è POST in quanto la stringa contenente il

      comando è inviata nel corpo del messaggio e non nell’header a differenza del comando

      GET.

      Una volta iniziata la comunicazione con il server vengono aperti due standard stream, uno

      di input e l’altro di output, in cui si scrive il messaggio e si legge la risposta.

      La connessione si chiude quando il server invia tutta la risposta.

      Il codice utilizzato è presentato di seguito:

         protected String doInBackground(Void... params) {
            String jsonStr = "";
            try {
               URL url = new URL("http://corenlp.run:80/");
               HttpURLConnection conn = (HttpURLConnection) url.openConnection();
               //istruzioni per caratterizzare la connessione
               DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
               wr.write(command.getBytes(Charset.forName("UTF-8")));
               wr.close();
               BufferedReader br = new BufferedReader(new
         InputStreamReader(conn.getInputStream()));
               String temp;
               while ((temp = br.readLine()) != null)
                   jsonStr += temp;
               br.close();
            } catch (Exception e) {
               e.printStackTrace();
            }
            return jsonStr;
         }

2.2 Interpretazione dei comandi
      Questa sotto-funzionalità è il perno principale dell’applicativo. L’ipotesi principale su cui

      si fonda è quella che ogni frase di senso compiuto, soprattutto per dare un comando, nella

      maggior parte delle volte, è formata da verbo e complemento oggetto (es. prendi la

      bottiglia). Il problema, quindi, che viene risolto è quello di dividere il verbo e il

      complemento oggetto a cui si riferisce.

      Questa sotto-funzionalità inoltre è quella che si occupa di costruire una forma di

                                                 18
“conoscenza sociale” da parte del robot.

La sotto-funzionalità in esame è divisa ulteriormente in due parti: la prima ricerca un

eventuale nome di persona all’interno della stringa attraverso il servizio Named Entity

Recognition, mentre la seconda ricerca all’interno della stessa stringa ogni verbo e ogni

nome grazie al servizio Lemmatization e Part-of-speech tagging.

Si vuole ricordare come il server risponde con un messaggio in formato JSON, quindi sono

previste delle linee di codice che trasformano la stringa di risposta del server, tramite

appositi costrutti e tipi contenuti nella libreria org.json, in un JSONObject e di questo ne

viene estratto un JSONArray. Da quest’ultimo vengono estrapolate le informazioni

necessarie per l’elaborazione che vengono selezionate attraverso i tag utilizzati dal Part-of-

speech tagging del Natural Language Processor utilizzato. In particolare, in questa sotto-

funzionalità vengono utilizzati i tag VB e NN, che rispettivamente indicano un verbo alla

forma base e un nome singolare.

Il risultato di questa sotto-funzione sono due array di stringhe contenenti una tutti i verbi e

l’altra tutti i nomi trovati nella stringa.

Per ottenere una struttura omogenea, vengono inseriti in questi due array anche il nome di

persona eventualmente trovato e un verbo, che è stato chiamato “social”, per identificare

l’azione da far compiere al robot.

Il vantaggio di avere due array distinti sta nel fatto che in ogni posizione del vettore

contenente i verbi, in corrispondenza della stessa posizione (cioè nello stesso valore

dell’indice), c’è il complemento oggetto a cui fa riferimento, realizzando di fatto uno

“splitting intelligente” della stringa in cui ogni verbo è associato al relativo complemento

oggetto, venendo incontro all’ipotesi fatta, cioè è stata realizzata una struttura del tipo

verbo-complemento oggetto.

Si vuole far notare che per evitare conflitti tra le due parti della sotto-funzionalità, nella

seconda vengono saltate tutti i nomi di persona. È stato evidenziato, inoltre, come alcuni

verbi e/o oggetti possono creare alcune incomprensioni nell’interpretazione del comando,

per cui sono state scartate durante l’esecuzione della sotto-funzione. Esempi lampanti sono

il verbo “be” e “please” e il nome “place”, saltato poiché il sistema riconosce quest’ultimo

                                              19
come nome e non come verbo.

Il codice fulcro della sotto-funzionalità è presentato di seguito:

                                          20
public void commandInterpreter(String response) {
            JSONObject responseJsonObj;
            JSONArray responseJsonArray;
            if (response != null) try {
                responseJsonObj = new JSONObject(response);
                Log.d("MAIN", responseJsonObj.toString());
                responseJsonArray = responseJsonObj.getJSONArray("sentences");
                for (int i = 0; i <
         responseJsonArray.getJSONObject(0).getJSONArray("tokens").length(); i++) {
                   if
         (responseJsonArray.getJSONObject(0).getJSONArray("tokens").getJSONObject(i).getStri
         ng("ner").contains("PERSON")) {
                      vb.add("social");
         nn.add(responseJsonArray.getJSONObject(0).getJSONArray("tokens").getJSONObject(i)
         .getString("lemma"));
                   }
                }
                for (int i = 0; i <
         responseJsonArray.getJSONObject(0).getJSONArray("tokens").length(); i++) {
                   if
         (responseJsonArray.getJSONObject(0).getJSONArray("tokens").getJSONObject(i).getStri
         ng("lemma").equals("be") ||
         (responseJsonArray.getJSONObject(0).getJSONArray("tokens").getJSONObject(i).getStri
         ng("lemma").equals("please")) ||
         (responseJsonArray.getJSONObject(0).getJSONArray("tokens").getJSONObject(i).getStri
         ng("ner").equals("PERSON")))
                      continue;
                   if
         (responseJsonArray.getJSONObject(0).getJSONArray("tokens").getJSONObject(i).getStri
         ng("pos").contains("VB")) {
                      vb.add(responseJsonArray.getJSONObject(0).getJSONArray("tokens").getJSO
         NObject(i).getString("lemma"));
                      if
         (responseJsonArray.getJSONObject(0).getJSONArray("tokens").getJSONObject(i).getStri
         ng("lemma").equals("stop"))
                         nn.add("no obj");
                   }
                   if
         (responseJsonArray.getJSONObject(0).getJSONArray("tokens").getJSONObject(i).getStri
         ng("pos").contains("NN"))
         nn.add(responseJsonArray.getJSONObject(0).getJSONArray("tokens").getJSONObject(i)
         .getString("lemma"));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            else
                Log.d("MAIN", "STRINGA VUOTA");
         }

2.3 Codifica dei comandi
      La sotto-funzionalità in esame si occupa di verificare se i verbi e/o gli oggetti riconosciuti

      sono rispettivamente funzioni che il robot svolge e/o oggetti che il robot vede e codifica il

      comando, l’oggetto e un eventuale errore, che si verifica quando la verifica di verbo e/o

                                               21
oggetto fallisce.

La verifica dei comandi e degli oggetti è un’operazione necessaria ai fini dell’obiettivo

finale poiché il robot non svolge ovviamente tutti comandi che si vogliono, ma ha un

dominio ristretto di funzioni preventivamente definito. In particolare i comandi eseguiti

dal robot sono di prendere, lasciare oggetti, conoscenza, di andare in una direzione e

fermarsi.

Una volta effettuata la verifica, il comando e/o l’oggetto vengono codificati secondo le

regole dettate da un protocollo di comunicazione, preventivamente accordato. Nello

specifico, il protocollo prevede tre bit di cui il primo indica la presenza di errori, il

secondo codifica il verbo e il terzo codifica l’oggetto. Si nota che se c’è un errore, gli altri

due bit sono posti a zero.

Per effettuare la verifica e la codifica, i verbi e gli oggetti sono stati inseriti in due strutture

dati HashMap, una per i verbi e l’altra per gli oggetti, della libreria java.util di tipo

 dichiarate in una classe Java del progetto, chiamata Dictionary. La

particolarità della struttura dati HashMap sta nel fatto che ogni elemento salvato è diviso

in due: un valore e una chiave. Nel nostro caso il valore, di tipo Integer rappresenta la

codifica del comando o dell’oggetto, mentre la chiave, di tipo String, è proprio il comando

o l’oggetto. All’interno dell’applicazione viene utilizzato il metodo containsKey(String

key), che prende una chiave come parametro e ne verifica la presenza nella HashMap, e il

metodo get(String key), che data una chiave in ingresso restituisce il valore associato.

Questi due metodi permettono, utilizzati in modo corretto, sia la verifica che la codifica, il

tutto in poche righe di codice.

Il risultato di questa sotto-funzionalità sono tre array di stringhe contenenti ognuno la

codifica rispettivamente di errori, verbi e oggetti.

Nel caso di nomi di persona, questi non vengono codificati, ma vengono lasciati inalterati

e mandati al robot così come sono.

Il codice per questa sotto-funzionalità è riportato di seguito.

                                            22
public void commandEncorder() {
            if ((vb.size() == 0) || (vb.size() != nn.size())) {
                error.add("1");
                command.add("0");
                object.add("0");
            } else {
                for (int i = 0; i < vb.size(); i++) {
                   String verb = vb.get(i);
                   String obj = nn.get(i);
                   String commandEncoded = diz.getCommandCoding(verb);
                   String objEncoded = diz.getObjectCoding(obj);
                   if (verb.equals("social")) {
                       error.add("0");
                       command.add(commandEncoded);
                       object.add(obj);
                   } else if ((commandEncoded.equals("not find")) || (objEncoded.equals("not
         find"))) {
                       error.add("1");
                       command.add("0");
                       object.add("0");
                   } else {
                       error.add("0");
                       command.add(commandEncoded);
                       object.add(objEncoded);
                   }
                }
            }
         }

2.4 Creazione del messaggio
      Questa sotto-funzionalità si occupa di creare il messaggio da mandare al robot. Ciò che fa

      è la concatenazione della tripla di elementi dei tre array creati dalla sotto-funzione che si

      occupa della codifica, per ogni posizione dei vettori. La concatenazione è possibile grazie

      al metodo append(String s) della classe StringBuilder.

      Il risultato finale sarà una stringa di cifre. Si vuole far notare che nel caso di un nome di

      persona, il messaggio mandato al robot non è formato da sole cifre ma anche di caratteri,

      che appunto rappresentano il nome di persona.

      Quando la creazione del messaggio è finita, viene abilitato l’invio della stringa da parte del

      thread che si occupa della comunicazione con il robot, ponendo al valore True una

      variabile Boolean addetta proprio alla verifica della presenza del messaggio.

      Il codice utilizzato è riportato di seguito:

                                                 23
public void commandCreator() {
           StringBuilder msg = new StringBuilder();
           for (int i = 0; i < error.size(); i++) {
              msg.append(error.get(i));
           }
           for (int i = 0; i < command.size(); i++) {
              msg.append(command.get(i));
           }
           for (int i = 0; i < object.size(); i++) {
              msg.append(object.get(i));
           }
           udpOutputData = msg.toString();
           sendUdp = true;
         }

2.5 Visualizzazione dei comandi
      Questa sotto-funzionalità non è importante ai fini dell’obiettivo finale, serve per capire il

      risultato finale dell’applicazione, soprattutto da parte dell’utente. Si occupa di visualizzare
      in due TextView, tipo particolare di Android con cui è possibile visualizzare un testo, la

      stringa riconosciuta dalla RecognizerIntent e la sua elaborazione da parte dell’algoritmo,

      sia sotto forma di comandi e/o oggetti riconosciuti sia sotto forma di codifica. In

      particolare il protocollo di visualizzazione scelto prevede la seguente regola:

             ERROR: ‘bit dell’errore’ COMMAND: ‘bit del comando’ – ‘comando’
                             OBJECT: ‘bit dell’oggetto’ – ‘oggetto’

      Nel capitolo successivo è possibile osservare nello specifico il risultato di tale sotto-

      funzione attraverso i casi di test.

      Il codice utilizzato è riportato di seguito:

         public void commandVisualizer() {
            StringBuilder res = new StringBuilder();
            if (vb.size() == 0)
                for (int i = 0; i < error.size(); i++)
                   vb.add("VB MISS");
            if (nn.size() == 0)
                for (int i = 0; i < error.size(); i++)
                   nn.add("OBJ MISS");
            for (int i = 0; i < error.size(); i++)
                res.append("ERROR: ").append(error.get(i)).append(" COMMAND:
         ").append(command.get(i)).append(" - ").append(vb.get(i)).append(" OBJECT:
         ").append(object.get(i)).append(" - ").append(nn.get(i)).append("\n");
            String result = res.toString();
            mCommandOutputTv.setText(result);
         }

                                                 24
Capitolo 3: Casi di test
      In questo capitolo verranno mostrati vari casi di test per mostrare come l’applicativo

      Android si comporta di fronte a diversi input.

      Verranno esplicitati gli input e i gli output previsti, intesi come messaggio costruito da

      mandare al robot.

3.1 Primo: comando singolo semplice
      INPUT: “Take the bottle”

      OUTPUT: 011

      COMPORTAMENTO:

      In questo test si è voluto testare un semplice comando al robot e, come previsto, il

      messaggio di uscita verso esso è 011.

                                              25
3.2 Secondo: comando singolo articolato
      INPUT: “Would you please to take me the bottle?”

      OUTPUT: 011

      COMPORTAMENTO:

      In questo secondo caso di test si vuole porre enfasi su quanto naturale è il linguaggio

      utilizzato per dare il comando con l’aggiunta non solo del verbo e del complemento

      oggetto ma anche di verbi ausiliari. L’uscita prevista coincide con quella reale, cioè 011.

                                               26
3.3 Terzo: comando fuori dal dominio delle funzioni eseguite dal robot
      INPUT: “Do you like a pizza?”

      OUTPUT: 100

      COMPORTAMENTO:

      In questo caso di test si è voluto testare il comportamento dell’applicativo in presenza di

      un input al di fuori del dominio delle funzioni del robot. L’uscita reale è 100 ed è pari a

      quella prevista.

                                              27
3.4 Quarto: due comandi semplici
      INPUT: “Take the bottle and take the glass”

      OUTPUT: 011012

      COMPORTAMENTO:

      Come ripetuto, uno degli obiettivi dell’algoritmo è quello di poter elaborare una stringa

      con all’interno più di un comando. In questo caso di test si verifica il corretto

      funzionamento della funzionalità. Il messaggio reale in uscita è pari a quello atteso. Si

      vuole far notare che l’algoritmo garantisce il corretto funzionamento anche in presenza di

      congiunzioni.

                                             28
3.5 Quinto: comandi multipli
      INPUT: “Take the bottle, take the glass and stop”

      OUTPUT: 011012044

      COMPORTAMENTO:

      In questo caso di test, si testa il comportamento dell’algoritmo in presenza di una stringa

      contenente più di due comandi. Il risultato finale è pari a quello atteso.

      Si vuole far notare che il comando stop è stato inserito poiché il robot in futuro potrebbe

      anche avere funzioni di movimento.

                                                29
3.6 Sesto: interazione sociale
      INPUT: “I’m David”

      OUTPUT: 05David

      COMPORTAMENTO:

      Come ripetuto, il robot prevede una sorta di interazione sociale che consiste nel

      riconoscere il nome dell’utente nel caso in cui viene inserito nell’applicativo. Il

      comportamento reale è pari a quello atteso. Particolare attenzione si pone sul messaggio in

      uscita che risulta essere 05David, cioè come già detto il nome non è codificato quindi

      viene mandato così com’è al robot.

                                              30
Conclusioni

     In questo lavoro di tesi abbiamo sviluppato un sistema per l’interpretazione dei comandi

     tramite riconoscimento vocale. Gli obbiettivi prefissati erano:

        •   l’utilizzo di un Natural Language Processing per l’elaborazione del comando

            dell’utente;

        •   rendere l’applicativo indipendente dal robot e dal Natural Language Processor e dal

            linguaggio utilizzato;

        •   creare un’interazione sociale tra utente e robot.

     Come si è visto nel capitolo in cui sono stati presentati i test, tali obiettivi sono stati

     raggiunti, mostrando i risultati ottenuti seguendo l’implementazione proposta nel capitolo

     2, utilizzando tecnologie mobile, basate su Android e Java e un motore di Natural

     Language processing in cloud.

     Tale Natural Language Processing utilizzato dal sistema implementato è fornito dalla

     Stanford University, chiamato Standord NLP. Di tale risorsa sono stati utilizzati i servizi di

     Named Entity Recognition, Lemmatization e Part-of-speech tagging in modo da

     permettere l’interpretazione di più comandi alla volta e implementando oltre il possibile
     controllo di una pattaforma robotica l’interazione sociale dell’utente con esso.

     Possibili sviluppi futuri possono essere:

        •   la possibilità di poter “insegnare” al robot eventuali comandi attaverso tecniche di

            Machine Learning (es. versare = prendere bottiglia + prendere bicchiere + girare

            mano bottiglia);

        •   Effettuare un’analisi semantica della frase in modo da non dover necessariamente

            specificare il dominio applicativo del nostro sistema.

                                                 31
Bibliografia
     [1]   Thomas Villacci, “Sviluppo di un framework per l’interazione uomo-robot basato

     sulle tecnologie di sintesi e riconoscimento vocale”, Tesi triennale, 2017.

     [2]   Daniel Jurafsky and James H. Martin, “Speech and Language Processing: An

     Introduction to Natural Language Processing, Speech Recognition, and Computational

     Linguistics, Prentice-Hall, 2nd edition, 2008.

     [3]   Google Cloud Platform Natural Language API, https://cloud.google.com/natural-

     language/.

     [4]   Amazon Comprehend, https://aws.amazon.com/comprehend/.

     [5]   IBM               Watson           Natural           Language             Understanding,

     https://www.ibm.com/watson/services/natural-language-understanding/.

     [6]   Microsoft     Azure    Cognitive        Services   Language   Understanding     (LUIS),

     https://azure.microsoft.com/it-it/services/cognitive-services/language-understanding-

     intelligent-service/.

     [7]   Introduzione a JSON, https://www.json.org/json-it.html.

     [8]   Stanford                   Log-linear               Part-Of-Speech               Tagger,

     https://nlp.stanford.edu/software/tagger.shtml.

     [9]   AsyncTask, https://developer.android.com/reference/android/os/AsyncTask.html.

     [10] Classe URL, https://docs.oracle.com/javase/7/docs/api/java/net/URL.html.

     [11] Classe,                                                               HttpURLConnection,

     https://docs.oracle.com/javase/7/docs/api/java/net/HttpURLConnection.html.

                                                   32
Puoi anche leggere