Esempio di Chatbot che Esplora l'Ambiente alla Ricerca di Avatar - Alessio Tralli Stefano Cacciaguerra Ph. D. in Informatica
←
→
Trascrizione del contenuto della pagina
Se il tuo browser non visualizza correttamente la pagina, ti preghiamo di leggere il contenuto della pagina quaggiù
Esempio di Chatbot che Esplora l’Ambiente alla Ricerca di Avatar. di Alessio Tralli rivista da Stefano Cacciaguerra Ph. D. in Informatica
Indice Introduzione ........................................................................................................................................ 1 Specifiche Iniziali................................................................................................................................. 5 Sviluppo del Progetto .......................................................................................................................... 8 Script ............................................................................................................................................. 10 Problematiche affrontate................................................................................................................ 23 Come utilizzare il progetto................................................................................................................. 26 Conclusioni ....................................................................................................................................... 28 2
Introduzione Second Life è un mondo virtuale - un ambiente tridimensionale online dato da una simulazione elettronica, i cui contenuti vengono creati e sono posseduti dai suoi stessi abitanti. Questi vengono rappresentati tramite degli avatar, personalizzabili in maniera praticamente illimitata. 3
Attualmente partecipano alla creazione del mondo di Second Life oltre 400.000 utenti attivi di tutto il pianeta (circa 10 milioni utenti totali). All'interno di questo spazio online, tridimensionale, persistente e in continua crescita, puoi agire, creare o diventare chiunque tu possa immaginare. Gli strumenti a disposizione permettono di creare qualsiasi cosa, in tempo reale e in collaborazione con gli altri utenti. L'avatar, sorta di corpo digitale, è incredibilmente dettagliato e permette una ricca e completa identificazione. La peculiarità del mondo di Second Life è quella di lasciare agli utenti la libertà di usufruire dei diritti d'autore sugli oggetti che essi creano, che possono essere venduti e scambiati tra i "residenti" utilizzando una moneta virtuale (il Linden Dollar) che può essere convertito in veri dollari americani, dando vita a reali opportunità di business in Second life. Su second life quindi puoi costruire e far muovere qualsiasi cosa vuoi costruire, puoi costruire semplici oggetti o oggetti composti componendo più prim insieme; puoi far compiere ad un oggetto qualsiasi operazioni tu voglia,utilizzando semplici script che trovi all’interno di second life o scrivendoli te utilizzando il linden script language (LSL). Il linden script language è un vero e proprio linguaggio di programmazione che reputo del tutto simile al linguaggio C o C# e comunque ben adattato dalla casa madre per gestire illimitate possibilità all'interno del mondo virtuale. Immagino che le versioni future del linguaggio consentiranno alcune cose, ad oggi non possibili. In conclusione, nella realizzazione del mio progetto ho utilizzato in modo uniforme sia script che prim; componendo insieme diverse prim ho creato il mio robot, aggiungendo diversi script,gli ho dato vita. 4
Specifiche iniziali Lo scopo del mio progetto è di creare un robot (od agente) autonomo che interagisca con l’ambiente. Mediante l’uso delle prim costruisco il robot e, con il linden script language creo il codice per muoverlo e farlo interagire con l’ambiente. La creazione del robot e dello script avviene in una sandbox area; la mia idea è di creare un robot che si muova autonomamente per l’ambiente senza che gli avatar possano interferire sul suo movimento e che comunichi durante il suo muovimento nell’ambiente circostante, con gli avatar che incontra sul percorso. Il robot per interagire con gli avatar deve rilevarli,per questa operazione intendo utilizzare un sensore impostandolo solo per rilevarmi gli agenti in un area di 5metri attorno al robot; LlSensorRepeat("", NULL_KEY,AGENT, 5, TWO_PI, 5); Immagine 2: robot in attesa 5
oltre al sensore per rilevare avatar è mia intenzione aggiungere un altro sensore che mi rilevi gli oggetti sul percorso per far si che se l’avatar incontri un ostacolo lo rilevi e cambi direzione. llSensorRepeat("", NULL_KEY,PASSIVE, 5, TWO_PI, 5); Il linden script language non permette di mettere due sensori diversi nello stesso script ma, posso tentare con due sensori in due script diversi; un sensore nel codice movimento rileva e parla con gli avatar, un sensore in un altro script sempre nello stesso oggetto,rileva ostacoli e gli evita. Al robot assegno delle frasi standard che ripete ogni qual volta incontra un avatar,queste frasi mi sono utili per instaurare una conversazione tra avatar e robot; l’avatar successivamente se intenzionato ad interagire col robot,digita delle frasi o domande al robot, il quale determina la risposta da dare all’avatar scegliendo tra un lotto di possibili risposte giuste. Immagine 3: robot che instaura comunicazione 6
Aggungerei infine alcuni dettagli per rendere il più realistico possibile il robot: - alla bocca del robot aggiungo una simulazione del movimento della bocca quando parla; quando il bot parla o gli faccio cambiare colore alla bocca facendo sembrare che il robot apra e chiuda la bocca mentre parla. - Aggiungo simulazione agli arti del bot, se è possibile applico dei script per farli muovere avanti e indietro mentro il robot si muove, in alternativa rendo i prim degli arti condizionabili degli effetti ambientali, così quando il robot si muove essi si muovono indietro facendo intuire che il robot si sta muovendo Immagine 4: movimento robot, con movimento simulato arti. 7
Sviluppo progetto Il robot tramite un sensore,si muove nell’ambiente,scegliendo casualmente la direzione di volta in volta in cui spostarsi. Durante i suoi spostamenti se il sensore rileva che ci sono degli avatar nella vicinanze (in base alla portata che scielgo per il sensore),prova ad instaurare una conversazione con l’avatar rispondendo però solo a determinate perché, quando il robot comunica, usa delle frasi impostate a priori. Immagine 5: robot che instaura comunicazione con due avatar Il robot è stato impostato per rispondere solo a determinate domande;essendo preimpostate,bisogna digitare correttamente la domanda per avere una risposta dal robot,in caso di domanda digitata non correttamente,il robot resta in attesa. 8
Quando un avatar gli pone una di queste domande,il robot sceglie a caso tra un lotto di diverse risposte una risposta e di conseguenza risponde alla domanda. Il robot può muoversi liberamente per l’ambiente,fermandosi quindi solo se rileva avatar o in alternativa tramite un comando “stop” da tastiera,per ripristinare il movimento con i sensori basta digitare un messaggio “vai”. Infine il robot può essere riportato alla posizione in cui è stato lanciando semplicemente attraverso il messaggio da tastiera “ritorna”. Immagine 6: robot ritorna in posizione iniziale 9
Script Per la realizzazione del bot che si muove e interagisce nell’ambiente ho decio di suddividere il codice in tre parti distinte: - uno script relativo al movimento e all’instaurazione della conversazione; - uno script solo sulla comunicazione dove inserisco le frasi del robot; - Uno script relativo al sensore che utilizo per aggirare ostacoli; Immagine 7: robot che si muove sul territorio 10
- Codice movimento bot // prima del default inserisco parte che mi serve per rilevare avatar list recent_avatars; add_avatar(string name) { if(!seen(name)) { recent_avatars += name; f (llGetListLength(recent_avatars) > 25) { recent_avatars = llDeleteSubList(recent_avatars,0,0); } } } integer seen(string name) { if(llListFindList(recent_avatars,[name]) > -1) { return TRUE; } return FALSE; } integer num = 0; default {// stato iniziale,dove inserisco funzioni da lanciare ll’avvio State_entry() { LlSensorRepeat("", NULL_KEY,AGENT, 5, TWO_PI, 5); llListen(0, "", llGetOwner(), ""); //ascolto canale 0 } // attivo il sensore se c'è un avatar nell'arco di 5metri sensor(integer total_number) { // rileva avatar e comunica con loro integer i; if(!seen(llDetectedName(i))) { llWhisper (0, ( string )total_number + " avatars trovati" ); for (i = 0; i < total_number; i++) { llWhisper (0, "ciao " + llDetectedName (i)); add_avatar(llDetectedName(i)); } llSleep(5); llSay(0,"vuoi parlare con me?"); llSleep(10); llSay(0,"rispondo solo a queste domande: help , si , no , cosa sei? , cosa fai? , come stai? , che ore sono?"); add_avatar(llDetectedName(0)); } } no_sensor()// se sensore non è attivo,bot si muove {//casualmente bot decide da che parte andare if (llFrand(1.0) >= 0.5) 11
{ if (llFrand(1. 0) >= 0.5) { llSay(0,"vado avanti ora"); llSleep(1); llSetPos(llGetPos()+); } else { llSay(0,"vado in dietro"); llSleep(1); llSetRot(llEuler2Rot() * llGetRot()); llSetRot(llEuler2Rot() * llGetRot()); llSleep(2.5); llSetPos(llGetPos()+); llSleep(2.5); llSetRot(llEuler2Rot() * llGetRot()); llSetRot(llEuler2Rot() * llGetRot()); llSleep(1); } } else { llSay(0,"sto decidendo dove andare..."); llSleep(2.5); if (llFrand(1.0) >= 0.5) { llSay(0,"vado a sinistra"); llSetRot(llEuler2Rot() * llGetRot()); llSleep(2.5); llSetPos(llGetPos()+); llSleep(2.5); llSetRot(llEuler2Rot() * llGetRot()); llSleep(1); } else { llSay(0,"vado a destra"); llSetRot(llEuler2Rot() * llGetRot()); llSleep(2.5); llSetPos(llGetPos()+); llSleep(2.5); llSetRot(llEuler2Rot() * llGetRot()); llSleep(1); } } llSay(0,"ora mi riposo,sono stanco"); } //comando che serve per comunicare con bot listen( integer channel, string name, key id, string message ) { if(message == "stop") { state fermo; //cambia stato } 12
} } state fermo { state_entry() { llListen(0, "", llGetOwner(), "");; // nuovo ascolto } listen( integer channel, string name, key id, string message ) { llSetPos(llGetPos()+); llSay(0,"sono fermo"); if(message == "vai") { llSay(0,"sono pronto"); state default; //cambia stato } if (message == "ritorna") { // fa tornare nella posizione iniziale while ( llVecDist( llGetPos(), startPosition) > 0.001) { llSetPos( startPosition ); } llSay( 0, "sono tornato qui" ); llResetScript(); } } } Il codice è essenzialmente diviso in due parti, una parte inserita in sensor() e una inserita in no_sensor. Prima dello stato default dove è contenuto tutto il codice, ho inserito un codice che mi aiuta a rilevare gli avatar presenti in zona e tramite questo codice un avatar viene rilevato una e una sola volta. Nello stato default come prima operazione inserisco lo state_entry() il cui contenuto,viene caricato all’apertura dello script. Oltre allo stato default dove si sviluppa essenzialmente tutto il codice, ho uno stato fermo; se digito da tastiera la parola “stop”, passo dallo stato default allo stato fermo e il robot si ferma nella posizione in cui si trova; in seguito tramite un altro messaggio, la parola “vai” digitata sempre da tastiera, passo dallo stato fermo allo stato default ritornando nella situazione iniziale gestita tramite sensor( ) e no_sensor(). 13
immagine 8: Codice movimentto Successivamente entro nello sviluppo del codice che,come ho detto è suddiviso in sensor() e no_sensor(); - In sensor( ) è presente il codice che mi rileva gli avatar,quindi ogni volta che il robot rileva all’interno del campo dei suoi sensori (in questo caso 5metri) instaura con lui una conversazione,dicendo una serie di frasi preimpostate,chiaramente se l’avatar si sposta ed esce dal campo del sensore del robot questo smette di comunicare - In no_sensor è presente il codice di movimento, se il robot non sta rilevando nulla nel campo del suo sensore, si sposta casualmente per l’ambiente muovendosi in modo casuale nelle seguenti direzioni: avanti, indietro, destra, sinistra. Se il comando random fa muovere il robot in una direzione che corrisponde al limite di un’area ad accesso negato,resta in attesa finché un’ulteriore comando random lo faccia andare in un’altra direzione. Quando durante il movimento il robot rileva un avatar nel campo del suo sensore, si ferma e instaura con lui la conversazione. 14
Il robot risponde anche ad alcuni messaggi da tastiera, tramite il messaggio “stop” il robot passa dallo stato default allo stato fermo; in questo stato il robot può solo interagire con gli utenti senza però muoversi. Nello state stop posso far eseguire al robot due diverse operazioni: tramite il messaggio da tastiera “ritorna”, faccio tornare il robot nella posizione di partenza (questo mi ritorna utile se il robot si muove verso determinate zone o passa attraverso muri e viene perso di vista); tramite il messaggio “vai”,il robot ritorna allo state default e quindi torna a compiere le funzioni primarie ( movimento e ricerca avatar). Immagine: io e robot 15
- Codice comunicazione // lista frasi di esempio list responseList = ["ciao,posso aiutarti?","ciao, dimmi tutto","ciao sn mash mallows,serve aiuto?"]; list responseList2 = ["sono un robot","sono mash mallows il robot viaggiatore"]; list responseList3 = ["giro per l'isola","facio un giro","sto ispezionando il terreno"]; list responseList4 = ["bene grazie..e tu?","sono stanco..e tu?","sono in forma,grazie"]; list responseList5 = ["spiacente,non ho risposte","mi dispiace,non so aiutarti"]; list responseList6 = ["ok,ciao","va bene","nessun problema"]; vector startPosition; integer i=0; default { // stato iniziale all’avvio dello script state_entry() { llListen( 0, "", llGetOwner(), "" ); startPosition = llGetPos(); } listen(integer channel, string name, key id, string messagio) { // risposta random a parola prestabilità if(messagio == "help") { integer listSize = llGetListLength(responseList); float random = llFrand(listSize); integer idx = llFloor(random); while(i
llSleep(0.25); llSetColor(, ALL_SIDES); llSleep(0.25); llSetColor(, ALL_SIDES); i = i + 1; } i=0; string message = llList2String(responseList2,idx); llSay(PUBLIC_CHANNEL,message); } if(messagio == "cosa fai?") { integer listSize = llGetListLength(responseList3); float random = llFrand(listSize); integer idx = llFloor(random); while(i
llSetColor(, ALL_SIDES); llSleep(0.25); llSetColor(, ALL_SIDES); llSleep(0.25); llSetColor(, ALL_SIDES); i = i + 1; } i=0; string message = llList2String(responseList5,idx); llSay(PUBLIC_CHANNEL,message); } if(messagio == "no") { integer listSize = llGetListLength(responseList6); float random = llFrand(listSize); integer idx = llFloor(random); while(i
Immagine 9: bot incontra e parla con un avatar Nel codice comunicazione ho prima del default 6liste corrispondenti alle possibili risposte che può dare il bot per ogni frase; il codice principale è tutto nello state default,all’inizio dello state default ho lo state_entry dove attivo le impostazioni per far comunicare via chat il bot con l’eventuale avatar che comunica con lui. Tramite comando if(message == “parola”) entro in una delle liste iniziali inserite prima del default e,tramite la funzione llfrand() il bot sceglie casualmente una risposta da dare all’avatar tra le possibili risposte che ci sono per quella domanda. All’interno del ciclo “if” di ogni domanda ho inserito un ciclo “while”;all’interno del ciclo while tramite llsetcolor() modifico il colore della prim in cui ho inserito il codice parola (nel mio caso la bocca del bot) e quindi quando il bot risponde alla domanda la bocca del bot cambia colore passando da bianco a nero,simulando il movimento di apertuta/chiusura della bocca stessa. La bocca cambia colore 4volte (sempre da bianco a nero), quando la condizione del while viene uguagliata esco dal ciclo while,resetto la 19
condizione del while e il bot digita in chat la risposta alla frase che gli viene posta. Dopo aver risposto alla domanda,il bot resta in attesa di ricevere altre domande o,se il sensore del codice movimento non rileva più l’avatar nel campo,il bot riprende a mouversi alla ricerca di altri avatar con cui instaurare una conversazione. Immagine 10: robot che instaura una conversazione 20
- Sensore oggetti default { state_entry() { llSensorRepeat("", NULL_KEY,PASSIVE, 5, TWO_PI, 5); } sensor(integer total_number) // total_number is the number of avatars detected. { llSay(0,"ci sono ostacoli,mi sposto"); if (llFrand(1.0) >= 0.5) { llSay(0,"vado a sinistra"); llSetRot(llEuler2Rot() * llGetRot()); llSleep(2.5); llSetPos(llGetPos()+); llSleep(2.5); llSetRot(llEuler2Rot() * llGetRot()); llSleep(1); } else { llSay(0,"vado a destra"); llSetRot(llEuler2Rot() * llGetRot()); llSleep(2.5); llSetPos(llGetPos()+); llSleep(2.5); llSetRot(llEuler2Rot() * llGetRot()); llSleep(1); } } } Questo codice viene utilizzato dal robot per rilevare e quindi evitare ebentuali ostacoli sul percorso. Questo codice lo inserisco in uno script diverso da quello del movimento perché utilizza anch’esso un sensore e,non possono coesistere due sensori nello stesso script. Il codice è tutto inserito nello state default, nello state_entry() inserisco la chiamata del sensore,quindi appena lancio il bot il sensore si attiva; successivamente in sensor() inserisco il codice vero e proprio. Se il sensore rileva oggetti nelle vicinanze, il robot decide se spostarsi a destra o a sinistra, muovendosi finche non evita l’ostacolo. 21
Quando nel campo del sensore non ci sono più ostacoli, il bot riprende a muoversi utilizzando lo script del codice movimento,questo finchè non ci sono più ostacoli nelle vicinanze. Immagine 11: robot avvisa di aver rilevato un ostacolo e decide di spostarsi Probleatiche Affrontate 22
Nello realizzazione dello script del robot, ho affrontato alcune problematiche;una delle problematiche principali è stata nella comunicazione. Fare un chatbot risulta abbastanza complicato,il robot non sempre in base alla frase che l’utente scrive riesce a dare la giusta risposta,ho provato ad utilizzare uno script che mi rileva le parole chiave in una frase e,da queste parole mi ricava la frase appropiata che il robot deve dire; ho incontrato problemi perché anche se il chatbot mi ricava nella frase le giuste parole chiave,poi mi scrive frasi in alcuni casi errate, facendomi scartare questo metodo. Per la comunicazione tra robot e utente quindi ho optato per un script comunicativo molto semplice, in cui il robot risponde solo a domande prestabilite e per queste domande a la possibilità di dare una risposta tra un lotto di 4. L’inconvegnente di questo script è che le domande poste dall’utente devono essere uguali a quelle inserite nello script, se no il robot non da nessuna risposta. Immagine 12: robot in attesa 23
Un’altra problematica affrontata nella realizzazione del progetto, riguarda il movimento del robot per via delle varie restrizioni in second life sulle zone; per il dislivello e, i vari ostacoli disseminati per il terreno. Durante il suo movimento il robot incontra aree in cui non si può entrare, se prova ad accedervi,compare un messaggio di errore e il robot non si muove in quella direzione; essendo il movimento del robot determinato da una scelta casuale,il robot resta in quella posizione fermo finche la casualità non lo fa muovere in un’altra direzione. Immagine 13: il robot si muove verso il limite di un’area. Il problema del dislivello del terreno non è riuscito a risolverlo,quindi se il robot si sposta in un’area con diverso dislivello, non si adegua ma continua a muoversi basandosi sul livello del terreno in cui è stato lanciato. 24
Per impedire al robot di scontrarsi con gli ostacoli avevo pensato a un sensore alternativo messo in un nuovo codice sempre all’interno del robot, questo perché nello stesso script 2sensori non può coesistere. Quest’operazione mi ha creato parecchi problemi, poiché anche se il secondo sensore mi rileva gli oggetti su percorso, non fa ritornare sempre indietro il robot sui suoi passi per fargli cambiare strada; questo può essere avvenuto per incompatibilità tra i due sensori, perché entrambi i sensori determinano un movimento e forse quando entrambi sono attivi e chiedono al robot di muoversi in una direzione esso fa fatica a fare entrambe le cose, il movimento del robot per evitare gli oggetti quindi non è sempre lineare,ad esempio nella rotazione del robot stesso,in alcuni casi per spostarsi in una direzione non riesce a ruotare nella suddetta direzione; dopo alcuni tentativi non sono riuscito a sistemare questo problema. Immagine 14: problema sensore oggetti 25
Il robot quindi alcune volte passa attraverso gli ostacoli ed anche se lì rileva non sempre gli evita. Una causa di questo problema può dipendere da second life, poiché quando il server è intasato alcune operazioni sono svolte molto a rilento e alcune volte anche in ritardi di alcuni minuti a volte. Utilizzo del progetto Il robot è molto semplice da usare; muovendosi in modo automatico, basta semplicemente lanciarlo in un’area e il robot inizia a muoversi. Il movimento è regolato da dei sensori, il sensore ha un raggio di 5metri,se non rileva avatar nel suo campo fa muovere il robot per l’ambiente alla ricerca di avatar con cui parlare; se un avatar entra nel campo del robot quest’ultimo si ferma e parla con l’avatar. Se durante il suo movimento il robot incontra ostacoli sul suo percorso (cioè prim statici senza alcun script) lì rileva e si sposta a destra o sinistra finché questi oggetti non sono più nel suo campo sensoriale. Il robot è stato progettato per rispondere solo a determinate domande; quando il robot incontra un avatar, lo saluta in primis, poi gli dice a quali domande può rispondere. 26
Immagine 15: movimento robot attivato\disattivato tramite messaggio L’avatar deve digitare la domanda in chat esattamente come richiesto dal robot, se la frase dell’avatar è diversa, il robot sta fermo in attesa mentre, se la frase è giusta, il robot sceglie casualmente tra un lotto di 4 risposte,quella da dare all’utente. Nel robot sono stati inseriti dei semplici comandi “stop” e “vai” molto utili all’utente perché servono per regolare il movimento del robot. Tramite il comando stop il robot termina l’ultimo movimento che stava eseguendo e poi si ferma in attesa (entra nello stato stop); in questa fase il robot può solo rispondere alle domande. Tramite il comando vai, viene ripristinato il codice di movimento del robot e, se nel campo del suo sensore non trova nessuno, riparte. Infine, quando si è nello stato stop tramite il comando da tastiera “ritorna”, torna nella posizione da cui è partito. 27
Conclusioni Realizzare un robot alla interno di questa realtà virtuale è stato molto interessante e divertente, un robot di questo genere può essere adoperato per molti usi. In un’area delimitata, il robot cerca gli avatar e comunica con loro. Nell’esempio mostrato, ho semplificato le domande a cui il robot risponde. Nessuno vieta di riscrivere meglio questa parte per affrontare discorsi più articolati. Inserendo nello script del robot, specifiche domande e risposte, si potrebbe utilizzare quest’ultimo per illustrare agli utenti in qual’area sono giunti e comunicargli informazioni di svariato genere. In quest’ottica, diventa una guida interessante per gli utenti che intendono visitare l’area in cui è situato. In particolare, si potrebbe pensare di farlo muovere su un percorso prestabilito. In questo modo, quando un utente si teletrasporta vicino ad il robot, quest’ultimo si attiva e compie un tragitto 28
prestabilito in cui spiega all’avatar la funzione e il relativo utilizzo delle strutture presenti sull’isola. In generale un robot di questo tipo è molto utile perché può svolgere diverse funzioni; le funzione spiegate in precedenza sono solo alcune delle svariate possibilità di impiego che può avere; e grazie all’uso di robot di questo genere si possono dare informazioni dettagliate di un oggetto o un’area senza essere chiamati personalmente in causa. BIBLIOGRAFIA E SITOGRAFIA Riferimenti cartacei AA.VV. (2007). Second Life la Guida Ufficiale. Wiley Publishing: Indianapolis, Indiana. Riferimenti Web Second Life: Your World. Your Imagination. (2007). http://secondlife.com Second Life Wiki. (2007). http://wiki.secondlife.com/wiki/Main_Page Second Life Italia. (2007). http://www.secondlifeitalia.com/ Wikipedia. (2007). http://it.wikipedia.org/wiki/Second_life LSL Wiki(2008) http://lslwiki.net/lslwiki/wakka.php?wakka=HomePage 29
Puoi anche leggere