Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Architecture Overview

nano-ros is a ROS 2 client stack for embedded and RTOS targets. The important architectural idea is separation by responsibility: user code talks to a ROS-shaped API, the core runtime owns entities and serialization, the RMW layer moves bytes, and the platform layer supplies OS or hardware primitives.

Layers

Application
  Rust / C / C++ node code

Board package (optional)
  Hardware init, network drivers, config loading, entry point

Core runtime
  Executor, Node, pub/sub/service/action handles, parameters,
  message traits, CDR serialization

RMW backend
  Zenoh, XRCE-DDS, Cyclone DDS, or a custom backend

Platform
  Clock, allocation, threading, sleep, random, sockets, libc,
  and bare-metal network polling

POSIX applications usually depend directly on nros. Embedded applications often depend on a board package that initializes hardware, networking, and platform glue before running user code.

Core Runtime

The core runtime is middleware-agnostic. nros-node owns the Executor, node creation, entity handles, timers, and the two API styles:

  • Node::create_* returns handles that the caller polls or awaits.
  • Executor::register_* installs callbacks dispatched by spin_once.

Message and service types are ordinary generated Rust, C, or C++ types with CDR serialization. The RMW backend receives serialized bytes; it does not own rosidl typesupport.

For the API split, see Execution Model and Two-Layer API.

RMW Layer

The RMW layer is the transport boundary. It creates sessions, publishers, subscribers, services, clients, and action channels, then moves serialized samples over the selected wire protocol.

Each Node picks its backend at build time. That compile-time selection replaces standard ROS 2’s runtime RMW_IMPLEMENTATION plugin loader, which is not available on many embedded targets. A single binary can link multiple backends and bridge between them — see Cross-backend Bridges.

For user-facing backend selection, see Choosing an RMW Backend. For design rationale, see RMW API Design.

Platform Layer

The platform layer supplies the primitives that desktop ROS 2 normally gets from the operating system: monotonic time, memory allocation, threading, sleep, random IDs, TCP/UDP sockets, multicast, and libc helpers. Bare-metal ports may also expose a network_poll() hook so the runtime can advance smoltcp while waiting.

The platform is selected at compile time together with the RMW backend and ROS edition. See Platform Model for the feature axes and Custom Platform for porting.

Board Packages

A board package combines a platform implementation with hardware setup and drivers. It typically provides:

  • a Config type loaded from config.toml or target-specific build settings,
  • network and clock initialization,
  • driver setup for Ethernet, UART, WiFi, or simulator I/O,
  • a run() entry point that starts the scheduler or main loop.

Board packages are optional for POSIX but useful for RTOS and bare-metal targets. See Custom Board Package.

Data Flow

Publishing follows this path:

user message -> CDR serializer -> RMW publish bytes -> transport

Receiving reverses it:

transport -> RMW receive bytes -> CDR deserializer -> user handle/callback

This boundary keeps the transport layer small and lets the same message types work across Rust, C, and C++ APIs.

Where to Go Next