61
UNIVERSITÀ DEGLI STUDI DI TRIESTE FACOLTÀ DI INGEGNERIA Dipartimento di Elettrotecnica, Elettronica ed Informatica ________________ Tesi di Laurea in PROGRAMMAZIONE DEI CALCOLATORI Navigazione di un robot mobile e autolocalizzazione con riferimenti visivi Laureando: De Franceschi Daniel Relatore: Prof. Massimiliano Nolich Anno Accademico 2008-2009 1

Tesi De Franceschi Daniel

Embed Size (px)

DESCRIPTION

Navigazione di un robot mobile e autolocalizzazione con riferimenti visivi

Citation preview

Page 1: Tesi De Franceschi Daniel

UNIVERSITÀ DEGLI STUDI DI TRIESTEFACOLTÀ DI INGEGNERIA

Dipartimento di Elettrotecnica, Elettronica ed Informatica________________

Tesi di Laurea inPROGRAMMAZIONE DEI CALCOLATORI

Navigazione di un robot mobile e autolocalizzazione con riferimenti visivi

Laureando:De Franceschi Daniel

Relatore:Prof. Massimiliano Nolich

Anno Accademico 2008-2009

1

Page 2: Tesi De Franceschi Daniel

2

Page 3: Tesi De Franceschi Daniel

Alla mia famiglia...

3

Page 4: Tesi De Franceschi Daniel

4

Page 5: Tesi De Franceschi Daniel

Indice generale1. Introduzione......................................................................................................................................62. La robotica........................................................................................................................................73. Basi del progetto.............................................................................................................................11

3.1. Player­Stage.............................................................................................................................113.2. Tesi precedente........................................................................................................................12

3.2.1. Dynamic Time Warping..................................................................................................123.2.2. Dynamic Planar Warping................................................................................................15

3.3. OpenCV..................................................................................................................................174. Il sistema sviluppato.......................................................................................................................19

4.1. Navigazione.............................................................................................................................194.1.1. Calcolo del percorso minimo data una mappa dell'ambiente...........................................19

4.1.1.1. Caricamento della mappa..........................................................................................194.1.1.2. Estrazione dei vertici................................................................................................204.1.1.3. Proiezione dei vertici................................................................................................224.1.1.4. Decomposizione delle linee in segmenti..................................................................234.1.1.5. Generazione dei poligoni.........................................................................................244.1.1.6. Costruzione del grafo...............................................................................................254.1.1.7. Calcolo del percorso minimo tra due punti tramite l'algoritmo di Dijkstra..............25

4.1.2. Navigazione del robot......................................................................................................264.2. Localizzazione mediante riferimenti visivi.............................................................................27

4.2.1. Analisi geometrica del problema del posizionamento.....................................................314.2.2. Detect dei landmark........................................................................................................35

4.2.2.1. Acquisizione dell'immagine.....................................................................................354.2.2.2. Ricerca dei landmark e verifica dei ritrovamenti....................................................364.2.2.3. Salvataggio dei landmark........................................................................................38

4.2.3. Caricamento strutture dati della libreria nativa...............................................................394.2.4. Richiamo degli algoritmi di calcolo................................................................................414.2.5. Prima verifica “algoritmica” dei risultati........................................................................41

4.3. Integrazione Robot mobile e autolocalizzazione....................................................................424.3.1. Interfaccia del software....................................................................................................42

5. Risultati sperimentali......................................................................................................................456. Conclusioni.....................................................................................................................................547. Appendice: How To........................................................................................................................56

7.1. Installazione di Player­Stage su Ubuntu/Linux 9.10................................................................567.2. Installazione librerie OpenCV su Ubuntu/Linux 9.10.............................................................567.3. Utilizzo delle JNI in Ubuntu 9.10............................................................................................577.4. Osservazione sul detect dei landmark.....................................................................................59

8. Bibliografia.....................................................................................................................................60

5

Page 6: Tesi De Franceschi Daniel

1. IntroduzioneL'utilizzo di robot mobili negli ambienti interni è diventato oggigiorno di uso corrente. Essi non vengono solo adibiti al trasporto ma anche a funzionalità più “semplici” come la pulizia degli ambienti. È nata pertanto l'esigenza di fornire ai robot la capacità di autolocalizzarsi negli spazi di lavoro con tecniche relativamente semplici e poco costose. Uno dei metodi utilizzati è l'odometria che stima la posizione del veicolo su ruote a partire dal numero di giri percorsi dalle ruote. È noto che gli odometri sono affetti ad errori che diventano via via sempre più grandi man mano che il robot si muove nell'ambiente. Pertanto la posizione reale e quella stimata tendono nel tempo a discostarsi sempre di più. Risulta necessario affiancare a questo strumento altri metodi per permettere di resettare l'errore odometrico.

In questa tesi è stato sviluppato un algoritmo di navigazione in ambiente interno per un robot mobile che utilizza un algoritmo di localizzazione tramite riferimenti visivi per resettare periodicamente l'errore odometrico. La base del progetto è una tesi precedente [1] in cui è stato realizzato un algoritmo in grado, mediante il calcolo della deformazione di landmark visuali posti nell'ambiente, di determinare la distanza tra il punto di visione e i landmark. Si è pensato di sfruttare l'algoritmo per la localizzazione durante la navigazione. É stata sistemata una webcam a basso costo sul robot e sono stati posizionati dei riferimenti visivi sul soffitto: questo ha consentito di sviluppare un algoritmo per stimare la posizione del robot e quindi consentire allo stesso di autolocalizzarsi. É stato necessario studiare la geometria del problema (robot – riferimenti visivi). Per implementare il metodo proposto bisogna posizionare dei landmark (semplici fogli stampati) sul soffitto e utilizzare una webcam a basso costo per le acquisizioni delle immagini. È inoltre richiesto un personal computer le cui risorse di calcolo possono essere anche limitate. Nel progetto sono stati utilizzati Player [2], OpenCV [3][4] e Java [5].

La tesi si articola secondo la seguente struttura. • Il secondo capitolo tratta in modo generico di alcuni aspetti legati ai robot e ai robot mobili e

alla loro evoluzione nel tempo. • Il terzo capitolo descrive le basi del progetto cioè i punti di partenza dalla quale si è

sviluppato tutto il resto. • Il quarto capitolo evidenzia cosa è stato sviluppato (navigazione e autolocalizzazione) e

mette in luce eventuali problematiche che è stato necessario risolvere lungo il percorso di sviluppo.

• Il quinto capitolo espone i test che sono stati effettuati e i risultati sperimentali conseguiti. • Le conclusioni sono presentate nel sesto capitolo e mettono in luce quali siano i limiti del

metodo ed eventuali possibili soluzioni. • L'appendice affronta alcune problematiche che riguardano la configurazione dell'ambiente di

sviluppo e l'installazione del sistema sviluppato.

6

Page 7: Tesi De Franceschi Daniel

2. La roboticaDa secoli l'uomo sogna di costruite dispositivi che siano in grado di imitare il comportamento degli esseri viventi. Il termine “robot” ha origine dal termine ceco “lavoro forzato” o “servo”. Il termine è stato introdotto dallo scrittore Karel Čapek nel suo dramma teatrale “I robot universali di Rossum” del 1921 dove diede vita a qualcosa di molto simile al mostro di Frankenstein cioè una creatura generata grazie a una combinazione tra chimica e biologia piuttosto che con metodi meccanici.

«Il vecchio Rossum, grande filosofo, [...] cercò di imitare con una sintesi chimica la sostanza viva detta protoplasma finché un bel giorno scoprì una sostanza il cui comportamento era del tutto uguale a quello della sostanza viva sebbene presentasse una differente composizione chimica, era l'anno 1932 [...]. Per esempio, poteva ottenere una medusa con il cervello di Socrate oppure un lombrico lungo cinquanta metri. Ma poiché non aveva nemmeno un pochino di spirito, si ficcò in testa che avrebbe fabbricato un normale vertebrato addirittura l'uomo. [...] Doveva essere un uomo, visse tre giorni completi. Il vecchio Rossum non aveva un briciolo di gusto. Quel che fece era terribile. Ma dentro aveva tutto quello che ha un uomo. Davvero, un lavoro proprio da certosino. E allora venne l'ingegner Rossum, il nipote del vecchio. Una testa geniale. Appena vide quel che stava facendo il vecchio, disse: È assurdo fabbricare un uomo in dieci anni. Se non lo fabbricherai più rapidamente della natura, ce ne possiamo benissimo infischiare di tutta questa roba. [...] Gli bastò dare un'occhiata all'anatomia per capire subito che si trattava d'una cosa troppo complicata e che un buon ingegnere l'avrebbe realizzata in modo più semplice. [...] Quale operaio è migliore dal punto di vista pratico? È quello che costa meno. Quello che ha meno bisogni. Il giovane Rossum inventò l'operaio con il minor numero di bisogni. Dovette semplificarlo. Eliminò tutto quello che non serviva direttamente al lavoro. Insomma, eliminò l'uomo e fabbricò il Robot.» [6]

Oggi le credenze popolari riguardo ai robot meccanici non sono molto differenti da quelle creazioni biologiche romanzesche. Non c'è limite alle possibili definizioni (data la profondità del suo significato) del termine “Robot”:

«Un manipolatore riprogrammabile e multifunzionale progettato per spostare materiali, componenti, attrezzi o dispositivi specializzati attraverso vari movimenti programmati per la realizzazione di vari compiti» [7]

«Macchina automatica capace di svolgere con opportuni comandi, alcune funzioni o attività proprie dell'uomo; automa meccanico» [8]

«Dispositivo meccanico che riproduce i movimenti e, generalmente l'aspetto esterno dell'uomo e degli animali. In cibernetica apparecchio automatico programmabile, destinato a sostituire autonomamente l'uomo in alcune attività manuali, specialmente quelle faticose, pericolose o costose, di alcuni settori dell'industria e della ricerca scientifica» [9]

Appare evidente come queste definizioni siano abbastanza distanti e relegate ad ambiti specifici.

7

Page 8: Tesi De Franceschi Daniel

Non voglio mettere in dubbio pareri sicuramente più autorevoli dei miei ma vorrei aprire una piccola discussione a tal proposito. La concezione sul cos'è un robot è mutata nel tempo: inizialmente concepito come essere “biologico” per poi essere relegato all'ambito puramente meccanico. E se questa nuova definizione fosse troppo restrittiva? Al giorno d'oggi virus e batteri vengono modificati e quindi riprogrammati per svolgere compiti specifici: mi chiedo se questi non possano essere considerati loro stessi dei robot. Di conseguenza, non tutti gli esseri biologici sono a loro volta considerabili robot?

Nella normale concezione di “dispositivo meccanico” la differenza tra una comune macchina e un robot potrebbe apparire piuttosto sfumata: entrambi devono essere alimentati, necessitano di attuatori e di meccanismi per poter interagire con l'ambiente e di una interfaccia utente per l'interazione con l'operatore [10]. Cos'è quindi che li distingue? L'avvento della microelettronica è stato il passo fondamentale per il cambio del paradigma per la progettazione di macchine: nasce la meccatronica cioè il paradigma moderno per la progettazione delle macchine. Ciò che cambia è l'introduzione di sensori e meccanismi di controllo all'interno dei dispositivi, che siano lavatrici, forni a microonde, fotocamere o robot industriali. La meccatronica applicata alla progettazione dei robot introduce assieme al controllo anche una più o meno sviluppata forma di intelligenza.

La nascita e lo sviluppo della robotica si deve principalmente al bisogno di macchine utili nell'industria. Da questo bisogno è nata la robotica industriale e l'automazione industriale. In questo caso l'ambiente è altamente strutturato e al posto degli operatori umani vengono utilizzati degli operatori esperti (cioè formati all'uso) che normalmente sono in grado di eseguire procedure ben definite e ripetitive. La presenza umana in questi ambienti di lavoro è ben delimitata. Successivamente la robotica industriale venne esportata nella cosiddetta robotica di servizio che differisce dalla robotica industriale per una maggior condivisione dello spazio di lavoro tra uomo e robot, per le maggiori capacità percettive e per comportamenti più reattivi. La robotica di servizio si è sviluppata su vari rami che vanno dalle applicazioni spaziali, alla robotica biomedica, alla robotica da guerra ma anche per applicazioni domestiche o di intrattenimento.

Un robot autonomo è una macchina capace di accettare ed eseguire comandi o missioni in ambienti non completamente strutturati senza l'intervento dell'uomo. La problematica è di pianificare i comportamenti del robot in un ambiente non noto a priori o variabile nel tempo in funzione della richiesta di esecuzione di un determinato compito.

I campi fondamentali per la progettazione e la realizzazione dei robot sono sopratutto l'ingegneria e l'informatica e di conseguenza anche la matematica. Molto spesso, però, si richiede a questi dispositivi di compiere delle operazioni o raggiungere determinati obbiettivi in modo più o meno autonomo e pertanto risulta di fondamentale importanza anche il campo dell'intelligenza artificiale che si può definire come l'abilità di un computer di svolgere funzioni e ragionamenti tipici della mente umana. L'espressione “intelligenza artificiale” fu coniata nel 1956 dal matematico americano John McCarthy. Lo scopo di questa disciplina sarebbe stato quello di “far fare alle macchine delle cose che richiederebbero l'intelligenza se fossero fatte dagli uomini” [11]. Si può pertanto affermare che la robotica cognitiva è diventata sempre di più interdisciplinare e oggigiorno necessita anche di discipline umanistiche (per esempio biologia, linguistica...) per raggiungere obbiettivi in campi molto diversi fra loro. Al giorno d'oggi infatti la robotica viene utilizzata negli ambiti più disparati. Giusto per citarne qualcuno:

• Biorobotica: studio dei sistemi biologici dal punto di vista “biomeccatronico” per lo sviluppo di dispositivi per applicazioni biomediche o sviluppo di metodologie e tecnologie innovative per la progettazione e realizzazione di macchine e sistemi bioispirati e biomimetici (ad esempio umanoidi ed animaloidi).

8

Page 9: Tesi De Franceschi Daniel

• Domotica: scienza che si occupa dello studio delle tecnologie atte a migliorare la qualità della vita nella casa e negli ambienti antropizzati.

• Robotica industriale: tipologia di robot utilizzata nella produzione industriale.• Robotica spaziale• Robotica evoluzionistica• Competizioni robotiche• …

Per un robot “mobile” [12][13] quello che fa la differenza è ovviamente l'ambiente operativo: il robot dovrebbe essere in grado di operare autonomamente in ambienti non strutturati e/o dinamici e parzialmente osservabili (lo spazio di lavoro può essere più ampio di quello immediatamente osservabile). Molto spesso possono essere inaccessibili all'uomo perché per esempio pericolosi o impossibili da raggiungere. I robot mobili si suddividono in varie categorie: i robot terrestri, robot sottomarini e i robot aerei. I robot terrestri possono usufruire di varie tipologie di strumenti di locomozione, non solamente ruote ma anche zampe oppure l'unione ruote/zampe. I robot sottomarini possono spostarsi mediante eliche o getti d'acqua mentre i robot aerei tramite ali - fisse o rotanti - oppure possono assumere strutture tipo dirigibili o palloni.

Un robot in generale è costituito da una struttura meccanica, da attuatori, sensori e sistemi di controllo. Gli attuatori si possono dividere in tre diverse tipologie: attuatori elettrici, idraulici e pneumatici. A seconda dell'uso che se ne deve fare si prediligerà una tipologia rispetto all'altra tenendo in considerazione pregi e difetti delle varie categorie. Per poter “percepire” l'ambiente il robot deve possedere dei sensori cioè dei dispositivi capaci di percepire e misurare proprietà fisiche dell'ambiente quali pressione, temperatura, distanze, luminosità... Un grande problema è l'incertezza delle informazioni che il robot “riceve” dai sensori non solo dovuta all'imperfezione dei sensori stessi ma anche dalle condizioni ambientali che possono essere anche molto variabili. I sensori si suddividono in due grandi categorie: sensori propriocettivi ed eterocettivi. I sensori

9

Illustrazione 1: Spirit, Mars Exploration Rover A

Page 10: Tesi De Franceschi Daniel

propriocettivi sono in grado di misurare grandezze proprie del robot come la posizione, la velocità dei giunti o delle ruote. I sensori eterocettivi sono in grado di misurare grandezze dell'ambiente dove il robot opera e si scompongo in quattro categorie: sensori di forza/coppia e tattili, sensori di prossimità o distanza, sistemi di visione e sensori speciali per applicazioni specifiche. Il sistema di controllo è il cervello del sistema, esso decide quali azioni deve compiere in base alle informazioni che riceve dai sensori e agli algoritmi di controllo che implementa.

Il robot disponibile nel laboratorio SMARTLAB è costituito da una piattaforma robotica circolare dotata di due motori in corrente continua con odometri, ha tre sensori ad ultrasuoni ed è comandato da un processore ARM. Come si vede nell'illustrazione 2 in cima al robot è posizionata la webcam utilizzata per la localizzazione del robot tramite i riferimenti visivi.

10

Illustrazione 2: Robot su cui sono stati effettuati i test di autolocalizzazione

Page 11: Tesi De Franceschi Daniel

3. Basi del progettoÉ possibile scomporre il progetto in due parti fondamentali: quella di navigazione e quella di autolocalizzazione. La parte di navigazione utilizza software open source del calibro di “Player” e “Stage” studiati per il corso di “Sistemi operativi per la robotica”. Tutto il lavoro è stato svolto in ambiente GNU/Linux (Ubuntu 9.10 Karmic Koala).

“Ubuntu è un sistema operativo libero e gratuito basato su GNU/Linux, che unisce stabilità, sicurezza e facilità di utilizzo. È perfetto per computer portatili, desktop e server e fornisce applicazioni adatte ad ogni esigenza, per l'uso in casa, a scuola o a lavoro.

Ubuntu prende il nome da un'antica parola africana che significa umanità agli altri, oppure io sono ciò che sono per merito di ciò che siamo tutti. La distribuzione Ubuntu migra lo spirito di Ubuntu nel mondo del software.” [14]

Per la parte di autolocalizzazione viene fatto un uso piuttosto massiccio delle librerie OpenCV [3] che sono librerie orientate alla “computer vision”. I linguaggi di programmazione utilizzati sono stati C++ e Java.

Per la stesura della tesi è stato utilizzato OpenOffice. Come riportato dalla home italiana del progetto:

“OpenOffice.org è una suite per ufficio completa, rilasciata con una licenza libera e Open Source che ne consente la distribuzione gratuita. Legge e scrive file nei formati utilizzati dai prodotti più diffusi sul mercato e, a garanzia della futura accessibilità dei dati, nel formato OpenDocument, standard ISO. Consente inoltre l'esportazione in formato PDF.OpenOffice.org è liberamente, gratuitamente e legalmente utilizzabile in ogni contesto, pubblico, privato, professionale e aziendale.” [15]

3.1. Player-Stage

Lo scopo dei due software è riassumibile come estratto dalla home page del progetto [2]:

The Player Project creates Free Software that enables research in robot and sensor systems. The Player robot server is probably the most widely used robot control interface in the world. Its simulation backends, Stage and Gazebo, are also very widely used.Released under the GNU General Public License, all code from the Player/Stage project is free to use, distribute and modify. Player is developed by an international team of robotics researchers and used at labs around the world.Software:

• Player robot device interfacePlayer provides a network interface to a variety of robot and sensor hardware. Player's client/server model allows robot control programs to be written in any programming language and to run on any computer with a network connection to the robot. Player supports multiple concurrent client connections to devices,

11

Page 12: Tesi De Franceschi Daniel

creating new possibilities for distributed and collaborative sensing and control. Player supports a wide variety of mobile robots and accessories. Look here for a list of currently supported components.

• Stage multiple robot simulatorStage simulates a population of mobile robots moving in and sensing a two-dimensional bitmapped environment. Various sensor models are provided, including sonar, scanning laser rangefinder, pan-tilt-zoom camera with color blob detection and odometry. Stage devices present a standard Player interface so few or no changes are required to move between simulation and hardware. Many controllers designed in Stage have been demonstrated to work on real robots.

• Gazebo 3D multiple robot simulatorGazebo is a multi-robot simulator for outdoor environments. Like Stage, it is capable of simulating a population of robots, sensors and objects, but does so in a three-dimensional world. It generates both realistic sensor feedback and physically plausible interactions between objects (it includes an accurate simulation of rigid-body physics). Gazebo presents a standard Player interface in addition to its own native interface. Controllers written for the Stage simulator can generally be used with Gazebo without modification (and vise-versa).

Player Project software runs on Linux, Solaris, *BSD and Mac OSX (Darwin).

3.2. Tesi precedente

La parte di localizzazione è basata sul lavoro di un altro tesista – Luca Camilotti – che nella sua tesi si è occupato degli algoritmi visuali per la localizzazione dei robot mobili [1] tramite la costruzione dell'algoritmo Dynamic Planar Warping. Lo scopo che ci si prefigge è il calcolo della posizione del robot tramite la determinazione della distanza dai landmark posti sul soffitto. La distanza dai landmark viene ricavata appunto mediante l'algoritmo Dynamic Planar Warping (DPW) che fa uso a sua volta dell'algoritmo Dynamic Time Warping (DTW).

3.2.1. Dynamic Time Warping

Il Dynamic Time Warping (DTW) è un metodo ben collaudato ed è utilizzato comunemente nel campo del riconoscimento dei suoni o “speech recognition”. Esso consiste nella ricerca della corrispondenza ottima tra i campioni di due sequenze monodimensionali che rappresentano solitamente l'andamento temporale di due segnali. La ricerca è implementata con un algoritmo di programmazione dinamica, che è in grado di semplificare la complessità del problema ad un ordine polinomiale.

Si considerino due sequenze di campioni. Tanto per fissare le idee, esse potrebbero essere ad esempio le risposte impulsive di due sistemi. Si supponga di sapere a priori che i due segnali sono legati da una certa relazione, ad esempio hanno lo stesso andamento nel tempo ma uno è più “dilatato” rispetto all'altro, oppure uno presenta un rumore che ne altera la forma, etc. Si vuole trovare una corrispondenza tra le due sequenze, ovvero si vuole mappare un segnale nell'altro. Il DTW si presta perfettamente a questo compito, perché trova la corrispondenza migliore possibile 

12

Page 13: Tesi De Franceschi Daniel

sotto certi vincoli imposti al problema.

Date quindi due sequenze di campioni 

X = x1, x2,... , xn  e   Y = y1, y2,... , ym , 

e definita una funzione di costo  cost x j , y i= f x j , y i che esprima quantitativamente la distanza tra una coppia di campioni, la corrispondenza ottima può essere determinata con la programmazione dinamica poiché vale la relazione ricorsiva

                      D i , j =cost x j , y imin { Di−1, j , D i−1, j−1 , Di , j−1}  

dove Dm ,n è la distanza di Dynamic Time Warping tra la sequenza X e la sequenza Y.

Si immagini di costruire una matrice come quella rappresentata in figura 3. Se viene marcata la cella (i, j) significa che il campione i­esimo della sequenza Y è stato associato (o mappato) con il campione j­esimo della sequenza X. Come si vede dal disegno, sono presenti due segmenti inclinati che demarcano i limiti superiore e inferiore oltre ai quali il cammino di mappatura non può andare. Tali limiti vengono assegnati ad hoc sulla base delle caratteristiche del problema.

L'algoritmo ha complessità polinomiale perché si devono eseguire al più  n⋅m operazioni. Infatti per calcolare la distanza  D i , j basta calcolare la funzione costo per  y i e  x j e sommare la distanza minima dei tre predecessori

  D i−1, j , D i−1, j−1 , D i , j−1 (3.2.1­1)

Calcolando le distanza nell'ordine opportuno, ovvero colonna per colonna e dal basso verso l'alto, ad ogni passo sono già stati calcolati tutti i predecessori.

13

Illustrazione 3: Matrice per la costruzione del  cammino ottimo.

Page 14: Tesi De Franceschi Daniel

Si può notare che una corrispondenza costruita in questo modo è del tipo “molti a molti”, poiché ad un punto nell'ascissa possono venir associati molti punti sull'ordinata, e viceversa. Ciò significa che la corrispondenza ottima trovata è bidirezionale, ovvero rappresenta la mappatura ottima di X con Y, ma allo stesso tempo è anche quella di Y con X (a parità di vincoli). Questa caratteristica è molto importante. Infatti, da un punto di vista matematico, ne consegue che alla fine del processo si trovano due applicazioni 

F : j ∈ℕi ∈ℕ  e   G :i ∈ℕ j ∈ℕ ,

ma nessuna delle due in generale è una funzione, per le ragioni spiegate sopra.

Quindi per rappresentare la sequenza mappata è necessario operare delle scelte tra più possibilità qualora ad un campione della sequenza test fossero associati più campioni della sequenza di riferimento (si supponga di voler mappare quest'ultima in quella di test). E' ragionevole a questo punto prendere, tra le varie possibilità, quella più vicina al campione test in termini di valore della funzione di costo.

Un'attenzione particolare va rivolta ai vincoli del problema. In primo luogo, la relazione ricorsiva (3.2.1­1) vincola la mappatura ad essere monotona, cioè a procedere incrementando almeno uno tra gli indici i e j. Questo garantisce che il cammino non possa mai “tornare indietro” (cosa che avrebbe poco senso). I limiti superiore ed inferiore, rappresentati dai due segmenti inclinati nella matrice di ricerca in figura 3, regolano l'entità della “deformazione” ammessa. Più le zone proibite per il cammino vengono ridotte, più la sequenza X può venir deformata per combaciare con Y e viceversa (trattandosi di una mappatura bidirezionale).

Infine vanno poste in risalto le condizioni al contorno. Normalmente si opera la ricerca fissando gli estremi delle due sequenze, ovvero si associa a priori y1 con x1 , e ym con xn . Dopo aver calcolato tutte le distanze, si procede con il backtracking per la ricerca del cammino ottimo partendo dalla cella (m,n) e andando a ritroso. Il fatto che il cammino si completi con la cella (1,1) è intrinsecamente garantito dal fatto che è l'unica cella a non avere predecessori.

14

Illustrazione 4: Ordine di calcolo delle  distanze D(i,j).

Page 15: Tesi De Franceschi Daniel

3.2.2. Dynamic Planar Warping

L'algoritmo per la mappatura di immagini si basa sull'algoritmo Dinamic Time Warping (DTW).

L'idea fondamentale è quella di considerare un'immagine come un vettore i cui elementi sono le righe di pixel dell'immagine stessa.

Da un punto di vista formale, sia A un'immagine (in scala di grigi) tale

A={ai , j con i , j=1,.. , N }

Il fatto di considerare, per ora, immagini quadrate è per comodità puramente notazionale. Tutti i ragionamenti che si faranno si potranno facilmente estendere al caso generale di immagini rettangolari.

Si indichi con a(i, :) l'i-esima riga di pixel dell'immagine A. In tal senso è possibile scrivere

A=[ a i ,1 , a i ,2 , a i ,3 , ... , a i , N ]T

Quindi, date due immagini A e B tali che

A=[ a i ,1 , a i ,2 , a i ,3 , ... , a i , N ]T (3.2.2-1)

B=[ b i ,1 , bi ,2 , bi ,3 , ... , b i , M ]T (3.2.2-2)

si intende applicare l'algoritmo DTW fornendo come sequenze di campioni le due immagini A e B, espresse nelle forme (3.2.2-1) e (3.2.2-2). Come detto all'inizio, ogni campione è in realtà un'intera riga di pixel.

Date queste premesse, per completare l'algoritmo basta definire la funzione di costo, cioè l'espressione della distanza tra due campioni. Ancora una volta si fa uso del Dynamic Time Warping. Trattandosi infatti del confronto tra due righe di pixel, è immediato pensare al confronto tra due sequenze monodimensionali di campioni. In questo modo la distanza risulta quella data dalla mappatura ottima tra le due righe.

Dal punto di vista della distorsione dell'immagine, le righe vengono deformate in modo

15

Illustrazione 5: Predecessori per D(i,j) (cella grigia). Tra questi  viene selezionato come precedente quello che ha valore minimo della distanza D.

Page 16: Tesi De Franceschi Daniel

indipendente l'una dall'altra. L'algoritmo è stato realizzato in modo da lavorare con immagini in bianco e nero. Questo semplifica la gestione delle immagini e facilita la definizione della distanza tra due pixel. Inizialmente si può considerare il valore assoluto della differenza tra le due intensità,

cost x j , y i=∣x j− y i∣

Sebbene sia un modo di operare che introduce numerose ambiguità, i risultati ottenuti con questa scelta sono interessanti.

E' importante tener conto che questo tipo di algoritmo permette di elaborare in tempi più che ragionevoli delle immagini di dimensioni normali, cosa che in generale non avviene per gli algoritmi multistadio. Resta pur sempre vero che il modello multistadio garantisce la monotonia e la continuità del warping, ma, per ora, si tratta di un modello puramente teorico e inapplicabile nella pratica.

Dal punto di vista computazionale, l'algoritmo presentato ha complessità di tipo polinomiale.

Per fissare le idee, si supponga che sia A che B abbiano dimensioni NxN . Trattandosi di applicare l'algoritmo DTW in modo nidificato, il “guscio” più esterno dell'algoritmo richiede al più N 2

operazioni. Tuttavia ognuna di queste operazioni è a sua volta un esecuzione dell'algoritmo DTW (N 2 operazioni). In totale, la complessità risulta essere

O N 2⋅N 2

=ON 4

Di seguito è riportato lo pseudo codice dell'algoritmo.

/* Dynamic Planar Warping */

for (j=1; j<=N; j++) for (i=1; i<=N; i++)

if (la cella è all'interno dei bordi)

distanza(i,j) = distanzaDTW(A(i,:),B(j,:)) +min(distanza(i-1,j), distanza(i,j-1),distanza(i-1,j-1);

backtracking(i,j) = precedente_con_distanza_minima;

end if end forend for

Lo pseudo codice fa uso della procedura distanzaDTW che implementa l'algoritmo DTW monodimensionale. Chiaramente, oltre a memorizzare il backtracking per ogni associazione tra le righe, è necessario memorizzare la mappatura dei pixel all'interno della riga stessa. Questo compito è affidato alla procedura che calcola la DTW monodimensionale. La mappatura ottima delle due righe confrontate viene salvata in una lista concatenata facente parte della struttura dati relativa alla cella (i, j).

/* Dynamic Time Warping */

for (j=1; j<=N; j++) for (i=1; i<=N; i++)

16

Page 17: Tesi De Franceschi Daniel

if (la cella è all'interno dei bordi)

costo(i,j) = |pixel(Y,i)-pixel(X,j)| +min(costo(i-1,j),costo(i,j-1),costo(i-1,j-1);

backtracking(i,j) = precedente_con_costo_minimo;

end if end forend for

memorizza_backtracking_in_lista;

A titolo esemplificativo sono riportati di seguito alcuni esempi di mappature elaborate con questo algoritmo.

La matrice di deformazione viene utilizzata nelle formule (4.2.1-1) e (4.2.1-2) del capitolo successivo.

3.3. OpenCV

Per le operazioni di detect e per una buona parte delle operazioni di calcolo vengono utilizzate le “OpenCV” [4] - Open Computer Vision - che sono librerie (orientate appunto alla computer vision) open source e multipiattaforma. Per l'uomo riuscire ad estrarre informazioni oggettive da un'immagine è un'operazione che normalmente potrebbe essere considerata banale ma altrettanto banale non è se a farlo è un sistema automatico. Le librerie OpenCV nascono per raccogliere le funzionalità degli algoritmi più utilizzati in questo ambito. È basata almeno parzialmente sulla Intel

17

Illustrazione 7:  Immagine Pattern

Illustrazione 6:  Immagine acquisita

Illustrazione 8:  Immagine ricostruita

Illustrazione 9: Immagine Pattern

Illustrazione 10: Immagine acquisita

Illustrazione 11:  Immagine ricostruita

Page 18: Tesi De Franceschi Daniel

Image Processing Library (IPL) sviluppata da Intel e oggi integrata nella libreria commerciale IIPP (Intel Integrated Performance Primitives). La licenza utilizzata è in stile BSD. Per l'utilizzo dei metodi più utilizzati delle OpenCV tramite Java è stato necessario l'utilizzo di un porting Java delle librerie: “Processing” [16]. Per l'installazione delle librerie e l'utilizzo del porting Java si rimanda all'apposita appendice.

18

Page 19: Tesi De Franceschi Daniel

4. Il sistema sviluppatoIl sistema sviluppato ha richiesto la realizzazione di due componenti “separati”: navigazione e autolocalizzazione. Infine è stato necessario unire le due parti.

4.1. Navigazione

Per quanto riguarda la navigazione del robot l'obbiettivo che ci si è proposti era la realizzazione di un “algoritmo” di navigazione con percorso minimo tra due punti data la mappa dell'ambiente. Si è supposto che il robot potesse muoversi liberamente nell'ambiente. Il problema è stato scomposto in due sottoproblemi: il calcolo del percorso minimo tra due punti data la mappa e la navigazione vera e propria.

4.1.1. Calcolo del percorso minimo data una mappa dell'ambiente

Il processo è formato da varie operazioni che possono essere distinte in: caricamento della mappa, estrazione dei vertici della mappa, proiezione dei vertici, decomposizione delle linee, generazione dei poligoni, creazione del grafo e calcolo del percorso minimo tramite Dijkstra.

4.1.1.1. Caricamento della mappa

Il caricamento dell'immagine avviene per semplicità tramite un package esterno alla Java SE. Questo package permette di caricare il contenuto dell'immagine in un oggetto del tipo BufferedImage.

19

Illustrazione 12: Mappa originale dell'ambiente

Page 20: Tesi De Franceschi Daniel

BufferedImage image = null;image = new PngImage().read(new java.io.File(nome_file));

Una volta che l'immagine è stata caricata, si prosegue alla realizzazione di una matrice di boolean con un numero di colonne pari al numero di pixel in larghezza e un numero di righe pari al numero di pixel in altezza dell'immagine. Ogni elemento della matrice viene posto a “true” se il pixel corrispondente nell'immagine è occupato da un “muro” o da un qualsiasi ostacolo.

4.1.1.2. Estrazione dei vertici

Il passo successivo è il riconoscimento e lo sfoltimento dei vertici. Da un file di testo opportunamente formattato vengono caricate le configurazioni che verranno utilizzate come strumento di confronto per gli elementi della matrice di boolean.

1 1 1 0 0 0 0 0 0 -1 0 1 0 00 0 0 0 0 0 1 1 1 -1 0 1 0 01 0 0 1 0 0 1 0 0 0 -1 0 1 00 0 1 0 0 1 0 0 1 0 -1 0 1 01 0 0 1 0 0 0 0 0 0 -1 0 1 0…

Ogni riga rappresenta una configurazione: i primi 9 valori rappresentano una matrice 3x3 di pixel, seguono due coppie di due valori ciascuno che indicano la direzione in cui spostarsi se viene trovata la configurazione nell'elemento della matrice dell'immagine e l'ultimo valore indica se il punto può essere considerato o meno un vertice. Nel caso della prima riga la configurazione indica la seguente situazione:

Cioè il “muro” è rappresentato dalle caselle nere mentre la casella grigia è la casella che l'algoritmo sta considerando. Seguendo il muro posso muovermi nella cella (-1, 0) oppure nella cella (1,0) rispetto al punto considerato. L'ultimo “0” indica che il punto non è considerato un vertice.

Un vettore conterrà i riferimenti di un insieme di oggetti del tipo “Configurazione” che conterranno le informazioni appena caricate dal file di testo.

Il metodo “trovaContorni” (ricorsivo) analizza riga per riga della matrice dell'”immagine” fintanto che non trova un pixel vuoto. Una volta individuato, viene chiamato il metodo “seguiContorno” (ricorsivo) che segue il contorno del “poligono” finché non torna al punto di partenza.

Per come è stato costruito l'algoritmo di ricerca del contorno e di conseguenza per come è fatto il file di configurazione è necessario che la mappa venga realizzata in modo tale che:

• Deve esserci un bordo esterno di “muro” di almeno un pixel sui bordi dell'immagine.

20

Page 21: Tesi De Franceschi Daniel

• I poligoni interni non devono avere uno spessore troppo sottile: una condizione accettabile è che i poligoni abbiano almeno dimensione 3x3.

Il risultato della sua elaborazione è rappresentato dai segmenti del contorno degli ostacoli che ha trovato lungo il cammino. A questo punto è però necessario “eliminare” temporaneamente il poligono trovato per poter continuare la scansione: se non venisse oscurato il poligono trovato si rischierebbe di “processarlo” altre volte. Per compiere questa operazione viene chiamato il metodo “cancellaPoligono” (anche questa ricorsivo) che non fa altro che partendo dal punto di partenza (in questo caso quello individuato da “trovaContorni”) oscurare tutti i pixel adiacenti e gli adiacenti degli adiacenti fintanto che non non ha più punti da oscurare poiché gli altri punti adiacenti sono già stati oscurati o sono nativamente oscurati. Ovviamente questa operazione viene fatta su una matrice ausiliaria per non perdere la matrice originale.

Il metodo “trovaContorni” continuerà la scansione fintanto che non ci saranno più zone “vuote”. A questo punto però è necessario svuotare la zona esterna trasformandola in vuota e richiamare nuovamente il metodo “trovaContorni” incaricandolo questa volta di trovare non più le zone vuote ma quelle piene in modo tale da riuscire a scovare eventuali catene di zone piene, vuote, piene, vuote una dentro l'altra. Il risultato di tutte queste operazioni è il “recupero” dei poligoni contenuti nella mappa.

Molti di questi poligoni potrebbero però essere facilmente semplificati: poiché l'immagine è una bitmap e al suo interno non sono presenti linee ma pixel è necessario ridurre il numero di vertici per alleggerire il carico computazionale delle operazioni successive. Il metodo predisposto a questo scopo è il metodo “cancellaVertici” che verifica se gruppi di tre vertici sono o meno allineati, cancellando l'intermedio nel caso questo accada. L'ultimo procedimento che a livello teorico avrebbe dovuto funzionare a livello pratico portava in alcuni casi all'approssimazione troppo brutale di alcune “tipologie” di poligoni pertanto il confronto è stato costruito in modo tale da considerare non più tre punti bensì quattro. Il risultato che si ottiene è un insieme di vettori di linee che rappresentano il contorno dei vari poligoni: un vettore per ogni poligono. L'approssimazione è ovviamente più marcata qualora siano presenti degli ostacoli obliqui rispetto agli assi dell'immagine oppure in presenza di poligoni che siano o contengano degli elementi curvilinei. Nell'esempio che si è scelto di utilizzare si può vedere come venga approssimata una circonferenza.

Il risultato ottenuto è visibile nell'immagine successiva:

21

Illustrazione 13: Ostacolo "tondo"

Illustrazione 14:  Ostacolo "tondo" approssimato

Page 22: Tesi De Franceschi Daniel

4.1.1.3. Proiezione dei vertici

L'obbiettivo è la scomposizione delle parti vuote della mappa (adesso formata solamente da linee ed eventualmente vertici) in poligoni (rettangoli e triangoli). In questo passo si generano tutte quelle linee (proiezione dei vertici precedentemente individuati) che una volta scomposti saranno i segmenti che formano il contorno dei poligoni interni e che saranno necessari per la costruzione del grafo.

Il metodo “creaLineeOriz” scorre tutti i vertici, genera due linee orizzontali una diretta verso sinistra, l'altra verso destra verificando quali intersezioni abbiano con gli ostacoli presenti sulla mappa. Se queste linee “esistono” le inserisce in un vettore per poter essere successivamente elaborate. Non tutte le proiezioni saranno considerate valide per esempio non ci può essere proiezione verso sinistra di un vertice che è coperto a sinistra da un muro.

Il metodo “creaLineeVert” fa esattamente la stessa cosa, solo che per le linee verticali. All'interno di

22

Illustrazione 15: Estrazione dalla mappa dei contorni

Illustrazione 16:  Esempio proiezione vertice

Page 23: Tesi De Franceschi Daniel

ognuno dei due metodi viene utilizzato un ulteriore metodo “eliminaFalsePositive” per eliminare quelle linee che erroneamente potrebbero venire generate in presenza di ostacoli di forma e di struttura “particolari”.

4.1.1.4. Decomposizione delle linee in segmenti

Il passo precedente ha permesso di ottenere le linee di “prolungamento” dei vertici, ma l'obbiettivo è di ottenere i segmenti che formano i vari poligoni all'interno della mappa. É quindi necessario decomporre le linee.

Il metodo “decomposizione” scansiona una alla volta le linee verticali trovando le linee orizzontali che si intersecano con le prime e le scompone a partire dalle intersezioni. Ovviamente ci sono dei casi in cui le linee non devono essere decomposte: se una linea verticale interseca una linea orizzontale in uno dei suoi due vertici solamente la linea verticale verrà decomposta. Nell'immagine

23

Illustrazione 17: I vertici sono stati proiettati

Illustrazione 18: Esempio decomposizione

Page 24: Tesi De Franceschi Daniel

18 la linea “l2” (generata dalla proiezione dei vertici) interseca una linea di bordo “l1” nel vertice “nV”. Solo la linea “l1” in questa passata verrà decomposta in due segmenti con un vertice in comune cioè “nV”. La linea “l2” verrà comunque decomposta in una passata successiva e con lei anche la linea “l3”.

Si vengono pertanto a formare non solo nuovi segmenti ma anche nuovi vertici sia internamente alle zone “vuote” sia sui bordi.

4.1.1.5. Generazione dei poligoni

É necessario scoprire i segmenti che fanno parte dei vari poligoni e generare una nuova struttura che contenga solo i vertici dei poligoni per poi poter calcolare i baricentri. Per semplicità, si è scelto di utilizzare un metodo per nulla ottimizzato: a partire da un vertice, scorre le linee e trova quelle che hanno il vertice stesso come estremo, poi “elimina” quelle che hanno direzione verso ”l'alto” e verso ”sinistra” e sulle linee restanti verifica a coppie se ci sono linee che uniscono i restanti estremi (nel caso del triangolo) o due linee che partendo dagli estremi precedenti si incontrano nello stesso punto.

Come contenitore è stata costruita una classe “Poligono” in grado peraltro di calcolare il baricentro dagli estremi che sono stati memorizzati. Poiché le “figure” che si ricavano sono solamente rettangoli e triangoli la classe necessita di saper determinare solamente il baricentro di triangoli e rettangoli.

24

Illustrazione 19: Vecchi e nuovi vertici

Page 25: Tesi De Franceschi Daniel

4.1.1.6. Costruzione del grafo

A partire dai poligoni si può creare il grafo che sarà formato da nodi e da archi congiungenti i vari nodi. Ogni arco deve essere pesato cioè bisogna assegnargli un valore che indichi in questo caso la distanza tra i due nodi che altro non è che la distanza tra i due baricentri dei poligoni associati ai due nodi (purchè i due poligoni siano adiacenti). Due poligoni vengono considerati adiacenti se hanno almeno un estremo in comune. Il grafo è formato da oggetti di tipo “Nodo” il cui contenuto è il baricentro del poligono oltre che due vettori, uno contenente i collegamenti tra nodi (riferimenti a oggetti di tipo Nodi) e il secondo che contiene invece il peso associato a ogni collegamento. Il metodo “creaGrafo” non fa altro che chiamare per ogni poligono il metodo “creaCollegamento” il cui compito è la verifica che il Nodo associato al poligono sia già stato inserito nel vettore dei nodi, altrimenti lo inserisce, verifica che siano stati inseriti per il nodo tutti i collegamenti con gli altri nodi e associa a ogni collegamento il peso corrispondente.

4.1.1.7. Calcolo del percorso minimo tra due punti tramite l'algoritmo di Dijkstra

L'algoritmo di Dijkstra permette di calcolare il percorso minimo che unisce due nodi di un grafo. Ad ogni nodo del grafo viene associato inizialmente un peso infinito tranne al nodo di partenza che riceve un peso pari a zero. Si aggiorna (se necessario) il peso dei nodi “adiacenti” al nodo di partenza con il peso dell'arco che unisce i due nodi, questo ovviamente se il nuovo peso è minore del precedente. Si rende “definitivo” come prossimo nodo il nodo che ha peso minimo. (ovviamente scartando i nodi già resi definitivi). Si aggiornano i pesi dei nodi adiacenti al nuovo attuale (il nuovo peso sarà dato dalla somma del peso precedente con il peso del collegamento unente i due nodi) scartando però i nodi che sono stati già resi definitivi. Alla fine del processo si ottiene non solo il peso minimo per il percorso tra i due nodi (partenza e destinazione) ma anche tutti i pesi minimi tra il nodo di partenza e tutti gli altri nodi. A ogni passata memorizzo lo stato del vettore dei

25

Illustrazione 20: Poligoni e loro baricentri

Page 26: Tesi De Franceschi Daniel

pesi in modo tale da poter recuperare il percorso. Si analizzano i vettori dei pesi (dall'ultimo fino al primo) considerando prima la posizione occupata dal nodo di arrivo e andando a ritroso nei vettori fino a trovare il nodo che ha causato la modifica del peso del nodo di arrivo. Si considera adesso il nodo che ha causato la modifica del peso per la successiva analisi fintanto che non si arriva al primo vettore. La lista dei nodi ottenuta rappresenta (invertita) il percorso che ha peso minimo.

Come si può facilmente notare i segmenti che definiscono il percorso sovrastano in alcuni casi degli ostacoli oppure sono a distanza troppo ravvicinata da essi. Questi problemi però vengono risolti dall'algoritmo di navigazione che è stato costruito in modo tale che il robot mobile si mantenga sufficientemente distante dai muri e sia in grado di evitare gli ostacoli.

4.1.2. Navigazione del robot

Essenzialmente si può scomporre il problema della ”guida” del robot in tre operazioni:1) Lettura dei sensori2) Presa di decisione3) Esecuzione della decisione

L'algoritmo per la percorrenza di una singola tratta è formato essenzialmente da un ciclo ”infinito” al cui interno sono presenti vari ”componenti”:

1) Lettura dei sensori2) Verifica dell'arrivo3) Rotazione verso l'obbiettivo (se nella vicinanza non ci sono ostacoli) oppure allontanamento

dall'ostacolo (se il robot è troppo vicino a un ostacolo)

26

Illustrazione 21: Percorso "minimo" tra due punti

Page 27: Tesi De Franceschi Daniel

4.2. Localizzazione mediante riferimenti visivi

Si necessita di una telecamera o più semplicemente di una webcam per la visualizzazione dell'ambiente. Grazie all'utilizzo di landmark piani di forma conosciuta (nel nostro caso circonferenze “colorate”) posti sul soffitto in posizioni note è possibile in base alla deformazione con la quale la webcam vede il marker determinare prima lo sforzo necessario per deformare il marker originale per ottenere quello visualizzato e poi grazie al primo passaggio la distanza della webcam dal marker. Con un unico marker sapendo l'altezza del soffitto rispetto alla webcam sarebbe possibile determinare solo una circonferenza lungo la quale è posizionato il robot che sostiene la webcam. Si potrebbe pensare allora di usa due marker ma anche in questo caso non si riuscirebbe a determinare la posizione poiché dalla triangolazione si otterrebbero due punti. Se i marker però sono diversi fra loro (nel nostro caso sono di colore diverso) e si conosce quale dei due sta “prima” dell'altro posso determinare su quale dei due punti è posizionata la webcam. I landmark utilizzati per gli esperimenti sono formati da due circonferenze concentriche di raggi diversi la cui corona esterna è colorata di nero e la superficie racchiusa dalla circonferenza più piccola è stata colorata o di rosso o di blu.

Inoltre si è supposto (per come è costruito l'algoritmo messo a punto nella tesi precedente) che l'asse delle ascisse fosse parallela con il segmento unente i centri dei due landmark (rosso e blu) e che la crescenza dei valori andasse dal landmark rosso a quello blu. È necessario conoscere la posizione assoluta dei landmark posti sul soffitto e poiché per semplicità si è fatto coincidere la direzione dell'asse delle ascisse con la congiungente i due centri, l'ordinata è fissata a zero per entrambi pertanto ciò che varia è solamente l'ascissa. Non è necessario che i landmark siano di dimensione prefissata, ma è fondamentale effettuare il salvataggio di un pattern cioè un'immagine di uno dei due landmark posizionando la webcam a piombo dal centro del ladmark a distanza dal soffitto uguale a quella che si userà per effettuare le misurazioni e rivolta esattamente verso l'alto. Il risultato è un immagine che contiene il landmark esattamente al centro dell'immagine. Quale sia il landmark scelto come pattern non ha alcuna rilevanza poiché gli algoritmi di “confronto” trasformano il pattern e i landmark rilevati in scala di grigi una volta che ne è stato identificato il tipo. I dati fondamentali che sono necessari all'algoritmo per determinare la posizione sono:

• Posizione dei landmark: La posizione dei landmark deve essere memorizzata all'interno di un file di testo chiamato “landmark.txt”. A livello teorico l'algoritmo era stato studiato per essere in grado di gestire diverse coppie di landmark diverse fra loro per il numero di cerchi neri presenti nella vicinanza della coppia. Si è deciso di permettere l'uso di un'unica coppia perciò della lista presente nel file gli unici valori “interessanti” sono quelli della prima

27

Illustrazione 22: Landmark Blu

Page 28: Tesi De Franceschi Daniel

coppia. Le informazione contenute sono in ordine: Ordinata del centro del landmark Rosso, Ascissa del centro del landmark Rosso (0 nel nostro caso), Ordinata del centro del landmark Blu, Ascissa del centro del landmark Blu (0 nel nostro caso).

• Caratteristiche della webcam: Devono essere memorizzate all'interno di un file di configurazione di nome “parametri.txt”. I dati necessari memorizzati sono:◦ φ: angolo “verticale” tra l'asse di rotazione verticale della webcam e il centro della

visione (nel caso dei test 65°).◦ θy: angolo di visione verticale (nel caso dei test 39°).◦ h: distanza dal fuoco della webcam al soffitto (nel caso dei test 2,345 [m]).◦ θx: angolo di visione orizzontale (nel caso dei test 50°).◦ RisoluzioneX: Risoluzione orizzontale della webcam (nel caso dei test 640 [px]).

• Pattern: Immagine di nome “pattern.JPG” realizzata con angolo φ=90° con la webcam posizionata all'altezza h in coincidenza con la proiezione sul pavimento del centro di uno dei due landmark (non ha alcuna importanza il colore).

Dal progetto precedente abbiamo “ereditato” oltre che la tesi (di fondamentale importanza per capire a grandi linee l'idea di funzionamento) un file C++ con i metodi necessari per il detect dei landmark (che poi non sono stati utilizzati) e i metodi per il calcolo delle distanze e della triangolazione (che hanno subito importanti variazioni) e un file Java per il richiamo dei metodi della classe in C++. Sono stati forniti inoltre anche tutti i file di configurazione, il pattern e le

28

Illustrazione 23: Angoli “fondamentali” della Webcam

Illustrazione 24: Pattern

Page 29: Tesi De Franceschi Daniel

immagini su cui erano stati fatti in precedenza i test. Il tutto era stato realizzato per il funzionamento in ambiente Windows pertanto la libreria compilata è una “dll”. Il fatto che il “main” sia realizzato in Java e utilizzi librerie native non dovrebbe stupire più di tanto anche se introduce una certa complicazione e rende il Java che di per se sarebbe un linguaggio multi-piattaforma dipendente dalla presenza delle librerie native nel sistema in uso. Come è noto il Java è un linguaggio multi-piattaforma nel senso che il codice viene “compilato” in un linguaggio intermedio detto bytecode che viene poi interpretato dalla JVM (Java Virtual Machine). La JVM è invece dipendente dal sistema operativo: se esiste la JVM per un certo sistema operativo di norma posso eseguire lo stesso codice compilato su macchine diverse e con SO diverso allo stesso modo purché sia installata la JVM su quel sistema. Questo ovviamente ha delle implicazioni piuttosto importanti come la riduzione dei tempi di sviluppi su sistemi diversi.

L'uso della libreria nativa da programma Java può essere fatto in modo differente: nel caso della tesi precedente è stato utilizzato SWIG [17], nella implementazione realizzata invece è stata utilizzata la JNI [18] (Java Native Interface). Questo ha reso necessario la modifica della libreria in C++ anche perché ulteriori complicazioni sono state introdotte dall'inserimento del codice Java di “richiamo” all'interno di un Package. Si rimanda all'appendice per i due “How to” per l'installazione delle librerie OpenCV su Ubuntu 9.10 Linux e la compilazione e l'uso delle librerie native con Java sempre sullo stesso sistema.

Una delle parti che ha richiesto più tempo è stato l'analisi e lo studio della geometria del problema. Per quanto le formule trigonometriche ricavate siano piuttosto elementari hanno richiesto comunque una certa attenzione soprattutto in considerazione dei diversi sistemi di riferimento che sono stati considerati.

Una volta installate correttamente le OpenCV il passo successivo è stato la costruzione del package contenente tutte le classi adibite all'operazione di detect dei landmark e al richiamo dei metodi nativi. All'interno del package sono state inserite varie classi alcune delle quali sono adibite a puri contenitori di informazioni. É possibile scomporre il procedimento in vari sotto-passi: detect dei landmark, caricamento nelle strutture dati della libreria nativa, richiamo degli algoritmi di calcolo e prima verifica “algoritmica” dei risultati.

29

Page 30: Tesi De Franceschi Daniel

Illustrazione 25: Rappresentazione grafica delle grandezze definite dal problema

Page 31: Tesi De Franceschi Daniel

4.2.1. Analisi geometrica del problema del posizionamento

Tutte le relazioni matematiche adibite al calcolo della distanza dai landmark, la triangolazione e il calcolo dell'angolo del robot sono state ricavate e adeguatamente modificate. La retta passante per il segmento HP y rappresenta il soffitto della stanza di test “posto” all'altezza h dalla webcam posizionata nel punto O. La webcam è rivolta verso l'alto con un certo angolo φ (rispetto al centro della visione). θx e θy rappresentano gli angoli di apertura orizzontale e verticale rispettivamente della webcam. L'angolo γy invece è l'angolo di un generico punto sul soffitto rispetto al pavimento. Il piano posto in MQ e parallelo all'asse x uscente dal punto O è il piano dell'immagine.Vengono fatte le seguenti definizioni:

a :=OA=OC−ACb2

:=MA=AQ=MC sin

g :=GD=DI=a tan x

2

:= y

2−

2

ma OC=h

sin e AC=MC sin

2−=MC cos , inoltre MC=HC−HM con

HC=tan

2−=h

sin

2−

cos

2−

=h

tg e HM =h tan − .

Si ottiene pertanto che

a=h

sin−h tan

1tan

cos eb2=h tan

1tan

sin .

Dalle definizioni precedenti si può dedurre che

yI=

b2a tan −y

y=arctan h

y−h tan

( tan y =h

HP y

ma HP y=MP yHM= y−h tg )

tan − y =RP y

OR, RP y=WPY cos , WPY=TPY−TW , TPY= y tan ,

TW=h−HM tan=hh tan tan=h tantan 1WPY= y tan −h tan tan1 RPY= y tan −h tan tan1cos

inoltre OR=OK sin

2−=OK cos , OK=HMMP yDK , HM =−h tan

MP y= y DK=h tan OK=h tan y−h tan OR=h tan y−h tancos

tan − y = y tan −h tan tan1cos

h tan y−h tancos=

y tan −htan tan 1h tan y−h tan

Definendo G :=−h tan tan 1 e F :=h tan −tan si ottiene che

tan − y =y tanG

yF. Si ricava che y I

=b2a

y tanGyF

Per la “x” vale invece:

x I=GDDP x

I=gDP x

I h :OD z=HP x : DP xI DP x

I=

HP x ODz

hODz=OP y

I sin y

31

Page 32: Tesi De Franceschi Daniel

OP yI cos − y=a⇒OP y

I=

acos− y

ODz=a

cos − ysin y

DP xI=

a sin y

hcos− yHP x HP x= x−FH

FH : h=GD :ODz⇒ FH=h g

acos −y

sin y

HP x= x−h g

acos − y

sin y

DP xI=

a sin y

h cos− yx−

h ga

cos − ysiny

=asin y

h cos− yx−g

x I=

a sin y

hcos − yx

Quello che si cerca è d= HP x2HP y

2 che rappresenta la distanza sul piano del soffitto tra O

proiettato e il punto HP x , HP y baricentro del landmark. A partire da

y I=

b2a

tan yGyF

x I=

a siny

hcos −yx

sostituendo y= yr yc e x= xrxc dove xc , yx è la coordinata del baricentro del landmark e xr e yr sono le posizioni dei pixel nell'immagine pattern si ottiene che

x I=

a sin y

hcos − yxcxr e y I

=b2a

tan yc yrG

yc yrF. Mettendo in risalto xc , yx si

ha

yc=

aGa tan yr− y I−

b2 yrF

y I−

b2−a tg

(4.2.1-1)

xc= xI hcos −y

a sin y − xr (4.2.1-2)

In pratica le due formule precedenti legano il baricentro del landmark con le coordinate dei pixel nell'immagine pattern e il pixel corrispondente nell'immagine di test. Applicando le relazioni per i punti del landmark si ottengono varie stime sulla posizione del baricentro. Il valore del baricentro considerato è la media di quelli calcolati.

Questa operazione deve essere ripetuta per entrambi i landmark ottenendo pertanto due distanze. Conoscendo la loro posizione nell'ambiente si può triangolare la posizione del robot. Il posizionamento del robot però non è dato solo dalle sue coordinate rispetto al sistema assoluto ma anche dal suo angolo di rotazione che può essere descritto come l'angolo compreso tra l'asse x del sistema di riferimento assoluto e l'asse x del sistema di riferimento del robot.

32

Page 33: Tesi De Franceschi Daniel

Nel grafico vengono rappresentati tre sistemi di riferimento: il sistema (x,y) che rappresenta quello assoluto (per semplicità si è fatto “coincidere” l'asse delle ordinate con la congiungente i centri dei landmark), il sistema (xI,yI) che è il sistema di riferimento del robot e infine il sistema di riferimento (xII,yII) che rappresenta la traslazione di (xI,yI) sul landmark rosso. Grazie alle operazioni precedenti siamo a conoscenza delle coordinate dei due landmark rispetto al sistema di riferimento del robot (xI,yI). Pertanto oltre che i segmenti “dr” e “db” e la distanza tra i due landmark si viene a conoscenza degli angoli interni al triangolo (grazie a Carnot).

R=arccos db2RB2−dr2

2 RB db

B=arccos dr2

RB2−db2

2 RB dr

=arccosdb2

dr 2−RB2

2db dr

La determinazione delle coordinate del robot presuppone due casi: se i landmark sono paralleli a uno degli assi del sistema di riferimento del robot come si è visto dai risultati sperimentali (che verranno discussi in seguito) molto spesso si verificano dei problemi nella determinazione della posizione, altrimenti si profilano altre due casistiche: il landmark rosso può essere a sinistra del blu o viceversa. Nel primo caso si ottiene che

x=R.XcosBdry=R.Y −sin Bdr

mentre nel secondo:x=B.X−cosRdby=B.Y sin Rdb

dove (B.X, B.Y) e (R.X, R.Y) sono le coordinate assolute del ladmark blu e rosso rispettivamente.

33

Illustrazione 26: Triangolazione e angolo del robot

Page 34: Tesi De Franceschi Daniel

Resta ancora da definire l'angolo con cui è ruotato il robot. Se si considera il sistema di riferimento (xII,yII) è possibile individuare 16 possibili configurazioni: 4 per la posizione del landmark rosso rispetto al sistema di riferimento (xI,yI) e per ognuna di queste 4 configurazioni per la posizione del landmark blu rispetto al sistema di riferimento (xII,yII). In realtà è possibile riassumere questi 16 casi nel seguente modo. Si definiscono

x BII :=x B

I− xR

I

yBII := yB

I− yR

I

Dalle quali si ricavano le seguenti relazioni:

=arctan −y B

II

x BII nel caso che il landmark blu si trovi nel I° o IV° quadrante rispetto al sistema di

riferimento (xII,yII) oppure

=signarctan −y B

II

x BII −arctan −

y BII

xBII nel caso che il landmark blu si trovi nel II° o III°

quadrante rispetto al sistema di riferimento (xII,yII).

34

Illustrazione 27: θ: R in I° quad. in (xI,yI) e B in I° quad. in (xII,yII)

Illustrazione 28:  : R in I° quad. in θ (xI,yI) e B in III° quad. in (xII,yII)

Illustrazione 29:  : R in IV° quad. inθ  (xI,yI) e B in IV° quad. in (xII,yII)

Illustrazione 30:  : R in III° quad. in θ (xI,yI) e B in IV° quad. in (xII,yII)

Page 35: Tesi De Franceschi Daniel

4.2.2. Detect dei landmark

L'operazione di detect si articola in un numero piuttosto limitato di passaggi e questo è dovuto alla bontà delle librerie OpenCV che permettono di sfruttare algoritmi molto complicati in modo facile e molto intuitivo. Il porting utilizzato permette di sfruttare solo alcune delle potenzialità dell'ambiente ma che sono risultate sufficienti allo scopo che ci si era preposti. Si possono schematizzare le seguenti operazioni: acquisizione dell'immagine, ricerca dei landmark e verifica dei ritrovamenti e salvataggio dei landmark.

4.2.2.1. Acquisizione dell'immagine

Per prima cosa è necessario istanziare un oggetto di tipo OpenCV:

OpenCV ocv = new OpenCV();

Il passo successivo è invece l'acquisizione dell'immagine dalla webcam. Questa operazione necessita prima di tutto della comunicazione all'oggetto “ocv” della classe OpenCV della risoluzione con la quale si vuole acquisire. È possibile anche specificare al metodo anche l'indice della camera che si vuole usare per la cattura: nel nostro caso però abbiamo considerato che la webcam da utilizzare fosse quella in posizione “0”. Nel caso si cercasse di acquisire con risoluzioni superiori a quelle supportate dalla webcam si otterrebbero delle immagini con la risoluzione richiesta ma le aree sovrabbondanti verranno acquisite come zone nere. Una volta inizializzata si può richiedere la cattura vera e propria dell'immagine che verrà memorizzata in un buffer interno delle OpenCV.

ocv.capture(risX, risY);ocv.read();

Per tener traccia dei risultati fin qui conseguiti l'immagine viene salvata su un file con estensione “png” in una directory che può essere definita dall'utente (le istruzioni sono illustrate nella sezione che riguarda l'interfaccia). Viene istanziato un oggetto della classe “BufferedImage” da cui viene “estratto” un riferimento a un oggetto di tipo “Graphics” che ci permette di scrivere pixel per pixel il colore associato al punto. A questo punto è possibile salvare su file l'immagine vera e propria tramite la classe “ImageIO”.

35

Illustrazione 31:  : R in III° quad. in θ (xI,yI) e B in II° quad. in (xII,yII)

Illustrazione 32:  : R in II° quad. in θ (xI,yI) e B in II° quad. in (xII,yII)

Page 36: Tesi De Franceschi Daniel

4.2.2.2. Ricerca dei landmark e verifica dei ritrovamenti

Per scoprire la posizione dei landmark all'interno dell'immagine per prima cosa si trasforma l'immagine in scala di grigi:

ocv.convert(OpenCV.GRAY);

Poi si impone all'immagine in scala di grigi una soglia “binaria”: se il colore in ogni punto supera una certa soglia il colore del punto viene settato a un valore passato per parametro altrimenti viene settato al valore 0. La soglia dipende dalla luminosità ambientale. Si è dunque cercato di mantenere più costante possibile la luminosità dell'ambiente in modo da poter mantenere sempre lo stesso livello di soglia e rendere più “ripetibili” i test.

ocv.threshold(80, 255, OpenCV.THRESH_BINARY);

36

Illustrazione 33: Immagine acquisita dalla webcam

Illustrazione 34: Immagine acquisita "convertita" in  scala di grigi

Page 37: Tesi De Franceschi Daniel

//80 valore di soglia, 255 valore da imporre al pixel se il //colore del pixel supera la soglia, OpenCV.THRESH_BINARY //tipo di thresholding

Una volta effettuata questa operazione si ha la speranza di aver “eliminato” tutti gli oggetti estranei ai landmark. L'ipotesi non è che il soffitto sia interamente “bianco”, ma che sul soffitto non ci siano oggetti o simboli di dimensione tale da poter essere confusi con i landmark. Come è possibile vedere dall'illustrazione 33 i test sono stati effettuati su un soffitto “piastrellato” e puntinato. Si può notare anche la presenza di due fonti di illuminazione al neon che date le notevoli dimensioni non possono essere fraintese con i landmark posti al centro del soffitto. Ora si vogliono determinare i contorni degli oggetti rilevati e le loro posizioni. Si utilizza pertanto il metodo “blobs” dell'oggetto “ocv” che riceve in input vari parametri: area minima (in pixel) accettata per l'oggetto, massima area (in pixel) accettata per l'oggetto, massimo numero di oggetti rilevabili, valore booleano che consente o meno il “ritrovamento” di oggetti interamente contenuti in altri.

Blob[] blobs = ocv.blobs(minX*minY, maxX * maxY, 100, true, OpenCV.MAX_VERTICES);

Per motivi ignoti si è stati costretti a permettere il ritrovamento di oggetti inscritti: in caso contrario il metodo si rifiutava di recuperare correttamente i marker nonostante sulle immagini non rilevasse altre “figure” oltre a loro.

37

Illustrazione 35: Treshold "binario" applicato all'immagine in scala di grigi

Page 38: Tesi De Franceschi Daniel

Il metodo, come è facile notare, restituisce un vettore di “Blob”. Ogni oggetto “Blob” contiene al suo interno un vettore di oggetti di tipo “Point” che rappresentano appunto i punti che formano il contorno. Quello che si vuole ottenere è un rettangolo entro il quale è contenuto il landmark. Pertanto per ogni oggetto “Blob” del vettore vengono analizzati i suoi punti e memorizzate le coordinate dei punti che sono più “esterne” rispetto al contorno. Si ottengono pertanto le coordinate di due punti che rappresentano gli estremi di un rettangolo che contiene il presunto landmark. Il fatto che l'algoritmo di “blobs” elimini le figure che hanno area (in pixel) minori del parametro non mi assicura comunque che le dimensioni del landmark siano “razionali”. Per esempio potrei ottenere un rettangolo di dimensione 90x2 pixel cioè 180 pixel avendo però fissato che le dimensioni X e Y non debbano essere superiori a 50 pixel per lato. Poiché non si è riusciti a testare la condizione di figure inscritte per sicurezza si è costruito un algoritmo in grado di verificare questa eventualità e nel caso eliminare la figura più interna. A questo punto è necessario estrarre un quadrato avente come centro il centro del rettangolo e come lato una dimensione fissata per ogni presunto landmark (la dimensione è fissata all'interno della libreria: è possibile modificarla ma poi è necessario ricompilarla). Si rende necessaria inoltre la memorizzazione dell'angolo superiore sinistro di ogni landmark trovato: la motivazione diverrà chiara in seguito. Quello che bisogna verificare adesso è il colore del landmark. Siamo a conoscenza che ogni landmark sarà più o meno centrato all'interno di ogni quadrato estratto. Considerare solo il colore del punto centrale non è però una buona politica: ecco perché viene analizzato un “intorno” del punto: per la precisione viene considerato un quadratino di dimensione 3x3 pixel avente centro il pixel centrale del quadrato e viene verificata la componente RGB predominate nell'area.

4.2.2.3. Salvataggio dei landmark

É il momento di salvare su file immagine (“png”) i due landmark per una successiva elaborazione. Il metodo è praticamente equivalente a come è stato descritto nel caso del salvataggio dell'immagine acquisita.

38

Illustrazione 36: Algoritmo "blobs" per il  riconoscimento dei contorni

Page 39: Tesi De Franceschi Daniel

4.2.3. Caricamento strutture dati della libreria nativa

Poiché non è stato utilizzato l'algoritmo di “detect” della libreria nativa è necessario precaricare manualmente i dati dei landmark nelle apposite strutture prima di chiamare i metodi di calcolo. Se la procedura non ha dato buon esito e questo può essere dovuto alla mancanza dei landmark nel campo visivo della webcam oppure a condizioni sfavorevoli di illuminazione dell'ambiente non è possibile calcolare la propria posizione ma si dovrà contare solo sui dati forniti dall'odometria. Vengono effettuati pertanto dei controlli sul rilevamento dei landmark. La struttura che la libreria nativa utilizza per la memorizzazione delle informazioni che ci interessano è così realizzata:

typedef struct { IplImage* img; int Xcorner; int Ycorner; double x; double y; double distanza; double angolo; long int costo; char colore; } U;U array[10]; // Struttura dati per la gestione delle immagini

Ecco una rapida spiegazione delle variabili contenute all'interno della struttura dati:• IplImage* img: Un puntatore a una struttura di tipo IplImage. Questa struttura oltre a

contenere l'immagine vera e propria contiene delle informazioni fondamentali sull'immagine: larghezza, altezza, profondità, dimensione, origine e altri dati.

• Xcorner: posizione X dell'angolo superiore sinistro del landmark rispetto all'immagine acquisita da cui è stato estratto.

• Ycorner: posizione Y dell'angolo superiore sinistro del landmark rispetto all'immagine acquisita da cui è stato estratto.

• X, y , distanza, angolo: questi valori verranno riempiti in un momento successivo dagli algoritmi di calcolo.

• Costo: anche questo campo verrà riempito successivamente e rappresenta il “costo” necessario per trasformare il pattern nel landmark ricavato dall'immagine acquisita.

• Colore: è un carattere che identifica il colore del landmark e può essere 'r', 'b' o 'v'.

Gli algoritmi di calcolo richiedono che l'array venga riempito in maniera ben determinata: nella posizione 0 deve essere inserita l'immagine così come è stata acquisita dalla webcam, nella posizione 1 invece deve venir inserito il landmark rosso e nella posizione 2 il landmark blu corredati dai dati necessari. L'idea iniziale era di passare la struttura IplImage direttamente dal programma Java ma poiché era decisamente più semplice far caricare direttamente alla libreria nativa il file immagine si è optato per questa soluzione. È stato necessario realizzare alcuni metodi

39

Illustrazione 37:  Landmark Blu e Rosso

Page 40: Tesi De Franceschi Daniel

per richiedere da Java il caricamento dell'immagine (o del landmark a seconda della posizione nel vettore) con i dati correlati (se necessari). Effettuare il caricamento dell'immagine da C++ è piuttosto simile al corrispondente metodo in Java:

IplImage * img = 0; img = cvLoadImage(fileName);

È importante però fare una precisazione: ogni qualvolta si passa dei parametri alla libreria nativa dal programma Java in verità non si sta passando l'equivalente del tipo che si vorrebbe passare in Java al C++. Se per esempio si decidesse di passare un intero, la libreria nativa riceverebbe un jint, jboolean per un bool, jstring per una stringa e così via. Queste primitive sono definite all'interno della libreria “jni.h” e fintanto si trattano jint o jboolean non si necessita di alcun tipo di conversione mentre il discorso cambia radicalmente nel caso di stringhe poiché i metodi delle librerie OpenCV si aspettano di ricevere un vettore di caratteri (char). La necessità di convertire pertanto i due formati diventa di basilare importanza. Ci vengono in aiuto dei metodi della classe JNIEnv. Ogni qualvolta definisco un metodo nativo che deve essere richiamato da Java, nel sorgente C++ avrà due parametri in più rispetto a quanto è stato definito in Java. Questi parametri sono JNIEnv* jenv, jobject job. Il primo parametro è un puntatore a un oggetto JNIEnv che fornisce una serie di funzioni che possono essere invocate nel codice nativo per accedere all'ambiente Java. Tra le funzioni ci sono quelle adibite alla conversione di stringhe. Il secondo parametro è il riferimento all'oggetto chiamante.

const char *fileName = jenv->GetStringUTFChars(fileNameJ,0);

La stringa però terminato l'utilizzo deve anche essere rilasciata:

jenv->ReleaseStringUTFChars(fileNameJ, fileName);

All'interno della libreria si fa spesso riferimento a dei file di configurazione (nello specifico “pattern.JPG”, “landmark.txt” e “parametri.txt”) che per come è stato scritto il “progetto” originale necessitano di trovarsi nella stessa direcory da cui viene lanciato il programma Java. Nel nostro caso però visto che ci si trova a lavorare con i package e per rendere il tutto più flessibile si è deciso di eliminare questa limitazione. Prima di poter richiamare un qualunque metodo della libreria nativa adibita a funzioni di calcolo sulle immagini è necessario passarle il percorso contenente i files di configurazione.

setConfigurationPath("/percorso/file/configurazione/");

Ora è possibile richiamare dal programma Java i metodi adibiti al caricamento delle strutture dati:

loadImg (path + fileName, 0, true); loadMarker (path + "RED.png", red.getxCorner(), red.getyCorner(), 'r', true); loadMarker (path + "BLUE.png", blue.getxCorner(), blue.getyCorner(), 'b', true);

Questi tre metodi sono metodi nativi e sono ovviamente implementati nella libreria nativa. Il primo metodo richiede il caricamento nella posizione 0 dell'array per la gestione delle immagini l'immagine che è stata acquisita (percorso e nome file). L'ultimo parametro semplicemente specifica se visualizzare o meno messaggi per il debugging. Il secondo metodo invece specifica non solo

40

Page 41: Tesi De Franceschi Daniel

l'immagine da caricare ma anche la posizione dell'angolo superiore sinistro dell'immagine su quella acquisita e il colore del landmark. In base al colore il metodo posizionerà l'immagine e i rispettivi dati nella posizione corrispondente dell'array.

4.2.4. Richiamo degli algoritmi di calcolo

A questo punto è possibile richiamare gli algoritmi di calcolo:

int ok = algoritmo(1);

Il metodo (sempre nativo) deve essere applicato ai due landmark in successione: il parametro specifica a quale landmark applicare le procedure di calcolo e rappresenta la sua posizione all'interno dell'array delle “immagini”. Il valore restituito è un valore intero: se 1 significa che l'operazione è andata a buon fine altrimenti restituisce 0. L'operazione può non andare a buon fine nel caso che l'immagine non possa essere caricata. I risultati dell'elaborazione vengono inseriti nell'array nella posizione corrispondente al landmark che si sta processando nei campi che in precedenza non ci si è preoccupati a ragione di riempire. Si può ora richiamare il metodo di triangolazione (sempre nativo):

ok = triangola(0.0, 1);

Il metodo necessita di due parametri. Il primo è un coefficiente di compensazione dell'errore sistematico sulla distanza ai landmark, infatti se si rileva che l'errore è percentuale nei confronti della distanza è possibile correggere il valore e teoricamente rendere più precisa la misura. Se per esempio in tutte le misurazioni riesco a determinare che l'errore sulla distanza è all'incirca del 7% in difetto posso inserire un coefficiente di errore di 0,07. Il valore può variare nell'intervallo [-1, 1]. Il secondo parametro è il valore che sarebbe stato ritornato dalla procedure di “detect” originale se si fosse deciso di utilizzarla. Il suo valore rappresenta un identificatore alla coppia di landmark acquisita. Abbiamo già fatto notare come a livello teorico nell'algoritmo originale si potessero utilizzare più coppie di landmark. Usando più coppie era però necessario conoscere le posizioni dei vari landmark rispetto allo stesso sistema di riferimento. Le posizioni sono contenute all'interno del file di configurazione “landmark.txt” ma poiché nel nostro caso il landmark è unico il problema del riconoscimento della coppia non sussiste, pertanto in qualunque caso si usano le informazioni della prima coppia. Il metodo restituisce un valore intero: 1 se i landmark necessari all'elaborazione sono stati individuati, 0 altrimenti.

4.2.5. Prima verifica “algoritmica” dei risultati

Se l'operazione precedente è andata a buon fine posso ricevere i valori calcolati tramite altri tre metodi nativi:

double posX = pos_X(); double posY = pos_Y(); double theta = pos_Theta();

Sfortunatamente ci sono delle situazioni (che verranno messe in luce successivamente) per la quale gli algoritmi restituiscono dei valori non validi. Pertanto prima di aggiornare la posizione si verifica che i valori ricevuti non siano di tipo “Nan” (Not a Number).

41

Page 42: Tesi De Franceschi Daniel

if (Double.isInfinite(posX) || Double.isInfinite(posY) || Double.isInfinite(theta) || Double.isNaN(posX) || Double.isNaN(posY) || Double.isNaN(theta)) { return new Results(false, 0, 0, 0, "Un valore è infinito"); } else return new Results(true, posX, posY, theta, "Dovrebbe essere ok");

“Results” non è altro che un classe che viene utilizzata come contenitore per i risultati.

4.3. Integrazione Robot mobile e autolocalizzazione

Le due componenti sono state aggregate in modo tale che fosse possibile sfruttarle in maniera autonoma: la navigazione può funzionare anche senza la localizzazione, la localizzazione può essere usata senza per forza utilizzare il robot mobile. Questo ovviamente ha avuto delle notevoli ripercussioni sul tempo necessario allo svolgimento dei test per la localizzazione: posizionato il robot nel punto voluto e con l'angolo appropriato (era necessario che la webcam visualizzasse i landmark) bastava semplicemente mandare in esecuzione il “Main” della localizzazione per ottenere in una cartella a scelta l'immagine acquisita, le immagini dei landamark estratti e un file di testo con i risultati.

4.3.1. Interfaccia del software

Nonostante fosse possibile realizzare un'applicazione a console era un po' uno spreco oltre che scomodo non utilizzare le capacità “grafiche” di Java nel realizzare in modo semplice e veloce le interfacce grafiche. La realizzazione di interfacce in Java è un argomento molto complesso e anche molto vasto. Dato che non sono uno specialista in questo campo non voglio fare un trattazione su come si costruiscono le interfacce in Java ma solo come sono state graficamente realizzate senza aver la pretesa di aver costruito qualcosa di funzionale e rispettoso degli standard. Una precisazione piuttosto importante riguarda i percorsi delle directory che sono fondamentali per il corretto funzionamento del software. I percorsi devono essere necessariamente passati per parametro al programma nel caso che non si utilizzi la macchina su cui sono state eseguite le prove (il che è ovviamente “logico”). I parametri sono nell'ordine:

• Percorso della directory che contiene la libreria nativa e i due file di configurazione necessari al funzionamento della libreria stessa e il pattern: “landmark.txt”, “parametri.txt”, “pattern.JPG”.

• Percorso dove salvare le immagini temporanee acquisite ed elaborate dal software.

Un esempio di “lancio” in esecuzione potrebbe essere:

java -jar Robot.jar /library/path /img/temp/path

Una volta mandato in esecuzione l'applicativo viene visualizzata una finestra in cui si richiede il nome e il percorso di un file di mappa “.world” da caricare (altro non è che un file di configurazione di mappa di Stage).

42

Page 43: Tesi De Franceschi Daniel

Il caricamento della mappa e la sua elaborazione sono operazioni che possono impiegare molto tempo pertanto si è deciso di inserire una form con barra di scorrimento a “rimbalzo” dotata di una label dove viene visualizzato il nome dell'operazione corrente. Questa form non specifica il tempo rimanente per lo svolgimento delle operazioni ma almeno il programma non appare in uno stato di “stallo”.

Una volta terminate queste operazioni appare un'altra finestra in cui viene visualizzata la mappa dell'ambiente, la posizione del robot oltre ad altre informazioni che possono essere visualizzate o nascoste mediante apposite check-box. Se si vuole mettere in evidenza alcuni aspetti della mappa o dell'elaborazione si può modificare a piacimento il colore di alcune componenti oppure ripristinare il “tema” originale. Cliccando sulla mappa si posiziona il punto di arrivo del robot. Cliccando poi sul bottone “Calcola” il software calcola il percorso minimo tra la posizione attuale del robot e la posizione di arrivo. Durante questa operazione viene visualizzata un'altra form in cui viene evidenziata l'esecuzione dell'elaborazione corrente. Al termine sulla mappa compare il percorso che è stato calcolato. Basta premere il bottone “Run!” per far percorrere al robot il percorso. In qualunque momento è possibile stoppare il robot tramite un'altra pressione sullo stesso pulsante. Un'altra porzione dell'interfaccia è riservata all'aggiornamento della posizione “odometrica” tramite i riferimenti visivi. Alla pressione del pulsante “Modifica tempo per aggiornamento” viene

43

Illustrazione 38: Caricamento mappa

Illustrazione 39: Elaborazione della mappa

Page 44: Tesi De Franceschi Daniel

visualizzata una dialog che richiede l'inserimento del tempo minimo (in secondi) per la ricerca dei landmark e l'aggiornamento della posizione. Questo non significa che esattamente ogni tot secondi il robot cercherà di autolocalizzarsi ma che non tenterà il riposizionamento prima del numero di secondi impostati. Se il numero di secondi impostato è zero il robot non effettuerà mai il riposizionamento.

44

Illustrazione 40: Interfaccia principale

Page 45: Tesi De Franceschi Daniel

5. Risultati sperimentaliTutte le misure effettuate sono stare realizzate nella stessa stanza e con le stesse condizioni di luce e ovviamente con la stessa webcam. I parametri che sono stati inseriti nei file di configurazione sono rispettivamente:

parametri.txt

φ 65°

θy 39°

h 2,345 [m]

θx 50°

RisoluzioneX 640 [px]

landmark.txt

X_Rosso -0,305 [m]

Y_Rosso 0,00 [m]

X_Blu +0,305 [m]

Y_Blu 0,00 [m]

È stata fatta una particolare attenzione nel posizionamento dei landmark sul soffitto. Sul soffitto non erano presenti oggetti o figure che potessero essere facilmente confuse con i landmark posizionati però era fondamentale posizionare i landmark in modo tale da facilitare il più possibile le misure: nel nostro caso era fondamentale che la congiungente i centri dei due landmark fosse parallela all'ascissa del sistema di riferimento pertanto si è scelto di far in modo che le “piastrelle” sul soffitto avessero le loro due dimensioni parallele e ortogonali rispettivamente all'asse delle ascisse. Ne è risultato pertanto che i muri della stanza di test fossero ortogonali e paralleli agli assi di riferimento. Di conseguenza è stato possibile seguire anche le piastrelle sul pavimento. Per comodità è stato proiettato il sistema di riferimento dal soffitto al pavimento dove era possibile con comodità effettuare le misurazioni. La webcam è stata posizionata sul robot all'altezza (fuoco) di 0,405 [m] e all'incirca al centro del robot mobile. Poiché l'altezza del soffitto che è stata misurata era di 2,750 [m] ne è risultato che l'altezza della webcam dal soffitto fosse appunto di 2,345 [m]. La risoluzione della webcam ovviamente era nota mentre gli altri parametri sono stati “stimati” tenendo conto della distanza e dello spazio visualizzato. Supponendo infatti che la distanza dal muro dalla webcam sia “d” e la lunghezza orizzontale visualizzata sia “l” risulta evidente che l'angolo θx sia:

θ x=2artanh l

2d

Lo stesso ragionamento si può applicare all'angolo verticale.

45

Page 46: Tesi De Franceschi Daniel

I landmark sono stati posizionati sul soffitto alle coordinate indicate in precedenza pertanto la distanza tra i due centri risulta essere 0,610 [m].

Sarebbe stato comodo poter posizionare la webcam a 90° rivolta pertanto verso il soffitto ma alcune relazioni all'interno degli algoritmi ce lo hanno impedito: le tangenti come è noto per angoli di 90°

schizzano a infinito. Il problema non sussisterebbe se si trovassero relazioni del tipo valoretg 90°

poiché in questo caso basterebbe aggiungere dei controlli e far risultare il rapporto nullo. Il problema però è che in alcune relazioni appaiono rapporti e differenze di infiniti.

L'angolo che è stato utilizzato (65°) è il medesimo utilizzato per i test della libreria realizzati per il lavoro di tesi precedente. La sua misurazione ha richiesto anche in questo caso un po' di lavoro supplementare poiché l'utilizzo di un goniometro era alquanto scomodo e il risultato non così attendibile. Questo perché l'angolo doveva coincidere con il centro della visuale verticale della webcam. Si è optato pertanto per una soluzione geometrica.

46

Illustrazione 42: Calibrazione Webcam

Illustrazione 41: Misura θx 

webcam

Page 47: Tesi De Franceschi Daniel

Si pone la webcam frontalmente a un muro a distanza fissata “d”. Fissando il tiltangle φ e

conoscendo θy è possibile determinare γ: =− y

2e di conseguenza r=d tan . A questo

punto basta ruotare la webcam fintanto che la parte inferiore dell'immagine acquisita coincide con l'altezza “r”.

Mentre per quanto riguarda le coordinate di posizionamento del robot si è potuto realizzare delle misure piuttosto precise, le misure degli angoli sono state piuttosto approssimative dato gli strumenti a disposizione anche considerando che si mirava più che altro a individuare la direzione del robot piuttosto che l'angolo effettivo.

I risultati delle misurazioni sono visibili nella pagina seguente.

47

Page 48: Tesi De Franceschi Daniel

Teoriche CalcolateX [m] Y [m] Angolo [rad] Angolo [°] X [m] Y [m] Angolo [rad] Angolo [°] dX [m] dY [m] dX/XTeorica*100 dY/YTeorica*100 dDiagonale [m] Errore dist. sul piano [m] Errore Angolo [°]0,835 0,875 2,356 135,000 1,005 0,598 2,235 128,05 0,170 0,277 20,394 31,709 0,040 0,326 6,950,320 0,815 2,793 160,000 0,418 0,743 2,713 155,43 0,098 0,072 30,518 8,838 0,023 0,121 4,570,000 0,860 0,000 0,000 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

-0,395 1,215 -2,618 -150,000 -0,345 1,251 -2,642 -151,4 0,050 0,036 12,750 2,956 0,020 0,062 1,4-0,475 0,705 -2,443 -140,000 -0,397 0,699 -2,682 -153,66 0,078 0,006 16,487 0,853 0,046 0,079 13,66-0,795 0,480 -2,618 -150,000 -0,783 0,377 -2,708 -155,18 0,012 0,103 1,505 21,427 0,060 0,104 5,18-0,755 0,000 -1,571 -90,000 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN-0,755 -0,433 -0,785 -45,000 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN-0,435 -0,620 -0,436 -25,000 -0,542 -0,492 -0,399 -22,88 0,107 0,128 24,548 20,675 0,026 0,167 2,12-0,315 -1,180 -0,175 -10,000 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN0,000 -1,120 0,000 0,000 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN0,000 -0,640 0,000 0,000 -0,069 -0,613 0,005 0,26 0,069 0,027 INF 4,274 0,023 0,074 0,260,290 -1,115 0,262 15,000 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN0,220 -0,620 0,349 20,000 0,155 -0,602 0,228 13,05 0,065 0,018 29,675 2,894 0,036 0,068 6,950,725 -0,820 0,436 25,000 0,743 -0,789 0,553 31,68 0,018 0,031 2,506 3,790 0,011 0,036 6,680,835 -1,405 0,785 45,000 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN1,040 -1,150 0,611 35,000 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN0,995 -0,435 0,873 50,000 1,057 -0,292 1,040 59,58 0,062 0,143 6,261 32,921 0,011 0,156 9,580,970 0,000 -0,873 -50,000 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN0,695 0,380 2,094 120,000 0,751 0,124 1,874 107,37 0,056 0,256 8,004 67,384 0,031 0,262 12,630,855 0,815 2,094 120,000 0,974 0,637 2,163 123,91 0,119 0,178 13,882 21,815 0,018 0,214 3,910,920 -1,115 0,873 50,000 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN0,595 -0,700 0,785 45,000 0,563 -0,703 0,627 35,9 0,032 0,003 5,319 0,371 0,018 0,032 9,1

-0,565 -1,275 -0,524 -30,000 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN-0,435 -0,840 -0,262 -15,000 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN-0,345 -0,530 -0,262 -15,000 -0,477 -0,410 -0,227 -13,03 0,132 0,120 38,206 22,672 0,004 0,178 1,971,305 0,995 2,356 135,000 1,210 1,189 2,502 143,38 0,095 0,194 7,288 19,497 0,055 0,216 8,380,738 0,915 2,618 150,000 0,882 0,787 2,526 144,71 0,144 0,128 19,545 14,042 0,006 0,193 5,290,540 0,565 2,618 150,000 0,676 0,399 2,570 147,27 0,136 0,166 25,201 29,459 0,003 0,215 2,73

-0,850 0,875 -2,443 -140,000 -0,858 0,851 -2,434 -139,44 0,008 0,024 0,946 2,725 0,011 0,025 0,56-0,600 0,535 -2,443 -140,000 -0,534 0,511 -2,491 -142,71 0,066 0,024 11,075 4,405 0,065 0,071 2,71-0,465 1,800 -2,967 -170,000 -0,420 1,833 -2,962 -169,73 0,045 0,033 9,630 1,849 0,022 0,056 0,27-0,830 1,380 -2,443 -140,000 -0,798 1,460 -2,538 -145,4 0,032 0,080 3,875 5,771 0,053 0,086 5,40,170 1,745 2,880 165,000 0,323 1,901 2,985 171,02 0,153 0,156 90,155 8,950 0,175 0,219 6,02

-0,635 1,510 -2,793 -160,000 -0,701 1,697 -2,644 -151,49 0,066 0,187 10,403 12,367 0,198 0,198 8,51-0,545 0,590 -2,356 -135,000 -0,587 0,672 -2,330 -133,52 0,042 0,082 7,673 13,830 0,892 0,092 1,480,370 0,880 2,356 135,000 0,547 0,891 2,295 131,49 0,177 0,011 47,762 1,281 1,046 0,177 3,510,685 -0,335 0,785 45,000 0,758 -0,284 0,722 41,4 0,073 0,051 10,630 15,257 0,809 0,089 3,6

-0,535 -0,345 0,000 0,000 -0,753 -0,131 0,001 0,06 0,218 0,214 40,700 62,091 0,764 0,305 0,060,980 0,565 1,571 90,000 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN0,360 0,600 3,142 180,000 0,530 0,646 3,121 178,82 0,170 0,046 47,222 7,657 0,836 0,176 1,180,350 1,325 3,142 180,000 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

-0,560 -0,360 -0,785 -45,000 -0,733 -0,105 -0,790 -45,26 0,173 0,255 30,913 70,963 0,741 0,309 0,26

Page 49: Tesi De Franceschi Daniel

Le misure di test che sono state effettuate mettono in luce come esistano delle zone “buie” dove la procedura non è in grado di determinare le posizioni della webcam. Questo accade sopratutto sugli assi e nel terzo e quarto quadrante dove la coordinata y (negativa) sembra aver un peso molto maggiore nell'impossibilità di calcolo rispetto al primo e secondo quadrante. In verità si è notato che qualora il robot fosse parallelo a uno dei due assi con una buona probabilità il risultato sarebbe stato non valido. Questo fatto è dovuto all'algoritmo DPW che stima la deformazione. Inoltre la distanza dai landmark appare fondamentale per il calcolo delle misure solamente se ci si trova con la coordinata y negativa. Si è notato che in quelle misure dove i risultati non erano validi (a meno del parallelismo tra assi e robot) bastava far proseguire il robot nella stessa direzione avvicinandolo man mano ai landmark per poter ottenere risultati validi. Pertanto una politica per l'acquisizione dei risultati potrebbe essere questa: qualora il robot cercando di localizzarsi rilevi i landmark ma non sia in grado di calcolare la posizione, verifica di non essere parallelo agli assi (altrimenti deve ruotare) e prosegue diritto nella stessa direzione. Dopo un certo intervallo di tempo se riesce a individuare i landmark prova a ricalcolare la posizione e così via. Tralasciando ora le misure non valide, si vuole individuare il grado di accuratezza delle misure rispetto alla posizione reale. Bisogna però tener conto di un paio di aspetti per poter correttamente interpretare i risultati. Per prima cosa le dimensioni del robot sono abbastanza importanti (~40 [cm] x 40 [cm]) e seconda cosa poiché l'errore odometrico è incrementale anche se si riuscisse a ridurre in maniera non perfetta ma significativa l'errore si potrebbe comunque considerarlo un buon risultato. Si presenteranno ora gli

49

Illustrazione 43: Distribuzione dei test: misure valide e non valide

-1,000 -0,500 0,000 0,500 1,000 1,500

-2,000

-1,500

-1,000

-0,500

0,000

0,500

1,000

1,500

2,000

ValidiNon validi

Page 50: Tesi De Franceschi Daniel

errori sulle due coordinate e infine l'errore sulla distanza tra il punto reale e quello calcolato.

Come si può notare dal grafico precedente gli errori sulla coordinata “x” sono più significativi sul primo e terzo quadrante.

50

Illustrazione 44: Errore sulla coordinata x per le misure valide

-1,000 -0,500 0,000 0,500 1,000 1,500

-1,000

-0,500

0,000

0,500

1,000

1,500

2,000

Validi

Page 51: Tesi De Franceschi Daniel

Cosa analoga avviene per le coordinate y: gli errori maggiori sembrano verificarsi sul primo e terzo quadrante. Per le altre misure non sembra che l'errore sia proporzionale alla distanza.

51

Illustrazione 45: Errore sulla coordinata y delle misure valide

-1,000 -0,500 0,000 0,500 1,000 1,500

-1,000

-0,500

0,000

0,500

1,000

1,500

2,000

Validi

Page 52: Tesi De Franceschi Daniel

Risulta anche in questo caso evidente che gli errori maggiori si verificano sul primo e terzo quadrante e non sembrano dipendere dalla distanza.

52

Illustrazione 46: Errore sulla distanza tra punto reale e calcolato per le misure valide

-1,000 -0,500 0,000 0,500 1,000 1,500

-1,000

-0,500

0,000

0,500

1,000

1,500

2,000

Validi

Page 53: Tesi De Franceschi Daniel

Sul piano quantitativo dei risultati si può dire che le distanze tra i punti reali e calcolati sono comprese tra il 33 [cm] e i 3 [cm] con una media di 15 [cm] di errore. La domanda che ci si pone è se possono essere o meno considerati risultati accettabili. Tenendo presente le considerazioni precedenti (dimensioni del robot e errore odometrico) potremmo considerarli risultati accettabili e utilizzabili: poiché gli errori odometrici possono dimostrarsi piuttosto pesanti (proprio perché incrementali) essere in grado di correggere seppur in modo approssimativo la posizione può rappresentare comunque un buon risultato. Gli angoli, pur considerando la scarsa precisione nella loro misura, presentano delle differenze minime rispetto a quelli calcolati: varia da 13,7° a 0,26° con una media sull'errore pari a 4,65°. Il risultato che ci si proponeva in questo caso era più che altro individuare la direzione del robot più che l'angolo preciso pertanto i risultati ottenuti possono essere considerati ben oltre l'aspettativa.

53

Teoriche CalcolateX [m] Y [m] Angolo [°] X [m] Y [m] Angolo [°] Errore distanza sul piano [m] Errore Angolo [°]-0,850 0,875 -140,000 -0,858 0,851 -139,44 0,025 0,56-0,830 1,380 -140,000 -0,798 1,460 -145,4 0,086 5,4-0,795 0,480 -150,000 -0,783 0,377 -155,18 0,104 5,18-0,535 -0,345 0,000 -0,753 -0,131 0,06 0,305 0,06-0,560 -0,360 -45,000 -0,733 -0,105 -45,26 0,309 0,26-0,635 1,510 -160,000 -0,701 1,697 -151,49 0,198 8,51-0,545 0,590 -135,000 -0,587 0,672 -133,52 0,092 1,48-0,435 -0,620 -25,000 -0,542 -0,492 -22,88 0,167 2,12-0,600 0,535 -140,000 -0,534 0,511 -142,71 0,071 2,71-0,345 -0,530 -15,000 -0,477 -0,410 -13,03 0,178 1,97-0,465 1,800 -170,000 -0,420 1,833 -169,73 0,056 0,27-0,475 0,705 -140,000 -0,397 0,699 -153,66 0,079 13,66-0,395 1,215 -150,000 -0,345 1,251 -151,4 0,062 1,40,000 -0,640 0,000 -0,069 -0,613 0,26 0,074 0,260,220 -0,620 20,000 0,155 -0,602 13,05 0,068 6,950,170 1,745 165,000 0,323 1,901 171,02 0,219 6,020,320 0,815 160,000 0,418 0,743 155,43 0,121 4,570,360 0,600 180,000 0,530 0,646 178,82 0,176 1,180,370 0,880 135,000 0,547 0,891 131,49 0,177 3,510,595 -0,700 45,000 0,563 -0,703 35,9 0,032 9,10,540 0,565 150,000 0,676 0,399 147,27 0,215 2,730,725 -0,820 25,000 0,743 -0,789 31,68 0,036 6,680,695 0,380 120,000 0,751 0,124 107,37 0,262 12,630,685 -0,335 45,000 0,758 -0,284 41,4 0,089 3,60,738 0,915 150,000 0,882 0,787 144,71 0,193 5,290,855 0,815 120,000 0,974 0,637 123,91 0,214 3,910,835 0,875 135,000 1,005 0,598 128,05 0,326 6,950,995 -0,435 50,000 1,057 -0,292 59,58 0,156 9,581,305 0,995 135,000 1,210 1,189 143,38 0,216 8,38

Page 54: Tesi De Franceschi Daniel

6. ConclusioniIn questa tesi è stata realizzata un'applicazione Java che implementa la navigazione di un robot mobile all'interno del simulatore robotico Player-Stage e che impiega un algoritmo di autolocalizzazione basato su riferimenti visivi per azzerare periodicamente l'errore odometrico. Il software di navigazione è un client “Player” che si collega al simulatore robotico “Stage”; il codice dell'autolocalizzazione utilizza in maniera massiccia le librerie “OpenCV” e l'algoritmo “Dynamic Planar Warping” (DPW), sviluppato in una tesi precedente. L'algoritmo DPW permette di calcolare il costo necessario per deformare l'immagine pattern per ottenere l'immagine di test e vengono messi in relazione i pixel delle due immagini. L'algoritmo DPW è implementato in linguaggio C++ ed è stato incapsulato nella classe Java mediante le Java Native Interface (JNI). Sono state ricavate le formule geometriche relative al problema: quelle che legano il robot ai landmark, quelle per il calcolo della distanza tra webcam e riferimenti visivi, quelle per la triangolazione e quelle per il calcolo dell'angolo di rotazione tra sistema di riferimento del robot e sistema di riferimento assoluto.

Il risultato della parte di localizzazione è un insieme di classi in grado di:

1. Catturare un'immagine dalla webcam.

2. Estrarre dall'immagine acquisita i landmark (se presenti).

3. Ricavare mediante il “Dynamic Planar Warping” la relazione tra pixel dell'immagine pattern e quelli dell'immagine del landmark estratto.

4. Determinare la distanza tra la webcam e ogni landmark presente nell'immagine acquisita.

5. Triangolare la posizione del robot in base alle distanze e ottenere le coordinate del robot rispetto al sistema di riferimento assoluto.

6. Calcolare l'angolo tra il sistema di riferimento del robot e quello assoluto.

La parte di navigazione è in grado di:

1. Data la mappa dell'ambiente in ingresso scomporla in poligoni e generare il grafo dell'ambiente.

2. Dati i punti iniziale e finale determinare il percorso più breve fra i due tramite l'algoritmo di Dijkstra: si ottengono pertanto una serie di tratte che devono essere percorse sequenzialmente per raggiungere l'obbiettivo (cioè il punto di arrivo).

3. Far percorrere fisicamente le tratte una dopo l'altra al robot mobile.

L'integrazione tra le due componenti invece permette di:

1. Far percorre al robot una per una le tratte.

2. Verificare il tempo trascorso dall'ultimo aggiornamento della posizione: se questo supera il tempo definito come limite il robot prova ad autolocalizzarsi. Se l'operazione va a buon fine il robot aggiorna la propria posizione, resettando l'errore odometrico, altrimenti percorre un'altra tratta.

Le prove sperimentali sono state effettuate in un unico ambiente con condizioni luminose “costanti” (luce accesa e tende chiuse) e questo ha permesso di garantire la ripetibilità dei test. Sono stati posti due riferimenti visivi sul soffitto a una distanza ben determinata tra i due e in posizione coerente rispetto al sistema di riferimento assoluto (la congiungente tra i due centri dei landmark deve essere necessariamente parallela all'asse delle ascisse del sistema di riferimento assoluto). Il

54

Page 55: Tesi De Franceschi Daniel

robot è stato posto in varie posizioni e con angoli diversi all'interno dell'ambiente: in ogni posizione sono state misurate le coordinate del robot e l'angolo stimato rispetto a un sistema di assi posti sul pavimento e sono state stimate con l'algoritmo proposto posizione e angolo del robot. Dai risultati ci si è resi conto che l'algoritmo “Dynamic Planar Warping” presenta alcune limitazioni: tende a non fornire risultati corretti oppure a non fornire proprio alcun risultato nel caso che il robot sia posizionato parallelamente a uno dei due assi del sistema di riferimento assoluto. Per supplire a questa “mancanza” si potrebbero intraprendere strade diverse. Una prima strada è quella di modificare il “Dynamic Planar Warping” per risolvere queste problematiche. Una seconda possibilità è inserire un terzo landmark vicino agli altri due, magari in maniera tale da formare un triangolo con i centri dei riferimenti visivi e quindi utilizzare due dei tre landmark che non siano “allineati” orizzontalmente o verticalmente nell'immagine acquisita. Un'altra possibilità è di utilizzare un'altra coppia di riferimenti posti ovviamente in un'altra posizione. In questo caso però sarebbe necessario inserire nelle coppie di landmark delle informazioni che permettano di distinguere le coppie fra loro. A questo punto basterebbe effettuare la triangolazione sulle due coppie e nel caso uno dei risultati non sia valido utilizzare l'altro. Ovviamente lo stesso discorso può essere realizzato con più di due coppie. Questa operazione avrebbe inoltre un altro vantaggio: sarebbe possibile gestire ambienti topologicamente più complessi e magari formati anche da più stanze.

I test effettuati mettono in luce come le prove che hanno dato dei risultati siano caratterizzati da un basso errore per quanto riguarda la distanza tra punto reale e calcolato e un basso errore tra angolo calcolato e reale. C'è da segnalare però che definire basso l'errore è subordinato alla precisione che viene richiesta dallo scopo. In questo caso infatti le aspettative erano quelle di correggere errori odometrici che essendo incrementali possono tendere anche a valori piuttosto alti (anche metri per tempi di attività piuttosto lunghi). Con la precisione che abbiamo ottenuto siamo in grado di effettuare anche la prima localizzazione: cioè inizialmente il robot potrebbe non conoscere in alcun modo la propria posizione e pertanto è costretto ad autolocalizzarsi. L'errore iniziale può essere considerato così catastrofico? Probabilmente no poiché se si definisce in maniera “coerente” il tempo tra un aggiornamento e l'altro e i percorsi da percorrere non sono troppo brevi il robot durante il suo movimento si autolocalizzerà altre volte prima di arrivare alla presunta destinazione.

55

Page 56: Tesi De Franceschi Daniel

7. Appendice: How ToUna parte considerevole del tempo che è stato necessario per la realizzazione di questo lavoro è stato speso per far funzionare le tre componenti fondamentali: le librerie OpenCV, Player­Stage e infine la JNI (Java Native Interface). Si spera di far cosa gradita riportando i passaggi fondamentali per il corretto funzionamento delle varie componenti. Il sistema su cui sono state usate e testate le seguenti procedure è una distribuzione Linux: Ubuntu 9.10. Un altro paragrafo di questo capitolo riguarda la soluzione all'impossibilità di utilizzo di alcune webcam da applicazione Java nonostante il sistema operativo le rilevi correttamente.

7.1. Installazione di Player-Stage su Ubuntu/Linux 9.10

Da terminale è necessario installare i seguenti pacchetti: robot­player, stage e tutte le relative dipendenze.

sudo apt-get install robot-player stage

Quando si cercherà di avviare il server con

robot-player world/simple.cfg

Dove “world/simple.cfg” è il percorso e nome di un file di configurazione di player, si riceverà un errore riguardo a un file mancante: rgb.txt.

err: unable to open color database /usr/X11R6/lib/X11/rgb.txt: No such file or directory (stage.c stg_lookup_color)

Per risolvere il problema è necessario recuperare il file rgb dall'url: http://wwwcdf.pd.infn.it/MLO/rgb/rgb.txt e spostarlo nella directory richiesto creando le directory e sotto­directory mancanti.

7.2. Installazione librerie OpenCV su Ubuntu/Linux 9.10

Installare OpenCV su Ubuntu (in questo caso su una 9.10) è un'operazione piuttosto semplice: basta semplicemente installare da repository quei pacchetti che hanno a che fare con OpenCV (compreso libcv-dev). Sfortunatamente non è altrettanto semplice utilizzare le OpenCV tramite Java [19]. Si necessita per prima cosa di “Processing” [16] (non presente nei repository). Dal sito http://processing.org/download/ è necessario scaricare la versione compilata. All'interno di una cartella a scelta è necessario inserire il file “core.jar” (presente all'interno della directory processing-1.0.x/lib), la directory Processing, OpenCV.jar libOpenCV.libjni libOpenCV.so dalla directory OpenCV/library dell'archivio presente all'indirizzo http://ubaa.net/shared/processing/opencv/download/opencv_01.zip

56

Page 57: Tesi De Franceschi Daniel

e la directory hypermedia presente al percorso /OpenCV/source/java/ dello stesso archivio.È necessario creare dei link simbolici ai file libcxcore.so, libcv.so, libcvaux.so, libml.so, libhighgui.so presenti nella directory /usr/lib/nella directory /usr/lib/jvm/java-6-sun-1.6.0.x/jre/lib/i386/.

Inoltre effettuare una copia della libreria libOpenCV.so in /usr/lib (Mi è oscuro perché facendo un link simbolico non funzioni).

Creare i link simbolici dei file libOpenCV.so e libOpenCV.jnilib nella directory /usr/lib/jvm/java-6-sun-1.6.0.x/jre/lib/i386/

7.3. Utilizzo delle JNI in Ubuntu 9.10

Compilare una libreria scritta in C, C++ per poter essere richiamata da un programma in Java è dopotutto abbastanza complesso e come se non bastasse bisogna tener conto della “composizione” del programma Java cioè se è composto da un package oppure se non è contenuto in un “progetto”.Le procedure sono state testate con una Ubuntu 9.10 a 32 bit.

1) Per prima cosa è necessario “dichiarare” all'interno del file Java quali saranno i “metodi” nativi che verranno utilizzati nel programma Java e la libreria che li conterrà (nell'esempio Filtro).

public native int trova(int jarg1, int jarg2, char jarg3); public native void libera_memoria(int jarg1); public native void on_screen(int jarg1, String jarg2);

static { try { System.loadLibrary("Filtro"); } catch (UnsatisfiedLinkError e) { System.err.println("Native code library failed to load.\n" + e); System.exit(1); } }

Ovviamente nel caso che non sia possibile caricare la libreria nativa verrà lanciata un'eccezione di tipo UnsatisfiedLinkError e la stessa eccezione verrà lanciata nel caso che successivamente non sia possibile richiamare un metodo nativo.

2) Il file java deve essere poi compilato e questa operazione può essere fatta o da terminale con javac Main.java

oppure in alternativa utilizzando un qualsiasi IDE come per esempio NetBeans.3) A questo punto bisogna generare l'header del file C/C++. Il comando da eseguire (da 

terminale) nella stessa directory del file class risultato della compilazione del punto precedente è semplicemente:

java -jni Main

Bisogna però tener conto di una complicazione: se si decide racchiudere tutto il programma 

57

Page 58: Tesi De Franceschi Daniel

Java all'interno di un Package è necessario dare il comando non dalla cartella del .class ma dalla cartella precedente a quella che contiene la cartella del Package. Per esempio se il Package è “Prova” e contiene Main.class devo lanciare il comando dalla directory che contiene la directory “Prova”. É necessario però modificare il comando dando non più solo “Main” ma “Prova.Main” cioè Package.FileClass.

4) Il risultato dell'operazione è un file con estensione “.h” che deve essere incluso nel file C/C++ che conterrà i metodi nativi. All'interno dell'header sono ovviamente presenti le dichiarazioni dei metodi nativi che verranno utilizzati dal programma Java ma perché il tutto funzioni è necessario che la loro implementazione nel file C/C++ abbia ovviamente la stessa signature.

5) Una volta implementati i metodi è arrivato il momento di compilare la libreria.

g++ `pkg-config --cflags opencv` `pkg-config --libs opencv` -o libFiltro.so -shared -Wl,-soname,libFiltro.so -I/usr/lib/jvm/java-6-sun-1.6.0.15/include -I/usr/lib/jvm/java-6-sun-1.6.0.15/include/linux/ Filtro.cpp -lc

• pkg­config ­­cflags opencv,  pkg­config ­­libs opencv: pkg­config è una utility che restituisce informazioni sulle librerie installate, in questo esempio le librerie opencv.

• ­o libFiltro.so: Il file di destinazione dell'output. NOTA: il nome della libreria deve essere “lib” seguita dal nome indicato dal file Java (System.loadLibrary("Filtro")) e con estensione “.so”.

• ­shared: serve a compilare la libreria come dinamica.• ­Wl,­soname,libFiltro.so: ­Wl serve a passare dei parametri al linker• ­I/usr/lib/jvm/java­6­sun­1.6.0.15/include ­I/usr/lib/jvm/java­6­sun­

1.6.0.15/include/linux/: Aggiunge la directory alla lista di directory in cui cercare i files di header.

6) Se la libreria compilata non si trova nella stessa directory del file “.class” è necessario specificare al momento dell'avvio o del Package o del semplice class la directory che contiene la libreria tramite l'opzione:

-Djava.library.path=/directory1/:directory2/

NOTE: 1) E' necessario far attenzione ai percorsi eventualmente presenti all'interno del file C/C++ che

si va a compilare. Se per esempio all'interno del codice si richiede l'apertura di un file che risiede nella stessa directory della libreria (es. parametri.txt) ma non è la stessa directory del programma Java compilato si riceverà un errore in apertura del file. Questo è dovuto al fatto che la directory corrente è quella da dove si è avviato il programma, non quella della libreria. Pertanto ci sono più possibilità: la prima è quella di mettere il path assoluto ai nomi dei file il che ovviamente introduce delle limitazioni piuttosto evidenti, un'altra possibilità è quella di passare alla libreria compilata il path dei file di configurazione necessari.

2) Se si avesse la necessità di modificare il nome del file Java o il nome del Package sarebbe necessario ricompilare la libreria nativa sostituendo le signature dei metodi con quelle nuove reperite dalla “compilazione” dell'header ricavato dal file “.java”.

58

Page 59: Tesi De Franceschi Daniel

7.4. Osservazione sul detect dei landmark

La prima parte fondamentale del detect dei landmark è ovviamente l'acquisizione dell'immagine. Purtroppo un problema che si è presentato riguarda l'impossibilità di acquisizione da alcune webcam se al momento dell'esecuzione del programma Java non viene precaricata la libreria condivisa “/usr/lib/libv4l/v4l1compat.so”. Per effettuare questa operazione è necessario anteporre alla chiamata del programma Java il prefisso

LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so

Per esempio se si dovesse lanciare un'applicazione Java “impacchettata” in un package di nome “ProvaOpenCV.jar” dovrei lanciare da shell il comando:

LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so java -jar ProvaOpenCV.jar

59

Page 60: Tesi De Franceschi Daniel

8. Bibliografia

1: Luca Camilotti, Algoritmi visuali per la localizzazione di robotmobili basati sulla programmazione dinamica, 20042: The Player Project, Purpose of the Player Project, 2009, http://playerstage.sourceforge.net/3: Gary Bradski, OpenCV, 2010, http://opencv.willowgarage.com/wiki/Welcome4: G. Bradski, A. Kaehler, Learning OpenCV, O'Reilly, 20085: Schildt Herbert, Java J2SE 6. Guida completa, McGraw-Hill, 20076: Karel Čapek, I robot universali di Rossum, Bevivino, 20067: U. Nehmzow, Robotica mobile. Un'introduzione pratica, Springer, 20088: Dizionario Garzanti, Dizionario della lingua italiana, Garzanti, 20039: Lo Zingarelli, Vocabolario della lingua italiana, Zanichelli, 199610: Cecilia Laschi, Corso di Percezione Robotica, 200911: Marvin Minsky, Seminario svoltosi nel NewHampshire, 195612: G. Dudek, M. Jenkin, Computational Principles of Mobile Robotics, Cambridge University Press, 200013: G. Gini, V. Caglioti, Robotica, Zanichelli, 200314: Ubuntu-it, Cos'è Ubuntu, 2010, http://www.ubuntu.com/; http://www.ubuntu-it.org/15: it.openoffice.org, Benvenuti in OpenOffice.org, 2010, http://www.openoffice.org/; http://it.openoffice.org/16: processing.org, What is "Processing"?, 2010, http://processing.org/17: swig.org, Welcome to SWIG, 2009, http://www.swig.org/18: SUN, Tutorials & Code Camps: JNI Technology, 199919: http://walkintothefuture.blogspot.com/2009/04/opencv-java-linux.html, OpenCV + Java + Linux, 2009

60

Page 61: Tesi De Franceschi Daniel

Ringraziamenti

Al termine di questa tesi non posso non citare tutte quelle persone che hanno reso possibile non solo la realizzazione di questo lavoro ma anche il raggiungimento della mia agognata laurea. Primi fra tutti ovviamente i miei genitori. Per quanto questo non sia un momento molto felice per la nostra famiglia non posso negare di aver sempre avuto il loro supporto.

Un enorme ringraziamento è dedicato al Prof. Massimiliano Nolich con cui ho realizzato questa tesi e che mi ha seguito anche per il tirocinio non solo per la sua sconfinata pazienza nei miei confronti ma anche per la sua grande disponibilità e competenza. Di fondamentale importanza inoltre è stata la sua capacità di arginare il mio pessimismo quando i risultati non mi sembravano poi così soddisfacenti. Un ringraziamento sentito a tutti i professori di facoltà e in genere a tutti quelli che mi hanno seguito in tutti questi anni cercando stoicamente di inculcare nel mio cervello incasinato più che le nozioni in sé (che avrei dimenticato poco dopo ovviamente) la capacità di ragionare. Vorrei ringraziare anche il mio professore di “Sistemi” delle superiori Giuseppe Rossi e la professoressa di “Matematica” Seno Gloria senza i quali la sopravvivenza all'università sarebbe stata decisamente più difficile e traumatica.

Un ringraziamento generale anche alla grande mole di parenti che ho la fortuna di avere, a tutti i cugini/cugine e sopratutto alle due più grandi.

Passando agli amici devo assolutamente citare Diego – il mio migliore amico – e Sara – la sua ragazza – per il loro continuo sostegno, sopportazione e per un fardello non loro. Tutti gli altri amici di Pn: Nico, Michele, Roberto, Manuel, Matteo e tutti quelli che sto ingiustamente ed indecorosamente dimenticando. Tutti gli amici e colleghi di Trieste per aver ascoltato in continuazione (disco rotto potrebbe essere la definizione corretta) le mie continue lamentele. Gli amici e coinquilini Davide, Irene, Giovanni e Alberto per aver sopportato le mie elucubrazioni informatiche o filosofiche e per non avermi ancora fatto ricoverare (forse sopratutto per quello).

Potrebbe sembrare decisamente illogico oltre che inutile “ringraziare” un pc ma in questo caso penso che il mio portatile (il “Vaiolo”) meriti decisamente una menzione d'onore: ha sconfitto l'acqua, la forza di gravità, la mia impazienza e a volta la mia stupidità. Santo subito!

E via verso una nuova avventura!

61