c01e.Document

c01e.Document
Università degli Studi di Bologna
FACOLTÀ DI I NGEGNERIA
Corso di Laurea in Ingegneria Informatica
ROBOTICA I NDUSTRIALE
I NTEGRAZIONE
DI VISIONE ARTIFICIALE E
CONTROLLO REAL TIME PER UN ROBOT
INDUSTRIALE
Tesi di Laurea di:
M ARCO G UIDETTI
Relatore:
C HIAR . MO P ROF. I NG . C LAUDIO M ELCHIORRI
Correlatori:
C HIAR . MO P ROF. I NG . A LBERTO T ONIELLI
D OTT. I NG . A LESSANDRO M ACCHELLI
Sessione Estiva
Anno Accademico 2001/2002
Parole chiave:
robotica
robot COMAU Smart-3S
controllo di robot
real time Linux
visione artificiale
L.A.R., Laboratorio di Automazione e Robotica.
D.E.I.S., Dipartimento di Elettronica, Informatica e Sistemistica.
Università di Bologna.
Le simulazioni sono effettuate in M ATLAB e S IMULINK, M ATLAB e S IMULINK sono
marchi registrati di T HE M ATH W ORKS , I NC .
La tesi è scritta in LATEX 2ε , la stampa è in P OST S CRIPT.
a chi mi ha dato la forza per farcela
iv
Ringraziamenti
Bologna, 17 Luglio 2002
Innanzi tutto vorrei ringraziare i miei genitori per tutto quello che hano fatto
per me in questi anni e per l’appoggio e la tranquillità che mi hanno donato. Un
garzie particolare a Luisa per essermi stata accanto e per avermi supportato in
quest’ultimo periodo. Grazie anche ai miei amici e ai compagni d’appartamento.
Desidero poi ringraziare tutti coloro che mi hanno aiutato a svolgere questa tesi,
in particolar modo vorrei ringraziare Prof. Ing. Claudio Melchiorri per avermi
dato la possibiltà di svolgere la tesi al L.A.R. e per la fiducia concessomi, vorrei
ringraziare Dott. Ing. Alessandro Macchelli per il costante aiuto e Dott. Nicola
Diolaiti per la disponibiltà.
Un grazie particolare anche a tutti i ragazzi del L.A.R. per il magnifico periodo
trascorso insieme.
Grazie a tutti,
Marco Guidetti
vi
Indice
Introduzione
1
1 Descrizione del sistema
1.1 Introduzione . . . . . . . . . . . . . . . . . .
1.2 Il robot SMART-3S e il controllore C3G 9000
1.3 Visione artificiale . . . . . . . . . . . . . . .
1.4 Gripper A.S.I . . . . . . . . . . . . . . . . .
1.5 Il PC IBM-compatibile . . . . . . . . . . . .
.
.
.
.
.
3
3
3
5
5
7
.
.
.
.
.
.
.
.
9
9
10
10
11
14
15
15
23
.
.
.
.
.
.
.
.
.
.
2 Controllo real time
2.1 I sistemi real time: generalità . . . . . . . . . . .
2.2 Real Time Linux . . . . . . . . . . . . . . . . .
2.2.1 Il kernel di Linux . . . . . . . . . . . . .
2.2.2 RTAI-Linux . . . . . . . . . . . . . . . .
2.3 Controllo del robot SMART-3S con RTAI-Linux .
2.3.1 Il modulo Bit3init.o . . . . . . . . . . . .
2.3.2 Il modulo rtai_comau.o . . . . . . . . . .
2.4 Osservazioni pratiche su RTAI-Linux . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
3 Visione artificiale
3.1 Introduzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2 Richiami di ottica e manipolazione d’immagini . . . . . . . . . . .
3.2.1 Ottica geometrica . . . . . . . . . . . . . . . . . . . . . . .
3.2.2 L’algoritmo di Canny . . . . . . . . . . . . . . . . . . . . .
3.3 Distanza fra robot e oggetto: soluzione teorica . . . . . . . . . . . .
3.3.1 Allineamento . . . . . . . . . . . . . . . . . . . . . . . . .
3.3.2 Calcolo della distanza . . . . . . . . . . . . . . . . . . . .
3.4 L’algoritmo di visione artificiale . . . . . . . . . . . . . . . . . . .
3.5 Precisazioni sull’algoritmo di visione . . . . . . . . . . . . . . . .
3.5.1 Arresto del manipolatore per determinare la dimensione dell’oggetto . . . . . . . . . . . . . . . . . . . . . . . . . . .
25
25
25
25
29
30
32
33
33
41
41
viii
Indice
3.5.2
3.5.3
Utilizzo di più fotogrammi nella determinazione
mensione dell’oggetto . . . . . . . . . . . . . .
Un motivo pratico per utilizzare PITCH e YAW
neamento . . . . . . . . . . . . . . . . . . . . .
4 Risulati sperimentali
4.1 Introduzione . . . . . . . . . . . . . . . . .
4.2 Come sono state ottenute le misure . . . . .
4.3 Misura dell’errore di calcolo della distanza .
4.4 Determinazione della costante pixel2cm . .
4.5 Conclusioni . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
della di. . . . . . 42
nell’alli. . . . . . 42
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Conclusioni
45
45
45
46
48
51
53
A I moduli del kernel di Linux
55
A.1 Introduzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
A.2 Moduli: funzionamento . . . . . . . . . . . . . . . . . . . . . . . . 55
A.3 Caricamento automatico di un modulo . . . . . . . . . . . . . . . . 57
B Il robot COMAU Smart-3S
B.1 Introduzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
B.2 Accensione del COMAU Smart-3S . . . . . . . . . . . . . . . . .
B.3 Comunicazione tra controllore C3G 9000 e PC . . . . . . . . . .
B.3.1 Come cambiare della modalità di funzionamento per il controllore C3G 9000 . . . . . . . . . . . . . . . . . . . . .
B.3.2 Come caricare del software nel C3G 9000 . . . . . . . . .
B.4 Calibrazione del COMAU Smart-3S . . . . . . . . . . . . . . . .
B.5 Possibili cause di errore . . . . . . . . . . . . . . . . . . . . . . .
Bibliografia
61
. 61
. 61
. 62
.
.
.
.
62
63
65
66
67
Elenco delle tabelle
4.1
4.2
Tabella errore medio. . . . . . . . . . . . . . . . . . . . . . . . . . 48
Tabella distanza media del bordo dal CdGG . . . . . . . . . . . . . 49
x
Elenco delle tabelle
Elenco delle figure
1.1
1.2
COMAU Smart-3S. . . . . . . . . . . . . . . . . . . . . . . . . . .
Gripper A.S.I.. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.1
Schema di principio di RTAI . . . . . . . . . . . . . . . . . . . . . 12
3.1
3.2
3.3
3.4
3.5
3.6
3.7
3.8
3.9
Ottica geometrica. . . . . . . . . . . . . . . . . . . . .
Calcolo della distanza con telecamera “monoscopica”.
Calcolo della distanza con telecamera stereoscopica. .
Esempio di applicazione dell’algoritmo di Canny. . . .
Telecamera montata su end effector. . . . . . . . . . .
Allineamento. . . . . . . . . . . . . . . . . . . . . . .
Screenshot del software di visione. . . . . . . . . . . .
Allineamento. . . . . . . . . . . . . . . . . . . . . . .
Risoluzione della telecamera. . . . . . . . . . . . . . .
4.1
4.2
4.3
Errore medio per differenti approach. . . . . . . . . . . . . . . . . 46
Errore massimo per differenti approach. . . . . . . . . . . . . . . . 47
Distanza media in pixel. . . . . . . . . . . . . . . . . . . . . . . . 50
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
4
6
26
27
29
30
31
32
34
37
39
xii
Elenco delle figure
Introduzione
La presente tesi è stata sviluppata presso il L.A.R., Laboratorio di Automazione
e Robotica, della facoltà di Ingegneria dell’Università di Bologna. Lo scopo della
tesi è stato quello di integrare, in un unico PC, un sistema distribuito sviluppato in
precedenti tesi [9].
Al L.A.R. è già stato sviluppato un sistema che permette l’afferraggio di un
oggetto collocato nello spazio da parte del gripper A.S.I. montato sul robot COMAU Smart-3S. L’afferraggio avviene con l’ausilio delle informazioni provenienti
da una telecamera posta sul gripper stesso. Questo sistema è distribuito, nel senso
che vi sono tre PC: uno controlla il robot, uno il gripper e l’altro gestisce le informazioni provenienti dalla telecamera e coordina il lavoro svolto dagli altri due. La
comunicazione fra i PC avviene attraverso la LAN1 presente in laboratorio.
Integrare in un unico PC tutta la gestione offre vantaggi legati all’indipendenza del sistema dallo stato della rete locale. Inoltre, offre maggiore velocità nello
scambio di informazioni tra task.
In questa tesi si è appunto integrato il sistema precedentemente descritto. Le
idee teoriche di base rimangono pressochè invariate, ma la realizzazione software
cambia profondamente. Infatti, se da un lato la parte di controllo del manipolatore
e soprattutto quella di controllo del gripper rimangono pressochè immutate, la parte
di visione richiede una profonda rivisitazione. Si deve tener presente che l’integrazione comporta un carico computazionale molto piú elevato, poichè tutto è svolto
da un’unico processore. Alla luce di ciò non è solo necessario modificare la parte
di software legata alla comunicazione fra i task, ma è necessario rivedere tutto il
progetto al fine di evitare sprechi di risorse di calcolo.
Considerando le tre parti del progetto si ha che: il controllo del manipolatore è
già ridotto al minimo e offre poco margine di miglioramento; il controllo del gripper
è eseguito da un processore presente su di una scheda esterna, quindi non sfrutta la
CPU del PC; l’unica parte realmente modificabile è quella di visione artificiale.
Il lavoro di questa tesi è riprogettare il software di visione, al fine di renderlo
compatibile con il funzionamento del sistema nel suo complesso.
1 LAN:
Local Area Network
2
Introduzione
In questa trattazione si è cercato di giustificare le scelte fatte durate lo sviluppo,
non manca nella dissertazione una parte teorica per comprendere le suddette scelte.
In particolare nel capitolo 1 si è voluto fornire una descrizione del sistema nel suo
complesso.
Nel capitolo 2 è stato illustrato il concetto di real time in teoria e nel contesto in cui
si pone questo lavoro.
Nel capitolo 3 sono illustrate le basi teoriche della visione artificiale in generale, e
il software sviluppato.
Nel capitolo 4 sono presentati dei dati sperimentali che giustificano scelte fatte
durante lo sviluppo del software.
Infine, in appendice A sono illustrati alcuni concetti teorici legati al kernel di
Linux; mentre in appendice B viene presentata una guida rapida all’utilizzo del
manipolatore COMAU Smart-3S.
Capitolo 1
Descrizione del sistema
1.1 Introduzione
Una breve introduzione al sistema può essere utile per focalizzare il lavoro svolto in questa tesi. Il sistema è costituito da un manipolatore industriale della COMAU, da una telecamera PULNiX, dal gripper A.S.I. e da un PC che controlla e
coordina tutto.
1.2 Il robot SMART-3S e il controllore C3G 9000
Il manipolatore presente al L.A.R. è costituito dal robot SMART-3S e dal controllore C3G900 della COMAU.
Il robot SMART-3S della COMAU è un manipolatore industriale a sei gradi di
libertà, i giunti sono tutti di tipo rotazionale e vengono controllati da attuatori di
tipo brushless con resolver calettati sull’albero per la misura di posizione. Il manipolatore non possiede il polso sferico, vedi figura 1.1, infatti gli assi di rotazione del
quarto e del sesto giunto giacciono su piani paralleli. Questa caratteristica non permette di disaccoppiare il problema dell’orientamento da quello del posizionamento
nel risolvere la cinematica inversa del manipolatore.
Il controllore C3G 9000 è il “cervello” del manipolatore, si occupa dell’interazione tra robot e operatore, della lettura delle posizione dei singoli giunti, dell’esecuzione dei programmi PDL2 e della determinazione delle correnti da fornire ai
motori.
All’interno del controllore vi è anche la parte di potenza, la quale serve per poter
generare le correnti necessarie al pilotaggio dei motori presenti sui singoli giunti.
4
Descrizione del sistema
Figura 1.1: COMAU Smart-3S.
L’unita di controllo presente al L.A.R. è basata sul bus Motorola VME e comprende tre schede:
1. RBC, gestisce l’interfaccia uomo-macchina e traduce ed interpreta i programmi PDL2;
2. SCC, è responsabile dell’interpretazione della traiettoria, del calcolo della
cinematica inversa, e del controllo di posizione del giunto;
3. Bit3, si occupa della comunicazione e sincronizzazione tra un eventuale PC
esterno e il controllore.
La presenza della scheda Bit3 sul bus VME del controllore permette di poter
comunicare, attraverso un cavo ad alta velocità, con un’altra scheda Bit3 presente
sul bus ISA di un PC IBM-compatibile. Questo offre la possibilità di controllare
il manipolatore dal PC, che si sincronizza con il controllore sfruttando l’interrupt
generato dal controllore stesso.
1.3. Visione artificiale
5
Quindi si intuisce che il manipolatore ha più modalità di funzionamento. Queste
modalità sono cinque e, escludendo quella normale, si distinguono l’una dall’altra
a seconda del punto, nello schema di controllo standard, in cui è aperto il controllore. La modalità che offre maggior libertà è quella in cui il PC legge le posizioni
dei sei giunti, esegue i calcoli necessari e scrive direttamente i setpoint di corrente. In questa modalità il controllore genera un interrupt di sincronizzazione ogni
millisecondo. Questa è l’unica modalità utilizzata nello sviluppo di questa tesi.
1.3 Visione artificiale
Il sistema di visione artificiale è composto da una telecamera PULNiX modello
TM-6CN in bianco e nero con uscita analogica e da un framegrabber. Il sistema è
costituito da un unica telecamera e non da un sistema di visione stereoscopica, ciò
comporta secelte particolari nell’algoritmo di visione per determinare la distanza.
Le caratteristiche hardware, sia della telecamere sia del framgrabber, sono state
tenute in considerazione in fase di progetto sia per la scelta della risoluzione che per
quel che riguarda il numero di frame per secondo (nel caso specifico 30fps).
Il driver per il framegrabber è presente nel kernel ufficiale di Linux, non ha
caratteristiche real time. Quest’ultima affermazione modifica l’algoritmo di presa,
infatti non è possibile associare un’immagine ad un istante preciso oppure ad una
posizione del robot. Per la gestione del framegrabber sono state utilizzate le librerie
libbgrab, questo ha permesso di evitare lo sviluppo delle funzioni di basso livello
per l’accesso alla scheda di acquisizione.
1.4 Gripper A.S.I
Il gripper è una pinza robotica dotata di tre dita identiche e indipendenti. Ogni
dito ha un grado di libertà che gli consente un movimento radiale. Il gripper è in
grado di afferrare oggetti relativamente grandi, ed operare bene anche con oggetti
piccoli, è rappresentato in figura 1.2.
Gli attuatori presenti sulla pinza sono motori di tipo lineare e sono in grado
di sviluppare, considerando le dimensioni ridotte, un’elevata potenza. Inoltre, su
ciascun dito vi sono più sensori:
sensore di posizione, indispensabile per conoscere la posizione del dito ed
eseguire un qualunque controllo;
6
Descrizione del sistema
finger
Falange media
Falange motrice
Attuatore
Figura 1.2: Gripper A.S.I..
sensore di prossimità, permette di avvicinare il dito all’oggetto senza toccarlo, quindi è utilizzato per chiudere in maniera sincrona tutte le dita sull’oggetto stesso;
sensore di forza, necessario per conoscere la forza esercitata sull’oggetto
preso, e per evitare che l’oggetto possa scivolare o essere danneggiato.
La presenza di questi sensori permette di creare più schemi di controllo da utilizzare nel momento opportuno durante la presa. Lo schema totale del regolatore è
formato da più schemi di controllo e seleziona quello da utilizzare in funzione dello
stato in cui si trova. I tipi di controllo realizzati sono i seguenti:
controllo di posizione, viene impiegato nel primo tratto di avvicinamento e
nell’ultima fase di presa;
controllo di prossimità, utilizzato per portare le dita a distanza costante
dall’oggetto e sincronizzarle per l’afferraggio;
controllo misto forza-posizione, utilizzato quando vi è il contatto con l’oggetto per garantire la presa.
È opportuno che la transizione da uno schema di controllo ad un altro avvenga senza
comportamenti bruschi e discontinui.
1.5. Il PC IBM-compatibile
7
Da quanto detto si evince che per controllare il gripper vi è la necessità di un
gran numero di calcoli. Il controllo della pinza è completamente gestito dalla fastprot. Questa è una scheda munita di DSP1 che può essere alloggiata su di un normale slot ISA di un qualsiasi computer IBM-compatibile. La potenza di calcolo
aggiunta dalla fastprot è indipendente dal resto del PC. Il kernel, che viene caricato
nella memoria della scheda DSP, esegue i calcoli necessari al controllo del gripper
e, quindi, svincola il processore del PC da questo lavoro.
Il driver di questa scheda e il software, per caricare il kernel in ambiente Linux,
sono stati sviluppati in precedenti tesi [11], entrambi non sono real time. Il caricamento del kernel nella fastprot avviene prima di eseguire il controllo, quindi non è
un’operazione che necessita dei concetti real time.
Il kernel caricato si occupa della gestione e del controllo del gripper. Un software generico, per utilizzare il gripper, deve solo inviare opportuni comandi al kernel, senza occuparsi di tutto il controllo. Un esempio chiarirà il concetto. Un software generico per far afferrare un oggetto al gripper deve semplicemente mandare
il comando di chisura delle dita al kernel, per far ciò deve scrivere un opportuno
valore ad un particolare indirizzo della fastprot. Il kernel sulla scheda, ricevuto il
comando, esegue tutto il necessari per risolvere il problema, cioè campiona i segnali
provenienti dai sensori del gripper e attua i motori in modo da afferrare l’oggetto.
È importante notare che tutta la gestione del gripper, al livello software, non è
a carico del processore del PC, quest’ultimo può dedicare il suo tempo al controllo
del robot e alla gestione della parte di visione artificiale.
1.5 Il PC IBM-compatibile
Per coordinare il manipolatore, il gripper e per gestire il sistema di visione artificiale si utilizza un normale PC IBM-compatibile. Il PC deve essere sufficientemente
potente e veloce per riuscire a rispondere all’interrupt del C3G 9000, e avere il tempo per eseguire l’algoritmo di visione artificiale. Deve, inoltre, possedere due slot
ISA per poter ospitare sia la scheda Bit3 sia la fastprot.
Il PC, utilizzato durante lo sviluppo di questa tesi, è un Pentium3 a 450 Mhz
con 256 MB di RAM. Sebbene la macchina sia abbastanza potente, lavora al limite
quando deve gestire tutto insieme.
Il sistema operativo presente sul PC è Linux, in particolare la distribuzione utilizzata è la RedHat 7.2. Forse di maggior importanza è il kernel real time utilizzato,
questo è il kernel puro di Linux versione 2.4.4 “patchato” con RTAI 24.1.5. Queste
versioni non sono più le più aggiornate, ma non sono neanche troppo datate. Si1 DSP:
Digital Signal Processor
8
Descrizione del sistema
curamente il kernel utilizzato offre maggior stabilità rispetto a quello usato in tesi
precedenti [9], il quale era una versione test.
Capitolo 2
Controllo real time
2.1 I sistemi real time: generalità
Un sistema software real time può essere definito come un “sistema che riesce
a garantire i vincoli temporali dei processi che manda in eseguzione”. I più noti
sistemi operativi moderni1 garantiscono buone prestazioni medie al sistema, mentre
i sistemi operativi real time rispettano i vincoli temporali del sistema in ogni istante,
penalizzando le prestazioni medie complessive del sistema stesso.
Le applicazioni real time possono essere distinte in due grandi famiglie:
Sistemi soft real time, in cui il software deve essere in grado di rispettare
nella maggior parte dei casi le temporizzazioni.
Sistemi hard real time, in cui il software deve essere in grado di garantire in
ogni caso tempi di risposta massimi.
In altre parole non è possibile basarsi sulla media delle performance per valutare
un sistema hard real time.
Queste riflessioni iniziali portano a definire quali sono le caratteristiche che un
sistema real time deve possedere:
Comportamento deterministico. Il sistema deve essere in grado di mettere in
esecuzione un task RT2 e concluderlo in modo riproducibile e deterministico,
cioè il tempo massimo di esecuzione deve poter essere noto con certezza.
Prontezza. I task RT devono avere latenza minima, cioè l’esecuzione del task
deve iniziare il più rapidamente possibile.
1 Come
2 RT:
ad esempio: UNIX, Linux e vari sistemi operativi di casa Microsoft
real time
10
Controllo real time
Robustezza. Il sistema deve funzionare sempre: un blocco della macchina
non deve avvenire per ovvie ragioni di sicurezza.
Esistono, attualmente, vari sistemi real time tra cui è doveroso citare QNX e
Real Time Linux.
2.2 Real Time Linux
I sistemi real time Linux sfruttano una variante del kernel ufficiale di Linux. Ne
esistono essenzialmente due: RTLinux e RTAI; entrambe si comportano in modo
molto simile e sfruttano le stesse idee di base. Per lo sviluppo delle applicazioni
legate a questa tesi si è deciso di usare RTAI, in quanto precedenti progetti sviluppati
al L.A.R. hanno utilizzato questa piattaforma. Ovviamente si è scelto di utilizzare
il medesimo kernel.
2.2.1 Il kernel di Linux
Il kernel di Linux non nasce per applicazioni hard real time. La struttura interna
è a divisione di tempo ed è studiata per ottimizzare le prestazioni medie del sistema, quindi alcune sue caratteristiche sono in contraddizione con quelle che sono le
esigenze di un kernel real time.
Si può notare che la sincronizzazione a “grana grossa”, utilizzata dai sistemi
Linux, implica che ci siano lunghi intervalli di tempo in cui un task ha l’accesso
esclusivo ad alcuni dati, questo ritarderà l’esecuzione di un processo RT che richieda gli stessi dati. D’altra parte una sincronizzazione a “grana fine” porta allo spreco
di molte risorse per gestire il cambio di contesto, a causa di continui passaggi da un
task all’altro. Linux utilizza quindi una sincronizzazione a grana grossa per ottimizzare la prestazione media. Da non trascurare poi il fatto che Linux concede prima o
poi una time-slice al processo con priorità più bassa, anche nel caso in cui ci sia un
processo più importante pronto ad andare in esecuzione. In un sistema real time un
processo con priorità maggiore non dovrebbe mai attendere a causa di un task con
una priorità minore. In un sistema generico, come Linux, vale la regola che: “tutti
i processi fanno progressi almeno ogni tanto”, questo è inaccettabile per un sistema
real time. Inoltre per ottenere buone prestazioni medie Linux riordina le richieste
di accesso all’hardware da parte dei vari processi al fine di renderne più efficiente
l’uso della macchina e tenta di riunire varie operazioni insieme per sfruttare meglio
l’hardware stesso. Si noti che Linux fa attendere i processi ad alta priorità finché
processi a priorità minore non abbiano rilasciato le risorse necessarie.
2.2. Real Time Linux
11
Linux, inoltre, ha la caratteristica di avere porzione di codice critico eseguito
con interrupt disabilitati. Disabilitare gli interrupt è il modo più semplice per risolvere problemi di sincronizzazione tra processi e di regolamentazione di accesso ad
aree dati comuni. Questa soluzione compromette la possibilità di rispondere immediatamente a richieste che vengono da eventi esterni, cosa inammissibile per sistemi
real time che devono gestire con prontezza segnali provenienti dal mondo esterno
che risultano, per definizione, asincroni.
Molto importanti sono anche le considerazioni su come viene trattata la variabile
temporale dai vari sistemi. Linux offre la possibilità di utilizzare una serie di timer
hardware presenti sulle schede dei PC IBM-compatibili. La risoluzione dei timer è
bassa e la loro accuratezza inadeguata per utilizzarli in applicazioni hard real time.
Da queste considerazioni si evince che Linux, senza opportune modifiche al kernel, è adatto a gestire applicazioni soft real time, ma non è sufficiente per controllare
applicazioni di tipo hard real time
2.2.2 RTAI-Linux
RTAI, acronimo di Real Time Application Interface, non è propriamente un sistema operativo, ma porta delle modifiche al kernel di Linux per trasformare il sistema in modo da poter eseguire applicazioni hard real time. In pratica RTAI funziona
utilizzando il kernel del sistema operativo Linux come un normale processo, eseguito da un piccolo sistema operativo real time. Linux è in realtà un processo in background del sistema operativo real time, e viene eseguito solo quando quest’ultimo
non ha processi real time da eseguire. Linux non può mai disabilitare gli interrupts
o impedire di essere posto in attesa dal sistema operativo real time. L’idea di base
è abbastanza semplice: basta fornire un’emulazione software dell’hardware che gestisce gli interrupts. In pratica, quando Linux invia una richiesta di disabilitazione
degli interrupts al hardware, il sistema operativo real time intercetta la richiesta, la
memorizza e la rigira a Linux come accettata. Cosí facendo non si dà la possibilità
a Linux di disabilitare gli interrupts hardware; indipendentemente dallo stato in cui
si trova Linux non potrà mai inserire ritardi nella gestione degli interrupts da parte
del sistema operativo real time. Tutte le richieste di interrupts da parte dell’hardware vengono intercettate dal sistema real time, che decide casa farne in funzione
dell’handler associato. Se il sistema real time possiede un handler specifico, allora questo viene eseguito, altrimenti significa che tale interrupt è destinato a Linux.
In tal caso il micro kernel ha due possibilità. Se Linux ha gli interrupt abilitati, la
richiesta gli viene passata come emulazione, altrimenti, nel caso in cui Linux abbia tentato di mascherare gli interrupt, il sistema real time marca la richiesta come
pendente, che verrà passata a Linux solo quando riabiliterà gli interrupts.
12
Controllo real time
Interuppts control hard
Real Time kernel
Real Time task
Linux
Real Time FIFOS
Linux processes
Figura 2.1: Schema di principio di RTAI
Per poter realizzare quanto detto in precedenza si sfrutta il concetto di RTHAL 3 .
Questa tecnica consiste nel creare una copia della tabella dei descrittori degli interrupts, intrappolare tutte le funzioni che gestiscono gli interrupts, generare una nuova
tabella di descrittori contenente le routine real time e prendere il controllo del timer
di sistema. Sotto queste condizioni si può affermare che Linux è un task di un sistema real time, un task che verrà eseguito solo quando la parte real time non ha nulla
da fare. Tutto ciò è ottenibile in modo semplice ed elegante sfruttando i moduli 4
del kernel di Linux. Un approccio di questo tipo ha il grande vantaggio che il cambio di contesto tra vari processi real time è particolarmente rapido, infatti i processi
sfruttano lo stesso spazio di indirizzamento. Ha, però, l’inconveniente di portare al
blocco di tutto il sistema nel caso in cui un modulo avesse dei problemi legati a una
non corretta programmazione. I task RT devo quindi essere programmati con molta
attenzione.
Questo modello di gestione del sistema operativo porta necessariamente alla
3 RTHAL:
Real Time Hardware Abstarction Layer.
modulo del kernel è un file oggetto che può essere “linkato” dinamicamente al kernel
stesso, con esso condivide lo spazio d’indirizzamento, quindi può utilizzare funzioni del kernel e
aggiungerne delle nuove.
4 Un
2.2. Real Time Linux
13
definizione di un ulteriore scheduler5 per il micro kernel real time. Questo scheduler
può essere modificato e, essendo un modulo, viene anch’esso caricato nel kernel
dinamicamente. Ciò permette di creare più scheduler e di utilizzare il più opportuno,
in funzione del tipo di macchina e dell’applicazione che dovrà essere eseguita.
Uno scheduler efficiente per un sistema real time ha bisogno di temporizzazioni
precise ed accurate. RTAI ha risolto questo problema utilizzando un timer programmabile6 presente su tutte le schede dei PC IBM-compatibili. Questo timer ha due
modalità di lavoro: oneshot mode e periodic mode. In entrambe le modalità, alla
fine dell’intervallo programmato, vi è la generazione di un interrupt per avvertire
il processore del tempo trascorso. La scelta di una o dell’altra modalità dipende
dall’applicazione. Il periodic mode è adatto per quei task RT che vengono messi
in esecuzione con tempistiche regolari, mentre la modalità oneshot risulta essere
molto più flessibile, ma anche leggermente più gravosa perché il timer deve essere
riprogrammato ogni volta.
Come si è visto, la parte real time del kernel è distinta da quella non real time,
questo ha permesso di poter sviluppare ed ottimizzare le due parti del sistema in
modo separato con vantaggi sia di ottimizzazione che di semplicità. Questo concetto di separabilità della parte real time da quella non real time è vero non solo per il
sistema nel suo complesso, ma anche per le applicazioni che vengono sviluppate sul
sistema stesso. In pratica ogni progetto può essere diviso nelle due parti precedentemente accennate. Per come è stato concepito il sistema si ha quindi che la parte real
time è sicuramente un modulo linkato nel kernel, mentre la parte non real time è
una normale applicazione di Linux. Perciò si ha la necessità di poter scambiare dati
fra il modulo e l’applicazione. RTAI mette a disposizione due modi per scambiare
dati fra kernel space e user space7 :
FIFO: è un semplice buffer real time, gestito come se fosse un file di caratteri
dove il lato real time scrive i dati e il lato Linux li legge o viceversa. Può
essere gestito in due modi: a polling, oppure è possibile associare una funzione handler alla FIFO che viene eseguita quando avvengono degli accessi
in lettura o scrittura sul buffer.
Shared memory: è un area di memoria allocata nel kernel space e condivisa
fra i task real time e i processi di Linux. Questo strumento è molto potente
5 Lo
scheduler è quella porzione del sistema operativo che gestisce le politiche e i meccanismi
interni che stabiliscono l’ordine con cui vengono eseguiti i vari task
6
Ci si riferisce al chip 8254: questo in realtà più che un timer è un contatore, conta, in pratica,
gli impulsi che arrivano su un determinato pin. Se a questo pin è applicato il clock del sistema il
contatore si trasforma in un ottimo timer, che, tenuto conto delle frequenze di lavoro dei moderni
processori, ha anche un elevata risoluzione.
7 Per user space si intende quello spazio di indirizzamento dove vengono eseguite le applicazioni
utente, esso è distinto e separato dal kernel space che è lo spazio di indirizzamento dove viene
eseguito il kernel e quindi tutti i task real time.
14
Controllo real time
perché è privo di limitazioni, ma ciò implica che le regole per un corretto
accesso ai dati devono essere create di volta in volta con molta attenzione.
Le applicazioni real time che, per necessità o comodità, vogliono offrire all’utente finale un’interfaccia grafica per gestire il micro kernel real time, traggono
vantaggio dalla sinergia tra task RT e processi Linux.
2.3 Controllo del robot SMART-3S con RTAI-Linux
Il sistema real time utilizzato al L.A.R. per controllare il robot SMART-3S è
RTAI-Linux. Tralasciando dettagli tecnici su come è realizzato il collegamento
hardware tra PC e robot8 , è sufficente sapere, per comprendere i concetti che stanno alla base del controllo real time, che sul bus ISA del PC è montata un scheda
chiamata Bit3, la quale è collegata direttamente al controllore. Leggendo opportune aree di memoria della suddetta scheda, è possibile conoscere la posizione dei
motori del robot e scrivendo su altre locazioni, è possibile imporre determinate correnti ai motori stessi. Inoltre ogni millisecondo il controllore genera un interrupt di
sincronizzazione e si aspetta che dopo 800µs siano presenti, in un’opportuna zona
di memoria, i valori di corrente da imporre ai motori. L’ordine di grandezza delle
tempistiche in gioco permette di intuire che il rispetto delle temporizzazioni è estremamente importante e si comprende quindi la necessità di utilizzare un sistema real
time per gestire il robot.
Considerando che i task real time sono in realtà dei moduli del kernel e che, nel
caso specifico, bisogna creare un driver per la scheda Bit3, si devono tener presente
tutte quelle funzioni presenti nel kernel che servono per gestire le periferiche e tutte
quelle regole per creare dei driver teoricamente corretti [10].
Per questa specifica applicazione si è deciso di creare due moduli distinti:
Bit3init.o: inizializza la scheda Bit3;
rtai_comau.o: controlla il robot in real time.
Questi due moduli hanno caratteristiche profondamente diverse: il primo ha
solo il compito di inizializzare la scheda Bit3 e non ha caratteristiche real time,
mentre il secondo si occupa del controllo in tempo reale del robot. Tener separate
le funzionalità permette di modificare la parte real time senza dover modificare
l’inizializzazione della scheda e viceversa; inoltre permette di ridurre al minimo
necessario il modulo real time, il quale risulta essere più leggero da mandare in
esecuzione. Entrando nel cuore del progetto queste caratteristiche sarrano spiegate
con più dettaglio.
8 Si
veda a tal proposito il capitolo 1
2.3. Controllo del robot SMART-3S con RTAI-Linux
15
2.3.1 Il modulo Bit3init.o
Questo modulo ha il compito tipico di un driver per periferica, cioè nel momento
in cui viene caricato nel kernel riserva le aree di memoria utilizzate dalla scheda e le
rilascia quando viene scaricato. Ha anche il compito di verificare che sia possibile
comunicare con il controllore del robot. Nel caso in cui questo non fosse possibile il
modulo libera le risorse e si “stacca” dal kernel. Quest’ultima caratteristica è molto
importante perché il modulo rtai_comau.o (che verrà descritto in seguito) richiede
esplicitamente che il modulo che inizializza la scheda sia “linkato” con il kernel. In
pratica la presenza del modulo Bit3init.o nello spazio di indirizzamento del kernel
è garante del fatto che esiste la comunicazione tra PC e COMAU e che la scheda
Bit3 è stata inizializzata correttamente.
2.3.2 Il modulo rtai_comau.o
Il modulo rtai_comau.o è il più importante, è quello che controlla il robot COMAU SMART-3S. Il compito principale che deve svolgere è rispondere all’interrupt
generato dal robot, ma non si possono trascurare tutte quelle operazioni che svolge per rendere il modulo veramente funzionale. Operazioni come, ad esempio, la
creazione delle FIFO fra user space e kernel space, che servono per far si che un
programma svillupato per Linux possa dare dai comandi al robot, e la creazione di
tutti quei meccanismi che servono per “ingegnerizzare” il progetto 9 .
È possibile raggruppare il lavoro svolto da questo modulo in tre macro compiti:
1. richiesta di un interrupt real time, questo interrupt non è mascherabile e
la funzione che gli viene associata è quella che, dopo opportuni controlli,
calcola le correnti da imporre ai motori;
2. creazione di un task periodico, questo task periodico ha il solo compito di
filtrare l’interrupt spurio;
3. creazione di FIFO per i comandi, queste FIFO servono per permettere il
controllo e il monitoraggio del robot da parte di applicazioni che operano nel
user space.
Entrando nel dettaglio delle singole voci è possibile precisare alcuni concetti. È
importante sottolineare che la separazione dei compiti è una scelta “didattica” per
9 Per
“ingegnerizzazione” del progetto si intendono tutte quelle funzioni che automatizzano alcune parti del sistema in modo da rendere il sistema stesso utilizzabile anche da persone che non conoscono profondamente i concetti fondamentali che stanno alla base del progetto. Si veda l’appendice
A per maggiori dettagli.
16
Controllo real time
far comprendere meglio il lavoro svolto da questo modulo, ma in realtà le tre voci
citate andrebbero viste come un tutt’uno.
Interrupt non mascherabile
Questo interrupt è gestito da RTAI. Il segnale che lo genera arriva direttamente
dal robot e la funzione che permette di associare il segnale al handler è la seguente:
void intr_handler(void)
{
/*
* Funzione associata al interrupt
* Viene eseguita tutte le volte che arriva l’interrupt numero 3.
* Non ha parametri d’ingersso ne di uscita.
*/
...
}
int init_module(void)
{
int res;
...
if((res=rt_request_global_irq(3,intr_handler))!=0)
return res;
...
}
void cleanup_module(void)
{
...
rt_free_global_irq(3);
...
}
Il codice che deve svolgere l’elaboratore per rispondere al interrupt è quello contenuto nella funzione intr_handler(). In questa funzione si eseguono i controlli
per assicurarsi che le posizioni dei giunti siano entro i limiti prefissati, le correnti
non superino i valori prestabiliti e i giunti non risultino bloccati. Se tutte le verifiche
vanno a buon fine allora viene invocata la funzione che ha il compito di calcolare
le correnti da attuare ai motori. Il codice dell’interrupt handler viene riportato per
permettere al lettore di comprendere meglio la funzione stessa.
2.3. Controllo del robot SMART-3S con RTAI-Linux
17
void intr_handler(void)
{
int err_CJL=0,err_CSL=0,err_CJB=0;
if (countint>8) {
outb(1,0x378);
countint=0;
WriteCurrents(currents0);
ReadMotorPositions(positions);
err_CJL=CheckJointLimits(positions);
err_CSL=CheckSpeedLimits();
err_CJB=CheckJointBlocked();
if ((!err_CJL)&(!err_CSL)&(!err_CJB)) {
save_cr0_and_clts(linux_cr0);
save_fpenv(linux_fpe);
restore_fpenv(task_fpe);
error_controllo=controllo(positions,currents);
save_fpenv(task_fpe);
restore_fpenv(linux_fpe);
restore_cr0(linux_cr0);
if (!error_controllo) {
WriteCurrents(currents);
for(i=0;i<6;i++)
oldpositions[i]=positions[i];
} else {
WriteCurrents(currents0);
DriveOff();
rt_disable_irq(3);
}
} else {
WriteCurrents(currents0);
DriveOff();
rt_disable_irq(3);
}
outb(0,0x378);
}
}
La funzione principe in questa routine è controllo(). In questa funzione si
usano pesantemente variabili reali e quindi si sfrutta la FPU10 . Per avere un cambio
di contesto più rapido, RTAI non salva di default lo stato della FPU passando da un
10 FPU
è l’acronimo di Floating Point Unit.
18
Controllo real time
task a un altro. Per evitare errori, è opportuno salvare esplicitamente lo stato della
FPU nel momento in cui si ha necessità di utilizzare tale unità e di ripristinarlo non
appena questo utilizzo termina. Questo è il significato del codice appena prima ed
immediatamente dopo l’invocazione della funzione controllo(). In tale funzione
si rende anche necessario l’utilizzo di variabili definite static11 , in caso contrario
si ha un improvviso crash del sistema. Questo è inaccettabile. Se il PC esegue un
riavvio non può più rispondere all’interrupt generato dal robot e quindi , poichè
l’ultimo valore scritto nella memoria del controllore è correnti nulle, si ha la caduta
del robot attratto dalla forza di gravità. Si noti anche che se il comportamento del
sistema fosse diverso, il crash del PC è in ogni caso inaccettabile. Si pensi come
caso estremo al controllo di un razzo per messa in orbita di satelliti, un crash del
sistema porterebbe ad una catastrofe.
Quando viene invocata la funzione controllo(), si ha la scrittura del valore
logico alto sulla porta parallela, quando termina il valore viene riportato a zero.
Questo genera un impulso sulla porta parallela, la cui durata coincide con il tempo
che impiega il processore ad eseguire i calcoli per rispondere al interrupt. Sebbene,
tutto questo, possa sembrare a prima vista inutile, è in realtà molto importante per
due motivi. Il primo motivo è sicuramente la possibilità di verificare che la scrittura
delle correnti da attuare avvenga veramente prima dei 800µs imposti dal COMAU; il
secondo è la possibilità di avere un’idea di quanto tempo il processore ha impiegato
per rispondere all’interrupt e, di conseguenza, quanto tempo rimane al sistema per
svolgere altre funzioni. Quest’ultimo dato è importante perchè fornisce un idea di
quanto tempo rimane al processore per svolgere applicazioni differenti dal controllo
del robot, come, ad esempio, un programma di visione artificiale.
Un’altra caratteristica di questo codice, che a prima vista può sembrare bizzarra,
è che, in realtà, i calcoli, necessari per conoscere le correnti, vengono svolti tutte le
volte che arriva un interrupt e che la variabile countint è maggiore di 8. Questo
serve per non considerare l’interrupt spurio che arriva ogni dieci millisecondi. La
tecnica utilizzata è estremamente semplice e sarà più chiara in seguito.
Creazione di un task periodico per il filtraggio dell’interrupt spurio
Testando l’arrivo degli interrupt è possibile osservare che ogni dieci millisecondi ne viene generato uno spurio ad una distanza di circa 200µs dal precedente. Con
11
Le variabili static sono locali al blocco in cui sono definite ma hanno durata pari a tutto
il tempo di vita del programma. Esse, pertanto, esistono prima che la funzione in cui sono definite
venga mandata in esecuzione e continuano ad esistere anche al termine della funzione stessa. Questo
evita un riallocazione delle risorse ogni volta che una funzione viene mandata in esecuzione, ma
necessitano di una maggior attenzione da parte del programmatore perché i valori in esse contenuti
sono persistenti.
2.3. Controllo del robot SMART-3S con RTAI-Linux
19
una misura del tempo precisa è possibile filtrare questo segnale spurio, escludendo
tutte le chiamate che distano meno di un intervallo di tempo prefissato dalla chiamata precedente. In pratica, il problema è risolvibile con un task periodico, con
periodo di 100µs, che incrementa un contatore tutte le volte che viene invocato. La
routine dell’interrupt dovrà quindi solo controllare che questo contatore abbia superato un valore prefissato. Nel caso in cui il controllo abbia risultato positivo viene
eseguito il codice del handler e riazzerato il contatore, altrimenti si esce senza far
nulla. Da queste parole è possibile comprendere perché e presente un controllo sulla
variabile countint nella routine di risposta all’interrupt, nel caso specifico si vede
che devono essere trascorsi almeno 800µs dalla chiamata precedente.
Il codice necessario per creare un task che viene mandato in esecuzione ogni
100µs è il seguente:
#define TICK_PERIOD
RT_TASK thread;
100000
static void intr_filtro(int t)
{
while(1) {
countint++;
rt_task_wait_period();
}
}
int init_module(void)
{
RTIME t_period;
...
#ifdef ONE_SHOT
rt_set_oneshot_mode();
#endif
rt_task_init(&thread,intr_filtro,0,STACK_SIZE,0,0,0);
t_period=start_rt_timer(nano2count(TICK_PERIOD));
rt_task_make_periodic(&thread,rt_get_time()+2*t_period,t_period);
...
}
È importante osservare che, come già accennato, RTAI usa un contatore come
timer, il quale ha come base di conteggio il clock di sistema. Al fine di rendere il
codice più portabile ed indipendente dalla frequenza del processore, si è utilizzata
la funzione nano2count(TICK_PERIOD) che converte i nano-secondi in numero di
clock macchina.
20
Controllo real time
Creazione delle FIFO di comunicazione fra user space e kernel space
Un task real time per il controllo di un robot senza possibilità di interagire con un
operatore esterno ha, sicuramente, un utilizzo limitato. Per ovviare a questo inconveniente nel modulo rtai_comau.o sono state create varie FIFO di comunicazione
tra user space e kernel space.
Tre sono le FIFO fondamentali in rtai_comau.o:
1. FIFO per comandare il robot. Questa FIFO permette di eseguire semplici
ma essenziali operazioni, come accendere e spegnere i motori del robot, oppure fermare il robot mentre esegue una determinata traiettoria cercando di
raggiungere un set point.
2. FIFO per controllare il robot. FIFO di maggior importanza per il controllo
del robot. È in questa coda che vengono scambiati i dati necessari per il
movimento del COMAU. È possibile chiedere al modulo di scrivere sulla
FIFO la posizione angolare di un singolo giunto e leggerla in un secondo
momento da un’applicazione che opera nel user space, oppure, viceversa, è
possibile fornire dei set point ai singoli giunti. Altri movimenti sono stati
implementati, come la possibilità di muoversi nelle direzioni definite dalle
terne cartesiane più caratteristiche della robotica. Impostate velocità massima
e direzione è possibile muovere il robot dando i comandi di START e di STOP,
oppure è possibile fornire un offset in centimetri. Nel caso in cui sia fornito
un offset, il modulo comunicherà il raggiungimento della posizione attraverso
la FIFO per i responsi dal robot.
3. FIFO per attendere responsi dal robot. FIFO che viene utilizzata dal modulo nel kernel per comunicare il raggiungimento di una posizione richiesta
in precedenza.
Tutte queste FIFO possono essere considerate sia dal lato utente sia dal lato
kernel, entrambi gli aspetti sono interessanti. Per spiegarne il funzionamento e il
tipo di utilizzo verrà presa in considerazione la FIFO per comandi, i concetti sono facilmente estendibili alle altre. Questa FIFO è unidirezionale; le applicazioni
presenti nel user space scrivono i comandi da passare al modulo, appena entrano
nella coda il kernel se ne accorge ed invoca l’handler associato. Entrando nel dettaglio, tenendo separati i due spazi di indirizzamento, è possibile comprendere il
funzionamento.
Considerando la FIFO per i comandi, vista dal lato del kernel space, si possono fare importanti osservazioni. Il codice sotto riportato rappresenta una parte di
modulo che sfrutta le FIFO RTAI per comunicare con altre applicazioni.
2.3. Controllo del robot SMART-3S con RTAI-Linux
#define CMDF
#define CMDFSize
21
0
1000
struct my_msg_struct_controllo {
int command;
...
};
int CMDF_handler(unsigned int fifo, int rw)
{
struct my_msg_struct msg;
if (rw == ’w’) {
rtf_get(CMDF,&msg,sizeof(msg));
switch (msg.command) {
...
case DRIVE_ON:
/*
* Codice per accendere i motori del COMAU
*/
break;
...
}
}
...
}
int init_module(void)
{
...
rtf_create(CMDF,CMDFSize);
rtf_create_handler(CMDF, X_FIFO_HANDLER(CMDF_handler));
...
}
La cosa più importante che si intuisce dalla gestione della FIFO, è la possibilità
di associare una funzione che venga invocata in modo automatico tutte le volte che
qualche task esegue una scrittura o lettura sulla coda. Nell’esempio riportato si ha
che, appena un’applicazione scrive o legge un valore sulla FIFO, viene eseguita
la funzione CMDF_handler(), la quale controlla se è avvenuta una scrittura nella
coda e in tal caso legge il valore presente nella FIFO stessa. Questa gestione è
estremamente intelligente, perché è possibile sincronizzare il modulo caricato nel
kernel con eventi asincroni, tipici del mondo esterno, senza aver la necessità di
22
Controllo real time
eseguire inutili polling sulla risorsa interessata, polling che porterebbe solo allo
spreco di risorse di calcolo.
Considerando ora le applicazioni che vengono eseguite nel user space, un esempio di programma potrebbe essere:
struct my_msg_struct_controllo {
int command;
...
};
void WriteToFifoCmd(int data)
{
struct my_msg_struct msg;
msg.command=data;
write(cmd,&msg, sizeof(msg));
}
int main()
{
int cmd;
...
if ((cmd = open("/dev/rtf0", O_WRONLY)) < 0){
exit(-1);
}
...
WriteToFifoCmd(DRIVE_ON);
...
close(cmd);
}
Si nota immediatamente che le FIFO vengono gestite come normalissimi file,
è questo, forse, il loro maggior vantaggio. Questa caratteristica permette di utilizzare il robot pur non avendo nessuna conoscenza di programmazione real time, ma
conoscendo solo cosa scrivere e leggere nelle FIFO create dal modulo rtai_comau.o.
Nel modulo rtai_comau.o si sono utilizzate le FIFO sia per la loro facilità di
utilizzo, sia perché non vi è la necessità di trasferire grandi quantità di dati. Un’alternativa alle FIFO esiste, è la “shared memory”, ma poichè necessita di grande
quantità di codice scritto per regolamentare gli accessi in memoria, il suo utilizzo
in questa applicazione non è giustificato.
2.4. Osservazioni pratiche su RTAI-Linux
23
2.4 Osservazioni pratiche su RTAI-Linux
Si è già accennato alla necessità che un sistema real time sia particolarmente
stabile e robusto. Il kernel di Linux è famoso per la sua estrema stabilità. Questa
caratteristica aiuta molto chi sviluppa applicazioni real time basandosi su un’accoppiata vincente, RTAI-Linux. Se i task real time sono ben testati, difficilmente
capiteranno spiacevoli sorprese. Inserire un modulo nel kernel è anche un modo per
metterlo al riparo da tutte le applicazioni presenti nel user space. È capitato che,
per errori grossolani dello sviluppatore (errori miei), il sistema si bloccasse. Nonostante ciò si è notato che il kernel, e solo quello, continuava a funzionare. Quindi
anche se tutte le applcazioni ad alto livello erano bloccate, il task real time continuava a leggere le posizioni dei giunti, calcolare le correnti da attuare e scriverle sulle
opportune aree di memoria. Tutto questo è prova di grande stabilità ed affidabilità.
24
Controllo real time
Capitolo 3
Visione artificiale
3.1 Introduzione
Nella robotica vengono spesso utilizzate celle di lavoro dove eventuali oggetti,
che un manipolatore deve afferrare, sono in posizioni precise e prestabilite. D’altra
parte, la multimedialità sta in questi ultimi tempi diffondendosi a 360 gradi, raggiungendo livelli tecnologici impensabili fino a pochi anni fa. Anche la robotica
è stata, per certi aspetti, contagiata da questa evoluzione. Non sono rari robot che
parlano, ascoltano e soprattutto vedono. Partendo da questo presupposto è facile immaginare robot, che dotati di telecamera, afferrano oggetti nello spazio non
conoscendone la posizione a priori.
3.2 Richiami di ottica e manipolazione d’immagini
È opportuno, al fine di comprendere meglio quello che verrà trattato in seguito,
riprendere alcuni concetti basilari dell’ottica geometrica. Verrà inoltre introdotto un
algoritmo di manipolazione dell’immagine, che permette di rilevare il contorno di
un oggetto ripreso da una telecamera.
3.2.1 Ottica geometrica
L’ottica geometrica è una branca della fisica che considera le onde elettromagnetiche nel campo del visibile, e sfrutta la geometria per spiegare come esse si
propagano. Questo tipo di approccio è valido fintantoché le discontinuità incontrate dall’onda nella sua propagazione hanno dimensioni molto grandi rispetto alla
26
Visione artificiale
lunghezza d’onda. Generalmente una telecamera rispetta questa ipotesi. Pochi e
semplici concetti sono sufficienti per comprendere quello che segue [1].
Fondamentale è sapere come si comporta un raggio luminoso che attraversa una
lente, e viene proiettato su di una superficie che è posta a distanza fissa dalla lente
stessa. Si consideri la figura 3.1. Un raggio luminoso che parte dal punto P, dopo
L
P
H
S
F
O
α
h
P’
l
Figura 3.1: Ottica geometrica.
aver attraversato la lente, colpisce la superficie S nel punto P’. Si definisce fattore
d’ingrandimento di una lente il valore M ottenuto come:
M
h
H
dove h è la distanza tra il punto P’ e l’asse principale della lente1 , mentre H è la
distanza tra P e il medesimo asse. Osservando la figura, è possibile notare un’altra
proprietà, infatti può essere ricavata la seguente equazione:
tan α
H
L
h
l
(3.1)
dove L è la distanza tra la proiezione del punto P sull’asse principale e il punto O 2 ,
e l è il suo analogo nel lato opposto della lente. Da questa equazione si conclude
che: considerando noto l e misurabile h, si ha che, data la distanza tra il punto P e
l’asse principale della della lente è ricavabile L, e viceversa.
Si noti inoltre che una telecamera può essere vista come un trasduttore che trasforma in segnale elettrico un raggio luminoso proveniente da un oggetto, e che può
essere schematizzata come in figura 3.1 dove S rappresenta il sensore CCD 3 .
1 L’asse
principale della lente è definito come la retta passante per i centri che definiscono le due
semicirconferenze che generano la lente.
2 Il punto O è detto centro ottico della lente ed è definito come il punto tale che ogni raggio
passante per esso esce in una direzione parallela al raggio incidente.
3 CCD: Charged Coupled Device. Dispositivi allo stato solido ad accoppiamento di carica, che
trasformano l’energia luminosa ricevuta in energia elettrica.
3.2. Richiami di ottica e manipolazione d’immagini
27
Tenedo conto delle affermazioni fatte fin ora, è possibile concludere che: se non
si conosce la dimensione dell’oggetto a priori, le informazioni contenute in un unico
fotogramma sono insufficienti per calcolare la distanza fra la telecamera e l’oggetto.
Si ha quindi la necessità di ottenere informazioni di due fotogrammi distinti. Due
strade sono percorribili per risolvere il problema e possono essere classificate in
funzione della telecamera che si utilizza.
1. Telecamera “monoscopica”: telecamera di tipo classico con un solo obiettivo. Per aver due fotogrammi distinti bisogna necessariamente scattarli in
istanti diversi, spostando la telecamera per ottenere due immagini differenti.
2. Telecamera stereoscopica: telecamera speciale con due obiettivi con assi
ottici paralleli. Questi permettono di riprendere la stessa scena da due punti
differenti nel medesimo istante.
Quello che non si può fare nello spazio si fa nel tempo, questa è la differenza che
si ha a seconda della telecamera adottata. Va da se che, nel caso di telecamera non
stereoscopica, l’oggetto di cui si vuole conoscere la distanza non si deve muovere
fra i due “scatti”.
Calcolo della distanza con telecamera “monoscopica”
Questo metodo di calcolo è, almeno teoricamente, molto semplice. Consiste
nel riprendere un oggetto fermo da una distanza incognita, allontanare la telecamera con offset noto e riprendere nuovamente l’oggetto. Valutando la variazione di
dimensione dell’oggetto, è possibile conoscerne la distanza dalla telecamera. La
situazione appena descritta è rappresentata in figura 3.2, dove è schematizzata una
L1
L2
P
P
H2=H1
α2
α1
S
O
h2 h1
l 1=l2
Figura 3.2: Calcolo della distanza con telecamera “monoscopica”.
telecamera e un punto P ripreso da due differenti distanze. Da questa schematizzazione è possibile trarre alcune conclusioni. Applicando l’equazione 3.1 nei due casi
28
Visione artificiale
è possibile ottenere il seguente sistema:
L1
l1
H1
h1
l2
H2
h2
L2
da cui con qualche passaggio si ottiene:
L1
A
h1
h1
dove
h2
A
L2
L1
(3.2)
Alcune osservazioni sono doverose. Si noti che il risultato L1 è dipendente solo
dalla differenza delle distanze da cui si riprende l’oggetto, e che il risultato ha la
stessa unità di misura di A visto che la frazione è adimensionale. Quest’ultima
affermazione permette anche di concludere che non si ha la necessità di conoscere
la dimensione reale dell’oggetto, e che h1 e h2 non devono essere una lunghezza,
ma possono anche essere misurati in pixel.
Calcolo della distanza con telecamera stereoscopica
Questo metodo di calcolo utilizza una base teorica semplice, ma richiede molta
accuratezza nel realizzare la telecamera.
Una telecamera stereoscopica può essere schematizzata come in figura 3.3, cioè
come due telecamere separate con assi visivi paralleli. Dato un punto P, i due raggi
luminosi, che partono dal punto stesso, passanti per i centri delle due lenti, formano
con gli assi ottici delle telecamere due angoli. Senza entrare nel dettaglio della dimostrazione, noti questi angoli e alcune caratteristiche costruttive della telecamera
stereoscopica, è possibile determinare la distanza che separa il punto P dalle lenti
della telecamera, cioè:
L
f α 1 α2 l d
(3.3)
È necessario che i due assi ottici siano paralleli e che i due sensori CCD siano
perfettamente sincronizzati nell’acquisire l’immagine. Quindi, ad ogni punto dell’immagine ripresa da un’obiettivo della telecamera che abbia un corrispondente
nel fotogramma catturato dall’altro obiettivo, è possibile associare una distanza del
punto dalla telecamera.
Si intuisce che diventa fondamentale trovare lo stesso punto dell’oggetto in entrambi fotogrammi, per poter determinare la distanza di quel punto dalle telecamere, tale ricerca è un compito gravoso. Particolari accorgimenti costruttivi possono ridurre l’insieme dei pixel in cui cercare il punto. Queste osservazioni portano
3.2. Richiami di ottica e manipolazione d’immagini
H1
29
H2
P
L
O1
O2
l
α1
α2
P’
S1
h1
P’’
S2
h2
d
Figura 3.3: Calcolo della distanza con telecamera stereoscopica.
alla conclusione che non è possibile ottenere una telecamera steroscopica mettendo insieme due telecamere classiche, è, invece, necessario che venga costruita e
progettata come un unica telecamera.
3.2.2 L’algoritmo di Canny
Nei problemi di afferraggio è fondamentale conoscere la forma dell’oggetto,
per far questo si può utilizzare l’algoritmo di Canny [2]. Questo algoritmo è utilizzato per rilevare il contorno degli oggetti. Il contorno di un oggetto presente in
un’immagine è formato da aree di punti dove il livello d’intensità varia nettamente.
Da questo si intuisce l’utilizzo dell’operatore gradiente per la ricerca dei punti di
massima variazione di luminosità.
L’algoritmo di Canny applica l’operatore gradiente ad un’immagine smussata
30
Visione artificiale
mediante filtro gaussiano, ed esegue una soppressione dei punti di non massimo e
di quelli perpendicolari alla direzione del contorno per ottenere bordi sottili. Il risultato dipende dalla scelta di alcuni parametri, come l’ampiezza del filtro gaussiano
e la soglia per la soppressione dei punti di non massimo. Nella scelta di questi parametri, si deve tenere presente che per ripulire le immagini da falsi bordi generati
da ombre, è necessario usare soglie abbastanza elevate, ma che questa scelta può
causare la perdita di alcuni dettagli.
(a) Ingresso
(b) Uscita
Figura 3.4: Esempio di applicazione dell’algoritmo di Canny.
In figura 3.4 è rappresentato un esempio di applicazione dell’algoritmo di Canny. A sinistra, in toni di grigio, è mostrata l’immagine data in ingresso all’algoritmo,
a destra, quella in uscita. Si noti che l’uscita è formata dai punti in cui è presente
una discontinuità di intensità nell’immagine d’ingresso.
Trovato il contorno di un oggetto, è possibile definire il centro di gravità “geometrico”. Questo è calcolato sfruttando solo informazioni legate alla geometria
dell’oggetto, senza far riferimento alla massa. La definizione più semplice è data
dalla media delle coordinate x e y dei punti che formano l’oggetto. Questa, e altre
definizioni simili, sono usate dall’algoritmo di visione per calcolare la distanza fra
oggetto e robot.
3.3 Distanza fra robot e oggetto: soluzione teorica
Si consideri un manipolatore con una telecamera “monoscopica” montata sull’end effector. Per afferrare un corpo rigido con il manipolatore, si deve individuare
la posizione del corpo rigido sfruttando solo la le informazioni provenienti dalla
telecamera..
3.3. Distanza fra robot e oggetto: soluzione teorica
31
Un corpo rigido nello spazio può essere caratterizzato dalla posizione e orientamento di una terna solidale al corpo stesso rispetto ad una terna fissa di riferimento.
Tre parametri sono sufficienti per individuare la posizione dell’oggetto, possono essere scelti arbitrariamente purchè siano linearmente indipendenti. Tre coordinate
cartesiane individuano un punto nello spazio rispetto ad una terna di riferimento, il
medesimo punto può essere caratterizzato da tre coordinate polari.
Afferrare un corpo rigido nello spazio con un robot significa, nella formulazione
più semplice del problema, far coincidere un punto del corpo rigido con un punto
solidale all’end effector del robot4 . Quindi dati due punti, uno solidale all’end effector e l’altro appartenente all’oggetto, è possibile farli coincidere muovendo il
robot lungo la retta che li congiunge, e spostando il manipolatore di un offset pari
alla distanza che li separa.
Risolvere il suddetto problema significa risolvere due sotto problemi:
allineamento, consiste nell’allineare l’asse d’approach del robot con la direzione in cui si dovrebbe muovere l’end effector per afferrare l’oggetto;
calcolo della distanza, consiste nello stimare la distanza tra oggetto e robot.
La scomposizione in due problemi minori non permette di risolverli in parallelo.
È necessario risolvere prima l’allineamento poi, in un secondo momento, valutare
la distanza dell’oggetto.
L’asse d’approach non deve necessariamente coincidere con l’asse visivo della
telecamera, ma è sufficiente che questi due siano paralleli. In figura 3.5 è rappresentato la parte terminale di un manipolatore, al quale è stata montata una telecamera.
Se i due assi sono paralleli, eseguire un’approach con il robot equivale a muovere
Ox
d
y
Oy
x
Figura 3.5: Telecamera montata su end effector.
la telecamera lungo il suo asse ottico. Quindi, allineare la telecamera e calcolare
la distanza tra telecamera e oggetto equivale, a parte offset noti a priori, calcolare la distanza fra end effector e oggetto. Per semplicità si è supposto di ragionare
nel piano, ma le considerazioni che seguono sono facilmente estendibili al caso
tridimensionale.
4 Un
punto solidale all’end effector non deve necessariamente appartenere all’end effector stesso.
32
Visione artificiale
3.3.1 Allineamento
Allineare il robot con l’oggetto significa, in ultima analisi, fare in modo che
la retta, individuata dall’asse ottico della telecamera, passi per un punto ben preciso dell’oggetto. La scelta più naturale del punto ricade sul centro di gravità
“geometrico”.
Si consideri una telecamera montata sull’end effector, per allinearla sono possibili due tipi di scelte. Una prima possibilità mantiene inalterato l’orientamento della
telecamera e utilizza solo movimenti sul piano perpendicolare all’asse visivo della telecamera stessa. L’altra possibilità usa rotazioni per modificare l’orientamento
della telecamera.
Considerando il montaggio della telecamera sul gripper, il primo metodo sfrutta
solo i movimenti NORMAL e SLIDE per effettuare l’allineamento, mentre l’altro
richiede l’uso dei movimenti PITCH e YAW per risolvere il problema.
I due metodi sono equivalenti se si utilizza un controllo che tiene conto solo del
segno dell’errore. Se si utilizza un qualsiasi altro controllo, che sfrutta anche il modulo dell’errore, allora la soluzione che usa PITCH e YAW presenta un vantaggio:
l’errore non dipende dalla distanza tra oggetto e telecamera.
L
e
α
l
E
Figura 3.6: Allineamento.
Con riferimento alla figura 3.6, l’angolo α rappresenta l’errore di rotazione,
mentre, E quello di traslazione. Con semplici osservazioni geometriche si può
notare che:
E
eL
l
e
α
arcsin
e
l
La variabile e si può considerare nota (basta un semplice conteggio di pixel), cosí
come il parametro l che è legato a fattori costruttivi della telecamera. La distanza
L, poichè l’allineamento avviene prima del calcolo della distanza, è da considerarsi
incognita. Un qualsiasi controllo che sfrutta le traslazioni della telecamera, basato
sul modulo dell’errore, è difficile da realizzare perché dipende da una grandezza
incognita. Più semplice da realizzare è un controllo che sfrutta le rotazioni della
3.4. L’algoritmo di visione artificiale
33
telecamera per annullare l’errore, in quanto quest’ultimo è noto con “precisione” 5 .
Da notare l’approssimazione fatta nel ragionamento, infatti si è supposto, che l’asse
di PITCH della telecamera e quello dell’end effector siano coincidenti anche se in
realtà sono paralleli. Lo stesso vale per l’asse di YAW.
Da quanto detto la soluzione che utilizza le rotazioni è migliore. Lo è anche
per un ulteriore motivo, che può essere chiarito solo nel momento in cui verranno
descritti i problemi, che nascono nel fondere insieme la parte real time e quella di
visione artificiale.
3.3.2 Calcolo della distanza
Calcolare la distanza di un punto dalla telecamera è semplice e basta applicare i concetti visti nel paragrafo 3.2.1, in tal caso le variabili hi , con i 1 2, che
compaiono in 3.2, sono univoche.
Se si considera un oggetto, che è formato da più punti, la scelta non è più univoca. Si potrebbe scegliere l’altezza o la larghezza dell’oggetto come valore da
assegnare ad hi . Un’altra scelta potrebbe essere di assegnare ad hi la media della
distanza tra i punti del contorno e il centro di gravità “geometrico”. Per comprendere il concetto si pensi ad un cerchio. La distanza media dei punti che formano il
contorno con il CdGG6 , disturbi a parte, è il raggio. Se il medesimo cerchio viene inquadrato da due differenti distanze, la sua dimensione cambia e quindi varia
anche il raggio.
Un’osservazione è doverosa, poichè il calcolo della distanza avviene dopo l’allineamento, parlare di CdGG o del centro dell’immagine è la stessa cosa, almeno
in teoria. In pratica non vi è la certezza che l’asse di approach del robot e l’asse
ottico della telecamera siano perfettamente paralleli. Questo errore di parallelismo
può far si che, dopo l’allontanamento, i due centri non coincidano più. Questo è il
motivo per cui è preferibile considerare il centro di gravità geometrico.
3.4 L’algoritmo di visione artificiale
L’algoritmo di visione artificiale si basa sui concetti teorici visti in precedenza.
Scopo di questo software è permettere al robot di afferrare un oggetto inquadrato dalla telecamera. Il software deve fornire gli strumenti per essere funzionale;
un operatore deve avere la possibilità di muovere il robot e di poter selezionare
l’oggetto che si vuole afferrare.
5 La
precisione è legata anche alla risoluzione della telecamera.
centro di gravita “geometrico”.
6 CdGG:
34
Visione artificiale
Figura 3.7: Screenshot del software di visione.
In figura 3.7 è rappresentato uno screenshot del software di visione. Una breve
descrizione può aiutare ad entrare più velocemente nell’ottica del software. La finestra principale è Robotic Vision, si possono notare tutte le strutture classiche per
l’interazione con operatore. La finestra TP rappresenta un “theach pendent” virtuale,
con questo strumento è possibile dare il DRIVE ON e il DRIVE OFF al robot, inoltre è possibile muoverlo con semplici clic del mouse. Un operatore può posizionare
il robot in modo tale da ottenere l’inquadratura che preferisce. La finestra COMAU’s
eye è aggiornata continuamente e vi è riprodotta l’immagine inquadrata dalla telecamera. In questa specifica figura, la pallina è stata selezionata per essere afferrata,
si nota infatti che è contenuta in un rettangolo verde; l’algoritmo considererà solo
le informazioni contenute nel suddetto rettangolo per afferrare l’oggetto.
Con questa descrizione in mente è possibile entrare nel dettaglio dell’analisi
del software. Nel progettare il software non si deve dimenticare che il controllo
del robot in real time è un compito gravoso per il processore, la manipolazione
d’immagine forse lo è ancora di più.
Per comprendere come è stato sviluppato l’algoritmo, e le scelte fatte durante
la sua creazione, si devono conoscere quali sono i compiti che l’algoritmo deve
svolgere. Questi sono tre e per ognuno viene creato un thread 7 , in modo tale da
7I
thread sono “processi leggeri”, nel senso che la creazione, distruzione e sincronizzazione sono
relativamente economiche grazie alla condivisione dello spazio di indirizzamento.
3.4. L’algoritmo di visione artificiale
35
poter essere svolto in parallelo agli altri. I macro-compiti sono:
creazione e gestione dell’interfaccia grafica del software. Questo thread
ha il compito di gestire tutta l’interfaccia grafica, è sempre attivo. Il compito
che svolge è occuparsi dell’interazione con l’operatore, ricevere in ingresso
comandi e parametri e fornisre in uscita informazioni utili per comprendere
le operazioni svolte dal software.
comunicazione con il modulo real time per il controllo del COMAU. Questo thread invia i comandi per far muovere il robot, è il cuore del software.
Legge le immagini dal framebuffer nel caso debba allineare il robot e calcolarne la distanza dall’oggetto.
gestione delle immagini provenienti dalla telecamera. Questo thread gestisce l’acquisizione delle immagini, è basato sulla libreria libbgrab. Il suo
compito è leggere l’immagine dal framegrabber e, dopo opportune modifiche, aggiornare la finestra COMAU’s eye. Due modifiche all’immagine sono
necessarie per motivi legati al risparmio di risorse. La prima è necessaria
perché, per ottenere migliori risultati nella stima della distanza, la risoluzione delle immagini acquisite è elevata, ma per risparmiare risorse di calcolo,
la risoluzione delle immagini visualizzate è bassa. La seconda perché l’immagine acquisita è in bianco e nero mentre per visualizzarla deve avere la
profondità del colore pari a quella dell’interfaccia grafica di Linux. Se non
si ha la necessità di aggiornare continuamente la finestra, questo thread viene
fermato.
Questi compiti devono essere svolti in parallelo, ma, per poter risparmiare risorse,
i thread non sono sempre in esecuzione, perciò vengono fermati appena viene a
mancare la necessità della loro esecuzione.
Per questo parallelismo, spiegare il software è sicuramente più complesso, forse
il metodo più lineare è seguire un percorso “temporale”, nel senso di spiegare i vari
passi che il programma esegue per afferrare un’oggetto. Le fasi in cui può essere
diviso sono:
1. inizializzazione del software;
2. posizionamento del robot e selezione dell’oggetto da afferrare;
3. allineamento della telecamera;
4. calcolo della distanza tra oggetto e telecamera;
5. avvicinamento a distanza minima;
36
Visione artificiale
6. afferraggio.
È possibile entrare nel dettaglio delle singole voci per comprendere meglio il programma.
Inizializzazione del software
Il software, appena inizia l’esecuzione, inizializza il sistema. Carica i moduli
del kernel necessari, attiva la comunicazione con il modulo real time che controlla
il robot e inizializza il framebuffer. Successivamente si divide in tre thread, uno
per ogni macro-compito. Se una qualunque di queste inizializzazioni non va a buon
fine, il programma esce segnalando l’errore.
Posizionamento del robot e selezione dell’oggetto da afferrare
In questa fase un operatore può muovere il robot per fare in modo che la telecamera inquadra l’oggetto che si vuole afferrare, per fare ciò ha a disposizione il
teach pendant virtuale. Il TP8 , creato in questo software, riprende quello realizzato
in precedenti tesi [9].
Inquadrato l’oggetto, è possibile selezionarlo con due semplici clic nella finestra
COMAU’s eye; il software considera questi due punti come spigoli opposti di un rettangolo, e sfrutta solo le informazioni contenute all’interno del rettangolo stesso per
afferrare l’oggetto, questo è il motivo per cui viene chiamata bound box. Utilizzare
solo le informazioni di una porzione dell’immagine ha un due vantaggi: da un lato
si ha un risparmio di risorse poichè si utilizza un immagine più piccola, dall’altro
si introducono meno disturbi, eliminando tutto quello che è esterno al rettangolo.
Selezionato l’oggetto, basta premere sul pulsante start per far si che il robot inizii
l’allineamento.
Allineamento della telecamera
Il problema è quello visto nel paragrafo 3.3.1, la soluzione pratica richiede qualche precisazione in più rispetto a quella già vista in teoria. La soluzione è la seguente: se l’asse ottico della telecamera passa per il centro di gravità geometrico, allora
il pixel che individua il CdGG è nel centro dell’immagine ripresa dalla telecamera.
Quindi, per risolvere il problema, si deve muovere il robot in modo tale che i due
punti coincidano. Con riferimento alla figura 3.8, sia C il centro di gravità geome8 TP:
Teach Pendant
3.4. L’algoritmo di visione artificiale
O
37
y
C
x
ex
T
ey
Figura 3.8: Allineamento.
trico e T il centro della telecamera. Per farli coincidere si muove il robot usando
PITCH e YAW con velocità proporzionale all’errore misurato in pixel. In pratica,
l’algoritmo determina il CdGG dell’oggetto e calcola gli errori nelle due direzioni,
imposta quindi la direzione e la velocità con cui muovere il robot. Successivamente acquisisce una nuova immagine e ripete il procedimento ricalcolando l’errore e
imposta una nuova velocità. Poichè, teoricamente, l’errore è diminuito, l’algoritmo
riduce la velocità del robot. Si intuisce, quindi, che il robot si muove velocemente
se l’errore è grande, riducendo la velocità man mano che i punti C e T si avvicinano.
Muovendo il robot cambia l’inquadratura, quindi l’oggetto si muove all’interno del fotogramma e perciò si deve muovere anche il rettangolo che lo seleziona.
La soluzione più semplice è la seguente: considerando due fotogrammi successivi, se l’oggetto si è spostato di un determinato numero di pixel In questo caso il
suo CdGG si sarà mosso dello stesso numero di pixel, quindi basta muovere il rettangolo di conseguenza. In realtà vi è un problema di inizializzazione, infatti nel
primo movimento non si ha il fotogramma precedente da confrontare, allora si muove la bound box di un numero di pixel proporzionale alla velocità con cui si muove
il robot. La costante di proporzionalità è stata determinata sperimentalmente per
tentativi.
È importante che durante l’allineamento l’oggetto rimanga sempre dentro la
bound box, in caso contrario parte del contorno potrebbe essere escluso dal calcolo
del CdGG, producendo un errore nella determinazione del centro stesso.
Durante l’allineamento l’errore dovrebbe solo diminuire, se per qualche motivo dovesse aumentare oltre un certo limite, allora il robot viene fermato perché
significa che l’oggetto è stato perso.
38
Visione artificiale
Inoltre, l’allineamento viene concluso solo quando in tre fotogrammi successivi
i punti T e C coincidono, questo garantisce maggior sicurezza sulla corretta esecuzione dell’allineamento. Cosí facendo si evitano errori dovuti a disturbi presenti
solo in un singolo fotogramma.
Calcolo della distanza tra oggetto e telecamera
Per determinare la distanza fra telecamera e oggetto si devono applicare i concetti visti nel paragrafo 3.3.2. Data l’immagine ripresa dalla telecamera, si determina il contorno dell’oggetto e il centro di gravità geometrico, successivamente si
calcola la distanza media dei punti che formano il contorno dal CdGG. Eseguendo
un approach negativo, si allontana il manipolatore dall’oggetto e si riesegue il calcolo precedente. Infine, si riporta il manipolatore nella posizione di partenza e si
ripete il calcolo della distanza media. Cosí facendo, si ottengono tre misure della
distanza media del contorno dal CdGG: la prima e la terza (dm1 e dm3 ) sono effettuate a distanza D dall’oggetto, mentre la seconda (dm2 ) ad una distanza pari a
D A. È possibile trovare la distanza D che separa oggetto e telecamera applicando
l’equazione:
A
dm2
dm2
(3.4)
D
2
dm1 dm2 dm3 dm2 dove A è la misura in centimetri del approach negativo eseguito dal manipolatore.
Questo è il minimo indispensabile per risolvere il problema, alcuni accorgimenti
possono migliorare molto il risultato finale.
Ricordando i concetti di ottica geometrica e applicando l’equazione 3.1, si ha
che:
K
dmi
(3.5)
D
dove K è una costante che dipende dalla dimensione dell’oggetto e da caratteristiche costruttive della telecamera. Da questa formula si evince che la dimensione
dell’immagine dell’oggetto è inversamente proporzionale alla distanza da cui viene
ripreso. In figura 3.9 è graficato l’andamento dell’equazione 3.5 con K 2500 9 . Si
può notare che, a parità di approach negativo eseguito, la differenza tra due valori di
dmi varia in funzione della distanza da cui si esegue il calcolo. Se si considera la telecamera come un trasduttore, il cui ingresso è la distanza tra telecamera ed oggetto
e l’uscita è la dimensione in pixel dell’oggetto stesso, è possibile affermare che la
sua sensibilità non è costante, ma è molto sensibile per oggetti vicini alla telecamera
e poco sensibile per quelli lontani. Partendo da queste considerazioni e analizzando
9 Il
valore di K utilizzato è stato determinato sperimentalmente. Vedi capitolo 4
3.4. L’algoritmo di visione artificiale
39
130
120
Dimensione immagine (pixel)
110
100
90
80
70
60
50
40
30
20
30
40
50
60
70
80
Distanza (cm)
Figura 3.9: Risoluzione della telecamera.
i dati sperimentali (vedi capitolo 4) è possibile affermare che il miglior punto di
lavoro della telecamera utilizzata in questo progetto è nell’intorno dei 35cm.
Quindi è possibile ottenere una maggior precisione nel determinare la distanza
tra oggetto e telecamera, se quest’ultima è posizionata circa a 35cm dall’oggetto
stesso. Per questo motivo si è scelto di eseguire, in caso di necessità, più volte la
procedura per determinare la distanza tra oggetto e telecamera. Il comportamento
dell’algoritmo è il seguente: se determinata la distanza questa risulta appartenere
ad un range tra i 32 5cm e 37 5cm allora il robot segue l’avvicinamento a distanza
minima, altrimenti si porta, errore parte, a 35cm e ridetermina la distanza con la
stessa procedura descritta in precedenza. Tutto questo garantisce migliori risultati.
Inoltre, per aumentare la precisione, tra due procedure di determinazione della
distanza viene rieseguito l’allineamento. Questo viene fatto per correggere errori di
approach dovuti al non perfetto parallelismo tra asse d’approach e asse visivo, e per
correggere movimenti non perfetti del manipolatore.
Modificare il punto di partenza della procedura del calcolo della distanza significa modificare la dimensione dell’oggetto ripreso; questo comporta una modifica
nella dimensione della bound box tra una procedura e l’altra. Si noti che, se si esegue un approach in avanti tra due procedure, il ridimensionamento del rettangolo di
selezione è una necessità, perché la dimensione dell’immagine dell’oggetto aumenta. Nel caso opposto, cioè si esegue un approach negativo, il ridimensionamento è
un’utilità per eliminare parte dei disturbi.
La soluzione del problema del ridimensionamento della bound box è sempli-
40
Visione artificiale
ce se si applicano i concetti dell’ottica geometrica. Si ottiene, infatti, la seguente
equazione:
Di D f
∆B Bi
(3.6)
Df dove Di rappresenta la distanza iniziale dall’oggetto, D f quella finale e Bi la dimensione iniziale della bound box. L’equazione 3.6 restituisce la variazione della bound
box in pixel se Bi corrisponde alla dimensione iniziale della medesima grandezza
misurata in pixel. Tale formula deve essere applicata sia alla dimensione verticale
che a quella orizzontale. Poichè l’oggetto è al centro dell’immagine, il ridimensionamento deve avvenire in tutte è quattro le direzioni, quindi metà ∆B è applicato in
una direzione e l’altra metà nella direzione opposta.
Si è già fatto notare che è importante che l’oggetto rimanga sempre tutto contenuto nel bound box, per questo motivo nel ridimensionamento si è applicato un
coefficiente moltiplicativo di sicurezza pari al 15%. Questo comporta metodi differenti di calcolo del ∆B a seconda che, per portarsi a 35cm dall’oggetto, si esegua
un approach negativo o positivo, cioè:
Di D f
1 15Bi
se D f Di
Df ∆B
(3.7)
Di D f
se D f Di
0 85Bi
Df Questo metodo di calcolo della distanza è sicuramente più macchinoso e, in
termini di tempo, più lungo rispetto all’utilizzo di un singolo approach negativo,
ma permette di ottenere risultati più precisi e ripetibili.
Avvicinamento a distanza minima
Determinata la distanza fra telecamera ed oggetto, viene eseguito un primo approach per portare la telecamera a 20cm dall’oggetto. Considerando il montaggio
della telecamera sul gripper, si ha che l’oggetto si trova, traslazione in alto a parte,
esattamente davanti al gripper.
L’approach per effettuare la presa viene spezzato in due fasi, cosí è possibile inserire una funzione per determinare i punti di presa ottima. L’immagine, passata alla
funzione di presa, è la migliore perché, essendo la telecamera particolarmente vicina all’oggetto, i disturbi sono sicuramente minori. Inoltre, in tale situazione, poichè
la distanza è definita, è possibile determinare la dimensione e altre caratteristiche
geometriche dell’oggetto10 .
10 Basta
moltiplicare per un coefficiente noto. Tale costante è stata determinata sperimentalmente
e vale: pixel2cm 0 028539647.
3.5. Precisazioni sull’algoritmo di visione
41
Se si considerano le caratteristiche costruttive del gripper, considerare le dimensioni reali e i raggi di curvatura dell’oggetto può essere molto utile nel determinare
i punti di presa ottima [3].
Afferraggio
Calcolata la presa ottima, con NORMAL e SLIDE si posiziona il manipolatore
in modo che l’asse d’approach del gripper passi per il CdGG dell’oggetto, successivamente si ruota l’end effector in modo tale che le dita del gripper vadano ad afferrare l’oggetto nei punti prestabiliti. Infine, con APPROACH si muove il robot per
fare in modo che l’oggetto si posizioni dentro il gripper. Quest’ultimo movimento
e parte della traslazione del polso sono dati solo da offset noti a priori e dipendenti
dal montaggio della telecamera sul gripper.
Si noti, infine, che questa fase avviene in catena aperta, in quanto l’oggetto non
è più inquadrato dalla telecamera.
3.5 Precisazioni sull’algoritmo di visione
Nella descrizione fatta fino ad ora, sono stati volutamente trascurati alcuni dettagli per non appesantire troppo la trattazione. Alcune precisazioni sono doverose,
poichè modificano il comportamento dell’algoritmo o migliorano il risultato finale.
3.5.1 Arresto del manipolatore per determinare la dimensione
dell’oggetto
Il modulo del driver per la gestione della scheda d’acquisizione non è real time.
Questo comporta che non è possibile associare ad un istante preciso l’immagine acquisita, di conseguenza è impossibile creare un legame tra posizione del robot e uno
specifico fotogramma. Da queste parole, si intusce la necessità di fermare il robot
per creare un corrispondenza univoca fra informazioni contenute nel fotogramma e
posizione del manipolatore. Tutto questo preclude la possibilità di calcolare la distanza mentre il robot si sta muovendo ed introduce inevitabili ritardi nella soluzione
del problema.
Per evitare questo inconveniente, l’algoritmo invia la richiesta al robot di eseguire un determinato movimento, e si mette in attesa della risposta da parte del manipolatore di avvenuto raggiungimento della posizione. A robot fermo, si acquisisce
l’immagine e la si lega alla posizione del manipolatore.
42
Visione artificiale
3.5.2 Utilizzo di più fotogrammi nella determinazione della dimensione dell’oggetto
Come detto in precedenza, il modulo per la gestione della scheda d’acquisizione non è real time, quindi il processo che risponde all’interrupt del COMAU è
più importante di quello che acquisisce l’immagine della telecamera. Può capitare
che, subito dopo il movimento del robot, l’immagine presente nel buffer del framegrabber sia in realtà “vecchia”, e non corrisponda a quella ripresa in quell’istante.
Ovviamente capita che l’immagine richiesta dopo un approach del manipolatore
corrisponda in realtà ad un immagine catturata quando il manipolatore si trovava in
un’altra posizione. Se si utilizza un unico fotogramma, tutto questo può produrre
errori nel calcolo della dimensione dell’oggetto.
Per evitare errori nella determinazione della distanza media dei punti del contorno del CdGG, vengono utilizzati più fotogrammi. L’algoritmo considera cinque
immagini e per ognuna calcola la dimensione dell’oggetto, successivamente scarta
il più grande e il più piccolo risultato ed esegue la media dei restanti.
3.5.3 Un motivo pratico per utilizzare PITCH e YAW nell’allineamento
Alla luce delle considerazioni fatte sul modulo real time e quello per il framegrabber, è possibile comprendere un’ulteriore motivo per cui è preferibile utilizzare
i movimenti PITCH e YAW per allineare il manipolatore.
Ricordando la tecnica utilizzata per allineare il robot, presentata nel paragrafo
3.3.1, si intuisce che se le immagini provenienti dalla telecamera non vengono aggiornate, non è possibile ricalcolare l’errore di posizionamento e, di conseguenza,
non viene ridotta la velocità con cui si tenta di eseguire l’allineamento. La situazione è aggravata dal fatto che, se ciò si verifica, non vi è neanche la possibilità da
parte dell’algoritmo di accorgersi che l’errore è aumentato e quindi di arrestare il
manipolatore.
Questa situazione non è immaginaria, anzi, è capitato che non venisse aggiornata l’immagine per qualche secondo. Se ciò accade quando l’errore è ancora grande,
spesso si ha la perdita dell’oggetto, poichè la velocità del robot è elevata.
Per ridurre la probabilità che ciò si verifichi, si è utilizzato un’immagine con
una risoluzione minore nella fase di allineamento. Questo accorgimento, però,
non ha eliminato il problema, visto che il carico computazionale in questa fase è
particolarmente elevato.
In conclusione, allineare utilizzando i movimenti PITCH e YAW ha il vantaggio
3.5. Precisazioni sull’algoritmo di visione
43
di avere un comportamento del robot più “tranquillo”. In tal caso, infatti, il polso
varia il suo orientamento ma non la sua posizione.
44
Visione artificiale
Capitolo 4
Risulati sperimentali
4.1 Introduzione
Nell’algoritmo di visione sono presenti costanti che, a prima vista, sembrano
create magicamente. In realtà, le costanti utilizzate sono state determinate sperimentalmente con una serie di misure. In questo capitolo verranno presentate tutte le tecniche utilizzate per determinare parametri fondamentali dell’algoritmo di
visione.
4.2 Come sono state ottenute le misure
Capire come sono stati ottenuti i dati è importante. La strada piú semplice è
ottenerli direttamente dall’algoritmo. Per farlo è stato modificato il software, inoltre
è stata creata una situazione “ambientale” particolare.
L’oggetto, del quale si vuole determinare la distanza dalla telecamera, è stato
sostituito da un foglio di carta attaccato ad una lavagna. Su tale foglio è riportato
un cerchio perfetto, con raggio pari a 5 cm. Il manipolatore è stato allineato con il
cerchio ed è stato posizionato ad una distanza nota dal cerchio stesso. Tale distanza
è pari a 25 cm. A questo punto si è avviata la procedura di misura. Questa determina un serie di grandezze che sono differenti a seconda dello scopo per cui è stata
eseguita. In ogni caso si ha la creazione di un file contente una grande quantità di
dati. Si ritiene inutile, in questa sede, presentare tabelle enormi piene di numeri, che
a prima vista possono sembrare inutili. Per tale motivo si è deciso di non riportare
i dati in questa tesi se non sottoforma di grafici, sicuramente piú significativi. In
ogni caso tali dati sono disponibili nel CD presente la L.A.R., insieme al software
generato durante questa tesi.
46
Risulati sperimentali
4.3 Misura dell’errore di calcolo della distanza
Determinare l’errore nella misura è importante e può aiutare a comprendere
scelte fatte nel creare il software.
Per determinare quello che serve è stata eseguita la seguente misura: posizionata
la telecamera come specificato nel paragrafo 4.2 è stata poi allontanata, fino ad una
distanza pari 70 cm, con passi di un centimetro. Ad ogni step è stata determinata la
distanza tra oggetto e telecamera. Queste misure sono stata eseguita con approach
differenti, nello specifico sono state eseguite misure con approach negativi pari a 8
cm, 10 cm, 12 cm e 14 cm. Le misure sono state poi ripetute sei volte e ne è stata
fatta la media limitare gli effetti di disturbi casuali.
Poichè la distanza reale tra oggetto e telecamera è nota, è possibile determinare
l’errore nella misura. In figura 4.1 è riportato l’andamento, per diffrenti tipi approa1.5
approach=14cm
approach=12cm
approach=10cm
approach=8cm
Errore (cm)
1
0.5
0
25
30
35
40
45
50
55
Distanza telecamera−oggetto (cm)
60
65
70
Figura 4.1: Errore medio per differenti approach.
ch, del valore assoluto dell’errore in funzione della distanza da cui è stata eseguita
la misura.
Analizzando il grafico è possibile notare che il modulo dell’errore ha un minimo
nell’intorno di 35 cm. Questo significa che se la distanza viene calcolata quando la
telecamera è a 35 cm dall’oggetto si ha maggior precisione nel risultato. Questo è il
motivo per cui l’algoritmo esegue l’avvicinamento a distanza minima solo se questa
4.3. Misura dell’errore di calcolo della distanza
47
è stata determinata da una distanza compresa tra 32.5 cm e 37.5 cm, in ogni altro
caso tenta di portarsi 35 cm per ricalcolare la distanza.
Alcune considerazioni sono immediate. L’errore, a prima vista, sembra abbastanza casuale, ma il suo valore assoluto è sempre minore di un centimetro. Un
osservazione è doverosa: i dati sono stati ottenuti calcolando la distanza tra telecamera e un cerchio nero diseganto su un foglio bianco, situazione particolarmente
favorevole. Se si utilizzano oggetti reali la situazione è peggiore. Riflessi, ombre e
situazioni particolari di luce modificano il risultato, cioè rendono il valore assoluto dell’errore maggiore. In ogni caso, durante lo sviluppo del software si è notato
che, con oggetti reali l’errore, calcolato nell’intorno dei 35 cm, è indicativamente
intorno al centimetro. Il peggioramento delle prestazioni da caso “ideale” e reale è
notevole, ma non disarmante se si considerano le dita del gripper. Errori di un centimetro mi sembrano accettabili considerando che il gripper ha dita che misurano 7
cm.
Una trattazione che considera solo l’errore medio e non quello massimo è sicuramente incompleta. Dai dati utilizzati in precedenza si è ricavato l’errore massimo
eseguito nel calcolo della distanza. I risultati ottenuti sono graficati in figura 4.2.
1.5
approach=14cm
approach=12cm
approach=10cm
approach=8cm
Errore (cm)
1
0.5
0
25
30
35
40
45
50
55
Distanza telecamera−oggetto (cm)
60
65
70
Figura 4.2: Errore massimo per differenti approach.
L’errore ha lo stesso andamento dell’errore medio e, ovviamente, ha il medesimo ordine di grandezza.
Un’ultima considerazione è importante. Nell’algoritmo si è scelto di utiliz-
48
Risulati sperimentali
zare un’approch negativo pari a 12 cm per determinare la distanza tra oggetto e
telecamera. Per motivare la scelta si consideri la tabella 4.1.
Approach (cm) Errore medio (cm)
8
0,055
10
0,022
12
0,017
14
0,015
Tabella 4.1: Tabella errore medio.
I dati presenti in suddetta tabella rappresentano la media dell’errore calcolato
posizionando la telecamera a circa 35 cm dall’oggetto1 . La media dell’errore è
stata determinate per approach differenti. In tal modo è possibile notare come cambia l’errore medio in funzione dell’approach eseguito. È evidente che, più questo
è grande piú è precisa la determinazione della distanza fra oggetto e telecamera.
D’altra parte, approach piccoli implicano movimenti meno vistosi del robot, quindi
sono preferibili. Si è scelto di utilizzare un’approch negativo pari a 12 cm, poichè è un giusto compromesso tra precisione di calcolo e movimenti “tranquilli”
del manipolatore. Un approach negativo maggiore a 12 cm non porterebbe ad un
miglioramento cosí significativo da giustificarne l’utilizzo.
4.4 Determinazione della costante pixel2cm
Determinare la dimensione reale, ed altre caratteristiche geometriche, di un oggetto conoscendone solo la dimensione in pixel è sicuramente di grande utilità. Ciò
è possibile solo se si conoscono le caratteristiche della telecamera e se si conosce la
distanza tra oggetto e telecamera.
Per determinare quello che serve è stata eseguita la seguente misura: posizionata
la telecamera come specificato nel paragrafo 4.2 è stata poi allontanata, fino ad una
distanza pari 70cm, con passi di un centimetro. Ad ogni step è stata determinata la
distanza media del bordo dal centro di gravità geometrico. Questa misura è stata
ripetuta per 12 volte. Per ogni distanza da cui è stata eseguita la misura si è fatta
la media dei valori ottenuti. Parte dei dati è stata riportata in tabella 4.2 perché in
seguito verranno tratte delle conclusioni che sfruttano questi dati.
La media calcolata è rappresentata in figura 4.3 dai punti blu. La linea rossa
1 Per
intorno di 35 cm si intende che le misure sono state eseguite con la telecamera posta a 33
cm, 34 cm, 35 cm, 36 cm e 37 cm
4.4. Determinazione della costante pixel2cm
L (cm)
25
30
35
40
45
50
55
60
65
70
49
h (cm)
150,08
125,29
107,43
93,99
83,53
75,19
68,35
62,67
57,82
53,26
Tabella 4.2: Tabella distanza media del bordo dal CdGG
rappresenta la curva che interpola i punti. Per ottenere questa curva si sono utilizzati concetti presenti nel paragrafo 3.2.1. Riprendendo la formula 3.1 è possibile
affermare che:
H l K
(4.1)
h
dove K l H
L
L
dove h rappresenta la media della distanza dei punti del bordo dal centro di gravità
geometrico misurata in pixel, H è l’analoga grandezza dell’oggetto reale ripreso e l
è un parametro caratteristico della telecamera. Si noti che, in questo semplice caso,
H rappresenta il raggio del cerchio disegnato sul foglio.
Dall’equazione 4.1 si evince che h è una funzione iperbolica. Di conseguenza
la curva rossa è data da un funzione del tipo:
y
a
x
b
(4.2)
dove, in questo esempio, con i dati misurati si ottiene a 3759 9 e b
60 10 6 .
Per oggetti differenti si avranno costanti differenti e quindi, anche, curve differenti.
Si noti che come ci si poteva spettare b è trascurabile, infatti in formula 4.1 non
compare.
Determinate le costanti a e b e possibile determinare la h di quel specifico oggetto per qualunque distanza. Per conferma della validità dei valori ottenuti si è
misurato la media della distanza dei punti del bordo dal CdGG con la telecamera
posta 20 cm dal cerchio, e si è ottenuto un valore pari a 187.50 pixel 2 , calcolando
lo stesso valore utilizzando 4.2 si ottiene:
y
2 Si
a
x
b
3759 9
20
187 99
noti che poichè è una media risulta che il numero dei pixel è un valore frazionario
(4.3)
50
Risulati sperimentali
160
Distanza media del bordo dal CdGG (pixel)
Dati misurati
Interpolazione dei dati misurati
140
120
100
80
60
40
25
30
35
40
45
50
55
Distanza telecamera−oggetto (cm)
60
65
70
Figura 4.3: Distanza media in pixel.
Se si conosce l’oggetto ci si può spingere oltre. Poichè il raggio del cerchio è
pari 5cm, si ha che per oggetti ripresi da 20cm di distanza è possibile determinare
la dimensione reale con un semplice conteggio di pixel, infatti si può dire che vale
la seguente corrispondenza:
37 59 pixel
1 cm
1 pixel
(4.4)
0 0266 cm.
Si definisce la costante di conversione da pixel a centimetri per un fotogramma
di un oggetto ripreso da 20 cm come: pixel2cm 0 0266cm pixel 1 .
Nota questa costante è possibile conoscere le caratteristiche geometriche di qualunque oggetto ripreso da 20 cm. Per conferma di ciò è possibile fare una semplice
misura. Se si sostituisce il cerchio precedentemente considerato con uno piú piccolo, è possibile conoscerne la dimensione sfruttando solo le informazioni provenienti
dalla telecamera. Infatti, considerato un cerchio di 2.5 cm di raggio ripreso da 20
cm, la media della distanza dei punti del contorno dal centro di gravità geometrico
è pari a 91.86 pixel. Se la dimensione reale non fosse stata nota si sarebbe potuta
determinare con:
r 91 86 pixel2cm 2 46 cm
(4.5)
dove r è il raggio del cerchio.
Si noti inoltre che la costante a dipende dalla dimensione dell’oggetto e da caratteristiche costruttive della telecamera. Dalla 4.1 e dai dati ottenuti dalle misure
4.5. Conclusioni
51
si ha che:
a
3759 9
(4.6)
751 98
H
5
Nota questa costante è possibile determinare il valore di a per il cerchio di raggio
pari a 2.5 cm e, quindi, sapere in anticipo il valore della media della distanza dei
punti del bordo dal centro di gravità geometrico. Applicando quanto detto a questo
esempio è possibile determinare il valore di h del cerchio di raggio 2.5 cm ripreso a
30 cm, infatti:
a
â
k
25 l
H l
1879 95
l
h
â
L
1879 95
30
Lo stesso valore determinato sperimentalmente è pari a h
62 66
(4.7)
61 68 pixel.
4.5 Conclusioni
I dati presenati hanno lo scopo di far comprendere il perchè di alcune scelte fatte
nell’algoritmo di visione. L’utilizzo di un “ambiente di misura” particolare permette
di ottenere costanti utilizzate nel normale svolgimento del compito di presa con
oggetti reali.
52
Risulati sperimentali
Conclusioni
Il lavoro qui concluso ha integrato in un unico PC un sistema distribuito formato
da tre computer, lo scopo di questo sistema è l’afferraggio di oggetti da parte del
gripper A.S.I montato sul robot COMAU Smart-3S
Piccoli ritocchi sono stati portati alla parte real time che gestisce il robot, questi
si sono resi necessari per rendere piú snella, veloce ed efficiente l’esecuzione dei
task RT. Praticamente immutata è la gestione del gripper, infatti essendo eseguita
su di una scheda a parte non sono stati necessarie modifiche sostanziali. Il software
di visione artificiale, invece, è stato ricreato partendo da zero, cercando, da un lato
di migliorarne la precisione dove ciò è stato possibile, e dall’altro di renderne piú
snella l’eseguzione dove ciò si è reso necessario.
A scapito di un leggero aumento del tempo impiegato per l’afferraggio, si è resa
questa operazione molto piú precisa. Si è inoltre notato che con l’attuale PC non è
possibile eseguire l’inseguimento dell’oggetto, in quanto il carico computazionale
per poterlo fare è troppo elevato.
Gli sviluppi futuri di questo lavoro possono spingersi in diverse direzioni. Sicuramente un primo passo potrebbe essere l’utilizzo di una telecamera stereoscopica per determinare la distanza fra oggetto e robot. Inoltre, a mio avviso, sarebbe
vantaggioso modificare il driver del framegrabber per renderlo real time, questo
eviterebbe la necessità di fermare il manipolatore per creare una corrispondenza
biunivoca tra immagine acquisita e posizione del robot.
54
Conclusioni
Appendice A
I moduli del kernel di Linux
A.1 Introduzione
Il kernel di un sistema operativo provvede alla gestione e al corretto funzionamento del computer. Tutto questo lavoro viene implementato via software dal
kernel, il quale viene caricato in memoria e messo in esecuzione al momento del
boot della macchina. I kernel moderni, per non essere di dimensioni spropositate visto la grande varietà di hardware sul mercato, sono modulari; in questo modo
si ha un kernel base di dimensioni ridotte, al quale vengono aggiunte funzionalità
caricando in esso i moduli quando servono.
Un modulo è, quindi, un programma oggetto1 che viene inserito nel nucleo
quando una certa funzionalità è richiesta. Il fatto che un modulo viene linkato al
kernel ci permette di intuire che esso andrà ad operare nel kernel space 2 . Nel momento in cui viene caricato nel nucleo mette a disposizione le sue risorse sia ad altre
parti del kernel che ai processi utente che ne richiedano i servigi.
A.2 Moduli: funzionamento
Può essere utile analizzare cosa succede quando un modulo viene “linkato”, a
causa di una richiesta esplicita da parte dell’utente (si vedrà in seguito come questa
procedura può essere automatizzata), per comprenderne meglio il funzionamento.
1 Un
programma oggetto ha questo nome perché, pur essendo codice eseguibile, e quindi un
programma, deve ancora subire delle modifiche affinché possa essere eseguito dal computer.
2 Il kernel space è in contrapposizione al user space nel quale operano le normali applicazioni
Questa divisione serve per evitare accessi non autorizzati alle risorse del sistema da parte di processi
utente.
56
I moduli del kernel di Linux
Viene di seguito riportato il codice di un ipotetico modulo al quale si farà riferimento
per spiegarne il funzionamento3 .
#define __KERNEL__
#define MODULE
#define EXPORT_SYMTAB
#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/io.h>
#include <asm/page.h>
#include <linux/ioport.h>
int sum(int a, int b)
{
return a+b;
}
EXPORT_SYMBOL(sum)
int init_module(void)
{
if (check_region(0x200,0xf)) {
printk("Area già riservata\n");
return ENODEV;
}
request_region(0x200,0xf,"example_module");
return 0;
}
void cleanup_module(void)
{
release_region(0x200,0xf);
printk("Modulo rimosso\n");
}
Compilato il sorgente è possibile caricarlo nel kernel in modo esplicito digitando al prompt il seguente comando:
[[email protected] misc]$ insmod ./example_module.o
Il comando insmod cerca di caricare il modulo nel nucleo risolvendo tutti quei simboli che si trovono nella tabella dei simboli del nucleo ed utilizzati dal kernel stesso,
quindi esegue la funzione init_module(). Questa funzione viene richiamata tutte
3 Si
ipotizzi che il file oggetto ottenuto dalla compilazione di questo sorgente si chiami
example_module.o.
A.3. Caricamento automatico di un modulo
57
le volte che il modulo viene caricato nel kernel. In essa vengono quindi inizializzate tutte quelle strutture dati che il modulo andrà poi ad utilizzare. Nell’esempio
riportato questa funzione controlla se una determinata area di memoria è libera e in
caso affermativo la riserva in modo che nessun altro modulo possa utilizzarla.
In modo del tutto analogo per rimuovere un modulo dalla memoria si deve digitare il comando:
[[email protected] misc]$ rmmod ./example_module.o
In questo caso viene seguita la funzione cleanup_module() che ha il compito di
rilasciare le risorse utilizzate dal modulo ripulendo la memoria della strutture definite in init_module(). Questo compito è essenziale perché se non venisse fatto
le risorse non sarebbero disponibili per altri moduli, anche se queste non sono più
utilizzate.
Il sorgente preso in esame è abbastanza semplice. Si noti che è definita una
funzione sum(), la quale esegue la somma di due numeri, che non è utilizzata dal
modulo preso ad esempio. In realtà tale funzione è messa a disposizione per altri
moduli che volessero utilizzarne i servigi. Si noti che con EXPORT_SYMBOL(sum) si
afferma l’intenzione di rendere disponibile ad altri moduli tale funzione. È possibile allora introdurre il concetto di module stacking: può accadere che un modulo
necessiti di una funzione implementata da un altro modulo e quindi prima di poterlo
caricare si ha la necessità di caricarne un altro. I moduli vengono allora “impilati”
uno sull’altro come avviene appunto nello stack da cui il nome di module stacking.
Un modulo che intenda utilizzare una funzione definita in un altro modulo deve
chiedere esplicitamente che venga caricato in memoria se non è già presente, e per
fare tutto ciò basta aggiungere nella funzione init_module() la seguente porzione
di codice:
int res;
if ((res=request_module(example_module.o))<0){
printk("Non è possibile caricare il modulo richiesto\n");
return res;
}
Dove request_module() è una speciale funzione che fa si che il kernel si incarichi di caricare tutti i moduli che occorrono al modulo richiesto e poi il modulo
stesso.
A.3 Caricamento automatico di un modulo
Si è accennato in precedenza che un modulo può venire caricato nel kernel anche
58
I moduli del kernel di Linux
senza una richiesta esplicita da parte di un utente, in modo del tutto automatico.
Prima di continuare è opportuno fare qualche precisazione.
In Linux è presente una directory che contiene dei file speciali, ogni file presente
in /dev rappresenta in realtà un dispositivo installato (o installabile) nel sistema,
questo permette di vedere un dispositivo come se fosse un normale file. Ogni file
speciale ha associato un major number e un minor number che rappresentano il
codice di identificazione di un determinato dispositivo. È possibile creare un file
speciale digitando il seguente comando:
[[email protected] dev]$ mknod -m 666 /dev/example_device c 200 0
Questo comando crea un file speciale di nome example_device il cui major number
è 200 e il minor number è pari a 04 .
Per ottenere il caricamento automatico del modulo si devono aggiungere parti
di codice al modulo stesso. Si consideri nuovamente l’esempio precedente e si
aggiunga al codice le seguenti parti:
...
#define MOD_NAME "example_module.o"
#define MOD_MAJOR 200
int example_device_open(struct inode *inode, struct file *file)
{
return 0;
}
int example_device_release(struct inode *inode, struct file *file)
{
return 0;
}
struct file_operations example_device_fops = {
open:example_device_open,
release:examples_device_release,
};
...
Inoltre si aggiunga dentro le funzioni init_module() e cleanup_module() i
seguenti pezzi di codice:
int init_module(void)
{
int res;
4 Per
ulteriori dettagli su mknod si faccia riferimento alle man pages.
A.3. Caricamento automatico di un modulo
59
...
if((res=register_chrdev(MOD_MAJOR,MOD_NAME,&example_device_fops))<0){
printk("Il major number %d non è libero\n",MOD_MAJOR);
return res;
}
...
}
void cleanup_module(void)
{
...
unregister_chrdev(MOD_MAJOR,MOD_NAME);
...
}
In questo semplice esempio compaiono due funzioni example_device_open()
e example_device_release() che non fanno nulla, in realtà in generale hanno un
ruolo molto importante e vengono eseguite tutte le volte che un programma nel user
space esegue una open() sul nodo che rappresenta il dispositivo con il major number coincidente al MOD_MAJOR. Tutte queste informazioni sono definite nella struttura example_device_fops che contiene i puntatori a tutte le funzioni che operano
sul nostro dispositivo e che corrispondono ad altrettante chiamate di sistema. Si noti
inoltre la funzione register_chrdev() che serve per “registrare” il dispositivo all’interno del nucleo legandolo una volta per tutte al suo major number. La funzione
complementare viene invocata all’atto della rimozione del modulo dal nucleo, per
rendere nuovamente disponibile la risorsa per altri dispositivi.
Resta ora da precisare il modo per collegare un determinato modulo ad un preciso major number. È necessario aggiungere una riga nel file di configurazione dei
moduli5 che crei questo legame. Ritornando all’esempio utilizzato fino ad ora, basta
aggiungere:
alias char-major-200 example_module.o
Fatto ciò il tentativo di apertura del file /dev/example_device avrà come effetto
il caricamento del modulo nel kernel.
Si noti che il modulo rimarrà in “linkato” al kernel fin tanto che non avverrà un
rimozione esplicita con l’opportuno comando, non vi è un metodo automatico di
rimozione dei moduli dal kernel space.
5 Nella
distribuzione RedHat questo file è /etc/modules.conf
60
I moduli del kernel di Linux
Appendice B
Il robot COMAU Smart-3S
B.1 Introduzione
La presente trattazione non è da intendersi sostitutiva ai manuali del COMAU
Smart-3S [4] presenti al LAR, l’utilità è quella di facilitare il reperimento delle
informazioni e di chiarire tutti quei problemi di ordine pratico in cui è possibile
imbattersi.
Precedenti tesi hanno già affrontato questo argomento, si ritiene utile riproporlo
con i necessari adattamenti per il sistema operativo Linux.
B.2 Accensione del COMAU Smart-3S
Per accendere e spegere il COMAU Smart-3S bastano alcune semplici operazioni, per accendere:
1. portare la leva di alimentazione sul rosso;
2. girare la chiave rossa su ON.
A questo punto il robot dovrebbe fare il boot. Per spegnerlo bisogan essere sicuri di
essere in modalità 0 ed eseguire:
1. girare la chiave rossa su OFF.
2. portare la leva di alimentazione sul verde;
Non riavviare il robot prima che siano trascorsi 20 30 secondi dallo spegnimeto.
Può accadere che eseguendo la procedura di accensione del controllore non si
riscontri nessun tipo di reazione. In tal caso si riporti la leva di alimentazione sul
62
Il robot COMAU Smart-3S
verde e si apra il C3G 9000. In alto a sinistra, all’interno dell’“armadio”, vi è un
interruttore classificato come: Moeller PKZ2, lo si porti in posizione “0”, poi in
posizione “1”. Si richiuda il C3G 9000 e si ripeta la procedura d’accensione. Nel
caso in cui il boot non avvenga ancora si ripeta quanto detto, in due o tre volte tutto
dovrebbe risolversi.
Se dopo svariati tentativi non vi è ancora segno di vita da parte del controllore
potrebbe essersi bruciato un fusibile all’interno del C3G 9000. Questo si trova nella
scheda la centro dell’“armadio”, dentro il porta fusibile nero, esattamente sopra ad
un relè giallo. Si controlli l’integrità del fusibile ed eventulamente lo si cambi.
B.3 Comunicazione tra controllore C3G 9000 e PC
Il controllore C3G 9000 può comunicare con un PC attraverso un cavo parallelo
oppure utilizzando un cavo seriale. Il primo metodo viene utilizzato per controllare il manipolatore dal PC quando il C3G 9000 è in modalità “aperta”, non viene
descritto nel dettaglio in quanto è stato ampiamente trattato nel capitolo 1. L’altro metodo di comunicazione è tramite un cavo seriale, si utilizza semplicemente
semplicemente per copiare il software dal PC al controllore o viceversa, non viene
assolutamente usato per il controllo.
B.3.1 Come cambiare della modalità di funzionamento per il
controllore C3G 9000
Come già accennato nella configurazione presente al L.A.R. sono possibili due
modalità di funzionamento: una detta “chiusa” e l’altra “aperta”. In modalità chiusa
l’utente può programmare il manipolatore con un linguaggio di alto livello 1, ma
non può agire sul controllo. In modalità aperta il controllo del manipolatore viene
eseguito direttamente dal PC, in tale modalità vi sono modi differenti di controllare
il robot in funzione del punto di apertura del anello di controllo. In questa tesi è
stata utilizzata solo la modalità aperta ad un millisecondo.
Per passare dalla modalità chiusa (modalità 0) e quella aperta a un millisecondo
(modalità 4) si deve eseguire la seguente procedura:
1. accertarsi che la chiave blu sul C3G 9000 sia su “LOCAL”.
2. caricare dal controllore i programmi ini e cnr1. Per farlo basta selezionare,
1 Il
linguaggio di programmazione del manipolatore COMAU Smart-3S è il PDL2.
B.3. Comunicazione tra controllore C3G 9000 e PC
63
dalla tastiera del C3G 9000, “PROGRAM”, “GO” e digitare “ini”, successivamente selezionare “GO” e digitare “cnr1”.
3. lanciato il software viene chiesto se sul bus VME è presente la scheda Bit3,
rispondere “s”, alla richiesta della modalità che si vuole utilizzare: rispondere
“4” per quella ad 1ms, viene inoltre chiesto il numero dell’arm: digitare “0”,
ed infine indicare i giunti che verranno gestiti dal PC.
4. attendere il riavvio del controllore.
Dopo il riavvio il controllore è necessario caricare i moduli per la comunicazione e per il controllo real time nel kernel di Linux, tali moduli sono Bit3init.o e
rtai_comau.o, si veda il paragrafo 2.3 per maggiori dettagli.
Per ritornare in modalità 0 si deve eseguire la seguente procedura:
1. ripetere i passi 1 e 2 della precedente procedura.
2. lanciato il software viene chiesto se sul bus VME è presente la scheda Bit3,
rispondere “s”, la successiva domanda è la modalità che si vuole utilizzare:
digitare “0”.
3. attendere il riavvio del controllore.
È importante non spegnere il PC quando i moduli per controllo real time sono
ancora “linkati” nel kernel e, ancor più importante, non spegnere il manipolatore
quando il controllore è in modalità 4. I motivi di tali affermazioni saranno più
chiari in seguito.
B.3.2 Come caricare del software nel C3G 9000
Il controllore C3G 9000 memorizza il sistema operativo e la calibrazione su
della RAM batterizzata, in alcune situazioni è possibile perdere il contenuto della
RAM. Nel caso in cui, all’avvio, il sistema operativo non sia più presente sulla RAM
il controllore tenta di fare il boot del sistema prelevando i file che gli servono dalla
porta com02 , in questo caso il controllore attiva automaticamente la comunicazione
mettendosi in stato client. Il cavo classificato come “cavo seriale di comunicazione
tra PC e C3G 9000” realizza fisicamente la connessione tra PC e controllore, questo
deve essere collegato tra la porta seriale del PC e la porta “comm:0” del controllore.
Si deve ora impostare il PC come server, per farlo basta digitare il seguente comando:
[[email protected] DISKC3G]$ kermit
2 Questa
porta è di tipo seriale ed è posta sul lato anteriore del controllore.
64
Il robot COMAU Smart-3S
dove nella directory DISKC3G è conrtenuto il sistema operativo del controllore. Per
rendere il PC server se deve digitare la seguente sequenza di comandi:
1. SET LINE /dev/ttyS0
2. SET SPEED 38400
3. server
Piochè il sistema operativo originariamente era nei dischetti, periodicamente il controllore chiederà di inserire il disco d’installazione successivo; basta premere invio
e tutto procederà. Qundo il trasferimento del sistema operativo è completato, per far
uscire il PC dal server mode basta premre “CTRL+C” e successivamente digitare
“exit”. A questo punto il robot può funzionare solo in modalità “chiusa”, per poter utilizzarlo anche nelle altre modalità sono necessari due ulteriori file: ini.cod e
cnr1.cod. Per poterli caricare la comunicazione deve essere impostata manualmente. Dal lato PC nulla cambia rispetto al trasferimento del sistema operativo. Dal
lato controllore è necessario eseguire la seguente procedura:
1. assicurarsi di essere nel menu principale tramite il tasto “PREV”.
2. selezionare “UTILITY”, “COMUNICATION” e “MOUNT”.
3. selezionare ora “KERMIT”, alla richiesta della porta sulla quale attivare la
comunicazione, digitare prima “/s”, poi “com0:”, mentre alla richiesta d’inserimento della velocità di trasmissione si può digitare “38400” se la stessa
scelta è stata fatto dal lato PC.
In questo modo la comunicazione è attiva. Si devono ora trasferire i due file, per
farlo basta eseguire la seguente procedura:
1. assicurarsi di essere nel menu principale tramite il tasto “PREV”.
2. selezionare “FILER” e “COPY”, alla richiesta del nome del file sorgente, digitare “com0:[nomefile.estensione]”3 , poi digitare la destinazione “rd:” (indica la RAM batterizzata).
Per copiare i file dal controllore al PC basta invertire sorgente e destinazione.
Per interrompere la comunicazione si deve: sul controllore selezionare “UTILITY”, “COMUNICATION” e “DISMOUNT”, a questo punto basta digitare “com0:”,
mentre sul PC basta ripetere quello detto in precedenza.
Con questi due file è possibile utilizzare il manipolatore anche in modalità
aperta.
3 Esempio:
“com0:*.cod”.
B.4. Calibrazione del COMAU Smart-3S
65
B.4 Calibrazione del COMAU Smart-3S
Calibrare significa “impostare lo zero dei resolver”. Se il robot non è calibrato
appare sul monitor del controllore la scritta “ARM NOT CALIBRATE”, in tal caso
è necessario eseguire la calibrazione e salvarla sulla RAM batterizzata.
La procedura di calibrazione è la seguente:
1. assicurarsi che la chiave blu sia su “PROGR”.
2. prendere il TEACH PENDANT e premere sui tasti “HOLD” e “DRIVE OFF”
del controllore se sono illuminati, ripetere la stesse operazioni sul TEACH
PENDANT e accendere i motori premendo il tasto “DRIVE ON”.
3. Utilizzando i tasti dei singoli motori mouvere i giunti in modo che le tacche
presenti sui giunti stessi coincidano.
4. assicurarsi di essere nel menu principale tramite il tasto “PREV”.
5. selezionare “CONFIGURE”, “ARM” e “CALIBRATE”, alla richiesta del numero dell’arm premere ENTER e digitare “*”, in modo che tutti i giunti
vengano calibrati.
6. spegnere i motori.
7. selezionare “PRT” e “SAVE”, alla richiesta della scheda di controllo premere
“ENTER” e successivamente digitare “y”. Questo permette di conservare la
calibrazione.
8. assicurarsi di essere nel menu principale tramite il tasto “PREV”.
9. selezionare “CONFIGURE”, “ARM” e “SAVE”, alla richiesta di conferma
digitate “y”. Questo salva la calibrazione nella RAM batterizzata.
Ora il robot è calibrato e pronto per essere utilizzato sia nello spazio operativo
sia in quello di giunto.
È possibile controllare la calibrazione visualizzando sullo schermo del controllore la posizione dei giunti. Per farlo basta assicurarsi di essere nel menu principale e selezionare “DISPLAY”, “ARM” e “JOINT”; in questo modo comparirà
sullo schermo una striscia azzurra con i dati che ci interessano. I gradi riportati
dovrebbero essere: 0 0 90 0 0 0 .
66
Il robot COMAU Smart-3S
B.5 Possibili cause di errore
Usare il COMAU Smart-3S richiede molta attenzione da parte dell’operatore.
Alcune situazioni dovrebbero essere evitate.
Non riavviare mai il PC qunado la comunicazione tra robot e calcolatore è attiva,
questa è una delle situazioni in cui si può avere la perdiata del sistema operativo
nel C3G 9000. Se il sistema è completamente perso problemi non ve ne sono,
se però il software non è perso ma danneggiato, non vi è la richiesta da parte del
manipolatore di caricare dall’esterno il sistema operativo. Una soluzione è attendere
che la RAM batterizzata si scarichi del tutto. Problemi analoghi si possono avere se
il manipolatore viene spento in modalità 4, è quindi opportuno rimettere sempre il
robot in modalità 0 dopo il suo utilizzo.
È necessario, inoltre, scaricare i moduli real time dal kerenl prima di eseguire
un “logout” dall’interfaccia grafica di Linux, in caso contrario si ha il blocco del PC
ed è necessario premere il tasto reset presente sul calcolatore.
Bibliografia
[1] Marcelo Alonso e Edward J. Finn. Elementi di fisica per l’univeristà,
volume 2. Masson S.p.A., seconda edizione, 1983.
[2] Jhon Canny. A computational approach to edge detection. IEEE Transactions
on pattern analysis and machine intelligence, PAMI-8(6), Novembre 1986.
[3] Raffaella Carloni. Manipolazione robotica: startgie di presa ottima di oggetti
planari. Tesi di Laurea, Università di Bologna, DEIS, 2002.
[4] COMAU S.p.A. C3G 9000, 3.0 edizione, 1991.
[5] Mark Watson Kurt Wall e Marck Whitis. Programmare in Linux. APOGEO,
2000.
[6] Paolo Mantegazza. Rtai programming guide. 2000.
[7] Matthias Kalle Dalheimer Matt Welsh e Lar Kaufman.
APOGEO, 2000.
Linux la guida.
[8] Havoc Pennington. GTK+/Gnome Sviluppo di applicazioni. APOGEO, 2000.
[9] Dietrich Pescholler. Applicazione di rtai linux per il controllo di un robot. Tesi
di Laurea, Università di Bologna, DEIS, 2001.
[10] Alessandro Rubini e Jonathan Corbet. Linux device drivers. O’Reilly, seconda
edizione, 2002.
[11] Luca Vittuari. Interfaccia per la scheda di protopizzazione rapida in ambiente
linux. Tesi di Laurea, Università di Bologna, DEIS, 2001.
68
Bibliografia
Was this manual useful for you? yes no
Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Download PDF

advertisement