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

Migration Guide for ROS 2 Users

This page maps standard ROS 2 concepts to their nano-ros equivalents. It is not an API reference; use it as a checklist when moving an existing rclcpp, rclc, or rclrs node toward nano-ros.

Concept map

You have (ROS 2)You get (nano-ros)Where
colcon workspace (src/*)nano-ros workspace: Node pkgs + one declarative Bringup pkg, whose system.toml carries one [image.<id>] row per deploy target. The binary is generated, not writtenProject layout
package.xmlkept, verbatim. What it deploys to is not in it — that is the bringup’s system.tomlAnatomy
.launch.xml / .launch.pykept — nros sync resolves them (RFC-0060) into a SystemModel the image bakes inBringup packages
ros2 launch pkg filenros build <image>, then run its binary — the launch product is compiled inImages
colcon buildnros build <image> — it generates the root and hands off to cmake / cargo / west / idf.py. Running those yourself still works when you point them at the generated build root, and colcon build still works for POSIX C++ workspacesC/C++ workspaces
rosdep installnros setup <board> --rmw <rmw>Install
RMW_IMPLEMENTATION=… at runtimecompile-time backend, one line: [system] rmw = "…" in system.toml, then nros syncSwitching RMW
generated msg packages (ament index)nros sync writes generated/ crates; the cargo patch table goes in the generated settings under build/, not in your packageMessage Generation
find_package(rclcpp)find_package(nano_ros) — ament-shaped, source-backedPorting a C++ node
ament_target_dependencies(t std_msgs)kept, verbatim (nano-ros’s ament verbs + find modules)same page

Setup

Standard ROS 2 usually starts from a distro install and a runtime RMW choice. nano-ros starts from a source checkout + a compile-time target tuple:

git clone --branch=v<X.Y.Z> https://github.com/NEWSLabNTU/nano-ros.git
cd nano-ros
./scripts/bootstrap.sh              # build the nros CLI (no `just` needed)
source ./activate.sh
nros setup linux --rmw zenoh       # native/ROS/zenoh quick start

Read Setup Compared to Standard ROS 2 before changing package code.

Node Lifecycle

ROS 2 applications typically call rclcpp::init(), create nodes, then spin. nano-ros opens an executor first; the executor owns the session, arena, and runtime budget. Nodes and entities are created from it.

See Differences from Standard ROS 2 and Execution Model and Two-Layer API.

Publishers and Subscriptions

Topic names, message names, and CDR wire encoding stay ROS-shaped. The main porting decision is whether to use:

  • polling handles from Node::create_*, or
  • callback registration through Executor::register_*.

Use polling for RTIC, Embassy, or tight RT loops. Use callbacks for desktop-style event-driven nodes.

Services and Actions

Service and action names map cleanly, but nano-ros exposes request / reply and goal / feedback / result paths through explicit handles and promises. Manual-poll paths may require explicit result handling in RTOS loops.

Start with the native examples, then check platform-specific examples for FreeRTOS, Zephyr, or bare-metal timing constraints.

QoS and Events

nano-ros keeps DDS-shaped QoS profile fields, but each backend advertises the policies it can enforce. Unsupported QoS is reported at entity creation instead of being silently downgraded.

See QoS, Status Events, and Discovery and Choosing an RMW Backend.

Message Generation

Standard ROS 2 builds generated message libraries as sibling packages. nano-ros generates Rust, C, or C++ bindings into the workspace or build tree and can use a shared generation cache.

See Message Binding Generation.

Backend Selection

Replace runtime RMW_IMPLEMENTATION=... with a compile-time selection:

  • zenoh for ROS 2 interop through rmw_zenoh_cpp (default).
  • xrce for agent-based micro-ROS-style deployments.
  • cyclonedds for direct DDS/RTPS interop with rmw_cyclonedds_cpp — no router or agent process at all — where the platform supports the required networking and memory model.

Common Porting Traps

  • Assuming the backend can change without rebuilding.
  • Creating heap-heavy callbacks on no_std targets without alloc.
  • Expecting ROS 2 graph introspection APIs on constrained targets.
  • Forgetting to match ROS domain ID, QoS reliability, or zenoh router mode during interop tests.
  • Treating a platform guide as optional when cross-compiling for RTOS or bare-metal targets.