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

Environment Variables Reference

Set a runtime variable in the shell that starts the program. Set a build-time knob in the shell before nros build, or per image in system.toml (an [image.<id>] env row, or the knob-registry table where the section below says so).

The checkout’s .env file for in-tree builds: see Internals → Build Commands.

Runtime Configuration

Examples use ExecutorConfig::from_env() for configuration:

VariableDescriptionDefault
ROS_DOMAIN_IDROS 2 domain ID0
NROS_LOCATORRMW locator (tcp/…, udp/…, serial/…, or tls/…)tcp/127.0.0.1:7447
NROS_SESSION_MODESession mode: client or peerclient
ZENOH_TLS_ROOT_CA_CERTIFICATEPath to CA certificate (PEM) for TLS(none)
ZENOH_TLS_ROOT_CA_CERTIFICATE_BASE64Base64-encoded CA certificate for TLS(none)
ZENOH_TLS_VERIFY_NAME_ON_CONNECTVerify server hostname in TLS (true/false)(none)

Retired legacy names: ZENOH_LOCATOR and ZENOH_MODE are no longer read. Setting either is a startup ERROR naming its replacement (NROS_LOCATOR / NROS_SESSION_MODE) — Rust panics in resolve_hosted / returns InitError::RetiredEnvVar from nros::init, C / C++ init returns RCL_RET_INVALID_ARGUMENT / NROS_CPP_RET_INVALID_ARGUMENT and logs the reason. Refused rather than ignored: an ignored locator would dial the default router and read as “no delivery”. ZENOH_TLS_* names are kept because TLS is currently zenoh-specific.

TLS Notes

  • POSIX: requires libmbedtls-dev (install it with your host’s package manager). File-path and base64 cert loading are both supported.
  • Bare-metal: only ZENOH_TLS_ROOT_CA_CERTIFICATE_BASE64 is supported (no filesystem). The certificate is embedded at build time.
  • The link-tls Cargo feature must be enabled on both the example and the nros crate.

Build-Time Configuration

VariableDescriptionRequired
ZENOH_PICO_DIRCMake install prefix for pre-built zenoh-pico (use with system-zenohpico feature on zpico-sys)Only with system-zenohpico
NROS_EXTRA_BOARD_PATHExtra board-search roots (PATH-style : separated). Each entry is a directory shaped like packages/boards/ — subdirs carrying nros-board.toml crates or */boards/<name>/board.cmake bundles. Read by the nros CLI’s board catalog AND nano_ros_use_board() (also settable as a CMake cache var there). Board keys stay global: a name found under two roots is an error, never shadowed.(unset)

ARM FVP (FVP_BaseR_AEMv8R)

Not license-gated: nros setup --tool arm-fvp fetches the model from a pinned Arm CDN permalink ([tool.arm-fvp] in nros-sdk-index.toml, digest-checked) into the SDK store. Arm publishes it for x86_64 Linux only. You need none of the variables below unless you installed a model yourself. See the ARM FVP getting-started chapter for the end-to-end build+run walk-through.

VariableDescriptionDefault
ARMFVP_BIN_PATHDirectory containing FVP_BaseR_AEMv8R (Zephyr-canonical, highest priority).(unset)
ARM_FVP_DIRInstall root; resolver scans models/Linux64_GCC-*/ underneath.(unset)

The model is found in this order: ARMFVP_BIN_PATH, ARM_FVP_DIR, FVP_BaseR_AEMv8R on PATH, then the store copy that nros setup --tool arm-fvp installs. Set ARMFVP_BIN_PATH at BUILD time as well as run time, because Zephyr’s armfvp.cmake caches the location at configure. For a model you downloaded by hand, set ARM_FVP_DIR to the extraction root. nros doctor --board fvp-aemv8r-smp reports whether the model resolves.

Changing how the FVP is resolved or run in the tree: see Internals → Zephyr in-tree examples.

Vendored source trees

You normally set none of these. nros setup puts each tree in the shared store, and every build locates it through one ladder: this variable, then the project’s [sources] row in system.toml, then a checkout submodule you are editing, then the store, then the checkout’s own copy. nros locate <name> --why prints which rung answered. Set a variable only to build against a tree of your own.

VariableTree
FREERTOS_DIRFreeRTOS kernel source
LWIP_DIRlwIP source
NUTTX_DIRNuttX RTOS source
NUTTX_APPS_DIRNuttX apps source
THREADX_DIRThreadX kernel source
NETX_DIRNetX Duo source
CYCLONEDDS_SOURCE_DIRCyclone DDS source

FREERTOS_PORT, FREERTOS_CONFIG_DIR, THREADX_CONFIG_DIR and NETX_CONFIG_DIR are board facts: each board’s nros-board.toml states them, and the build carries them from there. They are not user inputs.

Buffer Tuning

All optional – platform-appropriate defaults apply if unset. See Configuration for deployment-scenario guidance and platform guides for target-specific sizing.

Zenoh-pico (NROS_ZENOH_*)

Each knob here used to be spelled ZPICO_<X>. That old spelling is retired: set in the environment or in an [image.<id>] env row, it stops the build with an error naming the NROS_ZENOH_* name to use. The full list is the retired-names table.

VariableDescriptionDefaultCrate
NROS_ZENOH_FRAG_MAX_SIZEMax reassembled message size after defragmentation65536 / 2048zpico-sys
NROS_ZENOH_BATCH_UNICAST_SIZEMax unicast batch size before fragmentation65536 / 1024zpico-sys
NROS_ZENOH_BATCH_MULTICAST_SIZEMax multicast batch size8192 / 1024zpico-sys
NROS_ZENOH_MAX_PUBLISHERSMax concurrent publishers in zenoh shim8zpico-sys
NROS_ZENOH_MAX_SUBSCRIBERSMax concurrent subscribers in zenoh shim8zpico-sys
NROS_ZENOH_MAX_QUERYABLESMax concurrent queryables in zenoh shim8zpico-sys
NROS_ZENOH_MAX_LIVELINESSMax concurrent liveliness tokens in zenoh shim. DERIVED when the image declares anything: one per node name plus the session’s own, one per publisher, subscriber, service server and client, and the parameter and lifecycle families’ servers and publisher. A stated value wins.16 when nothing is declaredzpico-sys
NROS_ZENOH_MAX_PENDING_GETSMax concurrent in-flight service calls4zpico-sys
NROS_ZENOH_MAX_TL_PUBLISHERSRetention slots for TRANSIENT_LOCAL publishers in the zenoh shim. Each also takes one NROS_ZENOH_MAX_QUERYABLES slot: a transient-local publisher declares a queryable so a late joiner can query its last sample. An image whose endpoints are declared DERIVES this (an action_server row counts one for its /status), and a stated value below the declared demand fails the build naming the knob.2nros-rmw-zenoh
NROS_ZENOH_TL_RETAIN_BYTESBytes one retained TRANSIENT_LOCAL sample may hold. A larger publish is SENT but not retained, and says so once at WARN.1024nros-rmw-zenoh
NROS_ZENOH_TL_RETAIN_DEPTHSamples each TRANSIENT_LOCAL publisher retains and replays, oldest first, to a late joiner. DERIVED from the deepest KEEP_LAST(N) a transient-local publisher declares; the publisher is granted and advertises min(asked, this). Must be >= 1.1 when nothing is declarednros-rmw-zenoh
NROS_SUBSCRIBER_BUFFER_SIZEsmall receive-class slot per subscriber in the zenoh shim; the executor arena reads the same name. (ZPICO_SUBSCRIBER_BUFFER_SIZE is a dead spelling — nothing reads it.)1024nros-rmw-zenoh
NROS_ZENOH_SUBSCRIBER_LARGE_SIZElarge size-class slot, for subscriptions whose type does not fit the small block16384nros-rmw-zenoh
NROS_ZENOH_SUBSCRIBER_SIZE_THRESHOLDThe small/large class split: a subscription whose rx_buffer_hint exceeds it is served from large. The cmake message-bound derivation assumes the shipped value (NROS_MESSAGE_BOUNDS_DEFAULT_SMALL_CEILING), so moving it can make a derived class count disagree with runtime routing, which surfaces as a failed create_subscription.2048nros-rmw-zenoh
NROS_ZENOH_PUBLISHER_TX_BUFFER_SIZEPer-publisher TX arena for the zero-copy loan path; costs NROS_ZENOH_MAX_PUBLISHERS x this.1024nros-rmw-zenoh
NROS_ZENOH_MAX_LARGE_SUBSCRIBERSHow many large-class blocks this image reserves. 0 is legal: an image whose subscribed types all fit NROS_SUBSCRIBER_BUFFER_SIZE declares 0 and stops paying RING_DEPTH x LARGE_SIZE — 65,536 B at the defaults — for a class it never routes into. A hint no class can hold then fails create_subscription rather than dropping every sample. DERIVED, on both lanes — a Zephyr image gets it from Kconfig’s -1 sentinel, and a cargo image gets it from the build settings nros build generates under build/, joined over the types the image’s components subscribe to. Setting it here still wins.2nros-rmw-zenoh
NROS_ZENOH_SERVICE_BUFFER_SIZEPer-service-server static buffer in zenoh shim1024nros-rmw-zenoh
NROS_PARAM_SERVICE_INBOX_BYTESBytes one request slot holds in the inbox ring of a ROS parameter service queryable (six per node) or a REP-2002 lifecycle one (five per node) – the BUILTIN family, which the zenoh shim selects by service name. DERIVED: with nothing stated, the contract’s declared parameters bound it, as the largest request a set_parameters over the worst-declared node can produce (672 B on the Autoware Safety Island, against the transport’s 1,024). A contract declaring a string- or array-valued parameter needs the parameter store’s capacities to price, which the RMW cannot see, so the shim abstains there and the user-service slot stands. Setting it here still wins.derived, else NROS_SERVICE_INBOX_BYTESnros-rmw-zenoh
NROS_PARAM_SERVICE_INBOX_DEPTHRequests one parameter or lifecycle service queryable holds before the newest is dropped. One, because this traffic is one request and one reply from a client that waits (ros2 param, rclcpp’s SyncParametersClient) and a node’s services are polled serially in one spin. Raise it to 2 for an image serving a parameter dashboard. Must be >= 1.1nros-rmw-zenoh
NROS_ZENOH_GET_REPLY_BUF_SIZEStack buffer for service client replies4096zpico-sys
NROS_ZENOH_GET_POLL_INTERVAL_MSSingle-threaded polling interval in zenoh_shim_get()10zpico-sys
NROS_SMOLTCP_MAX_SOCKETSMax concurrent TCP sockets (smoltcp); brokered default. (ZPICO_SMOLTCP_MAX_SOCKETS is retired.)1 (brokered)nros-smoltcp
NROS_SMOLTCP_MAX_UDP_SOCKETSMax concurrent UDP sockets (smoltcp); 1 by default, 4 with the nros-smoltcp/rtps feature. (ZPICO_SMOLTCP_MAX_UDP_SOCKETS is retired.)1 (brokered)nros-smoltcp
NROS_SMOLTCP_BUFFER_SIZEPer-socket staging buffer (smoltcp). (ZPICO_SMOLTCP_BUFFER_SIZE is retired.)2048nros-smoltcp
NROS_SMOLTCP_CONNECT_TIMEOUT_MSTCP connection timeout (smoltcp). (ZPICO_SMOLTCP_CONNECT_TIMEOUT_MS is retired.)30000nros-smoltcp
NROS_SMOLTCP_SOCKET_TIMEOUT_MSTCP read/write timeout (smoltcp). (ZPICO_SMOLTCP_SOCKET_TIMEOUT_MS is retired.)10000nros-smoltcp

XRCE-DDS (NROS_XRCE_*)

These are read by nros-rmw-xrce-cffi’s build script, either from the environment or — on Zephyr — from CONFIG_<name> in .config. They set C #defines of the same name without the NROS_ prefix; the define is not itself an environment variable, so exporting XRCE_BUFFER_SIZE has no effect and reports no error.

VariableDescriptionDefaultMinCrate
NROS_XRCE_BUFFER_SIZEPer-slot receive buffer. See the note below — this is the receive ceiling.102464nros-rmw-xrce
NROS_XRCE_SUBSCRIBER_RING_DEPTHQueued samples per subscriber321nros-rmw-xrce
NROS_XRCE_MAX_SUBSCRIBERSMax concurrent subscribers. On Zephyr, DERIVED — see below.80nros-rmw-xrce
NROS_XRCE_MAX_SERVICE_SERVERSMax concurrent service servers. On Zephyr, DERIVED — see below.40nros-rmw-xrce
NROS_XRCE_MAX_SERVICE_CLIENTSMax concurrent service clients. DERIVED from the sizing descriptor — see below.40nros-rmw-xrce
NROS_XRCE_STREAM_HISTORYReliable stream history depth; sizes the per-session output buffer164nros-rmw-xrce
NROS_XRCE_CUSTOM_TRANSPORT_MTUCustom transport MTU; stream buffers are MTU x STREAM_HISTORY4096128nros-rmw-xrce
NROS_XRCE_TRANSPORT_MTUUDP/TCP transport MTU, and the Zephyr default of CUSTOM_TRANSPORT_MTU4096 (Zephyr 512)128nros-rmw-xrce
NROS_XRCE_SUBSCRIBER_BUFFER_SIZESubscriber ring entry size; derived from the declared subscriptions when unstated (Zephyr: -1)BUFFER_SIZE1nros-rmw-xrce
NROS_XRCE_SERVICE_REQUEST_BUFFER_SIZEApplication service-server request entry size. DERIVED from the declared servers’ requests beside the builtin splitBUFFER_SIZE1nros-rmw-xrce
NROS_XRCE_SERVICE_REPLY_BUFFER_SIZEService-client reply slot size. DERIVED from the declared clients’ repliesBUFFER_SIZE1nros-rmw-xrce
NROS_XRCE_BUILTIN_SERVICE_SERVERSHow many service-server slots are the parameter / lifecycle services’. DERIVED beside the total0 (no split)0nros-rmw-xrce
NROS_XRCE_BUILTIN_SERVICE_REQUEST_BUFFER_SIZERequest entry size of a builtin-family slotBUFFER_SIZE, raised to the parameter request1nros-rmw-xrce

Dropping MAX_SUBSCRIBERS, MAX_SERVICE_* and SUBSCRIBER_RING_DEPTH to 1, BUFFER_SIZE to 256, STREAM_HISTORY to 4 and CUSTOM_TRANSPORT_MTU to 512 takes the session struct from ~390 KB to ~10-20 KB.

Every variable in this table is a knob-registry row, so a project states it per image as [image.<id>.knobs.xrce] buffer_size = 256 — the name without NROS_XRCE_, lowercased (max_subscribers, max_service_servers, max_service_clients, subscriber_ring_depth, subscriber_buffer_size, service_request_buffer_size, service_reply_buffer_size, stream_history, transport_mtu, custom_transport_mtu) — rather than as an env row.

On Zephyr the three entity caps DERIVE, and the minimum is 0

CONFIG_NROS_XRCE_MAX_SUBSCRIBERS and CONFIG_NROS_XRCE_MAX_SERVICE_SERVERS default to -1, which means take the number from the entities this image declares (the contract sidecar beside the bringup’s launch file, or beside the bringup’s system.toml when it has no launch/). A listener that declares one subscription and no service is built with one subscriber slot and zero service-server slots, which is what took the session struct from 427,968 bytes to 59,088 on the zephyr cpp listener. Stating a number in Kconfig or the environment still wins over the derivation, in both directions.

CONFIG_NROS_XRCE_MAX_SERVICE_CLIENTS also defaults to -1, and its number comes from the image’s sizing descriptor on every road that writes one: the declared service clients plus three per action client (send_goal, cancel_goal, get_result). With no descriptor, or one that does not state both counts, the crate default of 4 stands.

Zero is a legal, honoured value for all three caps — it is not rounded up to 1. So creating an entity the image never declared does not truncate silently: the create fails with InvalidConfig and the backend logs which cap it hit, which knob moves it, and that the count came from the declaration.

NROS_XRCE_SUBSCRIBER_RING_DEPTH is deliberately NOT derivable — no inventory knows how deep a burst a subscriber must survive — but it does have a Kconfig symbol, and on Zephyr that is the way to set it: a Zephyr cargo build sees only the knobs nros_cargo_build.cmake forwards, and shell exports do not survive that.

NROS_XRCE_BUFFER_SIZE is the XRCE receive ceiling

A subscriber’s receive ring entry is a fixed uint8_t data[XRCE_BUFFER_SIZE], so a subscription’s own buffer size cannot raise it: asking for create_subscription_sized::<M, 16384> still stops at 1024, because the 16384 buffer is the destination of a copy that never happens. A sample that does not fit is refused on take with MessageTooLarge.

The static cost is XRCE_SUBSCRIBER_RING_DEPTH x XRCE_BUFFER_SIZE per subscriber, which is why the default is small — raise it deliberately, and consider lowering the ring depth at the same time.

A payload at or above the transport MTU (4096) arrives fragmented; the receive path reads the fragment chain and delivers it whole.

Compile-time only (not environment variables)

These are #defines in packages/rmw/xrce/nros-rmw-xrce/src/internal.h with no env or Kconfig knob. Changing them means editing that header.

DefineDescriptionDefault
XRCE_ENTITY_CREATION_TIMEOUT_MSTimeout for entity creation1000
XRCE_SERVICE_REPLY_TIMEOUT_MSPer-attempt service reply timeout50
XRCE_SERVICE_REPLY_TOTAL_MSTotal service reply budget5000
XRCE_SESSION_FLUSH_TIMEOUT_MSSession flush timeout100
XRCE_SESSION_CREATION_RETRIESSession creation retries3
XRCE_MAX_PENDING_REPLIESIn-flight service replies4
XRCE_SERVICE_REQUEST_RING_DEPTHQueued service requests per server4
XRCE_DEFAULT_AGENT_PORTDefault agent port2018

Core (NROS_*)

VariableDescriptionDefaultCrate
NROS_EXECUTOR_MAX_CBSMax executor callback slots (compile-time fixed array size)4nros-node
NROS_EXECUTOR_ARENA_SIZEExecutor arena size in bytes (compile-time fixed array size)4096nros-node
NROS_SUBSCRIPTION_BUFFER_SIZEDefault subscription/service buffer size (bytes)1024nros-node
NROS_LET_BUFFER_SIZEBuffer size for LET semantics per handle512nros-c
NROS_MAX_CONCURRENT_GOALSMax concurrent goals per action server (compile-time constant, not env-var configurable)4nros-c
NROS_MAX_PARAMETERSMax parameters in parameter server32nros-params
NROS_MAX_PARAM_NAME_LENMax parameter name length64nros-params
NROS_MAX_STRING_VALUE_LENMax string parameter value length256nros-params
NROS_MAX_ARRAY_LENMax parameter array length32nros-params
NROS_MAX_BYTE_ARRAY_LENMax byte array parameter length256nros-params
NROS_MAX_PARAM_DESCRIPTION_LENMax parameter description length; longer is truncated and logged, 0 = none (max 256)256nros-params

Design background