Tesi Jacopo

106
  CorsodiLaureainInformatica  Realizzazione e sviluppo di un mini-gioco per la riabilitazione della mano RELATORE Prof. Nunzio Alberto BORGHESE CORRELATORE Dott. Renato MAINETTI TESI DI LAUREA DI Jacopo Essenziale Matr. 740006 Anno Accademico 2013/2014

description

Tesi JacopoTesi JacopoTesi JacopoTesi JacopoTesi JacopoTesi Jacopo

Transcript of Tesi Jacopo

  • Corso di Laurea in Informatica

    Realizzazione e sviluppo di

    un mini-gioco per la riabilitazione

    della mano

    RELATORE

    Prof. Nunzio Alberto BORGHESE

    CORRELATORE

    Dott. Renato MAINETTI

    TESI DI LAUREA DI

    Jacopo Essenziale

    Matr. 740006

    Anno Accademico 2013/2014

  • i

    INDICE

    1. INTRODUZIONE

    2. RIABILITAZIONE

    a. RIABILITAZIONE A CASA: PROGETTTO REWIRE

    b. IGER: UN GAME ENGINE PER LA RIABILITAZIONE

    3. RIABILITAZIONE DELLA MANO

    a. STRUMENTI DIGITALI GIA UTILIZZATI NELLA RIABILITAZIONE DELLA MANO

    b. OBIETTIVO DEL PROGETTO REALIZZATO

    4. STRUMENTI SOFTWARE UTILIZZATI

    5. PANDA 3D

    a. FUNZIONAMENTO LOOP DI GIOCO

    b. COLLISION DETECTION IN PANDA3D

    c. MAPPATURA DI INPUT BIDIMENSIONALE NELLO SPAZIO: CAMERA ORTOGRAFICA

    d. MAPPATURA DI INPUT BIDIMENSIONALE NELLO SPAZIO: RAY CASTING

    6. LEAP MOTION CONTROLLER

    a. PROGRAMMARE IL LEAP API

    b. PRIMI TEST

    c. INTRODURRE NUOVE GESTURES GRABBING

    d. IL LEAP MOTION CONTROLLER E LA RIABILITAZIONE

    7. REALIZZAZIONE DEL GIOCO: HOT AIR BALLOON

    a. SCELTA DELLARCHITETTURA WEB-BASED

    b. IL PROGETTO DA REALIZZARE

    c. HTML 5 TAG CANVAS E REALIZZAZIONE DEL LOOP DI GIOCO IN JAVASCRIPT

    i. DEFINIRE LA ZONA DI GIOCO ALLINTERNO DELLA PAGINA WEB

    ii. INIZIALIZZARE E LANCIARE IL GIOCO

    d. HOT AIR BALLOON DISEGNARE SUL CANVAS

    e. HOT AIR BALLOON IL PRIMO SFONDO E LA MONGOLFIERA

    i. CARICAMENTO ASINCRONO E PRELOADING DELLE SPRITES.

    f. HOT AIR BALLOON RILEVARE E VALIDARE LINPUT DELLUTENTE

    i. RILEVARE LE GESTURES PINCH IN e PINCH OUT

    ii. MISURARE LA DISTANZA DELLE DITA SULLO SCHERMO

    iii. VALIDARE LINPUT DELLUTENTE

    g. HOT AIR BALLOON STRUTTURA DEL GIOCO E GAMEPLAY

    h. HOT AIR BALLOON FASI DI GIOCO

    i. HOT AIR BALLOON ANIMAZIONI

    j. HOT AIR BALLOON GAMEPLAY: MOVIMENTO DEI NEMICI; MONETE E COLLISION

    DETECTION

    k. HOT AIR BALLOON FEEDBACK E SUGGERIMENTI ALLUTENTE

    l. HOT AIR BALLOON SISTEMA DI AUTO-CALIBRAZIONE

    8. REALIZZAZIONE DELLA PIATTAFORMA PER I TERAPISTI

  • ii

    a. REQUISITI E NECESSITA DEI TERAPISTI

    b. IL PANNELLO DI CONFIGURAZIONE DEL GIOCO

    i. INVIO DELLA CONFIGURAZIONE DAL SERVER AL GIOCO

    c. IL PANNELLO DELLE STATISTICHE DEI PAZIENTI

    i. INVIO DEI DATI DI SESSIONE DAL GIOCO AL SERVER

    d. GESTIONE UTENTI E SICUREZZA

    9. CONCLUSIONI

    a. RISULTATI OTTENUTI CON HOT AIR BALLOON

    b. POSSIBILI SVILUPPI FUTURI

    10. BIBLIOGRAFIA

  • 1

    1 - INTRODUZIONE

    La riabilitazione fisica e cognitiva richiede ai pazienti un lavoro intenso e prolungato nel tempo.

    Il lavoro che i pazienti devono affrontare durante il periodo di riabilitazione costituito da esercizi

    ripetuti che mirano a sollecitare le funzionalit da recuperare. La figura del terapista, in qualit di

    istruttore, motivatore, assistente e osservatore del paziente durante lesecuzione dellesercizio

    riabilitativo fondamentale. E particolarmente importante che il paziente esegua gli esercizi in

    modo corretto per evitare linsorgere di problemi muscolari o scheletrici o acquisisca movimenti non

    corretti, situazione che viene indicata come maladaptation (adattamento dannoso).

    Purtroppo, oggigiorno, gli oneri relativi al supporto del personale, delle strutture e delle attrezzature

    necessarie a mantenere attivi ed efficienti i reparti di riabilitazione allinterno delle strutture

    sanitarie, sono quanto mai ingenti, ci costringe tali strutture a cercare di abbattere i costi,

    riducendo al minimo necessario la fornitura di tali servizi, rischiando cos di ridurre la qualit del

    servizio offerto.

    Una possibile soluzione al problema dei costi, che potrebbe addirittura innalzare il livello di qualit

    dei servizi riabilitativi offerti dalle strutture sanitarie, quella di decentralizzare il lavoro sul paziente,

    permettendo a questultimo di svolgere gran parte degli esercizi riabilitativi a casa, in modo

    autonomo, ma sempre sotto la supervisione dei terapisti.

    Questo approccio reso oggi possibile, dallampia diffusione, di nuovi strumenti a basso costo di

    interazione uomo-macchina (HID Human Interface Devices), che spesso vengono prodotti e

    utilizzati in ambito videoludico.

    Abbiamo ad esempio:

    - Microsoft Kinect

    - Wii Balance Board

    - Leap Motion Controller

    - Tablet e Smartphone con schermi multi-touch

    Questi dispositivi sono in grado di tracciare, con sufficiente precisione, molti dei movimenti nello

    spazio, o nel piano che compiono gli utenti che li utilizzano. Tali rilevazioni possono essere utilizzate

    in ambito riabilitativo per controllare la postura e i movimenti del paziente mentre svolge i propri

    esercizi di riabilitazione a casa, fornendo cos la possibilit ai terapisti di supervisionare a distanza il

    paziente, e al paziente di svolgere a casa il proprio lavoro di riabilitazione in completa sicurezza.

    Inoltre, essendo i dispositivi sopracitati, spesso nati dallindustria videoludica, possibile mappare

    allinterno di videogiochi creati ad hoc, gli esercizi di riabilitazione che ogni singolo paziente deve

    svolgere, creando cos degli esercizi-giochi (exer-games), che permettano di introdurre una

    componente di intrattenimento e divertimento allinterno dellesercizio, rendendo il lavoro di

    riabilitazione quotidiano pi stimolante.

    Questo ci che viene svolto oggi nellambito del progetto REWIRE (di cui si parler di seguito), ed

    ci che si cercato di fare, in piccolo, per quanto riguarda la riabilitazione della mano nel progetto

    descritto nei capitoli successivi.

  • 2

    2 - RIABILITAZIONE

    giusto, prima di procedere oltre, definire cosa si intende per riabilitazione e medicina fisica o

    riabilitativa, poich sar largomento centrale di tutto il lavoro descritto in seguito.

    Si tratta di quella branca della medicina volta alla diagnosi, terapia e riabilitazione di quelle disabilit

    derivate da malattie invalidanti, che possono compromettere le funzionalit motorie, cognitive o

    emozionali del paziente.

    La medicina riabilitativa coinvolge una serie di figure professionali tra cui quella del fisioterapista,

    che si occupa di valutare la condizione dei singoli pazienti e stabilire un percorso riabilitativo

    adatto, costituito, spesso da una serie di esercizi da compiere atti al recupero della funzionalit

    compromessa.

    La funzione del fisioterapista fondamentale nel processo riabilitativo, esso infatti non si limita a

    fornire una serie di esercizi che il paziente pu svolgere in autonomia, ma spesso, deve assisterlo

    durante lesecuzione fornendo tempestive correzioni in caso di errore, per impedire il

    peggioramento delle condizioni iniziali, e fornendo anche la giusta motivazione, che lo spinga a

    persistere nellesercizio e ad affrontare le inevitabili difficolt che affronter durante il suo percorso.

    importante tenere ben presente questa triplice funzione del terapista di:

    - Ideatore del programma di esercizi adatti al paziente

    - Correttore di eventuali errori commessi nellesecuzione dei singoli esercizi

    - Motivatore del paziente.

    In quanto questi tre elementi sono fondamentali affinch il processo riabilitativo vada a buon fine e

    dovranno, pertanto, essere presenti anche nel sistema intelligente che affiancher il paziente

    durante la riabilitazione a casa propria, quindi in assenza del terapista.

    2.a - RIABILITAZIONE A CASA: PROGETTO REWIRE

    REWIRE un progetto sostenuto dallUnione Europea che mira a generare una piattaforma di

    riabilitazione multi-livello basata su exer-games (http://www.rewire-project.eu).

    Scopo del progetto quello di creare un sistema personalizzato che possa essere distribuito su

    grande scala nelle case di tutti i pazienti che abbiano bisogno di affrontare un processo di

    riabilitazione per recuperare funzionalit compromesse.

    un progetto indirizzato a pazienti, dimessi dalle strutture ospedaliere, che hanno bisogno di

    continuare a eseguire esercizi di riabilitazione, sotto la sorveglianza remota dei loro terapisti.

    La piattaforma REWIRE costituita principalmente da tre macro-componenti:

    - PATIENT STATION (PS): Si tratta di un sistema, inteso come insieme di hardware / software,

    che viene installato a casa dei pazienti. Consiste in sostanza di un insieme di mini-videogiochi

    che vengono mostrati sullo schermo di un televisore ai pazienti.

    Il sistema di input segue il paradigma Hands Free (o a mani libere), si tratta, in breve di

    utilizzare una serie di dispositivi (ad esempio il Microsoft Kinect), per il tracciamento della

    posizione del paziente nello spazio, questo gli permette di interagire con lambiente virtuale

    senza dover agire su nessun dispositivo fisico quale ad esempio mouse, tastiera, joypads,

    joysticks ecc.

  • 3

    Cuore della Patient Station il Game Engine IGER (Intelligent Game Engine for

    Rehabilitation), sviluppato presso il Laboratorio di Sistemi Intelligenti Applicati del

    Diparitmento di Informatica dellUnviersit degli Studi di Milano, un Game Engine basato su

    Panda3D, che oltre a fornire le funzionalit classiche di un Game Engine, affronta una serie

    di problematiche dovute alla necessit di monitorare ed adattarsi alle necessit del paziente,

    analizzeremo queste problematiche nel dettaglio pi avanti.

    - HOSPITAL STATION (HS): Questa stazione, viene utilizzata dalle strutture e dal personale

    sanitario, permette di definire a distanza il programma personalizzato di esercizi che ogni

    paziente deve affrontare, inoltre fornisce gli strumenti per monitorare e analizzare i

    progressi dei singoli pazienti attraverso lelaborazione dei dati ricevuti dalle singole Patient

    Stations.

    - NETWORKING STATION (NS): Installata a livello regionale, la Networking Station, fornisce

    funzionalit per lanalisi avanzata dei dati collezionati dalle esperienze di riabilitazione dei

    singoli pazienti su tutte le strutture che utilizzano Rewire, questo permette di individuare e

    collezionare percorsi riabilitativi comuni tra diverse strutture, creando una consistente

    knowledge base, e permettendo cos di migliorare la qualit globale del servizio.

    Attualmente REWIRE fornisce principalmente strumenti e minigiochi studiati per la riabilitazione

    cognitiva in pazienti affetti da NSU (Negligenza Spaziale Unilaterale), o con disabilit fisiche post-

    ictus.

    Lo scopo ultimo quello di supportare e fornire strumenti riabilitativi adatti al maggior numero di

    patologie e disabilit possibili.

    2.b - IGER: Un game engine per la riabilitazione

    bene, ai fini di comprendere al meglio il progetto descritto in questo documento, spendere due

    parole su IGER, il game engine utilizzato allinterno della Patient Station di REWIRE.

    Un game engine un sistema (software) disegnato per la creazione e lo sviluppo di videogiochi. Si

    tratta, in sostanza, di una collezione di librerie che forniscono funzionalit atte a risolvere una serie

    di problematiche comuni allo sviluppo di quasi tutti i videogiochi.

    Tradizionalmente esso si compone di:

    - Rendering Engine (o Renderer): componente che si occupa della generazione dei singoli

    frame bidimensionali o tridimensionali a partire da modelli o sprites. il motore sul quale si

    basa la generazine di qualsiasi genere di animazione allinterno del gioco.

    - Engine Fisico: componente che si occupa di simulare la fisica allinterno del mondo virtuale

    ricreato allinterno del videogioco.

    - Collision Detection: ogni game engine deve fornire tool adeguati ed efficienti per la

    rilevazione di qualsiasi tipo di collisione tra i modelli caricati allinterno del gioco.

    - Tools opzionali: quali ad esempio, tool per la gestione dei suoni, le animazioni, lintelligenza

    artificiale, input devices differenti e tutto ci che pu essere utile allo sviluppo di un

    videogioco.

    IGER eredita tutti questi aspetti dal game engine su cui si basa, PANDA3D.

    Poich gli esercizi di riabilitazione possono essere molto diversi tra di loro e le abilit e bisogni dei

    pazienti possono variare, i videogiochi per la riabilitazione devono potersi adattare alle esigenze dei

  • 4

    singoli utenti, e nel frattempo essere in grado di monitorare e archiviare ogni singolo movimento,

    mantenendo il pi possibile invariata lesperienza di gioco da un paziente allaltro.

    IGER aggiunge alle funzionalit standard di un game engine tradizionale:

    - Tools standard: per la configurazione offline, da parte dei terapisti, dei singoli videogiochi

    riabilitativi, permettendo di aggiustare i parametri che pi si ritengono opportuni alle

    esigenze di un determinato paziente.

    - Strumenti per il graduale adattamento automatico dei parametri di gioco per meglio

    rispecchiare levoluzione delle abilit psicomotorie del paziente.

    - Strumenti per il monitoraggio in tempo reale dei movimenti dei pazienti.

    - Strumenti per lacquisizione e salvataggio dei dati di gioco sia per la valutazione dei progressi

    del paziente sia per la motivazione.

    Inoltre IGER fornisce un layer di astrazione sul device di Input, denominato IDRA (Input Device for

    Rehabilitaion Abstraction layer) questo per potersi adattare al meglio alle esigenze del paziente:

    Sar ad esempio pi facile utilizzare un joystick per un paziente affetto da NSU (Neglect) piuttosto

    che per un paziente con qualche tipo di paralisi alle braccia. Daltro canto un dispositivo come la

    Nintendo Wii Balance Board, non potr essere utilizzata da pazienti con qualche sorta di paralisi alla

    parte inferiore del corpo.

    Questo layer di astrazione sui dispositivi di Input permetter a qualsiasi paziente di giocare a

    qualsiasi gioco della piattaforma, in quanto esso fornisce un interfaccia di input verso il gioco

    comune a tutti i dispositivi.

    Al momento i dispositivi supportati da IGER sono:

    - Microsoft Kinect.

    - Sony Playstation 3 Eye camera.

    - Nintendo Wii Balance Board.

    - Tyromotion Tymo.

    - Motycon OpenGo Insoles.

    - Phantom Omni.

    - Novint Falcon.

    - E in parte il Leap Motion Controller.

  • 5

    3 - RIABILITAZIONE DELLA MANO

    Ispirandosi al modello fino a qui descritto, quello che si voluto fare in questo progetto stato

    ricreare, in piccolo, questi sistemi applicandoli al caso specifico della riabilitazione della mano.

    Questo progetto stato svolto in collaborazione con lunit di chirurgia della mano dellOspedale S.

    Giuseppe di Milano, diretta dal Prof. Giorgio Pajardi. A questo progetto hanno partecipato anche la

    Dott.ssa Erica Cavalli e la Dott.ssa Elena Mancon, le quali ci hanno invitato ad alcune sessioni di

    riabilitazione con una paziente e aiutato a inquadrare il tipo di lavoro che avremmo dovuto svolgere

    per realizzare il progetto. Per quanto riguarda il laboratorio AISLab, hanno collaborato al progetto il

    Dott. Renato Mainetti e il Dott. Michele Pirovano.

    Innanzi tutto bene inquadrare il target di pazienti considerato.

    Abbiamo avuto la possibilit di sviluppare un mini-gioco riabilitativo per pazienti molto giovani (dai

    quattro anni in su) affetti principalmente da agenesia delle dita della mano, o che hanno subito

    traumi che hanno portato allamputazione parziale o totale delle dita.

    Tali pazienti hanno subito un intervento di transfer delle falangi di alcune dita dei piedi al posto di

    quelle amputate o mancanti: scopo di tale operazione quella di restituire al paziente, almeno

    parzialmente, la funzionalit della mano, dando la possibilit di toccare e prendere oggetti.

    Si tratta di un intervento particolarmente consigliato, specialmente a pazienti affetti da agenesia

    delle dita, in quanto, essendo nati senza le dita della mano, e trovandosi nella fase iniziale di

    apprendimento, che specialmente a quellet, particolarmente legata allinterazione con

    lambiente circostante tramite il tatto e il contatto con gli oggetti, rischiano di sviluppare ritardi

    nellapprendimento.

    Anche in questo caso, la fase riabilitativa post-operatoria, particolarmente lunga, si tratta di periodi

    di tempo dellordine di diversi anni e ha in questo caso due obbiettivi:

    - Il primo, prettamente fisico, quello di esercitare il pi possibile le dita impiantate,

    effettuando dei movimenti di avvicinamento e allontanamento delle dita, rotazione e presa

    di oggetti.

    - Il secondo, di carattere pi neurologico, consiste in una serie di esercizi atti a sviluppare la

    consapevolezza nel bambino del nuovo arto e delle sue capacit.

    Bisogna notare come il target di utenza sia profondamente differente da quello a cui si riferisce ad

    oggi la piattaforma sviluppata allinterno del progetto REWIRE.

    Mentre per REWIRE si ha a che fare con pazienti generalmente affetti da danni cerebrali dovuti a

    ictus o a pazienti con problemi posturali o di movimento, in ogni caso adulti, in questo caso si ha a

    che fare con pazienti molto giovani, bambini, per cui le tecniche di intrattenimento, e motivazione

    del paziente vanno rivisitate in un'altra ottica.

    E importante, soprattutto, strutturare i giochi in maniera diversa, tenendo il conto dellet

    dellutente medio che lo andr ad utilizzare, in particolare:

    - Il gameplay deve essere adattato alle capacit e allet del bambino, non bisogna proporre

    nulla di molto complesso, ed fondamentale, per mantenere acceso linteresse del

    bambino, che a ogni azione o movimento svolto in maniera corretta dal paziente

    corrisponda un immediata risposta, divertente e stimolante del sistema.

    - Gli obbiettivi stabiliti dal gioco devono essere quanto pi flessibili possibile e non vincolanti,

    il modo in cui il bambino si approccer al gioco spesso imprevedibile, per tanto la

  • 6

    valutazione delle prestazioni e dei miglioramenti non potr essere misurata ad esempio

    dalla quantit di obbiettivi raggiunti, quanto dallosservazione dei dati ottenuti dalle

    misurazioni effettuate durante lintera sessione di gioco

    - Il feedback fornito al paziente dal sistema sia in caso di movimento scorretto che di

    motivazione deve essere studiato in maniera adeguata, ad esempio la figura del terapista

    virtuale, usato con gli adulti in REWIRE ha poco effetto su un paziente di quattro anni, avr

    sicuramente pi effetto uno smiley sullo schermo, piuttosto che fuochi dartificio, colori e

    animazioni.

    3.a - STRUMENTI DIGITALI GI UTILIZZATI NELLA RIABILITAZIONE DELLA MANO

    A seguito dei primi incontri effettuati con i terapisti abbiamo potuto apprendere, che al momento,

    vengono gi utilizzati in maniera del tutto sperimentale, dei videogiochi durante alcune sessione di

    riabilitazione con il bambino.

    Si tratta di giochi per tablet, generalmente iPad, sviluppati da terzi a scopo di intrattenimento. I

    terapisti, con i genitori dei giovani pazienti, hanno analizzato alcune delle applicazioni offerte nei

    vari App Store, scelto quelle che pi sembravano adatte al paziente in questione, e hanno provato

    ad utilizzarle durante alcune sessioni riabilitative.

    Questo tipo di approccio al problema porta sicuramente alcuni vantaggi:

    - Innanzi tutto la moltitudine di applicazioni e giochi presenti nei vari store multimediali, offre

    sicuramente unampia scelta, questo permette di trovare lapplicazione che pi riesce a

    catturare linteresse del bambino e sar quindi pi facile mantenerlo concentrato

    sullesercizio da svolgere.

    - Lapplicazione installata disponibile per tutti, senza necessit di infrastrutture particolari,

    come ad esempio un server ospedaliero per lo storage dei dati ottenuti dallapplicazione, o

    sistemi di autenticazione e gestione dei diversi pazienti, questo permette in sostanza ai

    genitori dei pazienti di installare sul proprio dispositivo la stessa applicazione provata in

    ospedale, e fare giocare il bambino a casa per esercitare il pi possibile la mano da riabilitare

    - Inoltre i costi relativi allacquisto di un gioco sullapp store sicuramente irrisorio rispetto a

    quello di realizzazione di applicazioni ad hoc.

    Vi sono per purtroppo una serie di svantaggi nellutilizzo di queste applicazioni commerciali,

    pensate per lintrattenimento in ambito medico/riabilitativo:

    - Spesso questi giochi non sono configurabili, non vi cio la possibilit da parte del terapista,

    n di predisporre una tabella di esercizi da svolgere, n di impostare il singolo gioco in modo

    da accettare unicamente il tipo di movimento desiderato.

    - Questi giochi non sono pensati per adattarsi alle capacit fisiche del loro utente, ci significa

    che generalmente un interazione errata viene interpretata come un errore, e il giocatore

    viene semplicemente penalizzato; in realt, come si visto in precedenza analizzando le

    funzionalit di IGER, nei videogiochi per la riabilitazione spesso necessario aggiustare

    gradatamente i parametri di gioco in modo da adattarsi alle capacit del singolo paziente.

    - Spesso utilizzando questi giochi necessaria la presenza fisica del terapista, in quanto il

    gioco non pensato per assistere e correggere lutente in caso di movimenti sbagliati, inoltre

    non si considera neanche laspetto motivazionale, per cui il paziente, rischia semplicemente

    di rimanere frustrato da un insuccesso, e pu rifiutarsi di continuare, oppure pu giocare

    controvoglia, aumentando cos il rischio di errore.

  • 7

    - Infine non viene fornita ai terapisti un interfaccia per lanalisi dei dati acquisiti durante il

    gioco, riguardanti i movimenti effettuati, per cui non possibile monitorare eventuali

    progressi o peggioramenti del paziente.

    3.b - OBIETTIVO DEL PROGETTO

    Alla luce di quanto descritto finora, a seguito degli incontri preliminari avuti coi terapisti, stato

    stabilito lobbiettivo del progetto da realizzare:

    Un prototipo di mini-gioco per pazienti a cui sono state gi impiantate due dita, lesercizio sar quello

    di avvicinare le dita come per pizzicare (pinching) lo schermo di un dispositivo touch screen (nel

    caso specifico dei test eseguiti, si tratta di un tablet), lapplicazione dovr reagire sia

    allavvicinamento che allallontanamento delle dita (pinch-in e pinch-out), dovr essere

    configurabile dal terapista tramite un opportuna interfaccia, e dovr essere in grado di registrare i

    movimenti effettuati durante lintera sessione di gioco, i dati raccolti dovranno poi essere presentati

    al terapista mediante un opportuna interfaccia in grado di evidenziare eventuali miglioramenti o

    peggioramenti delle abilit motorie del paziente.

    Lintero sistema di monitoraggio dovr essere trasparente al paziente, e il sistema di feedback in-

    game dovr essere adattato per essere di facile comprensione a bambini molto piccoli.

    Il prototipo verr realizzato utilizzando HTML5 e Javascript e verr installato su un webserver in

    universit, lapplicazione verr quindi resa disponibile alla struttura e testata su un campione di

    pazienti scelto a discrezione dei terapisti.

  • 8

    4 - STRUMENTI SOFTWARE UTILIZZATI

    Prima di addentrarsi nei dettagli dello sviluppo del progetto, bene parlare degli studi che sono stati

    effettuati su tecnologie gi esistenti quali il game engine Panda3D, il software di modellazione 3D

    Blender, e le API del Leap Motion controller, scopo di tali studi stato quello di prendere confidenza

    con alcuni degli strumenti utilizzati, ad oggi nello sviluppo di videogiochi sia allinterno del progetto

    REWIRE che in ambito commerciale.

    5 - PANDA 3D

    Panda 3D un game engine, un framework open source per il rendering 3D e lo sviluppo di

    videogiochi. Il nucleo scritto in C++ e le sue funzionalit possono essere estese utilizzando il

    linguaggio di scripting Python.

    Tra le features offerte ci sono:

    - Renderer 3D che utilizza sia le librerie Mircrosoft DirectX su Microsoft Windows, che le

    librerie OpenGL, compatibili con vari sistemi operativi

    - Librerie per la gestione dellaudio

    - Un physic engine integrato (oltre a supportarne di pi complessi, come ad esempio lNvidia

    Physx engine) che fornisce API per la gestione dei problemi pi comuni nello sviluppo dei

    videogiochi, quali quello del collision detection.

    - Un sistema di effetti particellari dedicato

    - Un sistema per la gestione delle GUI, per la realizzazione ad esempio di menu di gioco, o

    scritte o elementi grafici da mostrare sullo schermo durante la fase di gioco

    - Una semplice libreria PandaAI per una gestione basilare dellintelligenza artificiale nel

    gioco, che fornisce ad esempio strumenti per la ricerca di un oggetto nello spazio di gioco,

    levitare gli ostacoli, il trovare e seguire percorsi per spostarsi da un punto a un altro ecc.

    5.a - FUNZIONAMENTO LOOP DI GIOCO Il funzionamento basilare di un qualsiasi videogioco mai prodotto sempre il medesimo, e consiste

    sostanzialmente in quattro fasi:

    - Fase di inizializzazione (o init()): la fase in cui vengono istanziati e inizializzati tutti i

    componenti che verranno utilizzati allinterno del videogioco, dal timer, ai giocatori, agli

    oggetti inanimati, lambiente, suoni, luci ecc.

    - Fase di input: la fase in cui vengono letti dallesterno gli input del giocatore (per esempio

    il movimento di un joystick, la pressione di un tasto).

    - Fase di aggiornamento (o update()): la fase in cui vengono modificati alcuni parametri di

    gioco, come ad esempio la posizione dei giocatori.

    - Fase di disegno (o draw()): la fase in cui viene effettivamente disegnato il frame che verr

    mostrato al giocatore, con tutti i componenti e i modelli le cui propriet sono state definite

    nelle fasi precedenti.

    In genere la fase di inizializzazione, viene eseguita una sola volta, allavvio del gioco.

    Dopo di che si entra in un ciclo (loop) infinito (in realt non proprio infinito, ma termina in

    condizioni particolari, quali ad esempio la terminazione del gioco), che esegue alternativamente la

    fase di aggiornamento e di disegno del frame.

  • 9

    La velocit con cui avviene questo ciclo, o meglio lintervallo di tempo trascorso tra due fasi di

    disegno indica il frame rate del nostro gioco.

    In Panda3D, lo schema descritto sopra ovviamente implementato, ma trasparente al

    programmatore.

    Linizializzazione di un nuovo gioco e il conseguente lancio del ciclo di Update e Draw viene fatto in

    Python estendendo la classe ShowBase, che inizializza alcuni strumenti utili allo sviluppo del gioco

    quali ad esempio:

    - Il loader: utilizzato per caricare qualsiasi tipo di gameObject allinterno del nostro gioco, dai

    modelli 3d, alle textures, ai suoni, ecc.

    - Il render: che si occupa, di tutto ci che grafica allinterno del gioco

    - Il taskMgr: per la gestione dei vari task da eseguire allinterno del gioco

    - La camera: ovvero la telecamera di default che delimita larea attualmente visibile del gioco

    E diversi altri componenti.

    Inoltre la classe ShowBase, ci fornisce accesso al metodo run(), che in maniera del tutto trasparente

    avvia il loop di gioco.

    Tutta la logica che concerne il disegno del singolo frame in Panda3D gestita da un grafo di nodi, la

    cui radice loggetto render (o render2D nel caso di giochi bidimensionali); sar sufficiente

    impostare un nodo generato dal caricamento (tramite loader) di un qualsiasi modello

    tridimensionale come figlio delloggetto render (o come figlio di uno dei suoi figli), affinch il

    renderer di panda3D renderizzi loggetto nella scena.

    Ci che particolarmente utile in questo schema di gestione dei nodi ad albero, che possibile

    impostare parentele tra i diversi oggetti, in tal modo sar ad esempio possibile muovere, scalare o

    ruotare un singolo oggetto, non solo in funzione dellorigine della scena visualizzata, ma anche in

    funzione del suo genitore.

    Ultimo componente degno di nota, utile a descrivere macroscopicamente il funzionamento di un

    gioco creato con panda3D, il taskManager.

    Initialize

  • 10

    Il TaskManager, implementa in parte il concetto che sta dietro al metodo update, descritto nel

    capitolo precedente, si tratta di una struttura dati a cui si possono appendere funzioni, tali funzioni

    verranno eseguite a ogni loop e serviranno per i pi disparati scopi, come ad esempio:

    - Modificare la posizione della camera di gioco

    - Modificare la rotazione del giocatore sulla scena

    - Modificare qualsiasi parametro di gioco

    - Aggiornare i punteggi

    - Oppure semplicemente eseguire controlli per il debugging del gioco

    Ecco un esempio di codice per realizzare una semplice animazione, di una sfera che ruota su se stessa

    in panda3D.

    from direct.showbase.ShowBase import ShowBase

    from direct.task import Task

    class FirstGame (ShowBase):

    def __init__(self):

    # Call superclass constructor

    ShowBase.__init__(self)

    # Set default camera position

    base.disableMouse()

    self.camera.setPos(0,-10,0)

    # Load a model

    self.myModel = loader.loadModel("smiley.egg");

    # Reparent the model to render so that it will be displayed in the scene

    self.myModel.reparentTo(render)

    # Attach a task to taskManager to make the spin

    self.taskMgr.add(self.spinTheBall, "Spin The Ball Task")

    # TASKS

    def spinTheBall(self, task):

    # Rotate by 20 degrees per second

    angleDegrees = task.time * 20.0

    self.myModel.setHpr(angleDegrees, 0,0)

    return Task.cont

    #Instantiate and launch the game

    game = FirstGame()

    game.run()

    Una volta compresa la struttura di base di un gioco realizzato con panda3D si passati alla

    realizzazione di semplici giochi di test, nei quali si cercato di mappare un movimento su uno spazio

    bidimensionale, come quello del mouse, allinterno della scena di un gioco 3D, scopo di tale test

    stato quello di capire come effettuare il mapping dellinput ricevuto da un dispositivo esterno

    allinterno del gioco.

    Per questo tipo di test, sono stati utilizzati due approcci differenti:

    - Lutilizzo di una camera ortografica invece che proporzionale per inquadrare la scena, tale

    approccio consente di mappare, senza distorsioni unarea allinterno di uno spazio

    tridimensionale, su un piano.

    - Lutilizzo della tecnica del Ray Casting, che permette di rilevare sfruttando il sistema di

    collision detection integrato nel game engine, il punto sulla superficie nello spazio

    tridimensionale sul quale ci si trova col puntatore del mouse.

    Entrambe queste tecniche verranno descritte qui di seguito, ma per fare ci necessario prima

    introdurre il sistema di collision detection in Panda3D.

  • 11

    5.b - COLLISION DETECTION IN PANDA3D

    Il problema del rilevare le collisioni (Collision Detection), un problema chiave nello sviluppo di un

    qualsiasi videogioco, sia esso bidimensionale che tridimensionale.

    Ogni qual volta due oggetti si toccano, abbiamo una collisione, e se non vogliamo che, ad esempio,

    una palla che cade da 10 metri, attraversi semplicemente la superficie e prosegua indisturbata la sua

    caduta verso il nulla, dovremmo rilevare la collisione con il suolo e gestirla appropriatamente,

    fermando ad esempio la palla allimpatto, o se stiamo realizzando un gioco fedele alle leggi della

    fisica, la faccia rimbalzare pi volte fino a farla fermare completamente.

    Esistono varie tecniche per rilevare in maniera pi o meno efficiente la collisione tra due oggetti nei

    videogiochi.

    In videogiochi bidimensionali molto semplici, spesso viene usato quello che in inglese viene

    chiamato Box Collider:

    Si tratta di costruire un quadrato invisibile attorno agli sprites su cui vogliamo rilevare la collisione

    della stessa altezza e larghezza di entrambi gli oggetti, quando i due quadrati si intersecano, allora

    si verificata una collisione.

    In Panda3D, vengono forniti sostanzialmente due metodi per gestire il problema delle collisioni:

    1. La creazione di geometria dedicata alla collisione.

    2. Abilitare il rilevamento delle collisioni su tutta la geometria visibile.

    Il primo metodo di pi complessa implementazione, in quanto necessario costruire una

    geometria secondaria dedicata esclusivamente alla collision detection, ma pi efficiente in quanto i

    poligoni su cui rilevare le collisioni sono, in genere, molti meno, di quelli presenti in tutta la scena di

    gioco, e sono, di solito, anche figure poco complesse come cubi, sfere, ecc.

    Questo metodo dunque pi adatto ad applicazioni finite, il secondo invece molto pi grezzo, ma

    molto pi rapido da implementare.

    Il secondo metodo, ovviamente, di pi facile gestione, ogni elemento che costituisce la geometria

    visibile del gioco, pu collidere con qualsiasi altro elemento nel gioco, il vantaggio ovviamente

    dovuto al fatto che non necessario costruire geometrie dedicate alla collision detection, lo

    svantaggio, che i poligoni visibili allinterno di un gioco di media complessit pu essere spesso

    molto elevato, per cui il gioco costruito pu risultare molto oneroso in termini di risorse di calcolo

    richieste per gestire il rilevamento di collisioni su ognuno di essi.

    In ogni caso in Panda3D, il sistema di collisioni ruota sostanzialmente attorno ai seguenti oggetti:

    - CollisionSolids:

    o CollisionSphere

    o CollisionTube

    o CollisionPlane

    o CollisionPolygon

    o CollisionRay []

    Sono tutti i solidi, generalmente invisibili che costituiscono la collision geometry, se

    volessimo ad esempio far collidere la palla rotante creata nel capitolo precedente con

    qualche altro oggetto, allora dovremmo costruire una CollisionSphere invisibile attorno alla

    nostra palla, delle stesse dimensioni della palla stessa, a quel punto su questo oggetto

    riusciremmo a rilevare collisioni con altri collider.

  • 12

    - CollisionHandlers:

    Ce ne sono di diversi tipi in Panda3D, il pi semplice il CollisionHandlerQueue, che

    sostanzialmente si occupa di rilevare tutte le collisioni avvenute nella scena di gioco in un

    dato istante di tempo e inserirle in una coda, consultabile dal programmatore, che potr

    estrarre le diverse collisionEntries una per volta e gestirle nel modo che ritiene pi

    appropriato.

    - CollisionTraverser, che loggetto fondamentale del sistema di collisioni di Panda3D, si

    tratta in sostanza di una struttura dati che colleziona al suo interno tutti i collider creati dal

    programmatore nella scena: un collider sostanzialmente, una coppia oggetto

    (generalmente un collisionSolid) / handler.

    Ecco un esempio del sistema di collisioni di panda3D in funzione, le collisionSphere intorno alle due

    sfere sono state scalate in modo da essere un po pi grandi dei modelli visibili, in modo da essere

    facilmente visibili:

    5.c - MAPPATURA DI INPUT BIDIMENSIONALE NELLO SPAZIO: CAMERA ORTOGRAFICA

    Ora che abbiamo visto come funziona il sistema di collision detection in PANDA3D, possiamo tornare

    al problema originario, ovvero quello di mappare il movimento del mouse, che avviene su un piano

    bidimensionale, allinterno della scena di gioco in panda3D, mappato di default su un ambiente a 3

    dimensioni.

    La prima delle due tecniche elencate prima era quella della camera ortografica.

  • 13

    Il concetto che sta dietro a questa tecnica, quello di sostituire le lenti della camera che inquadra la

    scena di gioco, che di default sono lenti a proiezione prospettica: che riprendono lambiente, come

    farebbe una telecamera reale, o come farebbe locchio umano; con una lente ortografica, che

    elimina di fatto gli effetti prospettici, mantenendo le linee di proiezione perfettamente parallele fra

    di loro.

    Leffetto ottenuto dallutilizzo di queste lenti, ovviamente, la perdita di percezione visiva della terza

    dimensione, per cui ad esempio avvicinandosi o allontanandosi da un oggetto, esso non si

    ingrandisce n si rimpicciolisce: questo ovviamente poco intuitivo, ma fornisce un grande

    vantaggio, quello di poter scalare la scena inquadrata in modo da mappare in maniera diretta le

    coordinate, del dispositivo di input su due dimensioni, nel nostro caso un mouse, allinterno della

    scena di gioco.

    Per testare questa tecnica stato realizzato un mini-gioco in cui una pallina doveva seguire il

    puntatore del mouse allinterno di un percorso delimitato da dei muri laterali, quando la pallina

    toccava uno dei muri si bloccava e il gioco terminava.

    Analizziamo solo la parte di codice relativa al mapping del device allinterno della nostra scena:

    Sappiamo che Panda3D mappa la posizione del mouse con dei valori decimali compresi tra -1 e 1 sia

    sullasse delle ascisse che su quella delle ordinate, il nostro scopo dunque quello di montare le

    lenti ortografiche, e regolare la dimensione della pellicola fino a quando anche le coordinate della

    scena non sono comprese tra -1 e 1, in modo che a certe coordinate del mouse corrisponda il

    medesimo punto nella scena.

    stato definito un metodo setupCamera, che si occupa proprio di questo:

    # This method prepare the camera

    def setupCamera(self): # since this is a 2d game, we use Orthographic lenses, this should avoid

    # perspective related issues with the mouse lens = OrthographicLens()

    # we set the camera film size to fit 4/3 aspect ratio, x size is set to

    # 2, because we want the coordinate system to be in the [-1, 1] range lens.setFilmSize(2,1.5)# setFilmSize sets the camera film size in spatial

    units base.camNode.setLens(lens) # With Orthographic lenses, camera height doesn't really matters base.camera.setPos(0,0,10) base.camera.setHpr(0,270,0)

    Il metodo che setta la dimensione della pellicola, e quindi definisce la dimensione dellarea ripresa,

    setFilmSize.

    Una volta definita la dimensione dellarea ripresa si tratter solamente di convertire le coordinate

    del mouse, comprese tra -1 e 1 in coordinate spaziali, comprese tra -1 e 1 sullasse delle ascisse e -

    0.75 e +0.75 sullasse delle ordinate (questo valore per le ordinate dipendente dallaspect ratio

    della finestra di gioco,in questo caso 4/3), facciamo questo nel task del gioco che si occupa del

    tracciamento del mouse.

    La conversione che dobbiamo fare per lasse Y realizzata semplicemente sapendo che laspect ratio

    della nostra finestra 4:3, per cui si tratter di prendere le coordinate del mouse ricevute dividerle

    per 4 e moltiplicarle per 3, supponiamo ad esempio che il mouse si trovi in coordinate (0,1), allora

    la nostra posizione nello spazio di gioco sar 1 / 4 = 0,25 * 3 = 0,75.

  • 14

    Vediamo la parte che ci interessa:

    def trackMouse(self, task):

    # Track the mouse only if it's in the window otherwise we get errors

    if(base.mouseWatcherNode.hasMouse() == True and self.trackingEnabled == True):

    mousePos = base.mouseWatcherNode.getMouse()

    self.mouseVector = Vec3(mousePos.getX(), mousePos.getY(), 0)

    # Mouse position in X goes from -1 to 1

    tX = self.mouseVector.getX()

    # Since camera aspect ratio is 4:3, mouse relative position in our world

    # will be 4/3 of its absolute position

    tY = (self.mouseVector.getY() / 4) * 3

    newWaypoint = Point3(tX,tY,0)

    # etc. etc. . . . . .

    Ed ecco uno screenshot del gioco finito, da notare come la posizione della pallina corrisponda alle

    attuali coordinate del puntatore del mouse:

    5.d - MAPPATURA DI INPUT BIDIMENSIONALE NELLO SPAZIO: RAY CASTING

    La tecnica della camera ortografica vista nel capitolo precedente, semplifica di molto il problema

    della mappatura di devices bidimensionali, o che utilizzano semplicemente un sistema di coordinate

    differente rispetto a quello di panda3D, allinterno della scena di gioco; ma allo stesso tempo

    impedisce la realizzazione di giochi completamente tridimensionali: questo dovuto alla natura non

  • 15

    prospettica delle lenti ortografiche, che non permette di avere percezione della profondit e quindi

    della distanza tra la camera e i vari oggetti.

    La tecnica del ray casting, ci viene in soccorso nel momento in cui abbiamo necessit di rilevare il la

    posizione del mouse, o di altri dispositivi allinterno di una scena tridimensionale.

    Il procedimento consiste nel rilevare la posizione del mouse nel suo sistema di coordinate (-1,1) e

    proiettare ortogonalmente alla superficie di gioco un raggio (un collisionRay in panda3D) dalla

    telecamera: il punto in cui avviene la collisione col terreno, sar il punto su cui si trova il mouse nella

    scena.

    stato realizzato, anche in questo caso, un gioco simile a quello precedente, ma, questa volta,

    utilizzando lenti prospettiche e inquadratura non esattamente ortogonale alla superficie.

    Analizziamo anche in questo caso le parti di codice utili al fine di comprendere il funzionamento di

    questa tecnica:

    Innanzi tutto, quello che dobbiamo fare preparare il collisionRay che andr proiettato sulla

    superficie di gioco, si tratta di aggiungere semplice geometria di collisione:

  • 16

    # This generates a collisionRay and attaches it to the active camera, then it

    # returns a nodePath to that ray

    def setupMouseRayCastingLogic(self):

    collisionNode = CollisionNode('Mouse Ray collision node')

    self.pickerRay = CollisionRay()

    collisionNode.addSolid(self.pickerRay)

    return base.camera.attachNewNode(collisionNode)

    Da notare, lultima istruzione, in cui viene impostato il nodo relativo al nuovo collisionRay come figlio

    del nodo della telecamera: questo viene fatto perch proprio da essa che faremo partire il nostro

    raggio.

    A questo punto la classe collisionRay, ci consente comodamente di settare la posizione e

    lorientamento del nostro raggio tramite un comodo metodo setFromLens():

    Tale metodo setta lorigine del collisionRay su cui viene chiamato nel punto corrispondente alle

    coordinate nel range [-1,1] sul piano focale minimo (ovvero sul piano pi vicino allosservatore, che

    verr messo a fuoco dalla camera) e lo proietter, perpendicolarmente a questo piano, per una

    lunghezza virtualmente infinita.

    A questo punto, se riusciremo a rilevare una collisione tra il raggio e la nostra superficie, allora il

    punto di collisione sul terreno, sar il punto del gioco su cui il giocatore ha cliccato, potremmo quindi

    rilevare levento e gestirlo di conseguenza.

    # This tasks checks the mouse status, and eventually sets the tracked WayPoints

    def mouseMonitor(self, task): # We check if the mouse is within the game window if(base.mouseWatcherNode.hasMouse() == True): mpos = base.mouseWatcherNode.getMouse() # Shoot a ray from the camera towards the surface self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) base.cTrav.traverse(render) if self.cHan.getNumEntries() > 0: # This is so that we get the closest object self.cHan.sortEntries() pickedObj = self.cHan.getEntry(0).getIntoNodePath() if(pickedObj.getName() == "Ground Collision Node"): pickedObjPoint = self.cHan.getEntry(0).getSurfacePoint(render)

    # etc. etc. [. . .]

    Come possibile osservare dal codice, anche in questo caso, si utilizza un semplice il

    CollisionHandlerQueue per la gestione delle collisioni: si proietta il raggio invisibile verso la superficie

    con setFromLens, si chiama il metodo traverse() di collisionTraverser per rilevare le collisioni, se sono

    state rilevate delle collisioni con il collisionNode della superficie, allora il punto di collisione ovvero:

  • 17

    pickedObjPoint = self.cHan.getEntry(0).getSurfacePoint(render)

    il punto su cui lutente ha cliccato, secondo il sistema di coordinate del nostro gioco.

    Una volta presa analizzate le possibili tecniche per la gestione di input da diversi device in Panda3D,

    il lavoro s concentrato sullo studio delle potenzialit e la possibilit di integrare allinterno del

    game engine, un dispositivo di input differente, il Leap Motion Controller.

  • 18

    6 - LEAP MOTION CONTROLLER

    Il Leap Motion Controller, un dispositivo di input, pensato e sviluppato per il tracciamento

    dettagliato delle mani e di tutte le dita dellutente, senza richiedere nessuna forma di contatto fisico

    con il dispositivo.

    Il funzionamento molto simile a quello del Microsoft Kinect, ma a differenza di questultimo, il cui

    scopo principalmente quello di tracciare lintero corpo degli utenti nel suo raggio dazione, larea

    analizzata dal leap motion controller molto ristretta, questo permette di ottenere una risoluzione

    superiore a quella di kinect, che pu lavorare, in near mode, a 1 metro di distanza dal soggetto,

    contro il range di interazione di 7 - 25 cm del Leap, ci rende il dispositivo potenzialmente adatto a

    tracciare i movimenti della mano e la posizione delle singole dita nel dettaglio.

    6.a - PROGRAMMARE IL LEAP API

    Leap Motion fornisce agli sviluppatori una serie di librerie scritte in diversi linguaggi per interfacciarsi

    con il dispostivo: poich scopo dello studio effettuato era quello far funzionare il leap con Panda3D,

    sono state analizzate le librerie Python.

    Il concetto che sta dietro alla comunicazione con il leap, quello di creare una propria classe,

    sottoclasse di Listener, che implementi le funzioni che vengono richiamate per gestire i diversi tipi

    di eventi che possono essere sollevati dal device, vediamo i quelli fondamentali:

    - on_init(): questa funzione viene chiamata quando il controller a cui il nostro listener

    collegato, viene inizializzato: sar opportuno inserire qua tutta la logica di inizializzazione

    della nostra classe

    - on_connect(): questa funzione viene richiamata quando il dispositivo si connesso con il

    software del leap motion ed pronto a inviare frame

    - on_disconnect(): questa funzione esattamente opposta alla precedente, serve ad esempio

    a gestire il caso in cui il dispostivo venga accidentalmente scollegato dal computer.

    - on_exit(): questa funzione viene chiamata quando il nostro listener viene scollegato dal

    controller attivo, qua implementeremo tutta la logica di deallocazione della nostra classe.

    - on_frame(): questa la funzione pi importante, richiamata dallevento sollevato quando

    viene ricevuto un nuovo frame dal dispositivo, allinterno di questa funzione dovremmo

    compiere tutte quelle operazioni necessarie ad analizzare il singolo frame ricevuto, e ad

    estrapolare tutte le informazioni necessarie, alla nostra applicazione finale, nel nostro caso,

    il gioco costruito con panda3D, affinch essa risponda correttamente agli input dellutente.

    Oltre alla classe Listener, la libreria proposta dal produttore del dispositivo, ci fornisce una serie di

    classi che ci permettono di astrarre sui dati ricevuti dal dispositivo e di lavorare in comodit su aspetti

    quali ad esempio, la posizione della normale del palmo della mano, il numero di dita rilevate, la

    posizione della punta di un singolo dito, ecc.

    Analizziamo quelle fondamentali:

    - La classe FRAME: probabilmente la classe pi importante, essa contiene tutte le istanze di

    tutti i singoli oggetti rilevati nel frame corrente, quali ad esempio: quante mani sono state

    rilevate, quante dita, quanti strumenti (come matite, penne, ecc.), quanto grande al

    momento larea monitorata dal dispositivo, i frame al secondo generati attualmente, ecc.

  • 19

    - La classe HAND: fornisce informazioni su una singola mano rilevata dal dispositivo, da

    informazioni riguardo, la posizione del palmo, la direzione della normale, se si sta muovendo

    e se s in quale direzione e con che velocit, quante dita della mano sono state rilevate ecc.

    - La classe POINTABLE: fornisce informazioni analoghe a quelle della classe HAND, ma per il

    singolo dito della mano, o per il singolo tool rilevato. Le classi FINGER e TOOL estendono la

    classe POINTABLE.

    Le classi disponibili nella libreria, sono molte di pi, ma queste sono quelle fondamentali.

    bene inoltre spendere qualche parola su un altro elemento fondamentale dellhand tracking: le

    gestures.

    Per gesture si intende un tipo di movimento molto comune, ricorrente o che ha un intenzione

    particolare che pu essere compiuto dallutente.

    Il software del Leap in grado di riconoscere alcune di queste gestures, quali ad esempio la rotazione

    della punta del dito formando un cerchio: Gesture.Circle, oppure la traslazione di un dito sul piano

    orizzontale o verticale: Gesture.Swipe, o il movimento che simula la pressione di un pulsante

    Gesture.KeyTap o Gesture.ScreenTap, per ognuna di queste gesture possibile definire una

    serie di parametri per la validazione del tipo di movimento da rilevare, quali ad esempio velocit,

    ampiezza e direzione del movimento per personalizzare il tipo di risposta del dispositivo in funzione

    della nostra applicazione.

    Al momento le librerie del Leap non forniscono strumenti ufficiali per la realizzazione di gestures

    personalizzate, nonostante ci, in seguito verr descritto un test realizzato in panda3D per il

    rilevamento della gesture Grabbing ovvero della presa di un oggetto col Leap Motion Controller.

    Prima per descriviamo il primo test realizzato con il Leap Motion Controller:

    6.b - PRIMI TEST

    Scopo del test stato quello di prendere confidenza con le API fornite dal produttore del dispositivo,

    si realizzata una semplice applicazione a riga di comando che a ogni frame verificava linclinazione

    di una mano posizionata sopra il dispositivo e stampava su standard input stringhe come La mano

    punta verso il basso di gradi oppure la mano inclinata verso sinistra di gradi, ecc.

    Ovviamente il cuore di un applicazione cos semplice sar solamente limplementazione del metodo

    on_frame(), di cui riportiamo il codice;

    Il codice del main poco interessante, conterr unicamente la logica di inizializzazione del nostro

    listener e un loop infinito, che manterr il programma attivo fino alla pressione di un tasto,

    vediamo dunque la parte interessante:

  • 20

    # Questo l'evento che ci interessa realmente, ogni volta che il listener fa

    polling sul leap genera un frame che contiene tutte le info

    # su ci che il dispositivo riuscito a trackare

    def on_frame(self, controller):

    # Recupero il frame corrente

    frame = controller.frame()

    # Controllo che ci sia almeno una mano:

    if(not frame.hands.is_empty):

    print("%d Mano/i Rilevata/e" % (len(frame.hands)))

    # Recupero la prima mano, hands un vettore

    hand = frame.hands[0]

    # la direzione della mano intesa dal palmo verso le dita

    direction = hand.direction

    # la normale del palmo della mano, un vettore che

    # punta verso il basso

    normal = hand.palm_normal

    pitch = direction.pitch * Leap.RAD_TO_DEG

    roll = normal.roll * Leap.RAD_TO_DEG

    yaw = direction.yaw * Leap.RAD_TO_DEG

    if(pitch > 0):

    print("La mano punta verso l'alto di %f gradi" % (pitch))

    else:

    print("La mano punta verso il basso di %f gradi" % (pitch))

    if(roll < 0):

    print("La mano e' inclinata verso destra di %f gradi" % (roll))

    else:

    print("La mano e' inclinata verso sinistra di %f gradi" %

    (roll))

    if(yaw > 0):

    print("La mano e' ruotata verso destra di %f gradi" % (yaw))

    else:

    print("La mano e' ruotata verso sinistra di %f gradi" % (yaw))

    else:

    print("Metti la mano sopra il leap!")

    Come stato detto in precedenza, la callback on_frame viene richiamato dal software di tracking

    fornito col leap motion controller, ogni volta che il dispositivo trasferisce un frame al computer:

    per prima cosa utilizziamo il metodo frame della classe Controller per recuperare listanza del frame

    corrente.

    A questo punto con un semplice controllo sulla lista dimensione della lista di oggetti Hand nel frame

    corrente decidiamo se stampare la scritta Metti la mano sopra il leap!, o meno.

    Nel caso in cui la mano sia stata rilevata dal dispositivo, accediamo allattributo hands della classe

    frame, che sostanzialmente una lista di mani, e estraiamo il primo elemento, ovvero la prima mano

    rilevata.

    Ricaviamo direzione e normale del palmo, e ricaviamo attraverso dei semplici attributi gli angoli di

    inclinazione della mano (pitch, roll, yaw) che convertiamo da radianti a gradi, fatto ci

    stampiamo le stringhe pi appropriate.

    Ecco un esempio di output del programma:

  • 21

    Realizzato questo primo test, si cercato di utilizzare il leap motion controller allinterno di panda3D:

    stato realizzato in Blender un semplice modello tridimensionale di un aeroplano, che, una volta

    importato in panda3D, stato programmato per muoversi seguendo i dati rilevati a posizione e

    inclinazione della mano sul leap motion controller.

    Rispetto al test precedente, la differenza dovuta al fatto che questa volta non bastato limitarsi a

    stampare i valori di inclinazione della mano ottenuti a ogni frame, ma si dovuto mantenere in

    memoria i dati rilevati in un dato frame, fornendo i metodi necessari al recupero degli stessi

    allinterno di panda3D.

    Una delle difficolt riscontrate nellutilizzo del leap allinterno del loop di gioco stata quella di

    sincronizzare linput ricevuto dal dispositivo con la frequenza di aggiornamento del gioco stesso. Il

    problema dovuto al fatto che il leap, generalmente, genera frame a velocit diversa rispetto a

    quella necessaria al completamento del ciclo di aggiornamento del gioco: per tanto, se ad esempio,

    si cerca di accedere a un parametro impostato allinterno del leapListener in due punti del codice

    nella nostra procedura di aggiornamento di gioco, si rischia di ottenere valori diversi: perch pu

    accadere che nel tempo che abbiamo impiegato per arrivare alla seconda istruzione di accesso ai

    dati di movimento della mano, il leap abbia generato un nuovo frame, e il dato precedente stato

    sovrascritto.

    Si pu affrontare tale problema in due modi:

    - Sincronizzando il frame rate del gioco e del leap motion controller, cosa non banale, in

    quanto bisognerebbe richiedere al gioco un frame rate costante, cosa che penalizzerebbe

    calcolatori poco potenti che dovranno eseguire il gioco.

    - Organizzando il codice del gioco in modo da richiedere il valore estratto dal leap una sola

    volta per ciclo, e conservare quel valore fino a loop completato, eliminando cos qualsiasi

    problema di concorrenza alla fonte.

    stata adottata questa seconda strategia, analizziamo le parti fondamentali del codice in questo

    secondo test:

  • 22

    Innanzi tutto dovremo scrivere un listener personalizzato in grado di ottenere per ogni frame i gradi

    di rotazione della mano intorno ai tre assi, inoltre avremo bisogno della posizione normalizzata del

    palmo della mano rispetto allarea scansionata dal dispositivo lungo lasse Z, questo ci permetter

    di settare la velocit dellaereo in funzione della posizione della mano: pi la mano vicina al bordo

    superiore dellarea scansionata, pi la velocit sar alta, pi si avviciner al bordo inferiore, pi la

    velocit sar bassa.

    Il nostro listener estender ovviamente la classe Leap.Listener, concentriamoci su due dei metodi da

    implementare metodi:

    Il metodo on_init() , come abbiamo visto prima, il luogo in cui bisogna implementare tutta la logica

    di inizializzazione del nostro listener: poich dovremo poter accedere dal gioco ai dati sulla posizione

    della mano, dovremo dichiarare e inizializzare dei campi ad accesso pubblico che conterranno i dati

    rilevati a ogni frame.

    def on_init(self, controller):

    # Questo contiene il frame precedente, serve per rilevare le traslazioni

    # della mano

    self.prevFrame = None

    self.handPitch = None

    self.handRoll = None

    self.handYaw = None

    self.translationStatus = None

    self.reversed_normalized_palm_position = None

    print("Listener inizializzato...")

    Come possibile osservare, i dati ottenuti riguardano beccheggio (pitch), rollio (roll) e

    imbardata, (yaw) della mano.

    Concentriamoci ora sul metodo pi importante del listener, on_frame(): come nel test precedente

    dovremo accedere ai dati riguardanti la posizione rilevata della mano sopra il dispositivo e

    aggiornare le i campi impostati dal metodo di inizializzazione.

    I dati relativi alla rotazione della mano, vengono convertiti, anche in questo caso da radianti a gradi

    per moltiplicando il loro valore per la costante Leap.RAD_TO_DEG = (180/) con lunico scopo di

    semplificarne lutilizzo allinterno di panda3D.

    Degno di nota anche il metodo normalized_point() della classe InteractionBox (classe che

    rappresenta lattuale area scansionata dal dispositivo), tale metodo richiamato con argomento

    hand.palm_position restituisce la posizione normalizzata della mano nello spazio in un sistema di

    coordinate ([0,1],[0,1],[0,1]) dove 0 il punto allestremit inferiore dallarea nel range attuale del

    dispositivo e 1 il punto allestremit superiore per ognuno dei 3 punti cardinali dello spazio.

    Ecco di seguito il codice:

  • 23

    def on_frame(self, controller):

    # Recupero il frame corrente

    frame = controller.frame()

    # Controllo che ci sia almeno una mano:

    if(not frame.hands.is_empty):

    # Recupero la prima mano, hands e' un vettore

    hand = frame.hands[0]

    # la direzione della mano intesa dal palmo verso le dita

    direction = hand.direction

    # E' la normale del palmo della mano, un vettore che punta verso il

    # basso

    normal = hand.palm_normal

    # Rilevo l'attuale rotazione della mano

    self.handPitch = direction.pitch * Leap.RAD_TO_DEG

    self.handRoll = normal.roll * Leap.RAD_TO_DEG

    self.handYaw = direction.yaw * Leap.RAD_TO_DEG

    # Estraggo la posizione della mano sull'asse Z

    interactionBox = frame.interaction_box

    # Ottengo un vettore che rappresenta la posizione del palmo

    # normalizzata in relazione all'attuale

    # interaction_box

    normalized_palm_position =

    interactionBox.normalize_point(hand.palm_position)

    # Il leap usa un sistema di coordinate per cui l'avanti e' 0

    # e indietro e' 1, a me serve il contrario

    self.reversed_normalized_palm_position =

    1 - normalized_palm_position.z

    else:

    print("Metti la mano sopra il leap!")

    self.prevFrame = frame

    Costruito il nostro listener personalizzato, vediamo ora come utilizzare i dati ottenuti dal listener per

    far muovere laeroplano in panda3D. Innanzi tutto in fase di inizializzazione del gioco necessario

    istanziare il listener, facciamo ci nel costruttore della classe World, il cui scopo quello di creare il

    nostro mondo di gioco, chiamando la funzione controllerSetup cos implementata:

    def controllerSetup(self):

    # Istanzio il listener e il controller

    self.leapListener = MyLeapListener()

    self.leap = Leap.Controller()

    # Assegno il listener al controller

    self.leap.add_listener(self.leapListener)

    A questo punto accedendo alla variabile self.leapListener avremo accesso a tutti i campi pubblici

    riguardanti linclinazione e la posizione della mano nello spazio impostati nel punto precedente.

    Copia di questo oggetto viene quindi passata al costruttore della classe Player, il cui scopo quello

    di visualizzare e gestire il movimento del giocatore.

  • 24

    def move(self, task):

    # Get target values for pitch roll and yaw,

    targetPitch = self.inputListener.handPitch;

    targetRoll = self.inputListener.handRoll;

    targetYaw = self.inputListener.handYaw;

    # If values are set to None, simply terminate the task

    if(targetPitch is None or targetRoll is None or targetYaw is None):

    return task.cont

    # Yaw and Roll values are inverted in leap, so

    # we need to change their sign

    targetRoll *=-1

    targetYaw *=-1

    # Get dt to move smoothly

    dt = globalClock.getDt()

    # We want to rotate smoothly towards the target so we don't

    # simply set the player Hpr to the values

    # obtained from the inputListener, but we rotate a certain

    # number of degrees per second towards the target

    # Smoothly change heading

    if(self.playerRootNP.getH() < targetYaw):

    newH = self.playerRootNP.getH() - self.yawSpd * dt

    if(newH > targetYaw):

    newH = targetYaw

    if(self.playerRootNP.getH() > targetYaw):

    newH = self.playerRootNP.getH() - self.yawSpd * dt

    if(newH < targetYaw):

    newH = targetYaw

    else:

    newH = self.playerRootNP.getH()

    # Smoothly change pitch

    if(self.playerRootNP.getP() < targetPitch):

    newP = self.playerRootNP.getP() + self.pitchSpd * dt

    if(newP > targetPitch):

    newP = targetPitch

    if(self.playerRootNP.getP() > targetPitch):

    newP = self.playerRootNP.getP() - self.pitchSpd * dt

    if(newP < targetPitch):

    newP = targetPitch

    # Smoothly change roll

    if(self.playerRootNP.getR() < targetRoll):

    newR = self.playerRootNP.getR() + self.rollSpd * dt

    if(newR > targetRoll):

    newR = targetRoll

    if(self.playerRootNP.getR() > targetRoll):

    newR = self.playerRootNP.getR() - self.rollSpd * dt

    if(newR < targetRoll):

    newR = targetRoll

    # Rotate the plane

    self.playerRootNP.setHpr(newH,newP,newR)

    # Check Throttle

    self.checkThrottle()

    # This actually moves the plane

    self.playerRootNP.setPos(self.playerRootNP, 0,

    self.throttle * self.playerMaxSpd * dt,0)

    self.throttleLabel.setText("Throttle: %.1f" %(self.throttle * 100))

    return task.cont

    Come possibile osservare dal codice del Move Player Task creato nella classe Player, la gestione

    dellinput affrontata in maniera piuttosto semplice:

    Per prima cosa si accede allinputListener e si salvano in variabili locali i valori di inclinazione della

    mano rilevati dal dispositivo, in questo modo in caso il listener cambiasse tali valori perch il

    dispositivo ha generato un nuovo frame, avremmo comunque dei dati consistenti per il nostro ciclo

    di aggiornamento della posizione dellaeroplano.

  • 25

    A questo punto tramite semplici operazioni matematiche si convertono i dati ricevuti dal dispositivo

    in dati utilizzabili allinterno del gioco, per fare un esempio, possibile osservare come i gradi di

    rollio e imbardata dellaeroplano arrivino dal dispositivo con segno opposto a quello utilizzato

    allinterno di panda3D, in questo caso tali valori vengono semplicemente moltiplicati per -1 prima di

    essere utilizzati per il movimento del giocatore.

    In realt questi dati, una volta convertiti potrebbero essere utilizzati direttamente come parametri

    del metodo setHpr(H,P,R) della classe NodePath di panda3D per far corrispondere con un mapping

    diretto alla posizione della mano lesatta posizione dellaeroplano.

    Il problema di questo approccio che i movimenti dellaereo risulterebbero troppo repentini per

    essere realistici in caso di movimenti molto rapidi della mano dellutente; il codice scritto qua sopra

    cerca di ovviare al problema in maniera molto semplice: lattuale posizione della mano non la

    posizione attuale dellaereo, ma la posizione in cui laereo deve arrivare.

    Come possibile osservare, laereo ha delle velocit di rotazioni impostate per ogni asse: il valore

    ricevuto in input langolo a cui laereo deve arrivare (ad esempio targetRoll), se la rotazione attuale

    dellaereo inferiore o superiore rispetto allangolo obiettivo allora bisogna ruotare laereo verso

    tale angolo della sua velocit.

    In questo modo si ottiene un movimento molto pi fluido e naturale.

    6.c - INTRODURRE NUOVE GESTURE GRABBING

    Come stato detto nella parte di introduzione al Leap Motion Controller, al momento le API fornite

    dal produttore del dispositivo non forniscono strumenti semplici per lintroduzione di gestures

    personalizzate e le gestures rilevate di default dal dispositivo sono molto poche e limitate, in

  • 26

    particolare se si vogliono sviluppare giochi per la riabilitazione della mano, dove, a seconda della

    disabilit da riabilitare, necessario rilevare movimenti diversi.

    Si voluto perci esplorare la possibilit di rilevare movimenti non preimpostati, e il movimento

    scelto per questi test un movimento molto comune, quello di Grabbing o presa di un oggetto.

    Innanzi tutto bene spendere due parole sul perch rilevare questo movimento non un operazione

    cos banale con il leap motion controller, per fare ci ci avvaliamo di uno strumento molto comodo

    fornito con il software di gestione del dispositivo il visualizer:

    Si tratta di un software che si interfaccia col dispositivo e ci fornisce una rappresentazione

    tridimensionale di ci che il dispositivo sta rilevando nello spazio intorno a se in tempo reale.

    Come possibile osservare dallimmagine, nel caso della presa, il dispositivo non riesce a rilevare la

    presenza delle dita nel momento in cui esse si avvicinano troppo fra di loro: questo dovuto al fatto

    che il dispositivo osserva lambiente da un'unica posizione: dal basso, ci significa che nel momento

    in cui le dita cominciano a essere troppo vicine fra loro e sovrapposte, dal suo punto di osservazione,

    al palmo, esso non pi in grado di rilevarle e di conseguenza la lista fingers della classe hand del

    frame corrente indica 0 dita presenti.

    Il problema che a questo punto ci si pone come rilevare un evento come il grabbing, basato

    strettamente sulla distanza delle dita (che deve essere a ogni frame sempre minore) con un

    dispositivo in cui le dita superato un certo angolo spariscono?

    Ovviamente non si pu rilevare con certezza assoluta, ma si pu pensare alla seguente osservazione

    statistica:

    Se per un certo numero di frame, il dispositivo ha rilevato 5 dita, e magari per ognuno di essi, le

    punte delle dita si stavano avvicinando e improvvisamente a un certo frame, tutte le dita sono

    scomparse (e rimangono assenti anche nei frame successivi), allora c una buona probabilit (e si

    tratta di una probabilit, non di una certezza) che sia stata effettuata una gesture di grabbing.

    Scopo del test effettuato, era dunque scrivere una sotto-classe del Leap-Listener in grado di

    segnalare, utilizzando questa tecnica di monitoring delle dita rilevate frame per frame nel tempo,

    leventualit di una possibile gesture di presa, e il conseguente rilascio.

    Per prima cosa bisogna identificare un modo per poter segnalare allutente leffettivo rilevamento

    della gesture di grabbing, si potrebbe studiare un sistema ad eventi per cui a ogni gesture valida

    rilevata si potrebbe sollevare un evento che potremmo gestire allinterno della nostra applicazione.

  • 27

    Un alternativa meno complessa, vista la semplicit del nostro test, quella di utilizzare un campo

    pubblico del nostro listener (self.grab) di tipo booleano, che viene settata a true quando lutente ha

    effettuato una presa e a false quando non lha effettuata oppure lha rilasciata.

    Ci serviamo inoltre di una lista di interi che utilizzeremo per mantenere i dati relativi al numero di

    dita rilevate in un certo numero di frame trascorsi.

    Definiremo quindi un metodo catch_grab(hand) che verr chiamato allinterno del metodo

    on_frame per rilevare se sulla mano in argomento stata rilevata la gesture di grabbing, e in caso

    affermativo setter la variabile che abbiamo definito prima a true.

    Vediamo come si comporta il metodo catch_grab(hand):

    def catch_grab(self, hand):

    # If we have at least one element in our finger_story list

    if(not self.__finger_count_story is None):

    # Let's sort the finger list, we just need to get the maximum finger

    # number in the last 5 frames

    self.__finger_count_story.sort()

    max_finger =

    self.__finger_count_story[len(self.__finger_count_story) - 1]

    if(max_finger >= len(hand.fingers)):

    # If the maximum finger number from the last 5 frames is 5, and

    # now we got a 0, than this is a grab

    if(max_finger == 5 and len(hand.fingers) == 0):

    self.grab = True

    print("GRAB")

    # If grab is set to true, but we have five fingers in our

    # current frame, than we should release the grab

    if(self.grab == True and len(hand.fingers) == 5):

    self.grab = False

    print("GRAB RELEASED")

    # This if-else statement simply updates the list

    if(len(self.__finger_count_story) < 5):

    self.__finger_count_story.append(len(hand.fingers))

    else:

    self.__finger_count_story.pop(0)

    self.__finger_count_story.append(len(hand.fingers))

    # If we didn't have any element in our finger story list,

    # simply add one

    else:

    self.__finger_count_story = [len(hand.fingers)]

    In questo caso la nostra lista: __finger_count_story contiene fino a 5 element0,i ovvero il numero

    delle dita rilevate negli ultimi cinque frame, calcoliamo il numero massimo di dita rilevate in questi

    frame: questo viene fatto per eliminare alcune rilevazioni fasulle dovute a eventuali elementi di

    disturbo nellambiente scansionato dal leap, che possono per qualche frame far rilevare meno dita

    di quelle che sono realmente sul dispositivo, in questo modo consideriamo il numero massimo di

    dita rilevate in un dato frame con un valore attendibile del numero di dita che fino al frame scorso

    erano effettivamente sul dispositivo.

    A questo punto, come possibile osservare dal codice si tratta, semplicemente di confrontare il

    numero ottenuto prendendo il massimo dalla lista, con il numero di dita rilevate nel frame corrente

    e in particolare abbiamo che:

    SE avevamo 5 dita fino al frame scorso e il numero di dita rilevate in questo frame 0 allora lutente

    sta effettuando una presa.

    Inoltre:

  • 28

    SE avevamo gi rilevato un evento di grabbing, quindi self.grab settato a True e ora rileviamo di

    nuovo 5 dita sopra il dispositivo, allora la presa stata rilasciata.

    A questo punto se in un ipotetico gioco Panda3D, in cui vogliamo rilevare la presa di un oggetto,

    andiamo a controllare lo stato della variabile inputListener.grab, possiamo sapere se lutente sta

    cercando di prendere qualcosa o meno.

    Vediamo un esempio di esecuzione in un semplice gioco scritto in panda3D in cui utilizzando le

    tecniche di raycasting viste in precedenza rileviamo su una superficie la posizione della mano, se

    chiudiamo la mano scatenando levento di grabbing, allora una pallina sulla superficie comincer a

    seguire la nostra mano:

    6.d - IL LEAP MOTION CONTROLLER E LA RIABILITAZIONE

    Dai test effettuati, il Leap Motion Controller si dimostrato essere uno strumento particolarmente

    valido per la realizzazione di videogiochi per la riabilitazione della mano, in quanto permette un

    tracciamento preciso e molto rapido della posizione di ogni singolo dito, del palmo, della velocit di

    movimento e ci permette di sviluppare, con questi dati, moduli per il rilevamento di diverse

    gestures adeguate per i singoli esercizi richiesti dai terapisti.

    Nel caso specifico della riabilitazione della mano dei bambini, con cui abbiamo avuto a che fare in

    questo periodo di lavoro, per, stato deciso di non adottare il dispositivo, almeno nella fase iniziale,

    per i seguenti problemi riscontrati:

  • 29

    - Le dita impiantate sulla mano dei giovani pazienti, sono spesso troppo piccole per essere

    rilevate con precisione dal dispositivo: spesso, il software di visualizzazione del leap motion

    controller con cui abbiamo effettuato alcuni test, mostra unicamente il palmo della mano,

    ci rende praticamente impossibile realizzare qualsiasi tipo di esercizio che coinvolga le dita

    della mano.

    - Il Leap Motion Controller certamente uno strumento di facile utilizzo, molto immediato: si

    mette la mano sopra il dispositivo e succede qualcosa sullo schermo; per richiesta una

    certa coordinazione mano-occhio che non da dare per scontata per utenti con meno di 5

    anni: necessario infatti operare con la mano sopra al dispositivo, mentre allo stesso tempo

    si osserva uno schermo che non si trova sotto al dispositivo, questo obbliga lutente a

    operare sul leap senza guardarlo, il che porta spesso i bambini a spostarsi al di fuori del

    raggio dazione del dispositivo rendendo non fluido linput del programma e difficile, e poco

    preciso il rilevamento dei dati sul movimento effettuato.

    - Questo fa s che un sistema basato su leap non sia cos facile da istallare e utilizzare in pratica.

    Inoltre:

    - Un problema di attrezzature: il Leap Motion Controller non funziona da solo, ha bisogno

    almeno di un PC con sufficiente capacit hardware da gestire sia il software del Leap, che il

    videogioco riabilitativo che lo utilizza. Inoltre, essendo lo strumento da realizzare studiato

    per la riabilitazione a casa, necessaria una fase di configurazione e installazione dei

    software relativi al Leap e al gioco, operazione che non sicuramente alla portata di

    chiunque e che richiederebbe del personale dedicato, in grado di fornire il minimo di

    assistenza necessaria a chi deve configurare lambiente.

    - Un problema di costi: a differenza di molti altri dispositivi, come smartphone o tablet,

    difficilmente un paziente possieder a casa un Leap Motion Controller, esso dovrebbe quindi

    o essere fornito dalla struttura sanitaria o acquistato direttamente dal paziente, generando

    un problema di costi, che si voluto evitare, quanto meno nella prima fase di

    sperimentazione.

    Il Leap Motion Controller rimane comunque uno strumento assolutamente valido per la

    riabilitazione della mano in pazienti pi grandi, o per la riabilitazione cognitiva: ad oggi, infatti, il

    dispositivo stato gi parzialmente integrato allinterno del Game Engine IGER, per quanto riguarda

    il posizionamento del palmo e il tracciamento della posizione di un singolo dito o di un tool e andr

    ad aggiungersi alla lista dei dispositivi supportati dalla piattaforma REWIRE.

  • 30

    7 - REALIZZAZIONE DEL GIOCO: HOT AIR BALLOON Per quanto riguarda il progetto descritto nelle prossime pagine si preferito utilizzare dei comuni

    tablet, molto pi diffusi del Leap Motion Controller, per una serie di motivazioni:

    - Abbiamo innanzi tutto potuto notare come i giovani pazienti abbiano gi sviluppato un

    altissima dimestichezza nellutilizzo di questi dispositivi con applicazioni commerciali,

    questo semplifica di molto la fase di apprendimento nellutilizzo dellapplicazione che verr

    realizzata.

    - Spesso i pazienti, o le loro famiglie, sono gi in possesso di uno di questi dispositivi, vista la

    loro diffusione, ci permette di abbattere i costi.

    - Inoltre i dispositivi multi-touch permettono di rilevare pi dita contemporaneamente sullo

    schermo, il rilevamento molto preciso, e difficilmente le dita scompariranno senza che

    lutente le sollevi realmente dal dispositivo.

    Si cercato, come vedremo nel prossimo capitolo, di sviluppare unapplicazione che fosse

    compatibile con il maggior numero di dispositivi, pertanto, lintero gioco stato sviluppato come

    applicazione web in HTML5 e Javascript.

    7.a - SCELTA DELLARCHITETTURA WEB-BASED

    Le motivazioni di questa scelta sono molteplici:

    Innanzitutto, volendo realizzare unapplicazione per la riabilitazione a casa a bassissimo costo, lidea

    stata quella di dare la possibilit ai pazienti di sfruttare qualsiasi dispositivo di cui fossero gi in

    possesso a casa, per utilizzare lapplicazione sviluppata, gli unici requisiti sarebbero stati una

    connessione ad internet, un browser web e uno schermo touchscreen, di cui sono dotati ad oggi

    tutti i pi comuni smartphone e tablet.

    Inoltre prototipare un videogioco utilizzando le canvas di HTML 5 e javascript, molto pi rapido

    che sviluppare lo stesso nativamente per ciascun dispositivo da supportare, questo ha permesso di

    presentare ai terapisti in un tempo relativamente breve, un prototipo di gioco da testare sui pazienti.

    Larchitettura web-based presenta inoltre una serie di vantaggi anche per quanto riguarda lo

    sviluppo dellinterfaccia di configurazione e analisi dei dati da fare utilizzare ai terapisti.

    Anche in questo caso non necessario installare nulla in ospedale per permettere ai terapisti di

    accedere ai dati dei singoli pazienti, ma sufficiente sfruttare un qualsiasi terminale con accesso a

    internet per accedervi. Tutti i dati dei pazienti vengono mantenuti anonimamente sul server e sono

    sempre a disposizione dei terapisti

    I vantaggi delladottare questa architettura sono quindi: completa indipendenza dal client, velocit

    di sviluppo, gestione centralizzata dei dati dei pazienti, la possibilit di creare interfacce web per la

    configurazione e analisi dei dati relativi ai pazienti in maniera molto rapida ed efficace.

    Tale approccio presenta per alcuni svantaggi:

    Innanzi tutto un gioco sviluppato per un browser web non pu essere utilizzato in assenza di

    connessione a internet o con connessioni molto lente, ci pu non essere adatto per pazienti che

    abitano in luoghi con accesso difficoltoso alla rete.

  • 31

    Le capacit delle librerie grafiche per web per quanto molto avanzate, sono ancora lontane

    dallessere equiparabili a quelle disponibili per i singoli dispositivi, per tanto sar difficile realizzare

    videogiochi particolarmente complessi per browser web.

    Ad oggi esistono una serie di difficolt per quanto riguarda la riproduzione audio in videogiochi

    basati sul web che vengono utilizzati su dispositivi mobili.

    Inoltre lintera piattaforma sviluppata: gioco + pannello di configurazione + pannello di analisi ha

    bisogno di funzionare su un webserver centralizzato, questo deve essere installato, gestito e

    mantenuto direttamente dalla clinica che lo utilizza, tale gestione richiede personale competente e

    quindi un potenziale costo per la struttura.

    Detto ci, si comunque ritenuto opportuno utilizzare, almeno in questa fase preliminare questa

    architettura, per rendere disponibile ai clinici e ai pazienti nel pi breve lasso di tempo possibile un

    prototipo di piattaforma da testare e valutare per sviluppi futuri.

    7.b - IL PROGETTO DA REALIZZARE

    A seguito di una serie di incontri preliminari svolti con i chirurghi che si occupano di operare i

    pazienti, con i fisioterapisti che si occupano della riabilitazione, con una piccola paziente di 4 anni e

    i suoi genitori, stato deciso come procedere nella realizzazione del prototipo del primo videogioco.

    La paziente, molto giovane, affetta da agenesia delle dita di una mano, aveva subito qualche mese

    prima un operazione di transfer delle falangi di due delle dita dei piedi sulla mano.

    Abbiamo potuto assistere a una sessione di riabilitazione:

    Essa si divide sostanzialmente in due parti, una prima parte consiste in una serie di esercizi fisici in

    cui al paziente, attraverso il gioco, vengono fatti maneggiare oggetti di diversa consistenza e

    dimensione per realizzare costruzioni, tale processo serve a stimolare il processo di corticalizzazione

    del nuovo arto.

    La seconda parte, cognitiva, serve a fare prendere al paziente consapevolezza della sua nuova mano,

    e del fatto che essa pu essere usata in maniera funzionale per diversi scopi.

    Come gi accennato in precedenza, ci stato mostrato come i terapisti abbiano gi provato ad

    utilizzare applicazioni commerciali per tablet allinterno della sessione di riabilitazione.

    stato interessante osservare come la piccola paziente utilizzasse queste applicazioni: si trattava in

    genere di giochi senza uno scopo preciso, a cui ad una qualsiasi azione corrispondeva una reazione:

    applicazioni di disegno, o semplici giochi in cui toccando elementi della scena mostrata succedeva

    qualcosa.

    Tali applicazioni, come spiegato in precedenza, avevano il difetto di non richiedere un movimento in

    particolare, per cui non potevano essere utilizzate per svolgere e valutare un esercizio in particolare,

    ma solo per far esercitare e muovere la mano in libert alla paziente.

    A seguito delle osservazioni svolte durante la sessione di riabilitazione, abbiamo avuto un colloquio

    con i terapisti, con i quali abbiamo identificato un movimento da tracciare con il primo gioco da

    realizzare.

    Il movimento in questione quello di avvicinamento e allontanamento delle dita della mano a

    pizzico (in inglese pinching): questo ad esempio il movimento, molto spesso richiesto, da

  • 32

    applicazioni per la gestione di fotografie, per la scalatura delle immagini: allontanando le dita si

    zoomma ovvero si ingrandisce limmagine, avvicinandole si restringe.

    Abbiamo quindi pensato di realizzare un semplice gioco, la cui protagonista una mongolfiera che

    sale quando le dita di avvicinano, e scende quando si allontanano: scopo del gioco fare decollare

    la mongolfiera, farla volare in un cielo pieno di uccellini da evitare e monetine da prendere, e quindi

    farla atterrare dolcemente a destinazione.

    Insieme al gioco stata sviluppata un interfaccia per la configurazione dei parametri relativi al

    singolo paziente, e per lanalisi delle singole sessioni di gioco e della storia delle sessioni effettuate

    Nei capitoli che seguiranno verranno descritte tutte le fasi di sviluppo e le problematiche affrontate

    nello sviluppo di questo videogioco, e dellintera piattaforma per i terapisti.

    7.c - HTML 5 TAG CANVAS E REALIZZAZIONE DEL LOOP DI GIOCO IN JAVASCRIPT

    Elemento fondamentale per la realizzazione di videogiochi basati sul web ed eseguibili su un

    qualsiasi browser web, lelemento Canvas.

    Si tratta di un estensione dellHTML, che permette, tramite un linguaggio di scripting, nel nostro caso

    Javascript, il rendering dinamico di immagini bitmap.

    Il tag html canvas definisce un area di altezza e larghezza definiti su cui possibile, tramite API

    javascript dedicate disegnare dinamicamente, cos come viene fatto utilizzando in altri ambiti API

    per la grafica bidimensionale.

    Di per s il tag canvas delimita unicamente un contenitore di grafica bidimensionale, e le API ad esso

    associate sono unicamente API grafiche, il contenitore non predisposto di per se ad ospitare un

    videogioco.

    Come possibile, allora, realizzare animazioni sfruttando questo elemento?

    Il concetto di per s abbastanza semplice:

    Si scrive allinterno di una funzione, che dora in poi chiameremo DRAW, che verr richiamata

    costantemente ogni tot millisecondi tramite la funzione javascript setInterval(function, time)

    Questa funzione draw, non far altro che cancellare come prima cosa, lintero contenuto del canvas,

    e ridisegnarlo subito dopo con opportune modifiche.

    In questo modo genereremo una serie di frame, il cui framerate sar regolato dal parametro time

    che passeremo alla funzione setInterval.

    Trattandosi i giochi sostanzialmente di animazioni interattive, il pa