{"id":16966506,"url":"https://github.com/eldavoo/zeromq-experiment","last_synced_at":"2026-02-12T18:30:14.626Z","repository":{"id":194528881,"uuid":"662249502","full_name":"ElDavoo/zeromq-experiment","owner":"ElDavoo","description":"On understanding the feasibility of ZMQ in place of ROS","archived":true,"fork":false,"pushed_at":"2023-09-13T10:15:51.000Z","size":11319,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-26T12:41:25.596Z","etag":null,"topics":["jetson-nano","plotjuggler","ros2","ros2-foxy","zeromq","zmq"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ElDavoo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-07-04T17:31:00.000Z","updated_at":"2023-12-30T11:12:39.000Z","dependencies_parsed_at":"2023-09-13T21:45:11.029Z","dependency_job_id":null,"html_url":"https://github.com/ElDavoo/zeromq-experiment","commit_stats":null,"previous_names":["eldavoo/zeromq-experiment"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ElDavoo%2Fzeromq-experiment","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ElDavoo%2Fzeromq-experiment/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ElDavoo%2Fzeromq-experiment/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ElDavoo%2Fzeromq-experiment/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ElDavoo","download_url":"https://codeload.github.com/ElDavoo/zeromq-experiment/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239811416,"owners_count":19700961,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["jetson-nano","plotjuggler","ros2","ros2-foxy","zeromq","zmq"],"created_at":"2024-10-14T00:06:02.028Z","updated_at":"2026-02-12T18:30:14.562Z","avatar_url":"https://github.com/ElDavoo.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# zeromq-experiment\nQuesto progetto è un esperimento per valutare l'utilizzo di\n[ZeroMQ](https://zeromq.org/) \ncome libreria di messaggistica per software di veicoli autonomi, come il veicolo\n[F1/10](https://f1tenth.org/).  \nQuesto è un progetto universitario per il corso \"Real-Time Embedded Systems\", per l'Università degli studi di Modena e Reggio Emilia, anno 2022-2023.\n\n## Introduzione\n### ROS2\nROS2 è un framework open source basato su un modello di pubblicazione/sottoscrizione, in cui i messaggi vengono inviati da un nodo a un altro. Questo consente ai nodi di comunicare tra loro in modo semplice e tramite diversi livelli di affidabilità.\nROS2 non implementa un suo middleware (ovvero il software che si occupa dello scambio di messaggi fra i nodi), ma utilizza eProsima Fast DDS.\nFast DDS, a sua volta, utilizza UDP.\nROS2, quindi, è un framework completo con un suo sistema di compilazione, gestione pacchetti, scoperta dei nodi, riproduzione dei dati, etc.  \n### ZeroMQ\nZeroMQ è una libreria di messaggistica asincrona ad alte prestazioni, leggera e semplice che consente agli sviluppatori di creare applicazioni distribuite e concorrenti. È una libreria leggera e semplice da usare, che offre una vasta gamma di funzionalità per soddisfare una varietà di esigenze.  \nAl contrario di ROS2, quindi, non vengono offerti servizi ulteriori.\nZeroMQ utilizza TCP come ulteriore controllo di errori e perdita dati.  \n\n---\n\nZeroMQ, quindi, si presenta come una soluzione più difficile da utilizzare ma più leggera.\n### Obiettivo del progetto\nL'obiettivo del progetto è di confrontare la latenza delle due soluzioni software e stabilire la soluzione di minore latenza.\n\n## Background\nI pattern di comunicazioni sono indipendenti dalla soluzione scelta.  \nTuttavia, in ROS2 si preferisce utilizzare il pattern PUB-SUB.\n### Pattern Pubblicazione - Sottoscrizione (PUB-SUB)\n![Pattern Pubblicazione - Sottoscrizione](docs/pub_sub.png)\n\nNel pattern publicazione - sottoscrizione (documentato in lingua inglese come publisher - subscriber pattern), i nodi si interfacciano tra di loro scambiandosi direttamente determinate informazioni detti messaggi.\nEntrando maggiormente nel dettaglio, il nodo che fa da publisher pubblicherà un messaggio all'interno di un preciso topic, ovvero una sorta di mailbox, a cui si iscriveranno tutti i nodi subscriber che vorranno recepire quelle informazioni. Non è escluso che ci siano più nodi che pubblicano i messaggi ed inoltre solo i nodi di tipo publisher potranno inviare messaggi al topic: si può parlare, quindi, di comunicazione N-to-N unidirezionale.\n\n### Pattern del maggiordomo\n![Pattern del maggiordomo](docs/majordomo.png)  \n\nNel pattern del maggiordomo, i nodi client si interfacciano con un nodo intermediario (broker), che inoltrerà il messaggio al \nnodo responsabile dell'elaborazione dei dati (server). Ciò rende possibile l'utilizzo di intestazioni diversi, la presenza dinamica di più\nserver e client e garantisce una certa affidabilità nello scambio di messaggi.\n\n### Comunicazione tra nodi ROS2\nROS2 utilizza una nuova infrastruttura di comunicazione basata su Data Distribution Service (DDS), che migliora le prestazioni, la scalabilità e la sicurezza rispetto alla vecchia infrastruttura ROS1 basata sul protocollo TCP/UDP. Esistono implementazioni propritarie del DDS prodotte da svariati produttori ma è stata utilizzata quella utilizzata da ROS2 Foxy di default, ovvero [eProsima Fast](https://docs.ros.org/en/foxy/Installation/DDS-Implementations/Working-with-eProsima-Fast-DDS.html).\n![ROS2 DDS vs ROS1 TCP/UDP](docs/ros2_dds.png)\nSono state anche esplorate alcune configurazioni relative al QoS, nella fattispecie quelle necessarie al fine di rendere il canale non affidabile sulla falsariga del protocollo UDP.\nEssa è utilizzata under-the-hood dal framework in maniera trasparente per l'utente.\n```c\nstatic const rmw_qos_profile_t unreliable_qos_profile =\n{\n    RMW_QOS_POLICY_HISTORY_KEEP_LAST,\n    0, //queue depth\n    RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT,\n    RMW_QOS_POLICY_DURABILITY_VOLATILE,\n    RMW_QOS_DEADLINE_DEFAULT,\n    RMW_QOS_LIFESPAN_DEFAULT,\n    RMW_QOS_POLICY_LIVELINESS_SYSTEM_DEFAULT,\n    RMW_QOS_LIVELINESS_LEASE_DURATION_DEFAULT,\n    false // useless\n};\n```\n\n### Comunicazione tra nodi ZeroMQ\nZeroMQ permette l'utilizzo di svariati protocolli di trasporto, la cui scelta è dettata dai requisiti del sistema che si sta andando a sviluppare ed esse risultano essere invisibili alle API da utilizzare per la trasmissione dei messaggi; possono, quindi, essere utilizzate indipendentemente dal protocollo. Particolarità degne di nota risultano essere: \n1. non esiste un metodo `zmq_accept()`, quindi quando un socket è associato a un endpoint, inizia automaticamente ad accettare connessioni;\n2. la connessione di rete stessa avviene in background. ZeroMQ, si riconnetterà automaticamente se la connessione di rete dovesse essere interrotta (ad esempio, se il peer scompare e poi ritorna); quindi tutto avviene in maniera trasparente rispetto all'utente.\n\nNegli applicativi sviluppati per il benchmark, si è preferito utilizzare il tcp e l'ipc (interprocesso) in quanto sono due protocolli le cui proprietà maggiormente si avvicinano a quelli presenti in ROS2.\n#### TCP\n```sh\nzmq_bind (socket, \"tcp://*:5555\");\n```\nTCP è il trasporto unicast onnipresente, affidabile e affidabile. Nell'implementazione di ZeroMQ, è di tipo disconnesso in quanto non richiede che l'endpoint esista prima di connettersi ad esso. I client e i server possono connettersi e associarsi in qualsiasi momento, possono chiudersi e riaprirsi e rimanere sempre trasparenti alle applicazioni.\n#### IPC\n```sh\nzmq_bind (socket, \"ipc://somename\");\n```\nAnche IPC risulta essere disconnesso, come TCP; è implementato creando un file che verrà acceduto in scrittura dai nodi publisher e in sola lettura dai nodi subscriber.\n\n### Schemi di comunicazione\nSono riportati due schemi che riassumono le comunicazioni che avvengono tra i vari nodi, sia per le implementazioni ROS2 che per quelle ZeroMQ, con la nomenclatura dei topic utilizzata. In quest'ultimo, in quanto un canale di comunicazione (socket TCP o IPC) può essere utilizzato in maniera bidirezionale, tra le varie coppie di nodi è presenta una sola porta.\n#### ZeroMQ\n![ZeroMq Schema](docs/zeromq_schema.jpg)\n#### ROS2\n![ROS2 schema](https://github.com/ElDavoo/zeromq-experiment/assets/4050967/5eca201f-98d8-4ffa-913b-0ac451c3761a)\n\n# Valutazione\n## Ambiente di valutazione\nPer lo sviluppo e i test sono state usate due NVIDIA Jetson Nano Developer Kit, \ncollegate tramite Ethernet ai portatili degli studenti.\nL'ambiente di sviluppo utilizzato è stato VS Code in modalità remota (SSH).\n```sh\nroot@nano:~# lsb_release -a\nNo LSB modules are available.\nDistributor ID: Ubuntu\nDescription:    Ubuntu 20.04.6 LTS\nRelease:        20.04\nCodename:       focal\n\nsudo jetson-release\n\nSoftware part of jetson-stats 4.2.2 - (c) 2023, Raffaello Bonghi\nModel: NVIDIA Jetson Nano Developer Kit - Jetpack 4.6 [L4T 32.6.1]\nNV Power Mode[0]: MAXN\nSerial Number: [XXX Show with: jetson_release -s XXX]\nHardware:\n - P-Number: p3448-0000\n - Module: NVIDIA Jetson Nano (4 GB ram)\nPlatform:\n - Distribution: Ubuntu 20.04 focal\n - Release: 4.9.253-tegra\njtop:\n - Version: 4.2.2\n - Service: Inactive\nLibraries:\n - CUDA: 10.2.300\n - cuDNN: 8.2.1.32\n - TensorRT: 8.0.1.6\n - VPI: 1.1.15\n - Vulkan: 1.2.141\n - OpenCV: 4.6.0 - with CUDA: YES\n```\n- Toolchain utilizzata per i test: **GCC 9.4.0 aarch64-linux-gnu**\n- Versione di ROS2 utilizzata: **Foxy Fitzroy**\n- Versione di ZeroMQ utilizzata: **4.3.2**\n\nE' stato usato\n[PlotJuggler](https://github.com/facontidavide/PlotJuggler) 3.7.1 \nper visualizzare in tempo reale la telemetria dei nodi, installato su un pc separato.\n\n## Metodologia di valutazione\n\nConsultare la [guida apposita](docs/building.md) per visualizzare i comandi precisi.\n\n- Il sistema operativo è stato preparato con [queste](docs/real-time-tricks.md) istruzioni.\n- Le flag del compilatore sono quelle predefinite.\n\nSono stati implementati i seguenti pattern:\n - [Il pattern del maggiordomo](https://rfc.zeromq.org/spec/7/)\n - [Pattern pub-sub](https://rfc.zeromq.org/spec/29/).  \n\nIn entrambi i casi, la parte inviante:\n1. **Invia** un messaggio ogni 10ms, aumentandone ad ogni iterazione la dimensione di **1000 byte**. (La funzione di invio non è sincrona, il che significa che il messaggio viene inviato mentre il programma continua ad eseguire). Il messaggio ha contenuto casuale, per evitare influenze da parte di compressori e cache.\n2. **Campiona** il tempo attuale.\n3. **Attende la risposta** dalla parte ricevente.\n4. **Campiona** il tempo attuale.\n5. Calcola la **differenza** tra i due tempi campionati e manda al canale di **telemetria** (topic apposito).\n\nQuesta metodologia ci consente di calcolare il **Round Trip Time** (RTT) e di avere un'idea quindi della latenza, sia media che massima, del sistema, all'aumentare della dimensione del messaggio.\n\nQuesti pattern sono stati sviluppati sia per ROS2 che per ZeroMQ, in modo da poter confrontare le due soluzioni.\n\nPer ZeroMQ/pub_sub sono stati sviluppati due test, uno con IPC e uno con TCP, per valutare le differenze di prestazioni tra i due protocolli.  \nCon ROS2, questo non è stato necessario, in quanto come esplicitato prima esso fa uso del FastDDS che gestisce in maniera trasparente la comunicazione.  \n\nOgni test è stato eseguito su entrambe le schede, con PlotJuggler a registrare i dati e a visualizzarli in tempo reale.  \n\n\n\n## Risultati delle valutazioni\n- ZeroMQ con nodi su differenti core\n![ZeroMq](docs/0mq_different_cpus.png)\n- ZeroMQ con nodi sul medesimo core\n![ZeroMq](docs/0mq_same_cpu.png)\n- ROS2 con nodi su differenti core\n![ROS2](docs/ros2_different_cpus.png)\n- ROS2 con nodi sul medesimo core\n![ROS2](docs/ros2_same_cpu.png)\n- Visione d'insieme dei vari benchmark\n![Insieme](docs/all_together.png)\n\n# Conclusioni\nDai vari benchmark effettuati con ZeroMQ è possibile evincere che:\n1. Non si notano differenze apprezzabili tra un canale di comunicazione instaurato via TCP e uno via IPC.\n2. Il **pattern publisher - subscriber** risulta essere più prevedibile rispetto al **pattern del maggiordomo** in quanto sono presenti delle oscillazioni tra i valori di RTT (per rendere il grafico maggiormente leggibile è stato applicata una media mobile a 10 campioni).\n\nDai benchmark su ROS2 si può notare che:\n1. Il **pattern publisher - subscriber** e quello del **maggiordomo** si equivalgono con un leggero vantaggio a favore di quest'ultimo.\n\nInoltre è possibile vedere anche una differenza di comportamento in funzione del numero di core utilizzati: infatti ZeroMQ, nonostante abbia *under-the-hood* il supporto multi-thread, fatica in una configurazione multi-core a differenza di ROS2 che risulta essere penalizzato su una configurazione single-core, presumibilmente a causa dell'overhead applicato sui nodi essendo esso un framework a differenza di ZeroMQ il quale è una libreria.\n![Insieme](docs/core_comparison.png)\n\nUna cosa che accomuna ambedue le soluzioni è la presenza un maggiore RTT all'inizio della trasmissione che tende ad abbassarsi con l'esecuzione dei nodi: esso è giustificabile con l'overhead presente nei vari casi per la creazione di un canale di comunicazione in quanto i nodi trasmettono già dall'inizio nel mentre esso viene creato.\n\nSi può concludere, quindi, dicendo che ambedue le soluzioni abbiano dei vantaggi e degli svantaggi nel loro utilizzo, a seconda che si lavori con sistemi che possano trarre vantaggio da più core e dalla tipologia di pattern richiesto. Ultima ma non meno importante considerazione da fare è che la versione di ROS2 utilizzata è in fase EOL e risultano notevoli miglioramenti nelle versioni più recenti, in particolar modo sul layer DDS (e.g. [Zero Copy communication](https://www.eprosima.com/index.php/company-all/news/186-fast-dds-now-with-zero-copy)), che potrebbero confutare alcuni dei dati rilevati.\n\n# Riproduzione del progetto\nSeguire la\n[guida apposita](docs/building.md)\nper riprodurre il progetto.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feldavoo%2Fzeromq-experiment","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feldavoo%2Fzeromq-experiment","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feldavoo%2Fzeromq-experiment/lists"}