Equipaggiamenti come Lego Mindstorms, con accoppiamento rapido di sensori ed attuatori, rendono facile per gli utenti costruire behavior reattivi.
I problemi sono come mettere più intelligenza nel software e come sfruttare meglio i sensori.
Le buone intenzioni spesso sono frustrate da due problemi.
Nei primi lavori sul paradigma reattivo, come abbiamo visto, si avevano robot caratterizzati da un set molto piccolo di behavior i quali erano combinati internamente per produrre un behavior emergente complessivo.
Si è mostrato che i componenti chiave di un’architettura reattiva sono i behavior più il meccanismo di fusione dei behavior concomitanti.
Molte applicazioni sono state progettate come una serie di comportamenti, che funzionano secondo una sequenza riconoscibile.
Una delle prime applicazioni, alla quale molti robotici guardarono, consisteva nel raccogliere e depositare in un secchio una lattina di una qualche bevanda.
Questo problema implica che il robot vada alla ricerca di una lattina, si muova verso la lattina, quando l’ha trovata la raccolga, cerchi il bidone della spazzatura, si muova verso il bidone, lasci cadere la lattina.
E’ controintuitivo pensare che questi behaviors siano concorrenti o fusi in un unico behavior.
(C’è certamente la possibilità di concorrenza, per esempio quando evita gli ostacoli mentre si muove verso la lattina o il bidone.)
Le tecniche introdotte per controllare sequenze di behavior sono per la maggior parte concettualmente equivalenti alla costruzione di macro-behavior, dove la struttura dello schema è usata ricorsivamente per semplificare la programmazione del programma di controllo.
Questo capitolo tenta di aiutare il progettista a costruire un sistema di robot reattivo, alla luce di questi due deficit.
Iniziamo con il presentare un approccio diretto alla programmazione a oggetti per i behavior.
Questo approccio è basato sullo schema theory presentato nella lez. 11.
Il caso di studio enfatizza l’importanza di stabilire una nicchia ecologica per un robot reattivo.
Nella applicazione fatta da Arbib dello schema theory rivolto ad una teoria computazionale dell’intelligenza, un behavior è uno schema che è composto da un schema motorio ed uno schema percettivo.
Lo schema motorio e lo schema percettivo sono come pezzi di un puzzle; entrambi i pezzi devono essere messi insieme prima di avere un behavior.
Il behaviour del nutrirsi può essere modificato come uno schema comportamentale, o modalità come mostrato in figura.
Successivamente, sono presentate due tecniche per maneggiare sequenze di behavior: automi a stati finiti e script.
Vedremo ancora, come era da aspettarsi dal materiale presentato nella Lez. 11, che entrambe queste tecniche sembreranno molto simili all’IRM di Tinbergen e Lorenz.
Anche se la Programmazione a Oggetti non era ancora popolare nel periodo in cui si è sviluppato il Paradigma Reattivo, è utile guardare i behavior in termini di OOP.
Lo Schema theory va bene per trasferire concetti teorici in termini di OOP.
Lo Schema theory viene anche usato come ponte tra i concetti dell’intelligenza biologica e quella robotica, rendendo possibile una realizzazione pratica della reattività che sfrutta meccanismi di releasing innati ed affordances.
Si ricordi che un oggetto consiste di dati e metodi, anche chiamati attributi ed operazioni.
Come notato in precedenza, gli schemi contengono conoscenza specifica, dati locali, strutture e altri schemi.
In figura si vede come potrebbe essere definito uno schema. Secondo Arbib, uno schema in programmazione a oggetti sarà una classe. La classe avrà un metodo opzionale detto programma di controllo coordinato. Il programma di controllo coordinato è una funzione che coordina alcuni metodi o schemi nella classe derivata.
Tre classi sono derivate dalla Classe Schema:
I Behavior sono composti da almeno uno Schema Percettivo ed uno Schema Motore; questi schemi si comportano come metodi per la classe Behavior.
Usando l’UML (Unified Modeling Language) le classi Schema e Behavior appaiono come in fig. L’organizzazione degli OOP permette ad un behavior di essere composto di schemi percettivi multipli, schemi motore e behavior, il che equivale a dire che la definizione di un behavior è ricorsiva.
Perché è utile avere schemi percettivi e schemi motore multipli?
Ad esempio in qualche caso, può tornare utile avere due schemi percettivi, uno per sapere le condizioni di luce di giorno se si usa una telecamera ed uno per la notte se si usano gli infrarossi.
Si ricordi che un behavior primitivo è composto solo di uno schema percettivo e uno schema motore; non c’è nessun bisogno di avere alcun programma di controllo per il coordinamento.
Si può pensare che i Behavior primitivi siano monolitici, in quanto essi fanno solo una cosa. Poiché di solito essi sono un semplice mapping tra lo stimolo e la risposta, sono spesso programmati come un solo metodo, non composti da metodi multipli od oggetti.
I Behavior che sono assemblati da altri behavior o hanno schemi percettivi multipli e schemi motore li chiameremo “behavior astratti”, perché, rispetto a un behavior primitivo, sono alquanto lontani dai sensori e dagli attuatori.
L’uso del termine “behavior astratto” non deve essere confuso con una classe astratta in OOP.
L’esempio che segue mostra come può essere progettato un behavior primitivo che usa i principi della OOP.
Nel 1994, l’annuale AAAI Mobile Robot Competition aveva una gara su “Raccogli l’Immondizia”, gara che fu ripetuta nel 1995 all’AAA-IJCAI Mobile Robot Competition.
L’idea di base era di mettere un robot in un’arena vuota grande circa quanto un ufficio. Nell’arena ci sarebbero state lattine di CocaCola e tazze bianche collocate a caso. In due dei quattro angoli, c’era un bidone di raccolta blu; negli altri due, un bidone di immondizia colorato diversamente.
Il robot che raccoglieva più immondizia e la metteva nel bidone giusto, nel tempo assegnato, era il vincitore.
Per molto tempo, la strategia fu di trovare e riciclare le lattine di CocaCola, perché erano più facili da percepire per gli algoritmi di visione del robot essendo di colore rosso e blu.
L’esempio che segue mostra come può essere progettato un behavior primitivo che usa i principi della OOP.
Nel 1994, l’annuale AAAI Mobile Robot Competition aveva una gara su “Raccogli l’Immondizia”, gara che fu ripetuta nel 1995 all’AAA-IJCAI Mobile Robot Competition.
L’idea di base era di mettere un robot in un’arena vuota grande circa quanto un ufficio. Nell’arena ci sarebbero state lattine di CocaCola e tazze bianche collocate a caso. In due dei quattro angoli, c’era un bidone di raccolta blu; negli altri due, un bidone di immondizia colorato diversamente.
Il robot che raccoglieva più immondizia e la metteva nel bidone giusto, nel tempo assegnato, era il vincitore.
Per molto tempo, la strategia fu di trovare e riciclare le lattine di CocaCola, perché erano più facili da percepire per gli algoritmi di visione del robot essendo di colore rosso e blu.
Uno dei behavior di base necessario per raccogliere una lattina rossa e muoversi verso un bidone blu è move_to_goal.
Quando il robot vede una lattina rossa, deve muoversi verso di essa. Quando ha raccolto una lattina, allora deve trovare e poi muoversi verso un bidone blu.
È corretto dal punto di vista dell’ingegneria del software scrivere un behavior generale per muovere verso il goal, dove solo quello che è il goal regione rossa o blu può variare.
Il goal in questo esempio può essere passato come una instanziazione attraverso il costruttore dell’oggetto.
Scrivere un solo behavior generico per move_to_goal (color) è preferibile rispetto a scrivere un behavior move_to_red ed un behavior move_to_blue. Dal punto di vista dell’ingegneria del software, scrivere due behavior che fanno la stessa cosa è una possibilità per introdurre bug di programmazione.
Un codice modulare, generico può essere ben gestito dagli schemi.
Il behavior move_to_goal consisterà di uno schema percettivo che sarà chiamato estrai_goal ed uno schema motore che userà un campo attrattore chiamato pfields.attrattivo.estrai_goal che usa l’affordance del colore per estrarre dove è nell’immagine il goal, per poi calcolare l’angolo al centro della regione colorata e la grandezza della regione.
Queste informazioni formano il percetto del goal; l’affordance della lattina di Coca Cola può essere il colore, mentre le informazioni estratte dalla percezione sono l’angolo e la grandezza.
Lo schema motore attrattivo riceve il percetto ed è responsabile di far girare il robot verso il centro della regione rossa e muoverlo in avanti. Questo si può fare facilmente usando un campo attrattivo, in cui più grande è la regione, più forte è l’attrazione e più velocemente si muove il robot.
Il behavior move_to_goa1 può essere implementato come un behavior primitivo, dove goal_color è una maniera per rappresentare colori diversi come rosso e blu.
La tabella contiene alcuni aspetti molto importanti per la programmazione con i behavior.
Il suffisso di pfields su pfields.attraction() vuole dire che quell’attrazione è un metodo all’interno di un altro oggetto identificato come pfields.
I cinque campi di potenziale primitivi, visti precedentemente, potrebbero essere incapsulati in una classe chiamato PFields che ogni schema motore potrebbe usare.
PFields servirebbe come una libreria.
Una volta che i campi di potenziali in PFields sono scritti e verificati, il progettista non deve più programmarli di nuovo.
3. I Behavior si possono riusare se scritti adeguamente. In questo esempio, il behavior move_to_goal è scritto per accettare una struttura (od oggetto) definito da un colore e si muove poi verso una regione di quel colore. Questo vuole dire che il behavior può essere usato con lattine di Coca cola rosse e secchi di immondizia blu.
1. Introduzione
4. Esempi di applicazione del paradigma gerarchico
11. Schema Theory
13. Architetture Reattive a Sussunzione
14. Architetture a Campi di Potenziale
15. Architetture a Campi di Potenziale e Sussunzione
16. Progettazione di un sistema Reattivo - 1
17. Progettazione di un sistema Reattivo - 2
18. Progettazione di un sistema Reattivo - 3