ROS2
NODO
Un nodo è definibile come un'entità indipendente che utilizza ROS per comunicare con altri nodi. A
livello pratico, un nodo è un singolo processo esecutivo che esegue un calcolo specifico (unit of
computation).
L'architettura di ROS si basa fortemente sul concetto di modularità: ogni nodo deve avere un singolo
scopo ben definito. Ad esempio, un nodo potrebbe occuparsi esclusivamente di controllare i motori
delle ruote, mentre un altro potrebbe limitarsi a pubblicare i dati letti da un sensore laser. Un sistema
robotico completo, quindi, non è altro che un insieme di numerosi nodi che lavorano in concerto,
scambiandosi dati. Ogni nodo può inviare e ricevere dati tramite topics, servizi, azioni o parametri.
In un'architettura reale, avremo un Camera Node che si interfaccia direttamente con l'hardware della
telecamera. Questo nodo non processa l'immagine, ma si limita a inviare i dati tramite messaggi a un
Image Processing Node, che farà i calcoli veri e propri. Lo stesso vale per il laser.
In un'architettura reale, avremo un Camera Node che si
interfaccia direttamente con l'hardware della telecamera. Questo
nodo non processa l'immagine, ma si limita a inviare i dati tramite
messaggi a un Image Processing Node, che farà i calcoli veri e
propri. Lo stesso vale per il laser. Allargando la prospettiva, tutti questi nodi formano
un Grafo ROS (ROS Graph). Il nodo della telecamera
passa i dati a quello di elaborazione, che a sua volta
li passa a un nodo di Person Detection (rilevamento
persone). Questo dato, combinato con i dati del
laser e della localizzazione, confluisce in un nodo
centrale di Behavior Generation (generazione del
comportamento), che infine invierà i comandi ai nodi
dei motori e delle braccia.
Perché utilizzare questa architettura distribuita invece di un unico grande programma (codice
monolitico)? I vantaggi principali sono due:
1. Tolleranza ai guasti (Fault Tolerance): Se il nodo che gestisce la telecamera va in crash, il
sistema non si spegne. Il robot potrà continuare a muoversi usando i dati del laser, garantendo
un livello di sicurezza fondamentale in ambito biomedico.
2. Semplicità di Debug: Essendo ogni nodo responsabile di una sola funzione, è molto più facile
individuare e risolvere i bug.
Infine, a livello di programmazione, questi nodi vengono scritti utilizzando delle librerie client
specifiche di ROS: rclcpp se programmiamo in C++, o rclpy se utilizziamo Python.
Come fanno questi nodi indipendenti a trovarsi e a parlarsi in una rete? In ROS2, questo avviene
tramite un Processo di Discovery Distribuito e Automatico.
Affinché i nodi possano 'vedersi', devono appartenere allo stesso dominio, identificato dalla variabile
ROS_DOMAIN_ID. Se condividono questo ID, il processo avviene in quattro fasi:
1. Annuncio (Advertisement): Quando un nodo viene avviato, annuncia la propria presenza sulla
rete agli altri nodi.
2. Risposta: Gli altri nodi rispondono a questo annuncio inviando le proprie informazioni,
permettendo così di stabilire le connessioni appropriate. 1
3. Annunci Periodici: I nodi continuano ad annunciare periodicamente la loro presenza. Questo
permette a nodi avviati in un secondo momento di unirsi dinamicamente al sistema senza
dover riavviare tutto.
4. Disconnessione: Quando un nodo si spegne o va offline, invia un messaggio di notifica agli
altri per chiudere le connessioni.
Una volta che i nodi si sono 'scoperti', come si scambiano i dati? ROS mette a disposizione tre
paradigmi principali di comunicazione, da scegliere in base al tipo di task:
1. Topics (Il flusso continuo)
Utilizzano il modello Publisher/Subscriber. Un nodo (Publisher) pubblica un flusso continuo di dati
su un 'canale' chiamato Topic. Qualsiasi altro nodo (Subscriber) interessato a quei dati può iscriversi
al Topic per leggerli. È una comunicazione unidirezionale e continua, perfetta per lo streaming di dati
sensoriali (es. i frame di una telecamera).
2. Services (La chiamata sincrona)
Utilizzano il modello Client/Server. Il Service Client invia una specifica Richiesta (Request) al Service
Server, il quale elabora l'informazione e restituisce una Risposta (Response). È una comunicazione
sincrona (il client aspetta la risposta) ed è ideale per azioni rapide o per interrogare lo stato del
sistema (es. 'Accendi il LED' o 'Qual è il livello della batteria?').
3. Actions (Le operazioni complesse)
Le Actions sono simili ai Services, ma sono progettate per task lunghi e complessi, ed operano in
modo asincrono. L'Action Client invia un Goal (un obiettivo, es. 'Naviga fino in fondo al corridoio')
all'Action Server. Poiché l'operazione richiede tempo, il Server invia continui Feedback (es. la
percentuale di completamento o la posizione attuale) durante l'esecuzione, e solo alla fine restituisce
il Result (il risultato finale dell'operazione). Questo permette al nodo chiamante di non rimanere
bloccato in attesa e di poter annullare l'azione se necessario.
TOPICS
I Topics sono fondamentalmente dei "canali etichettati" (hanno un nome specifico, come
/sensore_forza) progettati per una cosa ben precisa: i flussi continui di dati.
- Publisher (Pubblicatore): È il nodo che produce il dato. Prende l'informazione dal sensore e la
"pubblica" su un Topic specifico.
- Subscriber (Sottoscrittore): È il nodo che consuma il dato. Se a un nodo serve
quell'informazione, si "iscrive" al Topic.
La regola d'oro qui è il broadcast: quando un Publisher invia un dato sul Topic, tutti i Subscribers
iscritti a quel Topic riceveranno il dato contemporaneamente.
Anonymous: legge il dato (Subscriber) non sa, e non gli interessa sapere, chi lo ha scritto (Publisher),
e viceversa. Se il nodo che pubblica i dati della telecamera si rompe e viene sostituito al volo da un
altro nodo telecamera, i nodi che leggono l'immagine non se ne accorgono nemmeno. I nodi non
comunicano mai direttamente tra di loro, ma sempre e solo attraverso il Topic. Questo rende il
sistema estremamente modulare e robusto.
Messages: unità di dati formattate secondo uno standard preciso (i file .msg), che definiscono le due
parti chiamate campi e costanti (es. un intero per la temperatura, un array per l'immagine) in modo
che chi legge sappia esattamente come interpretare la sintassi. 2
One-to-Many (Uno-a-Molti): Guarda il Camera
node. Pubblica immagini sul Topic /image_data.
A questo Topic sono iscritti
contemporaneamente due nodi diversi (l'Image
Processing node e l'Other Processing node).
Entrambi ricevono la stessa immagine nello
stesso istante e ci fanno cose diverse (magari
uno cerca volti, l'altro calcola la luminosità).
Many-to-One (Molti-a-Uno): Abbiamo un Laser
node e un Other lidar node. Entrambi sono
sensori laser fisicamente distinti, ma pubblicano i loro dati sullo stesso Topic /laser_data. Il nodo
Laser Processing node (Subscriber) si iscrive a quel singolo Topic e riceve i dati di entrambi i sensori,
unificandoli.
SERVICES
Services (Servizi) non servono per lo streaming continuo, ma per le Remote Procedure Calls (RPC),
ovvero le "chiamate a procedure remote". Significa che un nodo chiede a un altro nodo di eseguire un
calcolo o un'azione specifica, e aspetta di ricevere un risultato. In questo caso abbandoniamo il
modello Publisher/Subscriber e adottiamo il paradigma Client/Server:
Service Client: È il nodo che ha bisogno di un'informazione o di un'azione. Invia una Request
• (Richiesta) al server e aspetta. -> numero aribitrario
Service Server: È il nodo che riceve la richiesta, esegue la computazione e restituisce una
• Response (Risposta). -> un server per ogni computazione
I servizi devono essere utilizzati per processi rapidi (quickly processes). Non usiamo un servizio per far
navigare un robot da una stanza all'altra (ci vorrebbe troppo tempo e il client rimarrebbe bloccato in
attesa), lo usiamo per chiedere "Qual è il livello della batteria?" o "Accendi il laser".
Mentre puoi avere infiniti client che fanno richieste a uno stesso servizio, ci deve essere un solo
identico Service Server per ogni nome di servizio. (Se due server diversi rispondessero alla
domanda "Quanto è carico l'esoscheletro?", a chi dovrebbe credere il client?)
I servizi sono descritti e definiti in file .srv.
Request: Sono i dati di input che il Client invia. Nell'esempio il client
invia due numeri interi senza segno a 32 bit (uint32 a e uint32 b).
Response: È l'output atteso che il Server deve restituire.
Nell'esempio, è la somma dei due numeri (uint32 sum).
Flusso dei dati: I Topics sono per un flusso continuo (continuous data flow. I Services si chiudono non
appena la richiesta è soddisfatta, come chiedere al sistema "Esegui la calibrazione del braccio
robotico". Direzionalità: I Topics sono
unidirezionali (il Publisher "spara" il dato
e non sa chi lo riceve). I Services sono
bi-direzionali (il Client chiama, il Server
ascolta, agisce e risponde direttamente
al Client).
Paradigma: Publish/Subscribe contro
Request/Reply. 3
ACTIONS
Actions sono delle Preemptable Remote Procedure Calls. Significa che l'operazione può essere
interrotta o annullata prima che finisca e nel mentre vengono inviati dei feedback.
Un'Action è pensata per processi lunghi (long-running) costituiti da più steps, come la navigazione o
la manipolazione di oggetti, ed è strutturata sempre con il paradigma Client/Server:
Action Client: È chi richiede il task (invia il Goal). Durante l'esecuzione, non rimane bloccato:
• può fare altro, può monitorare lo stato di avanzamento e, se necessario, può annullare tutto.
Action Server: È chi riceve il task, lo esegue, invia aggiornamenti continui (Feedback) e alla
• fine restituisce l'esito definitivo (Result).
Come per i servizi, anche le azioni hanno un loro file di configurazione, i file
.action. Ci sono tre sezioni:
1. Il Goal (es. le coordinate XYZ da raggiungere).
2. Il Result (es. "Raggiunto" o "Fallito").
3. Il Feedback (es. "Distanza rimanente: 2 metri").
Un'Action è un costrutto di alto livello formato combinando 3 Services e 2 Topics insieme.
I 3 Services: 1. Send goal: Il Client usa questo
servizio per inviare la descrizione
dell'obiettivo. Il Server risponde subito
dicendo "Ok, lo accetto" oppure "No,
lo rifiuto".
2. Cancel goal: Se il Client decide di
abortire, chiama questo servizio
inviando l'ID dell'azione. Il Server
risponde confermando se l'azione è
stata interrotta.
3. Get results: Quando l'azione finisce, il Client usa questo servizio per farsi dare il report finale
(il Result). I 2 Topics (per i flussi di dati
continui):
1. Feedback: Il Server agisce
da Publisher su questo Topic,
inviando costantemente
messaggi. Il Client agisce da
Subscriber e legge questi
aggiornamenti in tempo reale.
2. Goal Status: È un Topic in
cui il Server pubblica lo stato attuale nella macchina a stati dell'azione (es. Executing,
Succeeded, Aborted, Canceled).
In alto abbiamo tre "attori" (le linee verticali tratteggiate):
1. Action Client: Il nodo che ordina l'azione.
2. Action Server: Il gestore delle comunicazioni sul lato server.
3. User defined execution method: Questo è il tuo vero codice C++ o Python! È la funzione che
materialmente muove i motori o fa i calcoli. 4
1. Esecuzione con Successo: Questo è lo scenario
in cui tutto fila liscio.
Seguendo le frecce dall'alto verso il basso:
• Il Client invia una goal request (es. "Vai alle
coordinate X, Y").
Il Server risponde quasi immediatamente con
•
una goal response (accept). Il server sta solo
dicendo "Ok, ho ricevuto il comando e la sintassi è
corretta", non che ha finito!
Subito dopo, il Client invia una result request,
•
dicendo al server: "Avvisami quando hai un risultato
definitivo". Essendo asincrona, il Client ora è libero di
fare altro.
Nel frattempo, il tuo codice (user defined method) inizia a lavorare. Mentre lavora, spara fuori
• una serie di publish feedback (es. "Sono al 10%", "Sono al 50%").
Alla fine, il tuo codice genera il risultato finale (set result), e il Server lo impacchetta in una
• result response che torna al Client. Operazione conclusa.
2. Preemptable
Cosa succede se premo l'arresto di emergenza? Tutto inizia
come prima, ma a metà dell'esecuzione il Client invia una
cancel request. Il server risponde con una cancel response
(accept), dicendo "Ricevuto, avvio la procedura di stop".
Guarda la freccia tratteggiata notify. Il server notifica al tuo
codice che c'è stata una richiesta di cancellazione. Il tuo
codice ha il tempo di fare le operazioni di spegnimento in
sicurezza. Invia un ultimo feedback e poi restituisce il
risultato (che questa volta sarà di tipo "Canceled"). È una
chiusura "aggraziata" (graceful shutdown).
3. Gestione obiettivi multipli Il Client non è costretto ad aspettare la fine della prima
azione per farne un'altra. Guarda il flusso:
Il Client invia il primo Goal. Il Server lo accetta e inizia a
•
mandare feedback.
Mentre il primo Goal sta ancora girando, il Client invia un
•
secondo goal request.
Il Server accetta anche questo. Ora vedi che i publish
•
feedback e le result response si intersecano.
A seconda di come programmi il tuo Server, questo
potrebbe significare due cose: o il server sta
gestendo le azioni in parallelo (se l'hardware lo
permette), oppure il secondo goal ha soppiantato il
primo. 5
Mentre un Service è un semplice "esegui e rispondi", un'Action Server ha al suo interno una vera e
propria macchina a stati che traccia costantemente in che fase si trova l'operazione (Accepted,
Executing, Canceling, Succeeded, Aborted).
Services: Fast procedure. Operazioni rapide, sincrone.
Actions: Longer task completion. Operazioni lunghe, asincrone, con feedback continuo e possibilità
di cancellazione.
PARAMETERS
I parametri ti permettono di configurare un nodo all'avvio o durante l'esecuzione (runtime) senza
toccare una riga di codice.
Ogni parametro è formato da:
Key (Chiave): Il nome del parametro (es. /camera/fps).
• Value (Valore): Il dato vero e proprio (es. 30, che è un
• intero).
Description: Una nota per ricordarti a cosa serve.
•
Quando si cerca di cambiare un parametro durante l’esecuzione di un nodo entrano in gioco due
Callbacks di sicurezza:
1. Set parameter callback (Il "Buttafuori"): Prima che il parametro venga effettivamente
modificato, questa funzione scatta, ispeziona il nuovo valore e decide se accettarlo o rifiutarlo
esplicitamente (es. "Errore: velocità superiore al limite di sicurezza").
2. On parameter event callback (Il "Messaggero"): Se il buttafuori ha accettato la modifica,
scatta questa seconda funzione. Serve per dire al tuo nodo: "Ehi, il parametro è cambiato con
successo, ora aggiorna i tuoi calcoli interni con il nuovo valore".
ROS_DOMAIN_ID:. È un numero (di default è 0). Solo i nodi che hanno lo stesso Domain ID possono
vedersi e comunicare tra loro. Distingue diverse reti ROS 2 che potrebbero essere in esecuzione sulla
stessa rete fisica (Wi-Fi).
ESERCIZIO 1
Nodo 1: Camera node Il suo unico scopo nella vita è accendere la telecamera, catturare i frame grezzi
(i pixel) e metterli a disposizione del sistema.
Come comunica? Poiché un video è un flusso continuo di dati (tanti frame al secondo), usa il
• paradigma Publish/Subscribe.
Il Camera node agisce da Publisher e pubblica i dati sul Topic /image_frame.
•
Nodo 2: Person detection node Questo è il "cervello visivo". Non sa nulla dell'hardware della
telecamera, sa solo leggere matrici di pixel.
Come comunica (Input)? Si iscrive come Subscriber al Topic /image_frame.
• 6
Esegue un codice per trovare le coordinate (X,Y) della persona nell'immagine.
• Come comunica (Output)? Una volta trovata la persona, diventa a sua volta un Publisher.
• Pubblica le coordinate spaziali della persona su un nuovo Topic chiamato /person_detected.
Anche qui usiamo un Topic perché la posizione della persona cambia continuamente mentre
cammina.
Nodo 3: Human-following node Questo è il controllore dei motori. Non gli interessa come l'immagine
è stata analizzata. Vuole solo sapere "dove devo andare?".
Come comunica? Si iscrive come Subscriber al Topic /person_detected.
• Cosa fa dentro? Prende le coordinate, calcola la cinematica (quanta potenza dare alla ruota
• destra e alla ruota sinistra) e invia i comandi ai driver hardware per far muovere fisicamente il
robot PAL.
ESERCIZIO 2
• Il Camera node acquisisce le immagini e le pubblica in continuo sul Topic /image_frame.
• Il Line Processing node è abbonato a /image_frame. Elabora l'immagine per trovare il centro
della linea nera e calcola le velocità (lineare e angolare) necessarie per tenere il robot centrato.
Pubblica questi comandi di velocità su un Topic chiamato /cmd_vel (Command Velocity).
• Il Motion controller è il nodo che comanda fisicamente i motori. Si iscrive a /cmd_vel e
trasforma le velocità logiche in impulsi elettrici per le ruote.
• Il Lidar node legge continuamente i dati laser (distanze e angoli) e li pubblica sul Topic /scan.
• L'Obstacle detection node è abbonato a /scan. La sua unica funzione è controllare se c'è
qualcosa troppo vicino (es. a meno di 1 metro). Finché non c'è ni
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
-
Appunti esame primo parziale Robotica biomedica
-
Appunti di Fondamenti di robotica biomedica
-
Appunti di Robotica biomedica della prima parte del corso (1° parziale)
-
Appunti di Robotica biomedica della seconda parte del corso (2° parziale)